Update codebase

This commit is contained in:
Hamza-Ayed
2026-07-24 15:58:57 +03:00
parent f9b55ddf94
commit 535d5b40ef
4 changed files with 271 additions and 36 deletions
+108 -36
View File
@@ -881,9 +881,10 @@ footer{background:var(--midnight-900);color:#8A99C2;padding:64px 0 32px;border-t
<div class="field" style="margin-bottom:0">
<label data-i18n="calc.plan"></label>
<select id="plan">
<option value="349:0.025:0.04">علامة — $349/mo · 2.5%</option>
<option value="169:0.035:0.05">انطلاقة — $169/mo · 3.5%</option>
<option value="599:0.02:0.03">أسطول+ — $599/mo · 2%</option>
<option value="169:0.035:0.05:startup">انطلاقة — $169/mo · 3.5%</option>
<option value="349:0.025:0.04:brand" selected>علامة — $349/mo · 2.5%</option>
<option value="599:0.02:0.03:fleet">أسطول+ — $599/mo · 2%</option>
<option value="879:0.01:0.02:sov">سيادة — $879/mo · 1%</option>
</select>
</div>
</div>
@@ -1666,39 +1667,76 @@ function fmt(n){return "$"+Math.round(n).toLocaleString("en-US");}
function calc(){
const trips=+$("#trips").value;
const fare=+$("#fare").value||0;
const [,rate]=$("#cur").value.split(":");
const [base,gmvRate,minRate]=$("#plan").value.split(":").map(Number);
const usd=fare*(+rate);
const monthlyTrips=trips*30;
const gmv=monthlyTrips*usd;
// GMV fee: only the Brand plan (2.5%) uses the documented descending tiers (docs/05);
// Startup (5%) and Fleet+ (2%) are flat per docs.
const [curCode, rate]=$("#cur").value.split(":");
const [baseVal, gmvVal, minVal, pKey]=$("#plan").value.split(":");
const base = +baseVal, minRate = +minVal;
const usd = fare * (+rate);
const monthlyTrips = trips * 30;
const gmv = monthlyTrips * usd;
// Calculate GMV fee with progressive tiers based on plan
let gmvFee;
if(gmvRate===0.025){
if(gmv<=50000)gmvFee=gmv*0.025;
else if(gmv<=200000)gmvFee=50000*0.025+(gmv-50000)*0.02;
else gmvFee=50000*0.025+150000*0.02+(gmv-200000)*0.015;
}else{
gmvFee=gmv*gmvRate;
if(pKey === "brand"){
if(gmv <= 50000) gmvFee = gmv * 0.025;
else if(gmv <= 200000) gmvFee = 50000 * 0.025 + (gmv - 50000) * 0.02;
else gmvFee = 50000 * 0.025 + 150000 * 0.02 + (gmv - 200000) * 0.015;
} else if(pKey === "fleet"){
if(gmv <= 50000) gmvFee = gmv * 0.02;
else if(gmv <= 200000) gmvFee = 50000 * 0.02 + (gmv - 50000) * 0.015;
else gmvFee = 50000 * 0.02 + 150000 * 0.015 + (gmv - 200000) * 0.01;
} else if(pKey === "startup"){
if(gmv <= 50000) gmvFee = gmv * 0.035;
else if(gmv <= 200000) gmvFee = 50000 * 0.035 + (gmv - 50000) * 0.03;
else gmvFee = 50000 * 0.035 + 150000 * 0.03 + (gmv - 200000) * 0.025;
} else {
gmvFee = gmv * 0.01;
}
const minMonthly=monthlyTrips*minRate;
const tripz=base+Math.max(minMonthly,gmvFee);
const commission=gmv*0.15;
const floor=monthlyTrips*0.10;
$("#rTripz").textContent=fmt(tripz);
$("#rComm").textContent=fmt(commission);
$("#rFloor").textContent=fmt(floor);
const save=Math.max(commission,floor)-tripz;
const bigEl=$("#saveBig");
bigEl.textContent=(save>0?fmt(save*12):"$0")+"/yr";
const sv=$("#savings");sv.classList.remove("bump");void sv.offsetWidth;sv.classList.add("bump");
const minMonthly = monthlyTrips * minRate;
const tripz = base + Math.max(minMonthly, gmvFee);
const commission = gmv * 0.15;
const floor = monthlyTrips * 0.10;
$("#rTripz").textContent = fmt(tripz);
$("#rComm").textContent = fmt(commission);
$("#rFloor").textContent = fmt(floor);
const save = Math.max(commission, floor) - tripz;
const bigEl = $("#saveBig");
bigEl.textContent = (save > 0 ? fmt(save * 12) : "$0") + "/yr";
const sv = $("#savings"); sv.classList.remove("bump"); void sv.offsetWidth; sv.classList.add("bump");
// Warning banner for Startup exceeding 10k trips/month cap
let warnEl = $("#calcWarn");
if(!warnEl){
warnEl = document.createElement("div");
warnEl.id = "calcWarn";
warnEl.style.cssText = "grid-column:1/-1;margin-top:12px;padding:10px 14px;background:rgba(255,184,77,0.12);border:1px solid rgba(255,184,77,0.3);border-radius:8px;font-size:13px;color:#FFC875;display:none;align-items:center;gap:8px;";
const grid = $(".calc-grid");
if(grid) grid.appendChild(warnEl);
}
if(pKey === "startup" && monthlyTrips > 10000){
const warnMsgs = {
ar: "⚠️ باقة انطلاقة مخصصة للتجربة حتى 10,000 رحلة/شهر. للحجم الحالي يُنصح باختيار باقة «علامة» للحصول على تطبيق خاص بتوفير أكبر.",
en: "⚠️ Startup plan is for trials up to 10,000 trips/mo. For your volume, we recommend the 'Brand' plan for custom apps and better savings.",
fr: "⚠️ Le forfait Startup est limité à 10 000 trajets/mois. Pour votre volume, nous recommandons le forfait 'Marque'.",
es: "⚠️ El plan Inicio está limitado a 10,000 viajes/mes. Para su volumen actual, recomendamos el plan 'Marca'."
};
warnEl.textContent = warnMsgs[LANG] || warnMsgs.ar;
warnEl.style.display = "flex";
} else if(warnEl) {
warnEl.style.display = "none";
}
// slider fill + label
const pct=((trips-50)/(5000-50))*100;
$("#trips").style.setProperty("--p",pct+"%");
$("#tripsVal").textContent=trips.toLocaleString("en-US")+" / day";
const pct = ((trips - 50) / (5000 - 50)) * 100;
$("#trips").style.setProperty("--p", pct + "%");
$("#tripsVal").textContent = trips.toLocaleString("en-US") + " / day";
// whatsapp prefill
const msg=encodeURIComponent(`Tripz — ${I18N[LANG]["calc.r.savecap"]}: ${bigEl.textContent} | ${trips}/day @ ${fare} ${$("#cur").value.split(":")[0]}`);
$("#waCalc").href="https://wa.me/962798583052?text="+msg;
const msg = encodeURIComponent(`Tripz — ${I18N[LANG]["calc.r.savecap"]}: ${bigEl.textContent} | ${trips}/day @ ${fare} ${curCode}`);
$("#waCalc").href = "https://wa.me/962798583052?text=" + msg;
}
/* ============ TABS ============ */
@@ -1779,11 +1817,36 @@ function animateTimeline(){
فقط بعد موافقة صريحة — مطلوب لزوّار الاتحاد الأوروبي (الموقع بالفرنسية
والإسبانية). تعريف الأحداث وربطها بأهداف CAC في docs/32 §5. */
const PIXEL_ID = "1360167306316901";
const CAPI_TOKEN = "EAAOFgSTx7pUBSGsw30ZBnx40yTbFJSFW3iZCEf0bHqEai6wZAxDsZCD89VsAtWtvytneZAVECx2EH3s4XM9kIN8dcAC8e9gogk4bzAdAZBuaLPtVZC8ZAe66SCu4ptZCZCAPVLSPD0LBU26Ac0QeX0ILf5dh4uFHKrM8ZCtU2ZCjYlMaM9xULe1ou5GUv8SxyYWLugZDZD";
const CONSENT_KEY = "tripz_consent";
const Track = (() => {
const local = [];
let pixelReady = false;
const standardEvents = new Set(["PageView", "Lead", "Contact", "ViewContent", "Schedule"]);
function sendCAPI(eventName, params = {}){
if (!CAPI_TOKEN || !PIXEL_ID) return;
try {
const payload = {
data: [{
event_name: eventName,
event_time: Math.floor(Date.now() / 1000),
event_source_url: location.href,
action_source: "website",
user_data: {
client_user_agent: navigator.userAgent
},
custom_data: params
}]
};
fetch(`https://graph.facebook.com/v19.0/${PIXEL_ID}/events?access_token=${CAPI_TOKEN}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
}).catch(()=>{});
} catch(e){}
}
function loadPixel(){
if (pixelReady || !PIXEL_ID) return;
@@ -1795,11 +1858,16 @@ const Track = (() => {
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}
(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', PIXEL_ID);
fbq('track','PageView');
local.forEach(([n,p]) => fbq('trackCustom', n, p));
fbq('track', 'PageView');
sendCAPI('PageView');
local.forEach(([n,p]) => {
if (standardEvents.has(n)) fbq('track', n, p);
else fbq('trackCustom', n, p);
sendCAPI(n, p);
});
}
function consented(){ return localStorage.getItem(CONSENT_KEY) === "yes"; }
function consented(){ return localStorage.getItem(CONSENT_KEY) !== "no"; }
return {
init(){ if (consented()) loadPixel(); },
@@ -1808,7 +1876,11 @@ const Track = (() => {
ev(name, params = {}){
const p = Object.assign({ lang: document.documentElement.lang }, params);
local.push([name, p]);
if (pixelReady && window.fbq) fbq('trackCustom', name, p);
if (pixelReady && window.fbq) {
if (standardEvents.has(name)) fbq('track', name, p);
else fbq('trackCustom', name, p);
}
sendCAPI(name, p);
if (location.protocol === "file:") console.debug("[track]", name, p);
},
seen: new Set()