新增連結測驗邀請註冊功能
This commit is contained in:
@@ -1,211 +1,27 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { ProtectedRoute } from "@/components/protected-route"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import {
|
||||
ArrowLeft,
|
||||
Copy,
|
||||
CheckCircle,
|
||||
Clock,
|
||||
Users,
|
||||
Link as LinkIcon,
|
||||
Send,
|
||||
RefreshCw,
|
||||
Eye,
|
||||
Trash2,
|
||||
Plus,
|
||||
Loader2,
|
||||
} from "lucide-react"
|
||||
import Link from "next/link"
|
||||
|
||||
// 定義測驗連結類型
|
||||
interface TestLink {
|
||||
id: string
|
||||
name: string
|
||||
type: 'logic' | 'creative' | 'combined'
|
||||
url: string
|
||||
createdAt: string
|
||||
expiresAt?: string
|
||||
isActive: boolean
|
||||
totalSent: number
|
||||
completedCount: number
|
||||
pendingCount: number
|
||||
}
|
||||
|
||||
// 定義已送出連結的狀態
|
||||
interface SentLinkStatus {
|
||||
id: string
|
||||
linkId: string
|
||||
recipientName: string
|
||||
recipientEmail: string
|
||||
sentAt: string
|
||||
status: 'pending' | 'completed' | 'expired'
|
||||
completedAt?: string
|
||||
testType: 'logic' | 'creative' | 'combined'
|
||||
score?: number
|
||||
}
|
||||
|
||||
export default function TestLinksPage() {
|
||||
const [currentLinks, setCurrentLinks] = useState<TestLink[]>([])
|
||||
const [sentLinks, setSentLinks] = useState<SentLinkStatus[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [newLinkName, setNewLinkName] = useState("")
|
||||
const [newLinkType, setNewLinkType] = useState<'logic' | 'creative' | 'combined'>('combined')
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
|
||||
// 模擬數據
|
||||
useEffect(() => {
|
||||
const mockCurrentLinks: TestLink[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: '2024年度綜合能力測驗',
|
||||
type: 'combined',
|
||||
url: 'https://hr-assessment.com/test/combined/abc123',
|
||||
createdAt: '2024-01-15T10:00:00Z',
|
||||
expiresAt: '2024-12-31T23:59:59Z',
|
||||
isActive: true,
|
||||
totalSent: 45,
|
||||
completedCount: 38,
|
||||
pendingCount: 7
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '創意能力專項測驗',
|
||||
type: 'creative',
|
||||
url: 'https://hr-assessment.com/test/creative/def456',
|
||||
createdAt: '2024-01-20T14:30:00Z',
|
||||
isActive: true,
|
||||
totalSent: 23,
|
||||
completedCount: 20,
|
||||
pendingCount: 3
|
||||
}
|
||||
]
|
||||
|
||||
const mockSentLinks: SentLinkStatus[] = [
|
||||
{
|
||||
id: '1',
|
||||
linkId: '1',
|
||||
recipientName: '張小明',
|
||||
recipientEmail: 'zhang.xiaoming@company.com',
|
||||
sentAt: '2024-01-15T10:30:00Z',
|
||||
status: 'completed',
|
||||
completedAt: '2024-01-16T09:15:00Z',
|
||||
testType: 'combined',
|
||||
score: 85
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
linkId: '1',
|
||||
recipientName: '李美華',
|
||||
recipientEmail: 'li.meihua@company.com',
|
||||
sentAt: '2024-01-15T11:00:00Z',
|
||||
status: 'completed',
|
||||
completedAt: '2024-01-17T14:20:00Z',
|
||||
testType: 'combined',
|
||||
score: 92
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
linkId: '1',
|
||||
recipientName: '王大偉',
|
||||
recipientEmail: 'wang.dawei@company.com',
|
||||
sentAt: '2024-01-15T11:30:00Z',
|
||||
status: 'pending',
|
||||
testType: 'combined'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
linkId: '2',
|
||||
recipientName: '陳小芳',
|
||||
recipientEmail: 'chen.xiaofang@company.com',
|
||||
sentAt: '2024-01-20T15:00:00Z',
|
||||
status: 'completed',
|
||||
completedAt: '2024-01-21T10:45:00Z',
|
||||
testType: 'creative',
|
||||
score: 78
|
||||
}
|
||||
]
|
||||
|
||||
setTimeout(() => {
|
||||
setCurrentLinks(mockCurrentLinks)
|
||||
setSentLinks(mockSentLinks)
|
||||
setLoading(false)
|
||||
}, 1000)
|
||||
}, [])
|
||||
|
||||
const handleCopyLink = (url: string) => {
|
||||
const handleCopyLink = () => {
|
||||
const url = `${typeof window !== 'undefined' ? window.location.origin : ''}/test-link`
|
||||
navigator.clipboard.writeText(url)
|
||||
// 這裡可以添加 toast 提示
|
||||
}
|
||||
|
||||
const handleCreateLink = () => {
|
||||
if (!newLinkName.trim()) return
|
||||
|
||||
const newLink: TestLink = {
|
||||
id: Date.now().toString(),
|
||||
name: newLinkName,
|
||||
type: newLinkType,
|
||||
url: `https://hr-assessment.com/test/${newLinkType}/${Math.random().toString(36).substr(2, 9)}`,
|
||||
createdAt: new Date().toISOString(),
|
||||
isActive: true,
|
||||
totalSent: 0,
|
||||
completedCount: 0,
|
||||
pendingCount: 0
|
||||
}
|
||||
|
||||
setCurrentLinks([...currentLinks, newLink])
|
||||
setNewLinkName("")
|
||||
setShowCreateForm(false)
|
||||
}
|
||||
|
||||
const getStatusBadge = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return <Badge variant="default" className="bg-green-500">已完成</Badge>
|
||||
case 'pending':
|
||||
return <Badge variant="secondary">進行中</Badge>
|
||||
case 'expired':
|
||||
return <Badge variant="destructive">已過期</Badge>
|
||||
default:
|
||||
return <Badge variant="outline">未知</Badge>
|
||||
}
|
||||
}
|
||||
|
||||
const getTypeName = (type: string) => {
|
||||
switch (type) {
|
||||
case 'logic':
|
||||
return '邏輯思維'
|
||||
case 'creative':
|
||||
return '創意能力'
|
||||
case 'combined':
|
||||
return '綜合能力'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<Loader2 className="h-8 w-8 animate-spin" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
alert('連結已複製到剪貼簿')
|
||||
}
|
||||
|
||||
return (
|
||||
<ProtectedRoute>
|
||||
<div className="min-h-screen bg-background">
|
||||
{/* Header */}
|
||||
<header className="border-b bg-card/50 backdrop-blur-sm">
|
||||
@@ -230,206 +46,69 @@ export default function TestLinksPage() {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="max-w-6xl mx-auto space-y-6">
|
||||
<Tabs defaultValue="current" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="current">目前測驗連結</TabsTrigger>
|
||||
<TabsTrigger value="sent">已送出連結狀態</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 目前測驗連結 */}
|
||||
<TabsContent value="current" className="space-y-6">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle>目前測驗連結</CardTitle>
|
||||
<CardHeader className="text-center">
|
||||
<CardTitle className="flex items-center justify-center gap-2">
|
||||
<LinkIcon className="w-6 h-6" />
|
||||
測驗連結
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
管理當前可用的測驗連結
|
||||
分享此連結給受測者,點擊後會自動收集用戶資料並開始測驗
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button onClick={() => setShowCreateForm(!showCreateForm)}>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
新增連結
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{/* 新增連結表單 */}
|
||||
{showCreateForm && (
|
||||
<Card className="mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">新增測驗連結</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="linkName">連結名稱</Label>
|
||||
<CardContent className="space-y-6">
|
||||
{/* 連結顯示區域 */}
|
||||
<div className="space-y-3">
|
||||
<Label>測驗連結</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
id="linkName"
|
||||
value={newLinkName}
|
||||
onChange={(e) => setNewLinkName(e.target.value)}
|
||||
placeholder="請輸入連結名稱"
|
||||
value={`${typeof window !== 'undefined' ? window.location.origin : ''}/test-link`}
|
||||
readOnly
|
||||
className="text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label htmlFor="linkType">測驗類型</Label>
|
||||
<Select value={newLinkType} onValueChange={(value: any) => setNewLinkType(value)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="logic">邏輯思維測驗</SelectItem>
|
||||
<SelectItem value="creative">創意能力測驗</SelectItem>
|
||||
<SelectItem value="combined">綜合能力測驗</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={handleCreateLink} disabled={!newLinkName.trim()}>
|
||||
建立連結
|
||||
</Button>
|
||||
<Button variant="outline" onClick={() => setShowCreateForm(false)}>
|
||||
取消
|
||||
<Button
|
||||
onClick={() => {
|
||||
const url = `${typeof window !== 'undefined' ? window.location.origin : ''}/test-link`
|
||||
navigator.clipboard.writeText(url)
|
||||
alert('連結已複製到剪貼簿')
|
||||
}}
|
||||
>
|
||||
<Copy className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 連結列表 */}
|
||||
<div className="space-y-4">
|
||||
{currentLinks.map((link) => (
|
||||
<Card key={link.id}>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-lg font-semibold">{link.name}</h3>
|
||||
<Badge variant={link.isActive ? "default" : "secondary"}>
|
||||
{link.isActive ? "啟用中" : "已停用"}
|
||||
</Badge>
|
||||
<Badge variant="outline">{getTypeName(link.type)}</Badge>
|
||||
{/* 功能說明 */}
|
||||
<div className="bg-muted/50 rounded-lg p-4 space-y-2">
|
||||
<h4 className="font-medium text-sm">功能說明:</h4>
|
||||
<ul className="text-sm text-muted-foreground space-y-1">
|
||||
<li>• 受測者點擊連結後會要求填寫基本資料</li>
|
||||
<li>• 系統會自動創建用戶帳號(密碼:Aa123456)</li>
|
||||
<li>• 填寫完成後自動跳轉到測驗選擇頁面</li>
|
||||
<li>• 支援邏輯思維、創意能力、綜合測試三種類型</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<span>建立時間: {new Date(link.createdAt).toLocaleString('zh-TW')}</span>
|
||||
{link.expiresAt && (
|
||||
<span>到期時間: {new Date(link.expiresAt).toLocaleString('zh-TW')}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-6 text-sm">
|
||||
<span className="flex items-center gap-1">
|
||||
<Users className="w-4 h-4" />
|
||||
總發送: {link.totalSent}
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-green-600">
|
||||
<CheckCircle className="w-4 h-4" />
|
||||
已完成: {link.completedCount}
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-orange-600">
|
||||
<Clock className="w-4 h-4" />
|
||||
進行中: {link.pendingCount}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
{/* 預覽按鈕 */}
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleCopyLink(link.url)}
|
||||
onClick={() => window.open('/test-link', '_blank')}
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
<Copy className="w-4 h-4 mr-2" />
|
||||
複製連結
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href={`/test/${link.type}`} target="_blank">
|
||||
<Eye className="w-4 h-4 mr-2" />
|
||||
預覽
|
||||
</Link>
|
||||
預覽測驗頁面
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</div>
|
||||
|
||||
{/* 已送出連結狀態 */}
|
||||
<TabsContent value="sent" className="space-y-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>已送出連結狀態清單</CardTitle>
|
||||
<CardDescription>
|
||||
追蹤已送出測驗連結的完成狀態
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>收件人</TableHead>
|
||||
<TableHead>測驗類型</TableHead>
|
||||
<TableHead>發送時間</TableHead>
|
||||
<TableHead>狀態</TableHead>
|
||||
<TableHead>完成時間</TableHead>
|
||||
<TableHead>分數</TableHead>
|
||||
<TableHead>操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{sentLinks.map((sentLink) => (
|
||||
<TableRow key={sentLink.id}>
|
||||
<TableCell>
|
||||
<div>
|
||||
<div className="font-medium">{sentLink.recipientName}</div>
|
||||
<div className="text-sm text-muted-foreground">{sentLink.recipientEmail}</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">{getTypeName(sentLink.testType)}</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{new Date(sentLink.sentAt).toLocaleString('zh-TW')}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{getStatusBadge(sentLink.status)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{sentLink.completedAt
|
||||
? new Date(sentLink.completedAt).toLocaleString('zh-TW')
|
||||
: '-'
|
||||
}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{sentLink.score ? `${sentLink.score}分` : '-'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href={`/admin/results?user=${sentLink.recipientEmail}`}>
|
||||
<Eye className="w-4 h-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
{sentLink.status === 'pending' && (
|
||||
<Button variant="outline" size="sm">
|
||||
<Send className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
)
|
||||
}
|
220
app/test-link/page.tsx
Normal file
220
app/test-link/page.tsx
Normal file
@@ -0,0 +1,220 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert"
|
||||
import { Loader2, User, Mail, Building, CheckCircle } from "lucide-react"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
export default function TestLinkPage() {
|
||||
const router = useRouter()
|
||||
const [userInfo, setUserInfo] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
department: ''
|
||||
})
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [isSuccess, setIsSuccess] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
const handleUserInfoChange = (field: string, value: string) => {
|
||||
setUserInfo(prev => ({
|
||||
...prev,
|
||||
[field]: value
|
||||
}))
|
||||
setError('') // 清除錯誤訊息
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!userInfo.name || !userInfo.email || !userInfo.department) {
|
||||
setError('請填寫所有必填欄位')
|
||||
return
|
||||
}
|
||||
|
||||
setIsSubmitting(true)
|
||||
setError('')
|
||||
|
||||
try {
|
||||
// 註冊用戶
|
||||
const response = await fetch('/api/auth/register', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: userInfo.name,
|
||||
email: userInfo.email,
|
||||
department: userInfo.department,
|
||||
password: 'Aa123456', // 預設密碼
|
||||
role: 'user'
|
||||
}),
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
// 註冊成功後自動登入
|
||||
const loginResponse = await fetch('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: userInfo.email,
|
||||
password: 'Aa123456'
|
||||
}),
|
||||
})
|
||||
|
||||
if (loginResponse.ok) {
|
||||
const loginData = await loginResponse.json()
|
||||
|
||||
// 存儲 token 和用戶資料到 localStorage
|
||||
if (loginData.accessToken && loginData.refreshToken) {
|
||||
localStorage.setItem('accessToken', loginData.accessToken)
|
||||
localStorage.setItem('refreshToken', loginData.refreshToken)
|
||||
localStorage.setItem('hr_current_user', JSON.stringify(loginData.user))
|
||||
}
|
||||
|
||||
setIsSuccess(true)
|
||||
// 2秒後跳轉到個人專區(儀表板)
|
||||
setTimeout(() => {
|
||||
// 使用 window.location.href 確保頁面完全重新載入
|
||||
window.location.href = '/home'
|
||||
}, 2000)
|
||||
} else {
|
||||
setError('註冊成功但自動登入失敗,請手動登入')
|
||||
}
|
||||
} else {
|
||||
const errorData = await response.json()
|
||||
setError(errorData.message || '註冊失敗,請稍後再試')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error)
|
||||
setError('註冊失敗,請稍後再試')
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardContent className="pt-6">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto">
|
||||
<CheckCircle className="w-8 h-8 text-green-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-green-600">註冊成功!</h2>
|
||||
<p className="text-muted-foreground mt-2">
|
||||
正在跳轉到個人專區...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<CardTitle className="text-2xl">測驗資料收集</CardTitle>
|
||||
<CardDescription>
|
||||
請填寫以下資料以開始測驗
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{error && (
|
||||
<Alert variant="destructive">
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name" className="flex items-center gap-2">
|
||||
<User className="w-4 h-4" />
|
||||
姓名
|
||||
</Label>
|
||||
<Input
|
||||
id="name"
|
||||
placeholder="請輸入您的姓名"
|
||||
value={userInfo.name}
|
||||
onChange={(e) => handleUserInfoChange('name', e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email" className="flex items-center gap-2">
|
||||
<Mail className="w-4 h-4" />
|
||||
電子郵件
|
||||
</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="請輸入電子郵件"
|
||||
value={userInfo.email}
|
||||
onChange={(e) => handleUserInfoChange('email', e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="department" className="flex items-center gap-2">
|
||||
<Building className="w-4 h-4" />
|
||||
部門
|
||||
</Label>
|
||||
<Select
|
||||
value={userInfo.department}
|
||||
onValueChange={(value) => handleUserInfoChange('department', value)}
|
||||
required
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="請選擇部門" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="資訊技術部">資訊技術部</SelectItem>
|
||||
<SelectItem value="人力資源部">人力資源部</SelectItem>
|
||||
<SelectItem value="財務部">財務部</SelectItem>
|
||||
<SelectItem value="行銷部">行銷部</SelectItem>
|
||||
<SelectItem value="營運部">營運部</SelectItem>
|
||||
<SelectItem value="其他">其他</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
處理中...
|
||||
</>
|
||||
) : (
|
||||
'開始測驗'
|
||||
)}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 p-3 bg-muted/50 rounded-lg">
|
||||
<p className="text-xs text-muted-foreground text-center">
|
||||
系統將自動為您創建帳號,預設密碼為:<strong>Aa123456</strong>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user