summaryrefslogtreecommitdiff
path: root/lib/rfq-last/due-date-edit-button.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/due-date-edit-button.tsx')
-rw-r--r--lib/rfq-last/due-date-edit-button.tsx216
1 files changed, 216 insertions, 0 deletions
diff --git a/lib/rfq-last/due-date-edit-button.tsx b/lib/rfq-last/due-date-edit-button.tsx
new file mode 100644
index 00000000..85a18a63
--- /dev/null
+++ b/lib/rfq-last/due-date-edit-button.tsx
@@ -0,0 +1,216 @@
+"use client"
+
+import { useState } from "react"
+import { format } from "date-fns"
+import { ko } from "date-fns/locale"
+import { Calendar as CalendarIcon, Clock, Edit2 } from "lucide-react"
+import { Button } from "@/components/ui/button"
+import { Calendar } from "@/components/ui/calendar"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover"
+import { cn } from "@/lib/utils"
+import { useToast } from "@/hooks/use-toast"
+import { useRouter } from "next/navigation"
+import { updateRfqDueDate } from "./service"
+
+interface DueDateEditButtonProps {
+ rfqId: number
+ currentDueDate: Date | string | null
+ rfqCode: string
+ rfqTitle: string
+}
+
+export function DueDateEditButton({
+ rfqId,
+ currentDueDate,
+ rfqCode,
+ rfqTitle
+ }: DueDateEditButtonProps) {
+ const [open, setOpen] = useState(false)
+ const [date, setDate] = useState<Date | undefined>(
+ currentDueDate ? new Date(currentDueDate) : undefined
+ )
+ const [time, setTime] = useState<string>(
+ currentDueDate
+ ? format(new Date(currentDueDate), "HH:mm")
+ : "17:00" // 기본값: 오후 5시
+ )
+ const [isLoading, setIsLoading] = useState(false)
+ const { toast } = useToast()
+ const router = useRouter()
+
+ const handleSave = async () => {
+ if (!date) {
+ toast({
+ title: "오류",
+ description: "마감일을 선택해주세요.",
+ variant: "destructive",
+ })
+ return
+ }
+
+ setIsLoading(true)
+ try {
+ // 날짜와 시간 결합
+ const [hours, minutes] = time.split(':').map(Number)
+ const dateTime = new Date(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ hours,
+ minutes,
+ 0,
+ 0
+ )
+
+ // ISO 문자열로 전송 (자동으로 로컬 타임존 포함)
+ const result = await updateRfqDueDate(
+ rfqId,
+ dateTime.toISOString(),
+ rfqCode,
+ rfqTitle
+ )
+
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: result.message,
+ })
+ setOpen(false)
+ router.refresh()
+ } else {
+ toast({
+ title: "오류",
+ description: result.message,
+ variant: "destructive",
+ })
+ }
+ } catch (error) {
+ toast({
+ title: "오류",
+ description: "마감일 수정 중 오류가 발생했습니다.",
+ variant: "destructive",
+ })
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+ <Dialog open={open} onOpenChange={setOpen}>
+ <DialogTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ className="h-7 px-2"
+ >
+ <Edit2 className="h-3 w-3 mr-1" />
+ 수정
+ </Button>
+ </DialogTrigger>
+ <DialogContent className="sm:max-w-[425px]">
+ <DialogHeader>
+ <DialogTitle>마감일 수정</DialogTitle>
+ <DialogDescription>
+ {rfqCode} {rfqTitle ? `- ${rfqTitle}` : ''}의 마감일을 수정합니다.
+ 변경 시 관련 업체에 이메일이 발송됩니다.
+ </DialogDescription>
+ </DialogHeader>
+ <div className="grid gap-4 py-4">
+ {/* 날짜 선택 */}
+ <div className="grid gap-2">
+ <label htmlFor="dueDate" className="text-sm font-medium">
+ 마감 날짜
+ </label>
+ <Popover>
+ <PopoverTrigger asChild>
+ <Button
+ id="dueDate"
+ variant="outline"
+ className={cn(
+ "w-full justify-start text-left font-normal",
+ !date && "text-muted-foreground"
+ )}
+ >
+ <CalendarIcon className="mr-2 h-4 w-4" />
+ {date ? format(date, "yyyy년 MM월 dd일", { locale: ko }) : "날짜를 선택하세요"}
+ </Button>
+ </PopoverTrigger>
+ <PopoverContent className="w-auto p-0" align="start">
+ <Calendar
+ mode="single"
+ selected={date}
+ onSelect={setDate}
+ initialFocus
+ locale={ko}
+ disabled={(date) => date < new Date(new Date().setHours(0, 0, 0, 0))}
+ />
+ </PopoverContent>
+ </Popover>
+ </div>
+
+ {/* 시간 선택 */}
+ <div className="grid gap-2">
+ <label htmlFor="time" className="text-sm font-medium">
+ 마감 시간
+ </label>
+ <div className="flex items-center gap-2">
+ <Clock className="h-4 w-4 text-muted-foreground" />
+ <input
+ id="time"
+ type="time"
+ value={time}
+ onChange={(e) => setTime(e.target.value)}
+ className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
+ />
+ </div>
+ </div>
+
+ {/* 현재 마감일시 표시 */}
+ {currentDueDate && (
+ <div className="text-sm text-muted-foreground">
+ 현재 마감일시: {format(new Date(currentDueDate), "yyyy년 MM월 dd일 HH:mm", { locale: ko })}
+ </div>
+ )}
+
+ {/* 선택한 날짜시간 미리보기 */}
+ {date && (
+ <div className="rounded-md bg-muted p-3">
+ <p className="text-sm font-medium">선택한 마감일시:</p>
+ <p className="text-sm text-muted-foreground">
+ {format(date, "yyyy년 MM월 dd일", { locale: ko })} {time}
+ </p>
+ </div>
+ )}
+ </div>
+ <DialogFooter>
+ <Button
+ variant="outline"
+ onClick={() => setOpen(false)}
+ disabled={isLoading}
+ >
+ 취소
+ </Button>
+ <Button
+ onClick={handleSave}
+ disabled={isLoading}
+ >
+ {isLoading ? "저장 중..." : "저장"}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+ } \ No newline at end of file