TorbatYar/frontend/app/page.tsx
Mortezakoohjani 579e0cdaf5 Link active apps on homepage and refresh landing page design.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 22:48:46 +03:30

161 lines
6.6 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import Link from "next/link";
import { AppStoreGrid } from "@/components/AppStoreGrid";
import { TenantSitePage } from "@/components/TenantSitePage";
import { Badge, Button, Container } from "@/components/ui";
import { PLATFORM_APPS } from "@/lib/apps-catalog";
import { useAuth } from "@/hooks/useAuth";
import { useTenantHost } from "@/hooks/useTenantHost";
import { useTheme } from "@/hooks/useTheme";
export default function HomePage() {
const host = useTenantHost();
if (host.isTenantHost) {
return <TenantSitePage />;
}
return <PlatformHomePage />;
}
const FEATURES = [
{ icon: "🔐", label: "ورود واحد SSO" },
{ icon: "🏢", label: "چند کسب‌وکار" },
{ icon: "☁️", label: "ابری و مقیاس‌پذیر" },
{ icon: "🎨", label: "White-label" },
];
function PlatformHomePage() {
const { theme } = useTheme();
const { isAuthenticated, login, loading } = useAuth();
const siteName = theme?.site_name ?? "Torbatyar";
const availableCount = PLATFORM_APPS.filter((app) => app.status === "available").length;
const quickApps = PLATFORM_APPS.filter((app) => app.status === "available" && app.href).slice(0, 4);
return (
<div className="pb-16">
{/* Hero */}
<section className="relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-[var(--color-primary-soft)] via-white to-[var(--color-secondary-muted)]" />
<div
className="absolute inset-0 opacity-[0.35]"
style={{
backgroundImage:
"radial-gradient(circle at 1px 1px, rgba(2,132,199,0.15) 1px, transparent 0)",
backgroundSize: "28px 28px",
}}
/>
<div className="pointer-events-none absolute -left-32 top-0 h-96 w-96 rounded-full bg-[var(--color-primary-muted)] blur-3xl" />
<div className="pointer-events-none absolute -right-20 bottom-0 h-72 w-72 rounded-full bg-[var(--color-secondary-muted)] blur-3xl" />
<Container className="relative py-14 sm:py-20">
<div className="mx-auto max-w-3xl text-center">
<Badge variant="primary" className="mb-5 px-4 py-1.5 text-sm">
نسل جدید SuperApp
</Badge>
<h1 className="text-4xl font-extrabold leading-tight tracking-tight text-secondary sm:text-5xl lg:text-6xl">
{siteName}
</h1>
<p className="mx-auto mt-5 max-w-xl text-base leading-8 text-gray-600 sm:text-lg">
یک پلتفرم، دهها سرویس حسابداری، CRM، سلامت، زیبایی و بیشتر.
همه با یک ورود واحد.
</p>
<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
{isAuthenticated ? (
<Link href="/dashboard">
<Button size="lg" className="min-w-[160px] shadow-lg shadow-primary/20">
رفتن به داشبورد
</Button>
</Link>
) : (
<Button
size="lg"
className="min-w-[160px] shadow-lg shadow-primary/20"
onClick={() => login()}
loading={loading}
loadingText="..."
>
ورود / ثبتنام
</Button>
)}
<a href="#apps">
<Button variant="outline" size="lg">
مشاهده اپلیکیشنها
</Button>
</a>
</div>
{/* Stats */}
<div className="mt-10 flex flex-wrap items-center justify-center gap-6 sm:gap-10">
<div className="text-center">
<p className="text-3xl font-extrabold text-primary">{availableCount}+</p>
<p className="mt-0.5 text-sm text-gray-500">اپلیکیشن فعال</p>
</div>
<div className="hidden h-10 w-px bg-gray-200 sm:block" />
<div className="text-center">
<p className="text-3xl font-extrabold text-primary">۱</p>
<p className="mt-0.5 text-sm text-gray-500">ورود واحد</p>
</div>
<div className="hidden h-10 w-px bg-gray-200 sm:block" />
<div className="text-center">
<p className="text-3xl font-extrabold text-primary"></p>
<p className="mt-0.5 text-sm text-gray-500">کسبوکار</p>
</div>
</div>
</div>
{/* Quick access chips */}
<div className="mx-auto mt-12 max-w-2xl">
<p className="mb-3 text-center text-xs font-medium text-gray-400">دسترسی سریع</p>
<div className="flex flex-wrap items-center justify-center gap-2">
{quickApps.map((app) => (
<Link
key={app.id}
href={app.href!}
className="inline-flex items-center gap-2 rounded-full border border-gray-200 bg-white/80 px-4 py-2 text-sm font-medium text-secondary shadow-sm backdrop-blur-sm transition-all hover:border-primary hover:text-primary hover:shadow-md"
>
<span>{app.icon}</span>
<span>{app.name}</span>
</Link>
))}
</div>
</div>
</Container>
</section>
{/* Features strip */}
<section className="border-y border-gray-100 bg-white/60 backdrop-blur-sm">
<Container className="py-5">
<div className="flex flex-wrap items-center justify-center gap-x-8 gap-y-3">
{FEATURES.map((f) => (
<div key={f.label} className="flex items-center gap-2 text-sm text-gray-600">
<span className="text-base">{f.icon}</span>
<span className="font-medium">{f.label}</span>
</div>
))}
</div>
</Container>
</section>
{/* App grid */}
<section id="apps" className="scroll-mt-20">
<Container className="py-12 sm:py-16">
<AppStoreGrid />
</Container>
</section>
{/* Footer */}
<footer className="border-t border-gray-100 bg-gray-50/80">
<Container className="flex flex-col items-center justify-between gap-3 py-6 text-center text-sm text-gray-500 sm:flex-row sm:text-right">
<p>
© {new Date().getFullYear()} {siteName} White-label SaaS Platform
</p>
<p>{theme?.support_email ?? "support@example.com"}</p>
</Container>
</footer>
</div>
);
}