From 4ee8b24cfadf47452807fa2af801385ed60ab47c Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 15 Sep 2025 14:41:01 +0000 Subject: (대표님) 작업사항 - rfqLast, tbeLast, pdfTron, userAuth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tbe-last/vendor/vendor-comment-dialog.tsx | 313 ++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 lib/tbe-last/vendor/vendor-comment-dialog.tsx (limited to 'lib/tbe-last/vendor/vendor-comment-dialog.tsx') diff --git a/lib/tbe-last/vendor/vendor-comment-dialog.tsx b/lib/tbe-last/vendor/vendor-comment-dialog.tsx new file mode 100644 index 00000000..8aa8d97c --- /dev/null +++ b/lib/tbe-last/vendor/vendor-comment-dialog.tsx @@ -0,0 +1,313 @@ +// lib/vendor-rfq-response/vendor-tbe-table/vendor-qa-dialog.tsx + +"use client" + +import * as React from "react" +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Label } from "@/components/ui/label" +import { Textarea } from "@/components/ui/textarea" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { Badge } from "@/components/ui/badge" +import { ScrollArea } from "@/components/ui/scroll-area" +import { toast } from "sonner" +import { + MessageSquare, + Send, + Loader2, + Clock, + CheckCircle, + AlertCircle +} from "lucide-react" +import { formatDate } from "@/lib/utils" + +interface VendorQuestion { + id: string + category: string + question: string + askedAt: string + askedBy: number + askedByName?: string + answer?: string + answeredAt?: string + answeredBy?: number + answeredByName?: string + status: "open" | "answered" | "closed" + priority?: "high" | "normal" | "low" +} + +interface VendorQADialogProps { + open: boolean + onOpenChange: (open: boolean) => void + sessionId: number | null + sessionDetail: any + onQuestionSubmit: () => void +} + +export function VendorQADialog({ + open, + onOpenChange, + sessionId, + sessionDetail, + onQuestionSubmit +}: VendorQADialogProps) { + + const [category, setCategory] = React.useState("general") + const [priority, setPriority] = React.useState("normal") + const [question, setQuestion] = React.useState("") + const [isSubmitting, setIsSubmitting] = React.useState(false) + const [questions, setQuestions] = React.useState([]) + const [isLoading, setIsLoading] = React.useState(false) + + // Load questions when dialog opens + React.useEffect(() => { + if (open && sessionId) { + loadQuestions() + } + }, [open, sessionId]) + + const loadQuestions = async () => { + if (!sessionId) return + + setIsLoading(true) + try { + const response = await fetch(`/api/tbe/sessions/${sessionId}/vendor-questions`) + if (response.ok) { + const data = await response.json() + setQuestions(data) + } + } catch (error) { + console.error("Failed to load questions:", error) + } finally { + setIsLoading(false) + } + } + + // Submit question + const handleSubmit = async () => { + if (!sessionId || !question.trim()) { + toast.error("질문을 입력해주세요") + return + } + + setIsSubmitting(true) + + try { + const response = await fetch(`/api/tbe/sessions/${sessionId}/vendor-questions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + category, + question, + priority + }) + }) + + if (!response.ok) throw new Error("Failed to submit question") + + toast.success("질문이 제출되었습니다") + + // Reset form + setCategory("general") + setPriority("normal") + setQuestion("") + + // Reload questions + await loadQuestions() + + // Callback + onQuestionSubmit() + + } catch (error) { + console.error("Question submission error:", error) + toast.error("질문 제출 중 오류가 발생했습니다") + } finally { + setIsSubmitting(false) + } + } + + // Get status icon + const getStatusIcon = (status: string) => { + switch (status) { + case "answered": + return + case "closed": + return + default: + return + } + } + + // Get priority color + const getPriorityColor = (priority?: string) => { + switch (priority) { + case "high": + return "destructive" + case "low": + return "secondary" + default: + return "default" + } + } + + return ( + + + + Q&A with Buyer + + {sessionDetail?.session?.sessionCode} - 구매자에게 질문하기 + + + +
+ {/* Previous Questions */} + {questions.length > 0 && ( +
+ + +
+ {questions.map(q => ( +
+
+
+ {getStatusIcon(q.status)} + + {q.category} + + {q.priority && q.priority !== "normal" && ( + + {q.priority} + + )} +
+ + {formatDate(q.askedAt, "KR")} + +
+ +
+
+ Q: {q.question} +
+ + {q.answer && ( +
+ A: {q.answer} + + ({formatDate(q.answeredAt!, "KR")}) + +
+ )} +
+
+ ))} +
+
+
+ )} + + {/* New Question Form */} +
+
+
+ + +
+ +
+ + +
+
+ +
+ +