"use client" import type React from "react" import { useEffect, useId, useState } from "react" import { useRouter } from "next/navigation" import { cn } from "@/lib/utils" import { TwoFactorSetupForm, TwoFactorVerifyForm } from "@/components/two-factor-flow" /* ------------------------------------------------------------------ */ /* Icons — inline SVG (currentColor), so every action can pair an */ /* icon with a real text label and we control size/stroke precisely. */ /* ------------------------------------------------------------------ */ type IconProps = { className?: string } const stroke = { fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round" as const, strokeLinejoin: "round" as const, } function MailIcon({ className }: IconProps) { return ( ) } function KeyIcon({ className }: IconProps) { return ( ) } function TicketIcon({ className }: IconProps) { return ( ) } function EyeIcon({ className }: IconProps) { return ( ) } function EyeOffIcon({ className }: IconProps) { return ( ) } function ArrowLeftIcon({ className }: IconProps) { return ( ) } function AlertIcon({ className }: IconProps) { return ( ) } function CheckIcon({ className }: IconProps) { return ( ) } function FlagIcon({ className }: IconProps) { return ( ) } function Spinner({ className }: IconProps) { return ( ) } /* ------------------------------------------------------------------ */ /* Shared styles */ /* ------------------------------------------------------------------ */ const focusRing = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tee-strong focus-visible:ring-offset-2 focus-visible:ring-offset-clubhouse-card" const inputBase = "w-full h-12 rounded-xl border bg-clubhouse-field px-4 text-base text-clubhouse-ink placeholder:text-clubhouse-muted/70 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tee-strong/70" const primaryBtn = cn( "inline-flex w-full min-h-[3.25rem] items-center justify-center gap-2 rounded-xl bg-tee-strong px-5 text-base font-semibold text-white shadow-sm transition-colors hover:bg-[#265a18] active:translate-y-px disabled:cursor-not-allowed disabled:opacity-55", focusRing, ) const secondaryBtn = cn( "inline-flex w-full min-h-[2.75rem] items-center justify-center gap-2 rounded-xl border border-clubhouse-border bg-clubhouse-card px-4 py-2.5 text-base font-medium text-clubhouse-ink transition-colors hover:border-tee-strong/40 hover:bg-clubhouse-field", focusRing, ) const backBtn = cn( "-mx-2 inline-flex min-h-[2.75rem] items-center gap-1.5 rounded-lg px-2 text-base font-medium text-tee-strong transition-colors hover:underline", focusRing, ) const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ const RESEND_SECONDS = 30 type Mode = "email" | "sent" | "password" | "code" type PostAuthMode = "2fa-verify" | "2fa-setup" | null type SessionUser = { id: string email: string display_name: string preferred_locale: string } type LoginResult = { status: "success" | "2fa_required" | "2fa_setup_required" user?: SessionUser two_factor_method?: "totp" | "email" } /* ------------------------------------------------------------------ */ /* Small building blocks */ /* ------------------------------------------------------------------ */ function FieldError({ id, children }: { id: string; children: React.ReactNode }) { return (
Vi sendte en innloggingslenke til {email}.
Åpne lenken på denne enheten for å logge inn. Det kan ta et minutt før den kommer frem.
{formError &&