Commit 32927760 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Update pricing page to match real packages + add subscription calculator slider

4 tiers in EGP: نسبة فقط (Free/12%), المبتدئ (1000/7.5%), المؤسسي (3500/5%),
الاحترافي (10000/3.5%). Interactive slider shows total cost based on monthly
collections volume, highlights the best-value plan dynamically.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 7d7030f4
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { Check, X } from "lucide-react"; import { Check, X, Clock } from "lucide-react";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import Navbar from "@/components/layout/Navbar"; import Navbar from "@/components/layout/Navbar";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import Container from "@/components/shared/Container"; import Container from "@/components/shared/Container";
import AnimateOnScroll from "@/components/shared/AnimateOnScroll"; import AnimateOnScroll from "@/components/shared/AnimateOnScroll";
import PricingCalculator from "@/components/sections/PricingCalculator";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { import {
...@@ -16,7 +17,7 @@ import { ...@@ -16,7 +17,7 @@ import {
AccordionContent, AccordionContent,
} from "@/components/ui/accordion"; } from "@/components/ui/accordion";
import { content } from "@/lib/content"; import { content } from "@/lib/content";
import { fadeUp, staggerContainer, staggerItem } from "@/lib/animations"; import { staggerContainer, staggerItem } from "@/lib/animations";
const pricing = content.ar.pricing; const pricing = content.ar.pricing;
...@@ -80,13 +81,13 @@ export default function PricingPage() { ...@@ -80,13 +81,13 @@ export default function PricingPage() {
initial="hidden" initial="hidden"
whileInView="visible" whileInView="visible"
viewport={{ once: true, amount: 0.2 }} viewport={{ once: true, amount: 0.2 }}
className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8 items-stretch" className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5 lg:gap-6 items-stretch"
> >
{pricing.plans.map((plan, index) => ( {pricing.plans.map((plan) => (
<motion.div <motion.div
key={plan.name} key={plan.name}
variants={staggerItem} variants={staggerItem}
className={`relative flex flex-col rounded-2xl border bg-white p-6 lg:p-8 shadow-sm transition-shadow hover:shadow-md ${ className={`relative flex flex-col rounded-2xl border bg-white p-5 lg:p-6 shadow-sm transition-shadow hover:shadow-md ${
plan.highlighted plan.highlighted
? "border-2 border-sky-500 shadow-sky-100" ? "border-2 border-sky-500 shadow-sky-100"
: "border-slate-200" : "border-slate-200"
...@@ -102,50 +103,60 @@ export default function PricingPage() { ...@@ -102,50 +103,60 @@ export default function PricingPage() {
)} )}
{/* Plan Header */} {/* Plan Header */}
<div className="text-center mb-6"> <div className="text-center mb-4">
<h3 className="text-xl font-bold text-navy-800"> <h3 className="text-xl font-bold text-navy-800">
{plan.name} {plan.name}
</h3> </h3>
<p className="mt-1 text-sm text-slate-500"> <p className="mt-1 text-xs text-slate-500">
{plan.description} {plan.subtitle}
</p> </p>
</div> </div>
{/* Price */} {/* Price */}
<div className="text-center mb-2"> <div className="text-center mb-1">
<span className="text-4xl lg:text-5xl font-bold text-navy-800" dir="ltr"> <span className="text-3xl lg:text-4xl font-bold text-navy-800">
{plan.price} {plan.price}
</span> </span>
</div>
{plan.period && ( {plan.period && (
<span className="text-sm text-slate-500 ms-1"> <p className="text-center text-sm text-slate-500 mb-3">
{plan.period} {plan.period}
</span> </p>
)} )}
</div>
{/* Platform Fee */} {/* Platform Fee */}
{"platformFee" in plan && plan.platformFee && ( <div className="text-center mb-4">
<div className="text-center mb-6"> <span className="inline-flex items-center gap-1.5 rounded-full bg-sky-50 px-3 py-1.5 text-xs font-medium text-sky-700">
<span className="inline-flex items-center gap-1.5 rounded-full bg-sky-50 px-3 py-1 text-xs font-medium text-sky-700"> <span>نسبة المنصة:</span>
{pricing.platformFeeLabel}: {plan.platformFee} <span className="font-bold">{plan.platformFee}</span>
<span className="text-sky-500">{pricing.collectionsLabel}</span>
</span> </span>
</div> </div>
)}
{/* Trial Badge */}
<div className="flex justify-center mb-5">
<span className="inline-flex items-center gap-1 text-xs text-slate-500">
<Clock className="w-3 h-3" />
{pricing.trialBadge}
</span>
</div>
<hr className="border-slate-100 mb-5" />
{/* Features */} {/* Features */}
<ul className="flex-1 space-y-3 mb-8"> <ul className="flex-1 space-y-2.5 mb-6">
{plan.features.map((feature) => ( {plan.features.map((feature) => (
<li <li
key={feature.text} key={feature.text}
className="flex items-center gap-3" className="flex items-start gap-2.5"
> >
{feature.included ? ( {feature.included ? (
<Check className="h-4 w-4 text-emerald-500 shrink-0" /> <Check className="h-4 w-4 text-emerald-500 shrink-0 mt-0.5" />
) : ( ) : (
<X className="h-4 w-4 text-slate-300 shrink-0" /> <X className="h-4 w-4 text-slate-300 shrink-0 mt-0.5" />
)} )}
<span <span
className={`text-sm ${ className={`text-sm leading-snug ${
feature.included feature.included
? "text-slate-700" ? "text-slate-700"
: "text-slate-400" : "text-slate-400"
...@@ -173,8 +184,11 @@ export default function PricingPage() { ...@@ -173,8 +184,11 @@ export default function PricingPage() {
</Container> </Container>
</section> </section>
{/* Pricing Calculator */}
<PricingCalculator />
{/* FAQ */} {/* FAQ */}
<section className="py-16 bg-slate-50"> <section className="py-16 bg-white">
<Container className="max-w-3xl"> <Container className="max-w-3xl">
<AnimateOnScroll> <AnimateOnScroll>
<h2 className="text-2xl sm:text-3xl font-bold text-navy-800 text-center mb-10"> <h2 className="text-2xl sm:text-3xl font-bold text-navy-800 text-center mb-10">
......
"use client";
import { useState, useMemo } from "react";
import { motion } from "framer-motion";
import Container from "@/components/shared/Container";
import AnimateOnScroll from "@/components/shared/AnimateOnScroll";
import { content } from "@/lib/content";
const pricing = content.ar.pricing;
const PLANS = pricing.plans.map((p) => ({
name: p.name,
subscription: p.priceNumeric,
feePercent: p.platformFeeNumeric,
}));
const MIN_COLLECTIONS = 10000;
const MAX_COLLECTIONS = 500000;
const STEP = 5000;
function formatMoney(amount: number): string {
return amount.toLocaleString("ar-EG") + " ج.م.";
}
export default function PricingCalculator() {
const [collections, setCollections] = useState(460000);
const calculations = useMemo(() => {
return PLANS.map((plan) => {
const commission = Math.round(collections * plan.feePercent);
const total = plan.subscription + commission;
return {
name: plan.name,
subscription: plan.subscription,
feePercent: plan.feePercent,
commission,
total,
};
});
}, [collections]);
const bestValueIndex = useMemo(() => {
let minTotal = Infinity;
let bestIdx = 0;
calculations.forEach((calc, idx) => {
if (calc.total < minTotal) {
minTotal = calc.total;
bestIdx = idx;
}
});
return bestIdx;
}, [calculations]);
return (
<section className="py-16 bg-slate-50">
<Container className="max-w-3xl">
<AnimateOnScroll>
<div className="text-center mb-10">
<h2 className="text-2xl sm:text-3xl font-bold text-navy-800">
{pricing.calculatorTitle}: {formatMoney(collections)}
</h2>
</div>
{/* Slider */}
<div className="mb-10 px-2">
<input
type="range"
min={MIN_COLLECTIONS}
max={MAX_COLLECTIONS}
step={STEP}
value={collections}
onChange={(e) => setCollections(Number(e.target.value))}
className="w-full h-2 bg-slate-200 rounded-lg appearance-none cursor-pointer accent-navy-800
[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5
[&::-webkit-slider-thumb]:bg-navy-800 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:cursor-pointer
[&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:h-5 [&::-moz-range-thumb]:bg-navy-800
[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:cursor-pointer"
dir="ltr"
/>
<div className="flex justify-between mt-2 text-xs text-slate-500" dir="ltr">
<span>{formatMoney(MIN_COLLECTIONS)}</span>
<span>{formatMoney(MAX_COLLECTIONS)}</span>
</div>
</div>
{/* Plan Cards */}
<div className="space-y-4">
{calculations.map((calc, index) => {
const isBest = index === bestValueIndex;
return (
<motion.div
key={calc.name}
layout
className={`relative rounded-2xl border-2 bg-white p-5 sm:p-6 transition-all ${
isBest
? "border-navy-800 shadow-lg"
: "border-slate-200"
}`}
>
{isBest && (
<span className="absolute -top-3 start-4 inline-flex items-center rounded-full bg-teal-500 px-3 py-0.5 text-xs font-semibold text-white">
{pricing.bestValueBadge}
</span>
)}
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<h3 className="text-lg font-bold text-navy-800">
{calc.name}
</h3>
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-slate-600">
<span>
اشتراك: {formatMoney(calc.subscription)}
</span>
<span>
عمولة: {formatMoney(calc.commission)} ({(calc.feePercent * 100).toFixed(calc.feePercent * 100 % 1 === 0 ? 0 : 1)}%)
</span>
</div>
</div>
<div className="mt-3 text-end">
<span className="text-2xl font-black text-navy-800">
{formatMoney(calc.total)}
</span>
</div>
</motion.div>
);
})}
</div>
</AnimateOnScroll>
</Container>
</section>
);
}
...@@ -149,79 +149,115 @@ export const content = { ...@@ -149,79 +149,115 @@ export const content = {
}, },
pricing: { pricing: {
title: "اختر الباقة المناسبة", title: "اختر الباقة المناسبة",
subtitle: ٤ يوم تجربة مجانية على كل الباقات", subtitle: ٠ يوم تجربة مجانية على كل الباقات",
monthly: "شهري", monthly: "شهري",
yearly: "سنوي", yearly: "سنوي",
yearlyDiscount: "وفر ٢٠%", yearlyDiscount: "وفر ٢٠%",
platformFeeLabel: "رسوم معاملات", platformFeeLabel: "نسبة المنصة",
collectionsLabel: "من التحصيلات",
trialBadge: "10 يوم تجريبي",
calculatorTitle: "حجم التحصيلات الشهرية",
bestValueBadge: "الأوفر",
plans: [ plans: [
{ {
name: "أساسي", name: "نسبة فقط",
price: "$20", subtitle: "ابدأ بدون أي تكلفة ثابتة",
period: "/شهر", price: "مجاناً",
platformFee: "5%", priceNumeric: 0,
description: "مثالي للأكاديميات الصغيرة والناشئة", period: "",
platformFee: "12%",
platformFeeNumeric: 0.12,
description: "مناسب للأكاديميات تحت التأسيس",
features: [ features: [
{ text: "حتى ٢٠٠ لاعب", included: true }, { text: "اشتراك شهري: ٠ ج.م", included: true },
{ text: "فرع واحد", included: true }, { text: "كل مزايا النظام الأساسية", included: true },
{ text: "٥ مستخدمين", included: true }, { text: "إدارة المشتركين والحضور", included: true },
{ text: "إدارة مالية", included: true }, { text: "الفواتير والمدفوعات", included: true },
{ text: "حضور وغياب", included: true },
{ text: "تقارير أساسية", included: true }, { text: "تقارير أساسية", included: true },
{ text: "نقاط البيع", included: false }, { text: "دعم عبر WhatsApp", included: true },
{ text: "المخزون", included: false },
], ],
cta: "ابدأ مجاناً", cta: "ابدأ مجاناً",
highlighted: false, highlighted: false,
}, },
{ {
name: "احترافي", name: "المبتدئ",
price: "$60", subtitle: "للأكاديميات الصغيرة والناشئة",
period: "/شهر", price: "1,000",
platformFee: "3%", priceNumeric: 1000,
description: "للأكاديميات المتوسطة والكبيرة", period: "ج.م / شهرياً",
badge: "الأكثر شيوعاً", platformFee: "7.5%",
platformFeeNumeric: 0.075,
description: "للأكاديميات الصغيرة والناشئة",
features: [ features: [
{ text: "حتى ١,٠٠٠ لاعب", included: true }, { text: "إدارة البرامج والمجموعات", included: true },
{ text: "حتى ٥ فروع", included: true }, { text: "الجدول الأسبوعي", included: true },
{ text: "١٥ مستخدم", included: true }, { text: "التسجيلات وقوائم الانتظار", included: true },
{ text: "كل المميزات", included: true }, { text: "تقارير متوسطة", included: true },
{ text: "نقاط البيع", included: true }, { text: "إشعارات بريد إلكتروني", included: true },
{ text: "المخزون", included: true },
{ text: "تقارير متقدمة", included: true },
{ text: "دعم أولوية", included: true }, { text: "دعم أولوية", included: true },
], ],
cta: "ابدأ الآن", cta: "ابدأ الآن",
highlighted: false,
},
{
name: "المؤسسي",
subtitle: "للأكاديميات المتوسطة والنامية",
price: "3,500",
priceNumeric: 3500,
period: "ج.م / شهرياً",
platformFee: "5%",
platformFeeNumeric: 0.05,
description: "للأكاديميات المتوسطة والنامية",
badge: "الأكثر طلباً",
features: [
{ text: "كل مزايا باقة \"المبتدئ\"", included: true },
{ text: "محرك التسعير الذكي", included: true },
{ text: "المنشآت ونظام الحارات", included: true },
{ text: "المخازن والمنتجات", included: true },
{ text: "الموارد البشرية والرواتب", included: true },
{ text: "نقطة البيع (POS)", included: true },
{ text: "إشعارات SMS + بريد", included: true },
{ text: "تقارير متقدمة + تصدير", included: true },
{ text: "صلاحيات متقدمة متعددة الأدوار", included: true },
{ text: "فترة تجريبية 10 أيام", included: true },
{ text: "فترة سماح 14 يوم", included: true },
],
cta: "ابدأ الآن",
highlighted: true, highlighted: true,
}, },
{ {
name: "مؤسسي", name: "الاحترافي",
price: "$100", subtitle: "للأكاديميات الكبيرة والسلاسل",
period: "/شهر", price: "10,000",
platformFee: "1%", priceNumeric: 10000,
description: "للمؤسسات والأندية الكبيرة", period: "ج.م / شهرياً",
platformFee: "3.5%",
platformFeeNumeric: 0.035,
description: "للأكاديميات الكبيرة والسلاسل",
features: [ features: [
{ text: "لاعبين غير محدودين", included: true }, { text: "كل مزايا الباقة المؤسسية", included: true },
{ text: "فروع غير محدودة", included: true }, { text: "فروع متعددة بلا حدود", included: true },
{ text: "مستخدمين غير محدودين", included: true }, { text: "تطبيقات مدربين + أولياء أمور", included: true },
{ text: "كل المميزات", included: true }, { text: "API للتكامل مع أنظمة خارجية", included: true },
{ text: "API كامل", included: true }, { text: "تخصيصات حسب الطلب", included: true },
{ text: "دعم مخصص", included: true }, { text: "مدير حساب مخصص", included: true },
{ text: "تخصيص حسب الطلب", included: true }, { text: "تدريب فريق العمل", included: true },
{ text: "مدير حساب", included: true }, { text: "أقل نسبة منصة (3.5%)", included: true },
{ text: "SLA + ضمان وقت التشغيل", included: true },
{ text: "استضافة خاصة (اختياري)", included: true },
], ],
cta: حدث معنا", cta: واصل معنا",
highlighted: false, highlighted: false,
}, },
], ],
faq: [ faq: [
{ {
q: "هل فيه فترة تجربة مجانية؟", q: "هل فيه فترة تجربة مجانية؟",
a: "نعم، ١٤ يوم تجربة كاملة على أي باقة بدون بطاقة ائتمان. لو مش مناسبة، لا تدفع شيء.", a: "نعم، ١٠ أيام تجربة كاملة على أي باقة بدون بطاقة ائتمان. لو مش مناسبة، لا تدفع شيء.",
}, },
{ {
q: "إيه هي رسوم المعاملات؟", q: "إيه هي نسبة المنصة؟",
a: "نسبة بسيطة تُضاف على كل تحصيل يتم عبر المنصة. كل ما ترقيت باقتك، قلت النسبة. الباقة المؤسسية ١% فقط.", a: "نسبة بسيطة تُحسب على كل تحصيل يتم عبر المنصة. كل ما ترقيت باقتك، قلت النسبة. الباقة الاحترافية ٣.٥% فقط.",
}, },
{ {
q: "هل أقدر أغير الباقة بعدين؟", q: "هل أقدر أغير الباقة بعدين؟",
...@@ -237,12 +273,16 @@ export const content = { ...@@ -237,12 +273,16 @@ export const content = {
}, },
{ {
q: "هل بتدعموا أكثر من فرع؟", q: "هل بتدعموا أكثر من فرع؟",
a: "نعم، الباقة الاحترافية تدعم حتى ٥ فروع والمؤسسية بدون حد.", a: "نعم، الباقة الاحترافية تدعم فروع بلا حدود.",
}, },
{ {
q: "هل فيه خصم للدفع السنوي؟", q: "هل فيه خصم للدفع السنوي؟",
a: "نعم، الدفع السنوي يوفر ٢٠% — يعني شهرين ببلاش.", a: "نعم، الدفع السنوي يوفر ٢٠% — يعني شهرين ببلاش.",
}, },
{
q: "هل يمكن البدء بباقة نسبة فقط ثم الترقية؟",
a: "بالضبط! ابدأ بدون أي تكلفة ثابتة ولما أكاديميتك تكبر ترقّى لباقة أقل نسبة.",
},
], ],
}, },
about: { about: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment