125 lines
3.6 KiB
TypeScript
125 lines
3.6 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
|
import { Button } from "@/components/ui/button"
|
|
import { AlertTriangle, Clock, CheckCircle } from "lucide-react"
|
|
|
|
interface TimeWarningModalProps {
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
type: 'warning' | 'timeout' | 'success'
|
|
title: string
|
|
message: string
|
|
showCountdown?: boolean
|
|
countdownSeconds?: number
|
|
}
|
|
|
|
export function TimeWarningModal({
|
|
isOpen,
|
|
onClose,
|
|
type,
|
|
title,
|
|
message,
|
|
showCountdown = false,
|
|
countdownSeconds = 0
|
|
}: TimeWarningModalProps) {
|
|
const [remainingSeconds, setRemainingSeconds] = useState(countdownSeconds)
|
|
|
|
useEffect(() => {
|
|
if (isOpen && showCountdown && remainingSeconds > 0) {
|
|
const timer = setInterval(() => {
|
|
setRemainingSeconds(prev => {
|
|
if (prev <= 1) {
|
|
clearInterval(timer)
|
|
onClose()
|
|
return 0
|
|
}
|
|
return prev - 1
|
|
})
|
|
}, 1000)
|
|
|
|
return () => clearInterval(timer)
|
|
}
|
|
}, [isOpen, showCountdown, remainingSeconds, onClose])
|
|
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
setRemainingSeconds(countdownSeconds)
|
|
}
|
|
}, [isOpen, countdownSeconds])
|
|
|
|
const getIcon = () => {
|
|
switch (type) {
|
|
case 'warning':
|
|
return <AlertTriangle className="w-8 h-8 text-yellow-500" />
|
|
case 'timeout':
|
|
return <Clock className="w-8 h-8 text-red-500" />
|
|
case 'success':
|
|
return <CheckCircle className="w-8 h-8 text-green-500" />
|
|
default:
|
|
return <AlertTriangle className="w-8 h-8 text-yellow-500" />
|
|
}
|
|
}
|
|
|
|
const getBgColor = () => {
|
|
switch (type) {
|
|
case 'warning':
|
|
return 'bg-yellow-50 border-yellow-200'
|
|
case 'timeout':
|
|
return 'bg-red-50 border-red-200'
|
|
case 'success':
|
|
return 'bg-green-50 border-green-200'
|
|
default:
|
|
return 'bg-yellow-50 border-yellow-200'
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
<DialogContent className={`sm:max-w-md ${getBgColor()}`}>
|
|
<DialogHeader>
|
|
<div className="flex items-center justify-center mb-4">
|
|
<div className="p-3 rounded-full bg-white shadow-lg">
|
|
{getIcon()}
|
|
</div>
|
|
</div>
|
|
<DialogTitle className="text-center text-xl font-bold">
|
|
{title}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
<div className="text-center space-y-4">
|
|
<p className="text-gray-700 leading-relaxed">
|
|
{message}
|
|
</p>
|
|
|
|
{showCountdown && remainingSeconds > 0 && (
|
|
<div className="flex items-center justify-center space-x-2">
|
|
<div className="w-8 h-8 rounded-full bg-red-500 text-white flex items-center justify-center font-bold">
|
|
{remainingSeconds}
|
|
</div>
|
|
<span className="text-sm text-gray-600">秒後自動關閉</span>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex justify-center space-x-3 pt-4">
|
|
<Button
|
|
onClick={onClose}
|
|
className={`px-6 ${
|
|
type === 'warning'
|
|
? 'bg-yellow-500 hover:bg-yellow-600 text-white'
|
|
: type === 'timeout'
|
|
? 'bg-red-500 hover:bg-red-600 text-white'
|
|
: 'bg-green-500 hover:bg-green-600 text-white'
|
|
}`}
|
|
>
|
|
{type === 'warning' ? '我知道了' : type === 'timeout' ? '確認' : '好的'}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|