Files
ai-showcase-platform/components/auth/forgot-password-dialog.tsx

192 lines
6.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type React from "react"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { Mail, ArrowLeft, CheckCircle } from "lucide-react"
interface ForgotPasswordDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
onBackToLogin: () => void
}
export function ForgotPasswordDialog({ open, onOpenChange, onBackToLogin }: ForgotPasswordDialogProps) {
const [email, setEmail] = useState("")
const [isLoading, setIsLoading] = useState(false)
const [isSuccess, setIsSuccess] = useState(false)
const [error, setError] = useState("")
const [resetUrl, setResetUrl] = useState("")
const [expiresAt, setExpiresAt] = useState("")
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError("")
if (!email) {
setError("請輸入電子郵件地址")
return
}
if (!email.includes("@")) {
setError("請輸入有效的電子郵件地址")
return
}
setIsLoading(true)
try {
const response = await fetch('/api/auth/forgot-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
})
const data = await response.json()
if (data.success) {
setResetUrl(data.resetUrl)
setExpiresAt(data.expiresAt)
setIsSuccess(true)
} else {
setError(data.error || "生成重設連結失敗")
}
} catch (err) {
setError("生成重設連結時發生錯誤")
} finally {
setIsLoading(false)
}
}
const handleClose = () => {
setEmail("")
setError("")
setIsSuccess(false)
setResetUrl("")
setExpiresAt("")
onOpenChange(false)
}
if (isSuccess) {
return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<div className="flex flex-col items-center space-y-4">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center">
<CheckCircle className="w-8 h-8 text-green-600" />
</div>
<DialogTitle className="text-2xl font-bold text-center"></DialogTitle>
<DialogDescription className="text-center"></DialogDescription>
</div>
</DialogHeader>
<div className="space-y-4">
<div className="bg-blue-50 p-4 rounded-lg">
<p className="text-sm text-blue-800 mb-2"></p>
<p className="text-sm text-blue-700 font-medium">{email}</p>
</div>
<div className="space-y-2">
<Label htmlFor="reset-link"></Label>
<div className="flex space-x-2">
<Input
id="reset-link"
value={resetUrl}
readOnly
className="font-mono text-sm"
/>
<Button
onClick={() => {
navigator.clipboard.writeText(resetUrl)
// 可以添加 toast 提示
}}
variant="outline"
size="sm"
>
</Button>
</div>
<p className="text-xs text-gray-500">
{new Date(expiresAt).toLocaleString('zh-TW')}
</p>
</div>
<div className="text-center">
<Button
onClick={() => window.open(resetUrl, '_blank')}
className="w-full"
>
</Button>
</div>
<div className="flex space-x-3">
<Button onClick={onBackToLogin} variant="outline" className="flex-1">
<ArrowLeft className="w-4 h-4 mr-2" />
</Button>
<Button onClick={handleClose} className="flex-1">
</Button>
</div>
</div>
</DialogContent>
</Dialog>
)
}
return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="text-2xl font-bold text-center"></DialogTitle>
<DialogDescription className="text-center">
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="reset-email"></Label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
id="reset-email"
type="email"
placeholder="請輸入您的電子郵件"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="pl-10"
required
/>
</div>
</div>
{error && (
<Alert variant="destructive">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
<div className="flex space-x-3">
<Button type="button" onClick={onBackToLogin} variant="outline" className="flex-1 bg-transparent">
<ArrowLeft className="w-4 h-4 mr-2" />
</Button>
<Button type="submit" disabled={isLoading} className="flex-1">
{isLoading ? "生成中..." : "生成重設連結"}
</Button>
</div>
</form>
</DialogContent>
</Dialog>
)
}