Files
mrp/client/src/modules/landing/LandingPage.tsx

387 lines
22 KiB
TypeScript
Raw Normal View History

2026-03-17 00:07:44 -05:00
import type { CSSProperties } from "react";
2026-03-16 23:59:31 -05:00
import { Link } from "react-router-dom";
type LandingVariant = "light" | "dark";
const heroMetrics = [
{ label: "On-time release rate", value: "98.2%", detail: "across 146 active jobs this week" },
{ label: "Planner response time", value: "14 min", detail: "from demand signal to released draft supply" },
{ label: "Inventory exposure", value: "$1.4M", detail: "visible by warehouse, location, and reservation" },
];
const moduleCards = [
{
eyebrow: "Commercial Control",
title: "Quotes, orders, revisions, and approvals stay connected.",
copy: "Customer commitments flow directly into execution without spreadsheet handoffs or revision blind spots.",
bullets: ["Revision comparisons", "Approval checkpoints", "Project linkage"],
},
{
eyebrow: "Production Visibility",
title: "Planning, projects, and work orders share the same reality.",
copy: "Material readiness, shortages, pegged supply, and station execution all stay visible from one operational surface.",
bullets: ["Live readiness rollups", "Reservation automation", "Capacity-ready planning"],
},
{
eyebrow: "Inventory Discipline",
title: "SKU structure, stock control, and purchasing are built for actual manufacturing.",
copy: "Family-based SKU generation, BOM-aware demand, transfer visibility, and vendor-backed replenishment keep the floor aligned.",
bullets: ["Master SKU builder", "BOM explosion", "Preferred-vendor sourcing"],
},
];
const timeline = [
{ time: "06:40", title: "Demand spike detected", detail: "Three approved sales orders added 28 assemblies to near-term demand." },
{ time: "07:05", title: "Planner drafts supply", detail: "System nets stock, open POs, and open work orders before recommending build and buy actions." },
{ time: "08:10", title: "Reservations applied", detail: "Available stock updates immediately across project, manufacturing, and purchasing views." },
{ time: "09:25", title: "Shipment package released", detail: "Packing slip PDF and label artifacts are ready from the same order thread." },
];
const proofCards = [
{ label: "Modules live", value: "10", note: "CRM, inventory, sales, purchasing, shipping, projects, manufacturing, planning, admin, branding" },
{ label: "Data domains unified", value: "1", note: "Single operational model instead of disconnected tools" },
{ label: "Container footprint", value: "1", note: "Frontend, backend, SQLite, uploads, Puppeteer PDF pipeline" },
];
const spotlightBoard = [
{ title: "Revenue committed", value: "$842K", change: "+18% vs last month", tone: "brand" },
{ title: "Shortage lines", value: "12", change: "-31% after planner actions", tone: "accent" },
{ title: "Work orders ready", value: "27", change: "6 waiting on materials", tone: "neutral" },
{ title: "Shipments due today", value: "9", change: "4 already packed", tone: "brand" },
];
2026-03-17 00:07:44 -05:00
function getThemeVars(variant: LandingVariant): CSSProperties {
const vars = variant === "dark"
? {
colorScheme: "dark",
"--color-brand": "88 150 255",
"--color-accent": "44 214 199",
"--color-surface-brand": "18 30 52",
"--color-surface": "10 20 38",
"--color-page": "3 10 24",
"--color-text": "236 241 255",
"--color-muted": "150 168 194",
"--color-line": "68 87 120",
}
: {
colorScheme: "light",
"--color-brand": "29 78 216",
"--color-accent": "13 148 136",
"--color-surface-brand": "244 247 251",
"--color-surface": "244 247 251",
"--color-page": "239 244 255",
"--color-text": "15 23 42",
"--color-muted": "92 111 139",
"--color-line": "196 210 233",
};
return vars as CSSProperties;
}
function panelClass(isDark: boolean) {
return isDark
2026-03-17 00:24:33 -05:00
? "border-line/70 bg-surface/90 shadow-[0_30px_80px_rgba(2,6,23,0.45)]"
: "border-line/70 bg-surface/90 shadow-[0_30px_80px_rgba(15,23,42,0.12)]";
2026-03-17 00:07:44 -05:00
}
function softPanelClass(isDark: boolean) {
return isDark
2026-03-17 00:24:33 -05:00
? "border-line/70 bg-page/80 shadow-[0_20px_60px_rgba(2,6,23,0.34)]"
: "border-line/70 bg-page/75 shadow-[0_20px_50px_rgba(15,23,42,0.1)]";
2026-03-17 00:07:44 -05:00
}
function chipClass(isDark: boolean) {
2026-03-17 00:24:33 -05:00
return isDark ? "border-line/70 bg-page/80" : "border-line/70 bg-surface/90";
2026-03-17 00:07:44 -05:00
}
2026-03-16 23:59:31 -05:00
function LandingExperience({ variant }: { variant: LandingVariant }) {
const isDark = variant === "dark";
2026-03-17 00:07:44 -05:00
const themeVars = getThemeVars(variant);
const variantLabel = isDark ? "Dark landing" : "Light landing";
2026-03-16 23:59:31 -05:00
const altRoute = isDark ? "/landing" : "/darklanding";
const altLabel = isDark ? "View light version" : "View dark version";
return (
2026-03-17 00:07:44 -05:00
<div id="top" style={themeVars} className="min-h-screen bg-page text-text">
<div className="relative overflow-hidden">
<div
className={`absolute inset-0 ${
isDark
? "bg-[radial-gradient(circle_at_12%_10%,rgba(88,150,255,0.28),transparent_26%),radial-gradient(circle_at_82%_18%,rgba(44,214,199,0.2),transparent_24%),linear-gradient(180deg,rgba(255,255,255,0.04),transparent_42%)]"
: "bg-[radial-gradient(circle_at_12%_10%,rgba(59,130,246,0.24),transparent_28%),radial-gradient(circle_at_82%_18%,rgba(20,184,166,0.18),transparent_24%),linear-gradient(180deg,rgba(255,255,255,0.72),rgba(255,255,255,0.08)_42%,transparent_60%)]"
}`}
/>
<div className={`absolute left-[-8%] top-20 h-80 w-80 rounded-full blur-3xl ${isDark ? "bg-sky-400/20" : "bg-blue-300/40"}`} />
<div className={`absolute right-[-10%] top-32 h-[28rem] w-[28rem] rounded-full blur-3xl ${isDark ? "bg-teal-300/16" : "bg-cyan-200/50"}`} />
<div className={`absolute left-[22%] top-[32rem] h-64 w-64 rounded-full blur-3xl ${isDark ? "bg-indigo-400/10" : "bg-violet-200/35"}`} />
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<div className="relative mx-auto flex w-full max-w-7xl flex-col gap-12 px-6 pb-20 pt-8 lg:px-8">
2026-03-17 00:24:33 -05:00
<header className={`flex flex-col gap-4 rounded-[28px] border px-5 py-4 xl:flex-row xl:items-center xl:justify-between ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="flex items-center gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[linear-gradient(135deg,rgb(var(--color-brand)),rgb(var(--color-accent)))] text-lg font-black tracking-[0.18em] text-white">
CX
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div>
<div className="text-xs font-semibold uppercase tracking-[0.34em] text-muted">CODEXIUM</div>
<div className="text-sm text-muted">Manufacturing resource planning without the ERP drag.</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</div>
<div className="flex flex-wrap items-center gap-3">
2026-03-17 00:24:33 -05:00
<span className={`rounded-2xl border px-4 py-2 text-sm font-semibold text-text ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
{variantLabel}
</span>
2026-03-17 00:24:33 -05:00
<Link to={altRoute} className={`rounded-2xl border px-4 py-2 text-sm font-semibold text-text transition hover:bg-page/70 ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
{altLabel}
</Link>
2026-03-17 00:24:33 -05:00
<Link to="/login" className={`rounded-2xl border px-4 py-2 text-sm font-semibold text-text transition hover:bg-page/70 ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
Open app
</Link>
<a
href="#contact"
className="rounded-2xl bg-[linear-gradient(135deg,rgb(var(--color-brand)),rgb(var(--color-accent)))] px-4 py-2 text-sm font-semibold text-white shadow-[0_18px_40px_rgba(24,90,219,0.28)]"
>
Book a walkthrough
</a>
</div>
</header>
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<section className="grid gap-10 lg:grid-cols-[1.05fr_0.95fr] lg:items-center">
<div>
2026-03-17 00:24:33 -05:00
<div className={`inline-flex items-center gap-2 rounded-full border px-4 py-2 text-xs font-semibold uppercase tracking-[0.24em] text-muted ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
Built for discrete manufacturing teams
</div>
<h1 className="mt-6 max-w-4xl font-['Space_Grotesk','Manrope',sans-serif] text-5xl font-black leading-[0.95] tracking-[-0.05em] text-text sm:text-6xl xl:text-7xl">
A sharper MRP for operators who need flow, not ERP theater.
</h1>
<p className="mt-6 max-w-2xl text-lg leading-8 text-muted">
CODEXIUM connects commercial demand, inventory truth, project execution, purchasing, shipping, and manufacturing control in one system designed to move work across the floor.
</p>
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<div className="mt-8 grid gap-3 sm:grid-cols-3">
{heroMetrics.map((metric) => (
2026-03-17 00:24:33 -05:00
<article key={metric.label} className={`rounded-[24px] border p-4 ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">{metric.label}</div>
<div className="mt-3 text-3xl font-black tracking-[-0.04em] text-text">{metric.value}</div>
<div className="mt-2 text-sm text-muted">{metric.detail}</div>
</article>
))}
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</div>
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<div className="relative">
2026-03-17 00:24:33 -05:00
<div className={`absolute -left-8 top-10 hidden h-20 w-20 rounded-[28px] border lg:block ${isDark ? "border-white/20 bg-white/10" : "border-white/40 bg-white/20"}`} />
<div className={`rounded-[32px] border p-5 ${isDark ? "bg-[linear-gradient(160deg,rgba(15,23,42,0.82),rgba(15,23,42,0.48))] shadow-[0_35px_90px_rgba(2,6,23,0.55)]" : "bg-[linear-gradient(160deg,rgba(255,255,255,0.68),rgba(255,255,255,0.24))] shadow-[0_35px_90px_rgba(15,23,42,0.18)]"} ${isDark ? "border-line/70" : "border-line/70"}`}>
<div className={`rounded-[28px] border p-5 ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="flex flex-wrap items-center justify-between gap-3">
<div>
<div className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Generated executive board</div>
<div className="mt-2 text-2xl font-black tracking-[-0.04em] text-text">This week in operations</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div className="rounded-full border border-emerald-400/35 bg-emerald-500/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.18em] text-emerald-700 dark:text-emerald-300">
Live-ready demo data
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</div>
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<div className="mt-5 grid gap-3 sm:grid-cols-2">
{spotlightBoard.map((card) => (
<article
key={card.title}
2026-03-17 00:24:33 -05:00
className={`rounded-[24px] border p-4 ${
2026-03-17 00:07:44 -05:00
card.tone === "brand"
? isDark
2026-03-17 00:24:33 -05:00
? "border-[rgb(var(--color-brand)/0.25)] bg-[rgb(var(--color-brand)/0.08)]"
: "border-[rgb(var(--color-brand)/0.25)] bg-[rgb(var(--color-brand)/0.08)]"
2026-03-17 00:07:44 -05:00
: card.tone === "accent"
? isDark
2026-03-17 00:24:33 -05:00
? "border-[rgb(var(--color-accent)/0.25)] bg-[rgb(var(--color-accent)/0.08)]"
: "border-[rgb(var(--color-accent)/0.25)] bg-[rgb(var(--color-accent)/0.08)]"
2026-03-17 00:07:44 -05:00
: softPanelClass(isDark)
}`}
>
<div className="text-sm font-semibold text-muted">{card.title}</div>
<div className="mt-3 text-4xl font-black tracking-[-0.05em] text-text">{card.value}</div>
<div className="mt-2 text-sm text-muted">{card.change}</div>
</article>
))}
</div>
<div className="mt-5 grid gap-3 xl:grid-cols-[1.3fr_0.7fr]">
2026-03-17 00:24:33 -05:00
<div className={`rounded-[24px] border p-4 ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="flex items-center justify-between gap-3">
<div className="text-sm font-semibold text-text">Project and manufacturing pulse</div>
<div className="text-xs uppercase tracking-[0.18em] text-muted">Generated snapshot</div>
</div>
<div className="mt-4 space-y-3">
{[
{ label: "Falcon enclosure program", progress: 86, status: "Ready for final assembly" },
{ label: "Orion service kit launch", progress: 61, status: "Waiting on one purchased line" },
{ label: "Atlas retrofit release", progress: 43, status: "Routing review in progress" },
].map((row) => (
2026-03-17 00:24:33 -05:00
<div key={row.label} className={`rounded-[20px] border p-3 ${isDark ? "border-line/70 bg-page/75" : "border-line/60 bg-page/75"}`}>
2026-03-17 00:07:44 -05:00
<div className="flex flex-wrap items-center justify-between gap-2">
<div className="font-semibold text-text">{row.label}</div>
<div className="text-xs uppercase tracking-[0.18em] text-muted">{row.progress}%</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:24:33 -05:00
<div className={`mt-3 h-2 overflow-hidden rounded-full ${isDark ? "bg-line/70" : "bg-line/70"}`}>
2026-03-17 00:07:44 -05:00
<div
className="h-full rounded-full bg-[linear-gradient(90deg,rgb(var(--color-brand)),rgb(var(--color-accent)))]"
style={{ width: `${row.progress}%` }}
/>
</div>
<div className="mt-2 text-sm text-muted">{row.status}</div>
</div>
))}
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</div>
2026-03-16 23:59:31 -05:00
2026-03-17 00:24:33 -05:00
<div className={`rounded-[24px] border p-4 ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-sm font-semibold text-text">Supply signals</div>
<div className="mt-4 space-y-3">
{[
{ sku: "AXL-4472", action: "Build", qty: "18 EA" },
{ sku: "KIT-2208", action: "Buy", qty: "240 EA" },
{ sku: "CAB-9031", action: "Transfer", qty: "64 EA" },
].map((signal) => (
2026-03-17 00:24:33 -05:00
<div key={signal.sku} className={`rounded-[18px] border px-3 py-3 ${isDark ? "border-line/70 bg-page/75" : "border-line/60 bg-page/75"}`}>
2026-03-17 00:07:44 -05:00
<div className="flex items-center justify-between gap-3">
<div>
<div className="font-semibold text-text">{signal.sku}</div>
<div className="mt-1 text-xs uppercase tracking-[0.18em] text-muted">{signal.action} recommendation</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div className="text-sm font-semibold text-text">{signal.qty}</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</div>
))}
2026-03-16 23:59:31 -05:00
</div>
</div>
</div>
</div>
</div>
2026-03-17 00:07:44 -05:00
</div>
</section>
2026-03-16 23:59:31 -05:00
2026-03-17 00:24:33 -05:00
<section className={`grid gap-4 rounded-[32px] border p-6 lg:grid-cols-3 ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
{proofCards.map((card) => (
2026-03-17 00:24:33 -05:00
<article key={card.label} className={`rounded-[24px] border p-4 ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">{card.label}</div>
<div className="mt-3 text-5xl font-black tracking-[-0.06em] text-text">{card.value}</div>
<div className="mt-2 text-sm text-muted">{card.note}</div>
2026-03-16 23:59:31 -05:00
</article>
))}
</section>
2026-03-17 00:07:44 -05:00
</div>
</div>
2026-03-16 23:59:31 -05:00
2026-03-17 00:07:44 -05:00
<main className="mx-auto flex w-full max-w-7xl flex-col gap-8 px-6 pb-24 lg:px-8">
<section className="grid gap-6 lg:grid-cols-3">
{moduleCards.map((card) => (
2026-03-17 00:24:33 -05:00
<article key={card.title} className={`rounded-[28px] border p-6 ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">{card.eyebrow}</div>
<h2 className="mt-4 font-['Space_Grotesk','Manrope',sans-serif] text-2xl font-bold tracking-[-0.04em] text-text">{card.title}</h2>
<p className="mt-4 text-sm leading-7 text-muted">{card.copy}</p>
<div className="mt-6 flex flex-wrap gap-2">
{card.bullets.map((bullet) => (
2026-03-17 00:24:33 -05:00
<span key={bullet} className={`rounded-full border px-3 py-2 text-xs font-semibold uppercase tracking-[0.16em] text-text ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
{bullet}
</span>
2026-03-16 23:59:31 -05:00
))}
</div>
</article>
2026-03-17 00:07:44 -05:00
))}
</section>
2026-03-16 23:59:31 -05:00
2026-03-17 00:24:33 -05:00
<section className={`grid gap-8 rounded-[32px] border p-6 lg:grid-cols-[0.9fr_1.1fr] ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div>
<div className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">How it moves</div>
<h2 className="mt-4 font-['Space_Grotesk','Manrope',sans-serif] text-4xl font-black tracking-[-0.05em] text-text">
One demand signal. One operating picture.
</h2>
<p className="mt-4 max-w-xl text-base leading-8 text-muted">
Most systems split quoting, planning, purchasing, inventory, shipping, and production into separate stories. CODEXIUM treats them as one chain, so each step inherits context instead of creating reconciliation work.
</p>
</div>
<div className="space-y-4">
{timeline.map((step) => (
2026-03-17 00:24:33 -05:00
<article key={step.time} className={`grid gap-4 rounded-[24px] border p-4 md:grid-cols-[92px_1fr] md:items-start ${softPanelClass(isDark)}`}>
<div className={`rounded-[18px] px-4 py-3 text-center ${isDark ? "bg-surface/80" : "bg-surface/90"}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Time</div>
<div className="mt-1 text-2xl font-black tracking-[-0.04em] text-text">{step.time}</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div>
<div className="text-lg font-bold text-text">{step.title}</div>
<div className="mt-2 text-sm leading-7 text-muted">{step.detail}</div>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
</article>
))}
</div>
</section>
<section className="grid gap-6 lg:grid-cols-[1.15fr_0.85fr]">
2026-03-17 00:24:33 -05:00
<article className={`rounded-[32px] border p-6 ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">Who this is for</div>
<h2 className="mt-4 font-['Space_Grotesk','Manrope',sans-serif] text-4xl font-black tracking-[-0.05em] text-text">
Teams graduating from spreadsheets, generic ERPs, or disconnected point tools.
</h2>
<div className="mt-6 grid gap-4 md:grid-cols-2">
{[
"Contract manufacturers that need real-time supply readiness before promising dates.",
"OEM operations teams that need projects, BOMs, purchasing, and work orders linked end to end.",
"Growing production shops that want branding, PDFs, approvals, and auditability without enterprise bloat.",
"Leaders who want a system operators will actually open all day, not just during month-end cleanup.",
].map((statement) => (
2026-03-17 00:24:33 -05:00
<div key={statement} className={`rounded-[22px] border p-4 text-sm leading-7 text-text ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
{statement}
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
))}
</div>
</article>
2026-03-17 00:24:33 -05:00
<article id="contact" className={`rounded-[32px] border p-6 ${panelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">Next step</div>
<h2 className="mt-4 font-['Space_Grotesk','Manrope',sans-serif] text-3xl font-black tracking-[-0.05em] text-text">
Pitch the platform with a page that already looks production-grade.
</h2>
<p className="mt-4 text-sm leading-7 text-muted">
Use this route as a commercial front door, demo backdrop, or customer-facing preview while the core app remains focused on execution.
</p>
2026-03-17 00:24:33 -05:00
<div className={`mt-6 space-y-3 rounded-[24px] border p-4 text-sm text-muted ${softPanelClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
<div className="flex items-center justify-between gap-3">
<span>Public route</span>
<span className="font-semibold text-text">{isDark ? "/darklanding" : "/landing"}</span>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div className="flex items-center justify-between gap-3">
<span>Core positioning</span>
<span className="font-semibold text-text">Modern manufacturing MRP</span>
2026-03-16 23:59:31 -05:00
</div>
2026-03-17 00:07:44 -05:00
<div className="flex items-center justify-between gap-3">
<span>Demo style</span>
<span className="font-semibold text-text">Generated commercial data</span>
</div>
</div>
<div className="mt-6 flex flex-wrap gap-3">
<Link
to="/login"
className="rounded-2xl bg-[linear-gradient(135deg,rgb(var(--color-brand)),rgb(var(--color-accent)))] px-4 py-3 text-sm font-semibold text-white shadow-[0_18px_40px_rgba(24,90,219,0.28)]"
>
Enter the app
</Link>
2026-03-17 00:24:33 -05:00
<a href="#top" className={`rounded-2xl border px-4 py-3 text-sm font-semibold text-text transition hover:bg-page/70 ${chipClass(isDark)}`}>
2026-03-17 00:07:44 -05:00
Back to top
</a>
</div>
</article>
</section>
</main>
2026-03-16 23:59:31 -05:00
</div>
);
}
export function LandingPage() {
return <LandingExperience variant="light" />;
}
export function DarkLandingPage() {
return <LandingExperience variant="dark" />;
}