Loading
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
/**
* Auth Flow — 인증 화면 모음 템플릿.
*
* 구성: 로그인 / 회원가입 / 비밀번호 재설정 화면을 탭으로 전환.
* 각 화면은 라벨+인풋(Form 패턴) + 소셜 로그인 + 보조 링크.
*/
type Screen = "login" | "signup" | "reset";
const TABS: { id: Screen; label: string }[] = [
{ id: "login", label: "Log in" },
{ id: "signup", label: "Sign up" },
{ id: "reset", label: "Reset" },
];
function Field({ label, type = "text", placeholder }: { label: string; type?: string; placeholder: string }) {
return (
<div className="space-y-1.5">
<label className="text-xs font-medium">{label}</label>
<input
type={type}
placeholder={placeholder}
className="h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none focus:ring-2 focus:ring-ring/40"
/>
</div>
);
}
function SocialButtons() {
return (
<div className="grid grid-cols-2 gap-2">
<Button variant="outline" size="sm" className="gap-1.5">
<span aria-hidden></span> GitHub
</Button>
<Button variant="outline" size="sm" className="gap-1.5">
<span aria-hidden>G</span> Google
</Button>
</div>
);
}
export function AuthFlowTemplate() {
const [screen, setScreen] = React.useState<Screen>("login");
return (
<div className="flex h-[640px] w-full items-center justify-center overflow-hidden rounded-lg border border-border bg-muted/30 p-6">
<div className="w-full max-w-sm">
{/* 화면 전환 탭 (데모용) */}
<div className="mb-4 flex justify-center gap-1 rounded-lg bg-muted p-1">
{TABS.map((t) => (
<button
key={t.id}
type="button"
onClick={() => setScreen(t.id)}
className={cn(
"flex-1 rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
screen === t.id
? "bg-background text-foreground shadow-sm"
: "text-muted-foreground hover:text-foreground",
)}
>
{t.label}
</button>
))}
</div>
<div className="rounded-xl border border-border bg-card p-6 shadow-sm">
<div className="mb-5 text-center">
<div className="mx-auto mb-3 flex size-9 items-center justify-center rounded-lg bg-primary text-sm font-bold text-primary-foreground">
G
</div>
<h2 className="text-base font-semibold">
{screen === "login" && "다시 오신 걸 환영해요"}
{screen === "signup" && "계정 만들기"}
{screen === "reset" && "비밀번호 재설정"}
</h2>
<p className="mt-1 text-xs text-muted-foreground">
{screen === "login" && "계정으로 로그인하세요."}
{screen === "signup" && "몇 초면 시작할 수 있어요."}
{screen === "reset" && "가입한 이메일로 링크를 보내드려요."}
</p>
</div>
{/* Login */}
{screen === "login" && (
<div className="space-y-3">
<Field label="이메일" type="email" placeholder="you@example.com" />
<Field label="비밀번호" type="password" placeholder="••••••••" />
<div className="flex items-center justify-between text-xs">
<label className="flex items-center gap-1.5 text-muted-foreground">
<input type="checkbox" className="size-3.5 rounded border-border" /> 로그인 유지
</label>
<button type="button" onClick={() => setScreen("reset")} className="text-primary hover:underline">
비밀번호 찾기
</button>
</div>
<Button className="w-full">로그인</Button>
<Divider />
<SocialButtons />
<p className="text-center text-xs text-muted-foreground">
계정이 없으신가요?{" "}
<button type="button" onClick={() => setScreen("signup")} className="text-primary hover:underline">
가입하기
</button>
</p>
</div>
)}
{/* Signup */}
{screen === "signup" && (
<div className="space-y-3">
<Field label="이름" placeholder="홍길동" />
<Field label="이메일" type="email" placeholder="you@example.com" />
<Field label="비밀번호" type="password" placeholder="8자 이상" />
<label className="flex items-start gap-1.5 text-xs text-muted-foreground">
<input type="checkbox" className="mt-0.5 size-3.5 rounded border-border" />
<span>이용약관 및 개인정보 처리방침에 동의합니다.</span>
</label>
<Button className="w-full">계정 만들기</Button>
<Divider />
<SocialButtons />
<p className="text-center text-xs text-muted-foreground">
이미 계정이 있으신가요?{" "}
<button type="button" onClick={() => setScreen("login")} className="text-primary hover:underline">
로그인
</button>
</p>
</div>
)}
{/* Reset */}
{screen === "reset" && (
<div className="space-y-3">
<Field label="이메일" type="email" placeholder="you@example.com" />
<Button className="w-full">재설정 링크 보내기</Button>
<p className="text-center text-xs text-muted-foreground">
<button type="button" onClick={() => setScreen("login")} className="text-primary hover:underline">
← 로그인으로 돌아가기
</button>
</p>
</div>
)}
</div>
</div>
</div>
);
}
function Divider() {
return (
<div className="relative my-1">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-border" />
</div>
<div className="relative flex justify-center">
<span className="bg-card px-2 text-[11px] text-muted-foreground">또는</span>
</div>
</div>
);
}