211 lines
8.4 KiB
TypeScript
211 lines
8.4 KiB
TypeScript
"use client"
|
|
|
|
import Link from "next/link"
|
|
import { Icon } from "@iconify/react"
|
|
import { LandingReveal } from "@/components/landing/landing-reveal"
|
|
import { LANDING_APPS } from "@/components/landing/landing-data"
|
|
import { useChromeIdentity } from "@/lib/hooks/use-chrome-identity"
|
|
import { getAuthentikEnrollmentUrl } from "@/lib/auth/oidc-config"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
function HeroDock() {
|
|
const apps = LANDING_APPS.filter((app) => app.href)
|
|
|
|
return (
|
|
<div className="flex flex-wrap items-center justify-center gap-3 sm:gap-4">
|
|
{apps.map((app, index) => (
|
|
<Link
|
|
key={app.name}
|
|
href={app.href!}
|
|
title={app.name}
|
|
className="landing-dock-tile landing-glass group flex size-14 items-center justify-center rounded-2xl transition-transform hover:scale-110 sm:size-16"
|
|
style={{ "--float-delay": `${index * 0.55}s` } as React.CSSProperties}
|
|
>
|
|
<img
|
|
src={app.icon}
|
|
alt={app.name}
|
|
className="size-8 object-contain transition-transform group-hover:scale-110 sm:size-9"
|
|
draggable={false}
|
|
/>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
/** Fenêtre « produit » stylisée (pas un vrai screenshot — du pur CSS). */
|
|
function HeroPreview() {
|
|
const rows = [
|
|
{ from: "Conseil d'administration", subject: "Ordre du jour — revue Q3", time: "09:12", unread: true },
|
|
{ from: "UltiAI", subject: "Résumé de vos 12 mails non lus", time: "08:47", ai: true },
|
|
{ from: "Marie Laurent", subject: "Spécifications produit v2 (UltiDocs)", time: "08:30" },
|
|
{ from: "Infra", subject: "Sauvegarde hebdomadaire effectuée ✓", time: "07:58" },
|
|
]
|
|
|
|
return (
|
|
<div
|
|
className="landing-glass-strong relative mx-auto w-full max-w-3xl rounded-2xl p-2 shadow-[0_40px_90px_-40px_rgba(30,40,90,0.45)]"
|
|
aria-hidden
|
|
>
|
|
<div className="flex items-center gap-1.5 px-3 py-2">
|
|
<span className="size-2.5 rounded-full bg-[#ff5f57]" />
|
|
<span className="size-2.5 rounded-full bg-[#febc2e]" />
|
|
<span className="size-2.5 rounded-full bg-[#28c840]" />
|
|
<div className="ml-3 flex h-6 flex-1 items-center rounded-full bg-[var(--landing-chip)] px-3 text-[11px] text-[var(--landing-muted)]">
|
|
suite.votre-domaine.fr/mail
|
|
</div>
|
|
</div>
|
|
<div className="flex overflow-hidden rounded-xl border border-[var(--landing-line)]">
|
|
<div className="hidden w-40 shrink-0 flex-col gap-1 border-r border-[var(--landing-line)] bg-[var(--landing-card)] p-3 sm:flex">
|
|
<div className="landing-cta--primary landing-cta mb-2 h-8 w-full rounded-full text-xs">
|
|
Nouveau message
|
|
</div>
|
|
{["Boîte de réception", "Favoris", "Programmés", "Brouillons"].map(
|
|
(label, i) => (
|
|
<div
|
|
key={label}
|
|
className={cn(
|
|
"flex items-center justify-between rounded-full px-3 py-1.5 text-xs",
|
|
i === 0
|
|
? "bg-[var(--landing-chip)] font-semibold text-[var(--landing-chip-fg)]"
|
|
: "text-[var(--landing-muted)]"
|
|
)}
|
|
>
|
|
<span>{label}</span>
|
|
{i === 0 ? <span>12</span> : null}
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
<div className="flex-1 divide-y divide-[var(--landing-line)] bg-[var(--landing-card-strong)]">
|
|
{rows.map((row) => (
|
|
<div key={row.subject} className="flex items-center gap-3 px-4 py-3">
|
|
<span
|
|
className={cn(
|
|
"size-2 shrink-0 rounded-full",
|
|
row.unread ? "bg-[var(--landing-glow-a)]" : "bg-transparent"
|
|
)}
|
|
/>
|
|
<span
|
|
className={cn(
|
|
"w-32 shrink-0 truncate text-xs sm:w-40 sm:text-[13px]",
|
|
row.unread ? "font-semibold" : "text-[var(--landing-muted)]"
|
|
)}
|
|
>
|
|
{row.from}
|
|
</span>
|
|
<span className="min-w-0 flex-1 truncate text-xs text-[var(--landing-muted)] sm:text-[13px]">
|
|
{row.ai ? (
|
|
<span className="mr-1.5 inline-flex items-center gap-1 rounded-full bg-[var(--landing-chip)] px-1.5 py-px text-[10px] font-semibold text-[var(--landing-chip-fg)]">
|
|
<Icon icon="mdi:creation-outline" className="size-3" />
|
|
IA
|
|
</span>
|
|
) : null}
|
|
{row.subject}
|
|
</span>
|
|
<span className="shrink-0 text-[11px] text-[var(--landing-muted)]">
|
|
{row.time}
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function LandingHero() {
|
|
const identity = useChromeIdentity()
|
|
|
|
return (
|
|
<section className="relative px-4 pb-20 pt-14 sm:px-6 sm:pt-20">
|
|
<div className="mx-auto flex w-full max-w-5xl flex-col items-center gap-8 text-center">
|
|
<LandingReveal>
|
|
<span className="landing-glass inline-flex items-center gap-2.5 rounded-full px-4 py-1.5 text-xs font-medium text-[var(--landing-muted)] sm:text-sm">
|
|
<span className="landing-pulse-dot" aria-hidden />
|
|
Open source · Souveraine · Prête pour l'IA
|
|
</span>
|
|
</LandingReveal>
|
|
|
|
<LandingReveal delay={0.08}>
|
|
<h1 className="text-balance text-4xl font-bold leading-[1.06] tracking-tight sm:text-6xl lg:text-7xl">
|
|
Toute votre suite de travail.
|
|
<br />
|
|
<span className="landing-gradient-text">Chez vous.</span>
|
|
</h1>
|
|
</LandingReveal>
|
|
|
|
<LandingReveal delay={0.16}>
|
|
<p className="mx-auto max-w-2xl text-balance text-base leading-relaxed text-[var(--landing-muted)] sm:text-lg">
|
|
Mails, fichiers, documents collaboratifs, contacts et assistant IA :
|
|
l'alternative complète à Google Workspace et Microsoft 365,
|
|
open source et hébergée sur <em className="not-italic font-semibold text-[var(--landing-fg)]">votre</em> infrastructure.
|
|
</p>
|
|
</LandingReveal>
|
|
|
|
<LandingReveal delay={0.24} className="flex flex-col items-center gap-4">
|
|
{identity ? (
|
|
<>
|
|
<p className="text-sm text-[var(--landing-muted)]">
|
|
Bonjour {identity.firstName} — votre suite vous attend.
|
|
</p>
|
|
<div className="flex flex-wrap items-center justify-center gap-3">
|
|
<Link
|
|
href="/mail/inbox"
|
|
className="landing-cta landing-cta--primary h-12 px-7 text-base"
|
|
>
|
|
Ouvrir Ultimail
|
|
<Icon icon="mdi:arrow-right" className="size-5" aria-hidden />
|
|
</Link>
|
|
<Link
|
|
href="/drive"
|
|
className="landing-cta landing-cta--ghost h-12 px-7 text-base"
|
|
>
|
|
Ouvrir UltiDrive
|
|
</Link>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<div className="flex flex-wrap items-center justify-center gap-3">
|
|
<Link
|
|
href="/login"
|
|
className="landing-cta landing-cta--primary h-12 px-7 text-base"
|
|
>
|
|
Se connecter
|
|
<Icon icon="mdi:arrow-right" className="size-5" aria-hidden />
|
|
</Link>
|
|
<a
|
|
href={getAuthentikEnrollmentUrl()}
|
|
className="landing-cta landing-cta--ghost h-12 px-7 text-base"
|
|
>
|
|
Créer un compte
|
|
</a>
|
|
</div>
|
|
<a
|
|
href="#demo"
|
|
className="group inline-flex items-center gap-1.5 text-sm font-medium text-[var(--landing-muted)] transition-colors hover:text-[var(--landing-fg)]"
|
|
>
|
|
ou essayez la démo interactive, sans compte
|
|
<Icon
|
|
icon="mdi:arrow-down"
|
|
className="size-4 transition-transform group-hover:translate-y-0.5"
|
|
aria-hidden
|
|
/>
|
|
</a>
|
|
</>
|
|
)}
|
|
</LandingReveal>
|
|
|
|
<LandingReveal delay={0.32} className="w-full">
|
|
<HeroDock />
|
|
</LandingReveal>
|
|
|
|
<LandingReveal delay={0.4} className="w-full pt-6">
|
|
<HeroPreview />
|
|
</LandingReveal>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|