Files
tripz-llc/marketing/js/calculator.js
T
Hamza-AyedandClaude Opus 5 0de8573d27 fix(marketing): تصحيح حاسبة التوفير ونسبة GMV لباقة النمو
- باقة النمو صارت شريحتين: 2% حتى $50k ثم 1.5% حتى $200k (كانت 2% حتى
  $200k)، محدَّثة في الخمس لغات
- مقارنة المنافس صارت 15% من GMV مع حدّ أدنى $0.10 للرحلة، بدل 10%/5%
- استُخرجت tripzMonthly كدالة مستقلة، وأُضيفت crossoverTripsPerDay
- تُعرض الآن نقطة التعادل تحت رقم التوفير، وكذلك حين لا يوجد توفير بعد

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:21:34 +03:00

119 lines
4.6 KiB
JavaScript

/* ============ CALCULATOR (docs/05 formula) ============ */
function fmt(n){return "$"+Math.round(n).toLocaleString("en-US");}
const CURS=[
{val:"JOD:1.41",key:"calc.opt.jod"},
{val:"EGP:0.021",key:"calc.opt.egp"},
{val:"SYP:0.00007",key:"calc.opt.syp"},
{val:"IQD:0.00076",key:"calc.opt.iqd"},
{val:"USD:1",key:"calc.opt.usd"},
{val:"EUR:1.08",key:"calc.opt.eur"},
{val:"MAD:0.10",key:"calc.opt.mad"},
{val:"XOF:0.0017",key:"calc.opt.xof"}
];
const PLANS=[
{val:"349:0.025:0.04:launch",key:"calc.opt.launch"},
{val:"599:0.02:0.03:growth",key:"calc.opt.growth"},
{val:"879:0.01:0.02:sov",key:"calc.opt.sov"}
];
function buildCalcDropdowns(){
const d=I18N[LANG];
const curSel=$("#cur"),planSel=$("#plan");
const curVal=curSel.value,planVal=planSel.value;
curSel.innerHTML="";planSel.innerHTML="";
CURS.forEach(c=>{const o=document.createElement("option");o.value=c.val;o.textContent=d[c.key]||c.val;curSel.appendChild(o);});
PLANS.forEach(p=>{const o=document.createElement("option");o.value=p.val;o.textContent=d[p.key]||p.val;planSel.appendChild(o);});
curSel.value=curVal;planSel.value=planVal;
}
function tripzMonthly(base, pKey, gmv, monthlyTrips, minRate){
let gmvFee;
if(pKey === "launch"){
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 === "growth"){
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 {
gmvFee = gmv * 0.01;
}
const minMonthly = monthlyTrips * minRate;
return base + Math.max(minMonthly, gmvFee);
}
function crossoverTripsPerDay(base, pKey, minRate, usd){
for(let t = 1; t <= 10000; t++){
const mTrips = t * 30;
const gmv = mTrips * usd;
const tMonthly = tripzMonthly(base, pKey, gmv, mTrips, minRate);
const cMonthly = Math.max(gmv * 0.15, mTrips * 0.10);
if(cMonthly >= tMonthly){
return t;
}
}
return null;
}
function calc(){
const trips=+$("#trips").value;
const fare=+$("#fare").value||0;
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;
const tripz = tripzMonthly(base, pKey, gmv, monthlyTrips, minRate);
const commission = gmv * 0.15;
const floor = monthlyTrips * 0.10;
$("#rTripz").textContent = fmt(tripz);
$("#rComm").textContent = fmt(commission);
$("#rFloor").textContent = fmt(floor);
const rivalMax = Math.max(commission, floor);
const save = rivalMax - tripz;
const bigEl = $("#saveBig");
const noteEl = $("#saveNote");
const crossover = crossoverTripsPerDay(base, pKey, minRate, usd);
if(save > 0){
bigEl.textContent = fmt(save * 12) + "/yr";
if(noteEl){
noteEl.style.display = "block";
const crossTxt = (I18N[LANG] && I18N[LANG]["calc.r.crossover"])
? I18N[LANG]["calc.r.crossover"].replace("{n}", crossover || 101)
: (LANG === "ar" ? `نقطة التعادل والتوفير تبدأ من ${crossover || 101} رحلة/يومياً` : `Break-even and real savings start at ${crossover || 101} trips/day`);
noteEl.textContent = crossTxt;
}
} else {
bigEl.textContent = "$0/yr";
if(noteEl){
noteEl.style.display = "block";
const crossTxt = (I18N[LANG] && I18N[LANG]["calc.r.crossover"])
? I18N[LANG]["calc.r.crossover"].replace("{n}", crossover || 101)
: (LANG === "ar" ? `تبدأ بالربح والتوفير مع Tripz عند وصولك لـ ${crossover || 101} رحلة/يومياً` : `You start saving with Tripz once you reach ${crossover || 101} trips/day`);
noteEl.textContent = crossTxt;
}
}
const sv = $("#savings"); sv.classList.remove("bump"); void sv.offsetWidth; sv.classList.add("bump");
const tripsEl = $("#trips");
const minTrips = +tripsEl.min || 50;
const maxTrips = +tripsEl.max || 5000;
const pct = ((trips - minTrips) / (maxTrips - minTrips)) * 100;
tripsEl.style.setProperty("--p", pct + "%");
$("#tripsVal").textContent = trips.toLocaleString("en-US") + " / day";
const msg = encodeURIComponent(`Tripz — ${I18N[LANG]["calc.r.savecap"]}: ${bigEl.textContent} | ${trips}/day @ ${fare} ${curCode}`);
$("#waCalc").href = "https://wa.me/201023248456?text=" + msg;
}
/* ============ CALC INPUTS ============ */
["trips","fare","cur","plan"].forEach(id=>$("#"+id).addEventListener("input",calc));