"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import {
FileText,
Layers,
MousePointer2,
Download,
Cpu,
CheckCircle2,
ArrowRight,
Layout,
PieChart,
FileSpreadsheet,
Presentation,
MessageSquare,
ShieldCheck,
Menu,
X,
Languages,
Monitor,
Eye,
} from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { useI18n } from "@/lib/i18n";
import { HeroVisual } from "./hero-visual";
import { API_BASE } from "@/lib/config";
import { LanguageSwitcher } from "@/components/ui/language-switcher";
const Logo = () => (
);
const Navbar = () => {
const [isOpen, setIsOpen] = useState(false);
const { t } = useI18n();
return (
setIsOpen(!isOpen)} className="text-brand-dark dark:text-white p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg transition-colors">
{isOpen ? : }
{isOpen && (
)}
);
};
const Hero = () => {
const { t } = useI18n();
return (
{t('landing.hero.tag')}
{t('landing.hero.titleLine1')}
{t('landing.hero.titleLine2')}
{t('landing.hero.description')}
{t('landing.hero.visualCaption')}
);
};
const Steps = () => {
const { t } = useI18n();
const steps = [
{ num: t('landing.steps.step1.num'), title: t('landing.steps.step1.title'), desc: t('landing.steps.step1.desc'), icon: },
{ num: t('landing.steps.step2.num'), title: t('landing.steps.step2.title'), desc: t('landing.steps.step2.desc'), icon: },
{ num: t('landing.steps.step3.num'), title: t('landing.steps.step3.title'), desc: t('landing.steps.step3.desc'), icon: },
];
return (
{t('landing.steps.process')}
{t('landing.steps.title')}
{t('landing.steps.subtitle')}
{steps.map((st, i) => (
{st.icon}
{st.title}
{st.desc}
))}
);
};
const FeaturesContext = () => {
const { t } = useI18n();
return (
{t('landing.features.tag')}
{t('landing.features.title')}
{[
{ icon:
, title: t('landing.features.context.title'), desc: t('landing.features.context.desc') },
{ icon:
, title: t('landing.features.glossary.title'), desc: t('landing.features.glossary.desc') },
{ icon:
, title: t('landing.features.vision.title'), desc: t('landing.features.vision.desc') },
].map((item, i) => (
))}
);
};
const LayoutFeatures = () => {
const { t } = useI18n();
// Deux vraies pages de document : même structure, deux langues.
// Le terme en gras montre le respect de la terminologie (glossaire).
const DocPage = ({ side }: { side: "source" | "target" }) => (
{side === "source" ? "FR — original" : "EN — traduit"}
{side === "source" ? t("landing.beforeAfter.sourceTitle") : t("landing.beforeAfter.targetTitle")}
{side === "source" ? t("landing.beforeAfter.sourcePara1") : t("landing.beforeAfter.targetPara1")}
{side === "source" ? (
<>
{t("landing.beforeAfter.sourcePara2Before")}{" "}
{t("landing.beforeAfter.sourceTerm")} {" "}
{t("landing.beforeAfter.sourcePara2After")}
>
) : (
<>
{t("landing.beforeAfter.targetPara2Before")}{" "}
{t("landing.beforeAfter.targetTerm")} {" "}
{t("landing.beforeAfter.targetPara2After")}
>
)}
{side === "source" ? t("landing.beforeAfter.sourceItem1") : t("landing.beforeAfter.targetItem1")}
{side === "source" ? t("landing.beforeAfter.sourceItem2") : t("landing.beforeAfter.targetItem2")}
cahier-des-charges.docx
3 pages · 2 481 mots
);
return (
{t("landing.layout.title")} {t("landing.layout.title2")}
{t("landing.layout.subtitle")}
{/* sceau central : la promesse, entre les deux pages */}
{t("landing.beforeAfter.seal")}
{/* trois preuves précises, pas des promesses vagues */}
{[
{ icon:
, label: t("landing.beforeAfter.proof1") },
{ icon:
, label: t("landing.beforeAfter.proof2") },
{ icon:
, label: t("landing.beforeAfter.proof3") },
].map((proof, i) => (
{proof.icon}
{proof.label}
))}
);
};
const FormatsSection = () => {
const { t } = useI18n();
const formats = [
{ id: ".DOCX", name: t('landing.formats.word.name'), icon: , items: [t('landing.formats.word.i1'), t('landing.formats.word.i2'), t('landing.formats.word.i3'), t('landing.formats.word.i4')] },
{ id: ".XLSX", name: t('landing.formats.excel.name'), icon: , items: [t('landing.formats.excel.i1'), t('landing.formats.excel.i2'), t('landing.formats.excel.i3'), t('landing.formats.excel.i4')] },
{ id: ".PPTX", name: t('landing.formats.pptx.name'), icon: , items: [t('landing.formats.pptx.i1'), t('landing.formats.pptx.i2'), t('landing.formats.pptx.i3'), t('landing.formats.pptx.i4')] },
{ id: ".PDF", name: t('landing.formats.pdf.name'), icon: , items: [t('landing.formats.pdf.i1'), t('landing.formats.pdf.i2'), t('landing.formats.pdf.i3'), t('landing.formats.pdf.i4')] },
];
return (
);
};
const PricingSection = () => {
const { t } = useI18n();
const [isAnnual, setIsAnnual] = useState(true);
// Prices come from the same live endpoint as /pricing (admin-configurable);
// the hardcoded values below are only a fallback while it loads or fails.
const [livePrices, setLivePrices] = useState>({});
useEffect(() => {
fetch(`${API_BASE}/api/v1/auth/plans`, { cache: 'no-store' })
.then(r => (r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))))
.then(json => {
const d = json.data ?? json;
const map: Record = {};
for (const plan of d.plans ?? []) {
if (typeof plan.price_monthly === 'number' && plan.price_monthly > 0) {
map[plan.id] = {
monthly: plan.price_monthly,
annualMonthly: plan.price_yearly > 0 ? plan.price_yearly / 12 : plan.price_monthly,
};
}
}
setLivePrices(map);
})
.catch(() => { /* keep marketing defaults */ });
}, []);
const priceFor = (id: string, fallbackMonthly: number, fallbackAnnual: number): string => {
const live = livePrices[id];
const value = live
? (isAnnual ? live.annualMonthly : live.monthly)
: (isAnnual ? fallbackAnnual : fallbackMonthly);
return Number.isInteger(value) ? String(value) : value.toFixed(2);
};
const plans = [
{ id: 'starter', name: t('landing.pricing.starter.name'), desc: t('landing.pricing.starter.desc'), monthlyPrice: 9, annualPrice: 7, features: [t('landing.pricing.starter.f1'), t('landing.pricing.starter.f2'), t('landing.pricing.starter.f3'), t('landing.pricing.starter.f4')], cta: t('landing.pricing.starter.cta'), popular: false },
{ id: 'pro', name: t('landing.pricing.pro.name'), desc: t('landing.pricing.pro.desc'), monthlyPrice: 19, annualPrice: 15, features: [t('landing.pricing.pro.f1'), t('landing.pricing.pro.f2'), t('landing.pricing.pro.f3'), t('landing.pricing.pro.f4'), t('landing.pricing.pro.f5'), t('landing.pricing.pro.f6')], cta: t('landing.pricing.pro.cta'), popular: true },
{ id: 'business', name: t('landing.pricing.business.name'), desc: t('landing.pricing.business.desc'), monthlyPrice: 49, annualPrice: 39, features: [t('landing.pricing.business.f1'), t('landing.pricing.business.f2'), t('landing.pricing.business.f3'), t('landing.pricing.business.f4'), t('landing.pricing.business.f5'), t('landing.pricing.business.f6')], cta: t('landing.pricing.business.cta'), popular: false },
];
return (
{t('landing.pricing.title')}
{t('landing.pricing.subtitle')}
setIsAnnual(false)} className={`text-sm font-bold uppercase tracking-widest transition-all ${!isAnnual ? 'text-brand-dark dark:text-white underline underline-offset-8' : 'text-brand-dark/55 dark:text-white/55 hover:text-brand-dark dark:hover:text-white'}`}>
{t('landing.pricing.monthly')}
setIsAnnual(true)} className={`text-sm font-bold uppercase tracking-widest transition-all relative ${isAnnual ? 'text-brand-dark dark:text-white underline underline-offset-8' : 'text-brand-dark/55 dark:text-white/55 hover:text-brand-dark dark:hover:text-white'}`}>
{t('landing.pricing.annual')}
(-20%)
{plans.map((p, i) => (
{p.name}
{p.desc}
{priceFor(p.id, p.monthlyPrice, p.annualPrice)} €
/ {t('landing.pricing.month')}
{p.features.map((f, j) => (
{f}
))}
{p.cta}
))}
{t('landing.pricing.footer')}
);
};
const CTASection = () => {
const { t } = useI18n();
return (
{t('landing.cta.title')}
{t('landing.cta.subtitle')}
{t('landing.cta.button')}
);
};
const Footer = () => {
const { t } = useI18n();
return (
{t('landing.footer.desc')}
{t('landing.footer.product')}
{t('landing.footer.rights')}
import('@/components/ui/cookie-consent').then(m => m.reopenCookieConsent())}
className="text-[10px] font-bold text-brand-dark/50 dark:text-white/50 uppercase tracking-[0.2em] hover:text-brand-dark dark:hover:text-white transition-colors"
>
{t('cookieConsent.reopen')}
wordly.art
);
};
export default function LandingPage() {
return (
);
}