ultisuite-client/components/migration/onboarding-ui.tsx
R3D347HR4Y 6c7278a3aa
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(onboarding): implement claim and migration pages with OAuth support
- Added OnboardClaimPage and OnboardMigrationPage components for user onboarding.
- Integrated OAuth login flow for Google and Microsoft accounts.
- Implemented error handling and user feedback for claim and migration processes.
- Created MigrationStepList and MigrationOnboardingAlerts components for progress tracking.
- Added MailDomainsSection and MigrationProjectsPanel for admin settings.
- Introduced e2e tests for onboarding migration scenarios.
2026-06-13 12:47:03 +02:00

147 lines
5.4 KiB
TypeScript

"use client"
import type { MigrationProject } from "@/lib/api/hooks/use-hosted-mail"
export type MigrationOnboardingHints = {
needs_user_oauth: boolean
oauth_provider?: string
waiting_for_admin: boolean
waiting_reason?: string
has_migration_credentials?: boolean
needs_microsoft_admin_consent?: boolean
}
const WAITING_MESSAGES: Record<string, string> = {
project_not_activated:
"Votre administrateur doit activer le projet de migration avant que l'import ne démarre. Vos jobs resteront en attente jusqu'à cette activation.",
}
export function usesAppOnlyAuth(project?: Pick<MigrationProject, "auth_mode">): boolean {
return project?.auth_mode === "google_dwd" || project?.auth_mode === "microsoft_app"
}
export function appOnlyAuthStepLabel(project?: MigrationProject): string {
if (project?.auth_mode === "microsoft_app") {
return "Import automatique (app Microsoft)"
}
if (project?.auth_mode === "google_dwd") {
return "Import automatique (compte de service)"
}
return "Autoriser l'import Google / Microsoft"
}
export function waitingForAdminMessage(reason?: string): string {
if (!reason) {
return "En attente d'une action administrateur avant le démarrage de l'import."
}
return WAITING_MESSAGES[reason] ?? "En attente d'une action administrateur."
}
export function MigrationStepList({
steps,
}: {
steps: { label: string; done: boolean; current: boolean }[]
}) {
return (
<ol className="space-y-2 text-sm">
{steps.map((step) => (
<li
key={step.label}
className={`flex items-center gap-2 rounded-md px-3 py-2 ${
step.current ? "bg-primary/10 font-medium" : step.done ? "text-muted-foreground" : ""
}`}
>
<span
className={`inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-xs ${
step.done
? "bg-green-600 text-white"
: step.current
? "border-2 border-primary text-primary"
: "border border-muted-foreground/40 text-muted-foreground"
}`}
>
{step.done ? "✓" : "·"}
</span>
{step.label}
</li>
))}
</ol>
)
}
export function MigrationOnboardingAlerts({
project,
onboarding,
}: {
project?: MigrationProject
onboarding?: MigrationOnboardingHints
}) {
if (!onboarding) return null
return (
<div className="mt-4 space-y-3">
{onboarding.waiting_for_admin && (
<p className="rounded-md bg-amber-500/10 px-3 py-2 text-sm text-amber-800">
{waitingForAdminMessage(onboarding.waiting_reason)}
</p>
)}
{usesAppOnlyAuth(project) && !onboarding.waiting_for_admin && (
<p className="rounded-md bg-blue-500/10 px-3 py-2 text-sm text-blue-800">
{project?.auth_mode === "microsoft_app" ? (
<>
Import Microsoft 365 configuré par votre administrateur (authentification app-only).
Aucune autorisation OAuth personnelle requise l&apos;import démarre automatiquement
une fois le projet actif et le consentement admin accordé.
</>
) : (
<>
Import Google configuré par votre administrateur (compte de service). Aucune autorisation
OAuth personnelle requise l&apos;import démarre automatiquement une fois le projet
actif.
</>
)}
</p>
)}
{onboarding.needs_microsoft_admin_consent && project?.source_provider === "microsoft" && (
<p className="rounded-md bg-amber-500/10 px-3 py-2 text-sm text-amber-800">
L&apos;administrateur de votre organisation Microsoft 365 doit accorder le consentement
admin à l&apos;application Ultimail
{project?.auth_mode === "microsoft_app"
? " (permissions application : Mail, Calendrier, Contacts, OneDrive)."
: "."}{" "}
{project?.auth_mode !== "microsoft_app" &&
"Vous pouvez autoriser votre compte personnel ci-dessous, mais l'import organisationnel peut échouer tant que ce consentement n'est pas fait."}
</p>
)}
{onboarding.needs_user_oauth &&
!onboarding.has_migration_credentials &&
!onboarding.waiting_for_admin &&
!usesAppOnlyAuth(project) && (
<p className="rounded-md border px-3 py-2 text-sm text-muted-foreground">
Étape suivante : autorisez l&apos;accès à votre compte{" "}
{project?.source_provider === "microsoft" ? "Microsoft 365" : "Google Workspace"} pour
lancer l&apos;import de vos données.
</p>
)}
{onboarding.has_migration_credentials && !onboarding.waiting_for_admin && (
<p className="rounded-md bg-green-500/10 px-3 py-2 text-sm text-green-700">
Autorisation enregistrée l&apos;import progresse en arrière-plan.
</p>
)}
</div>
)
}
export function shouldShowOAuthButton(
project: MigrationProject | undefined,
onboarding: MigrationOnboardingHints | undefined,
provider: "google" | "microsoft"
): boolean {
if (!project || !onboarding) return false
if (usesAppOnlyAuth(project)) return false
if (onboarding.waiting_for_admin) return false
if (project.source_provider !== provider) return false
if (onboarding.has_migration_credentials) return false
return onboarding.needs_user_oauth
}