"use client" import { Suspense, useEffect } from "react" import Link from "next/link" import { useRouter, useSearchParams } from "next/navigation" import { Button } from "@/components/ui/button" import { Progress } from "@/components/ui/progress" import { MigrationOnboardingAlerts, MigrationStepList, appOnlyAuthStepLabel, shouldShowOAuthButton, usesAppOnlyAuth, } from "@/components/migration/onboarding-ui" import { type MigrationJob, useMigrationStatus, useStartMigrationOAuth, } from "@/lib/api/hooks/use-hosted-mail" import { useAuthReady } from "@/lib/api/use-auth-ready" import { ULTICAL_APP_NAME } from "@/lib/suite/page-metadata" const SERVICE_LABELS: Record = { mail: "Mail", contacts: "Contacts", calendar: ULTICAL_APP_NAME, drive: "Drive", } function jobProgress(job: MigrationJob): number { const imported = job.stats_json?.imported ?? 0 const total = job.stats_json?.estimated_total ?? imported if (typeof total === "number" && total <= 0) { return job.status === "completed" ? 100 : 10 } if (typeof imported !== "number" || typeof total !== "number") { return job.status === "completed" ? 100 : 10 } return Math.min(100, Math.round((imported / total) * 100)) } export default function OnboardMigrationPage() { return (

Chargement…

} >
) } function OnboardMigrationContent() { const params = useSearchParams() const router = useRouter() const token = params.get("token") const oauth = params.get("oauth") const { authenticated } = useAuthReady() const statusQuery = useMigrationStatus() const oauthMutation = useStartMigrationOAuth() const data = statusQuery.data const project = data?.project const onboarding = data?.onboarding const jobs = data?.jobs ?? [] useEffect(() => { if (!statusQuery.data) return const interval = setInterval(() => { void statusQuery.refetch() }, 5000) return () => clearInterval(interval) }, [statusQuery]) useEffect(() => { if (!authenticated || !token) return if (data?.invite?.status === "invited") { router.replace(`/onboard/claim?token=${encodeURIComponent(token)}`) } }, [authenticated, token, data?.invite?.status, router]) if (!authenticated) { const returnTo = token ? `/onboard/migration?token=${encodeURIComponent(token)}` : "/onboard/migration" return (

Connectez-vous pour suivre votre migration.

) } const claimed = data?.invite?.status === "claimed" const oauthDone = Boolean(onboarding?.has_migration_credentials) const importRunning = claimed && !onboarding?.waiting_for_admin && (oauthDone || usesAppOnlyAuth(project) || jobs.some((j) => j.status === "running")) const steps = [ { label: "Compte revendiqué", done: claimed, current: !claimed }, { label: "Projet activé par l'admin", done: claimed && !onboarding?.waiting_for_admin, current: claimed && Boolean(onboarding?.waiting_for_admin), }, { label: usesAppOnlyAuth(project) ? appOnlyAuthStepLabel(project) : "Autorisation Google / Microsoft", done: usesAppOnlyAuth(project) ? !onboarding?.waiting_for_admin && claimed : oauthDone, current: claimed && !onboarding?.waiting_for_admin && !usesAppOnlyAuth(project) && !oauthDone, }, { label: "Import en cours", done: jobs.length > 0 && jobs.every((j) => j.status === "completed"), current: importRunning, }, ] const showGoogleOAuth = shouldShowOAuthButton(project, onboarding, "google") const showMicrosoftOAuth = shouldShowOAuthButton(project, onboarding, "microsoft") return (

Migration en cours

{project?.name ?? "Votre migration"} — statut {project?.status ?? "…"} {project?.delta_mode ? " (sync delta post-bascule MX)" : ""}

{oauth === "success" && (

Autorisation enregistrée. L'import démarre en arrière-plan.

)} {oauth === "error" && (

Échec de l'autorisation OAuth. Réessayez ci-dessous.

)}
{jobs.length === 0 ? (

{onboarding?.waiting_for_admin ? "Les jobs seront créés après activation du projet par votre administrateur." : "Aucun job de migration actif pour le moment."}

) : ( jobs.map((job) => (
{SERVICE_LABELS[job.service] ?? job.service} {job.status}
{typeof job.stats_json?.imported === "number" && (

{Math.round(job.stats_json.imported)} éléments importés {typeof job.stats_json.estimated_total === "number" ? ` / ~${Math.round(job.stats_json.estimated_total)}` : ""}

)} {job.error &&

{job.error}

}
)) )}
{showGoogleOAuth && ( )} {showMicrosoftOAuth && ( )}
) }