From 4614210aa9878922cfa1e424ce677ef893a1b6b2 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 29 Sep 2025 13:31:40 +0000
Subject: (대표님) 구매 권한설정, data room 등
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../table/template-edit-sheet.tsx                  | 305 +++++++++++++++++++++
 1 file changed, 305 insertions(+)
 create mode 100644 lib/project-doc-templates/table/template-edit-sheet.tsx

(limited to 'lib/project-doc-templates/table/template-edit-sheet.tsx')

diff --git a/lib/project-doc-templates/table/template-edit-sheet.tsx b/lib/project-doc-templates/table/template-edit-sheet.tsx
new file mode 100644
index 00000000..a745045c
--- /dev/null
+++ b/lib/project-doc-templates/table/template-edit-sheet.tsx
@@ -0,0 +1,305 @@
+// lib/project-doc-template/template-edit-sheet.tsx
+"use client";
+
+import * as React from "react";
+import {
+  Sheet,
+  SheetContent,
+  SheetDescription,
+  SheetHeader,
+  SheetTitle,
+  SheetFooter,
+} from "@/components/ui/sheet";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { Textarea } from "@/components/ui/textarea";
+import { Badge } from "@/components/ui/badge";
+import { Switch } from "@/components/ui/switch";
+import { toast } from "sonner";
+import { updateProjectDocTemplate } from "@/lib/project-doc-templates/service";
+import type { ProjectDocTemplate, DocTemplateVariable } from "@/db/schema/project-doc-templates";
+import { Plus, X, Save, Loader2 } from "lucide-react";
+
+interface TemplateEditSheetProps {
+  template: ProjectDocTemplate | null;
+  open: boolean;
+  onOpenChange: (open: boolean) => void;
+  onSuccess?: () => void;
+}
+
+export function TemplateEditSheet({
+  template,
+  open,
+  onOpenChange,
+  onSuccess,
+}: TemplateEditSheetProps) {
+  const [isLoading, setIsLoading] = React.useState(false);
+  const [formData, setFormData] = React.useState({
+    templateName: "",
+    description: "",
+    variables: [] as DocTemplateVariable[],
+    status: "ACTIVE",
+  });
+
+  // 템플릿 데이터 로드
+  React.useEffect(() => {
+    if (template && open) {
+      setFormData({
+        templateName: template.templateName || "",
+        description: template.description || "",
+        variables: template.variables || [],
+        status: template.status || "ACTIVE",
+      });
+    }
+  }, [template, open]);
+
+  // 변수 추가
+  const addVariable = () => {
+    setFormData({
+      ...formData,
+      variables: [
+        ...formData.variables,
+        {
+          name: "",
+          displayName: "",
+          type: "text",
+          required: false,
+          defaultValue: "",
+          description: "",
+        },
+      ],
+    });
+  };
+
+  // 변수 제거
+  const removeVariable = (index: number) => {
+    setFormData({
+      ...formData,
+      variables: formData.variables.filter((_, i) => i !== index),
+    });
+  };
+
+  // 변수 업데이트
+  const updateVariable = (index: number, field: string, value: any) => {
+    const updatedVariables = [...formData.variables];
+    updatedVariables[index] = {
+      ...updatedVariables[index],
+      [field]: value,
+    };
+    setFormData({
+      ...formData,
+      variables: updatedVariables,
+    });
+  };
+
+  // 저장 처리
+  const handleSave = async () => {
+    if (!template) return;
+
+    setIsLoading(true);
+    try {
+      const result = await updateProjectDocTemplate(template.id, {
+        templateName: formData.templateName,
+        description: formData.description,
+        variables: formData.variables,
+        status: formData.status,
+      });
+
+      if (result.success) {
+        toast.success("템플릿이 수정되었습니다.");
+        onOpenChange(false);
+        onSuccess?.();
+      } else {
+        throw new Error(result.error);
+      }
+    } catch (error) {
+      console.error("Failed to update template:", error);
+      toast.error(error instanceof Error ? error.message : "템플릿 수정에 실패했습니다.");
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  return (
+    <Sheet open={open} onOpenChange={onOpenChange}>
+      <SheetContent className="w-[600px] sm:max-w-[600px] overflow-y-auto">
+        <SheetHeader>
+          <SheetTitle>템플릿 수정</SheetTitle>
+          <SheetDescription>
+            템플릿 정보와 변수를 수정할 수 있습니다. 파일을 변경하려면 새 버전을 생성하세요.
+          </SheetDescription>
+        </SheetHeader>
+
+        <div className="space-y-6 py-6">
+          {/* 기본 정보 */}
+          <div className="space-y-4">
+            <div>
+              <Label htmlFor="templateName">템플릿 이름</Label>
+              <Input
+                id="templateName"
+                value={formData.templateName}
+                onChange={(e) => setFormData({ ...formData, templateName: e.target.value })}
+                placeholder="템플릿 이름을 입력하세요"
+              />
+            </div>
+
+            <div>
+              <Label htmlFor="description">설명</Label>
+              <Textarea
+                id="description"
+                value={formData.description}
+                onChange={(e) => setFormData({ ...formData, description: e.target.value })}
+                placeholder="템플릿 설명을 입력하세요"
+                className="min-h-[80px]"
+              />
+            </div>
+
+            <div>
+              <Label htmlFor="status">상태</Label>
+              <select
+                id="status"
+                className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
+                value={formData.status}
+                onChange={(e) => setFormData({ ...formData, status: e.target.value })}
+              >
+                <option value="ACTIVE">활성</option>
+                <option value="INACTIVE">비활성</option>
+                <option value="DRAFT">초안</option>
+                <option value="ARCHIVED">보관</option>
+              </select>
+            </div>
+          </div>
+
+          {/* 변수 관리 */}
+          <div>
+            <div className="flex items-center justify-between mb-4">
+              <Label>템플릿 변수</Label>
+              <Button
+                type="button"
+                variant="outline"
+                size="sm"
+                onClick={addVariable}
+              >
+                <Plus className="mr-2 h-4 w-4" />
+                변수 추가
+              </Button>
+            </div>
+
+            {/* 기본 변수 표시 */}
+            <div className="mb-4 p-3 bg-muted/50 rounded-lg">
+              <p className="text-xs font-medium mb-2">기본 변수 (수정 불가)</p>
+              <div className="space-y-1">
+                <Badge variant="secondary">document_number</Badge>
+                <Badge variant="secondary" className="ml-2">project_code</Badge>
+                <Badge variant="secondary" className="ml-2">project_name</Badge>
+              </div>
+            </div>
+
+            {/* 사용자 정의 변수 */}
+            {formData.variables.length > 0 ? (
+              <div className="space-y-3">
+                {formData.variables.map((variable, index) => (
+                  <div key={index} className="p-3 border rounded-lg space-y-3">
+                    <div className="flex items-center justify-between">
+                      <span className="text-sm font-medium">변수 #{index + 1}</span>
+                      <Button
+                        type="button"
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => removeVariable(index)}
+                      >
+                        <X className="h-4 w-4" />
+                      </Button>
+                    </div>
+
+                    <div className="grid grid-cols-2 gap-3">
+                      <div>
+                        <Label>변수명</Label>
+                        <Input
+                          value={variable.name}
+                          onChange={(e) => updateVariable(index, "name", e.target.value)}
+                          placeholder="예: vendor_name"
+                        />
+                      </div>
+                      <div>
+                        <Label>표시명</Label>
+                        <Input
+                          value={variable.displayName}
+                          onChange={(e) => updateVariable(index, "displayName", e.target.value)}
+                          placeholder="예: 벤더명"
+                        />
+                      </div>
+                    </div>
+
+                    <div className="grid grid-cols-2 gap-3">
+                      <div>
+                        <Label>타입</Label>
+                        <select
+                          className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
+                          value={variable.type}
+                          onChange={(e) => updateVariable(index, "type", e.target.value)}
+                        >
+                          <option value="text">텍스트</option>
+                          <option value="number">숫자</option>
+                          <option value="date">날짜</option>
+                          <option value="select">선택</option>
+                        </select>
+                      </div>
+                      <div className="flex items-center justify-between rounded-lg border p-2">
+                        <Label className="text-sm">필수</Label>
+                        <Switch
+                          checked={variable.required}
+                          onCheckedChange={(checked) => updateVariable(index, "required", checked)}
+                        />
+                      </div>
+                    </div>
+
+                    <div>
+                      <Label>설명</Label>
+                      <Input
+                        value={variable.description || ""}
+                        onChange={(e) => updateVariable(index, "description", e.target.value)}
+                        placeholder="변수 설명 (선택사항)"
+                      />
+                    </div>
+                  </div>
+                ))}
+              </div>
+            ) : (
+              <div className="text-center py-4 text-sm text-muted-foreground">
+                사용자 정의 변수가 없습니다.
+              </div>
+            )}
+          </div>
+        </div>
+
+        <SheetFooter>
+          <Button
+            variant="outline"
+            onClick={() => onOpenChange(false)}
+            disabled={isLoading}
+          >
+            취소
+          </Button>
+          <Button
+            onClick={handleSave}
+            disabled={isLoading}
+          >
+            {isLoading ? (
+              <>
+                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
+                저장 중...
+              </>
+            ) : (
+              <>
+                <Save className="mr-2 h-4 w-4" />
+                저장
+              </>
+            )}
+          </Button>
+        </SheetFooter>
+      </SheetContent>
+    </Sheet>
+  );
+}
\ No newline at end of file
-- 
cgit v1.2.3

