summaryrefslogtreecommitdiff
path: root/lib/qna/table/update-qna-sheet.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qna/table/update-qna-sheet.tsx')
-rw-r--r--lib/qna/table/update-qna-sheet.tsx206
1 files changed, 206 insertions, 0 deletions
diff --git a/lib/qna/table/update-qna-sheet.tsx b/lib/qna/table/update-qna-sheet.tsx
new file mode 100644
index 00000000..72a3c633
--- /dev/null
+++ b/lib/qna/table/update-qna-sheet.tsx
@@ -0,0 +1,206 @@
+"use client"
+
+import * as React from "react"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import { ScrollArea } from "@/components/ui/scroll-area"
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+} from "@/components/ui/sheet"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
+
+import { updateQnaSchema, type UpdateQnaSchema } from "@/lib/qna/validation"
+import { QNA_CATEGORY_LABELS, QnaViewSelect } from "@/db/schema"
+import { updateQna } from "../service"
+import TiptapEditor from "@/components/qna/tiptap-editor"
+
+interface UpdateQnaSheetProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ qna: QnaViewSelect | null
+}
+
+export function UpdateQnaSheet({ open, onOpenChange, qna }: UpdateQnaSheetProps) {
+ const [isUpdatePending, startUpdateTransition] = React.useTransition()
+
+ const form = useForm<UpdateQnaSchema>({
+ resolver: zodResolver(updateQnaSchema),
+ defaultValues: {
+ title: "",
+ content: "",
+ category: undefined,
+
+ },
+ })
+
+ // qna 데이터가 변경될 때 폼 초기화
+ React.useEffect(() => {
+ if (qna) {
+ form.reset({
+ title: qna.title,
+ content: qna.content,
+ category: qna.category,
+ })
+ }
+ }, [qna, form])
+
+
+ function onSubmit(input: UpdateQnaSchema) {
+ if (!qna) return
+
+ startUpdateTransition(async () => {
+ try {
+ const result = await updateQna(qna.id, input)
+
+ if (result.success) {
+ toast.success(result.message || "질문이 성공적으로 수정되었습니다.")
+ onOpenChange(false)
+ } else {
+ toast.error(result.error || "질문 수정에 실패했습니다.")
+ }
+ } catch (error) {
+ toast.error("예기치 못한 오류가 발생했습니다.")
+ console.error("질문 수정 오류:", error)
+ }
+ })
+ }
+
+ return (
+ <Sheet open={open} onOpenChange={onOpenChange}>
+<SheetContent className="flex h-full w-full flex-col gap-6 sm:max-w-4xl">
+<SheetHeader className="text-left">
+ <SheetTitle>질문 수정</SheetTitle>
+ <SheetDescription>
+ 질문의 제목과 내용을 수정할 수 있습니다. 수정된 내용은 즉시 반영됩니다.
+ </SheetDescription>
+ </SheetHeader>
+
+ <Form {...form}>
+ <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0 space-y-6">
+ {/* 작성자 정보 표시 */}
+ {qna && (
+ <div className="rounded-md border border-muted bg-muted/50 p-3 text-sm">
+ <div className="font-medium text-muted-foreground mb-1">질문 정보</div>
+ <div className="space-y-1">
+ <div>작성자: {qna.authorName} ({qna.authorEmail})</div>
+ <div>회사: {qna.companyName || "미지정"}</div>
+ <div>작성일: {new Date(qna.createdAt).toLocaleDateString("ko-KR")}</div>
+ <div>답변 수: {qna.totalAnswers}개 / 댓글 수: {qna.totalComments}개</div>
+ </div>
+ </div>
+ )}
+
+ {/* 제목 입력 */}
+ <FormField
+ control={form.control}
+ name="title"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>제목 *</FormLabel>
+ <FormControl>
+ <Input
+ placeholder="질문의 제목을 입력해주세요"
+ disabled={isUpdatePending}
+ className="text-base"
+ {...field}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ <FormField
+ control={form.control}
+ name="category"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>카테고리 *</FormLabel>
+ <Select
+ onValueChange={field.onChange}
+ defaultValue={field.value}
+ disabled={isUpdatePending}
+ >
+ <FormControl>
+ <SelectTrigger>
+ <SelectValue placeholder="카테고리를 선택해주세요" />
+ </SelectTrigger>
+ </FormControl>
+ <SelectContent>
+ {QNA_CATEGORY_LABELS.map((option) => (
+ <SelectItem key={option.value} value={option.value}>
+ {option.label}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 내용 입력 (리치텍스트 에디터) */}
+ <FormField
+ control={form.control}
+ name="content"
+ render={({ field }) => (
+ <FormItem className="flex flex-col flex-1 min-h-0">
+ <FormLabel>내용 *</FormLabel>
+ <FormControl className="flex flex-col flex-1 min-h-0">
+ <TiptapEditor
+ content={field.value}
+ setContent={field.onChange}
+ disabled={isUpdatePending}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </form>
+ </Form>
+
+ <SheetFooter className="gap-2 pt-4 border-t">
+ <Button
+ type="button"
+ variant="outline"
+ onClick={() => onOpenChange(false)}
+ disabled={isUpdatePending}
+ >
+ 취소
+ </Button>
+ <Button
+ type="submit"
+ onClick={form.handleSubmit(onSubmit)}
+ disabled={isUpdatePending}
+ >
+ {isUpdatePending ? "수정 중..." : "수정 완료"}
+ </Button>
+ </SheetFooter>
+ </SheetContent>
+ </Sheet>
+ )
+} \ No newline at end of file