summaryrefslogtreecommitdiff
path: root/lib/basic-contract/template/update-basicContract-sheet.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/basic-contract/template/update-basicContract-sheet.tsx')
-rw-r--r--lib/basic-contract/template/update-basicContract-sheet.tsx245
1 files changed, 46 insertions, 199 deletions
diff --git a/lib/basic-contract/template/update-basicContract-sheet.tsx b/lib/basic-contract/template/update-basicContract-sheet.tsx
index 07bac31b..0236fda5 100644
--- a/lib/basic-contract/template/update-basicContract-sheet.tsx
+++ b/lib/basic-contract/template/update-basicContract-sheet.tsx
@@ -8,7 +8,6 @@ import { toast } from "sonner"
import * as z from "zod"
import { Button } from "@/components/ui/button"
-import { Checkbox } from "@/components/ui/checkbox"
import { Switch } from "@/components/ui/switch"
import {
Form,
@@ -20,14 +19,6 @@ import {
FormDescription,
} from "@/components/ui/form"
import {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
-import {
Sheet,
SheetClose,
SheetContent,
@@ -45,45 +36,14 @@ import {
DropzoneInput
} from "@/components/ui/dropzone"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
-import { Separator } from "@/components/ui/separator"
import { Badge } from "@/components/ui/badge"
import { updateTemplate } from "../service"
import { BasicContractTemplate } from "@/db/schema"
-import { BUSINESS_UNITS, scopeHelpers } from "@/config/basicContractColumnsConfig"
-
-// 템플릿 이름 옵션 정의
-const TEMPLATE_NAME_OPTIONS = [
- "준법서약 (한글)",
- "준법서약 (영문)",
- "기술자료 요구서",
- "비밀유지 계약서",
- "표준하도급기본 계약서",
- "GTC",
- "안전보건관리 약정서",
- "동반성장",
- "윤리규범 준수 서약서",
- "기술자료 동의서",
- "내국신용장 미개설 합의서",
- "직납자재 하도급대급등 연동제 의향서"
-] as const;
+import { scopeHelpers } from "@/config/basicContractColumnsConfig"
-// 업데이트 템플릿 스키마 정의 (리비전 필드 제거, 워드파일만 허용)
+// 업데이트 템플릿 스키마 정의 (파일 업데이트 중심)
export const updateTemplateSchema = z.object({
- templateName: z.enum(TEMPLATE_NAME_OPTIONS, {
- required_error: "템플릿 이름을 선택해주세요.",
- }),
legalReviewRequired: z.boolean(),
-
- // 적용 범위
- shipBuildingApplicable: z.boolean(),
- windApplicable: z.boolean(),
- pcApplicable: z.boolean(),
- nbApplicable: z.boolean(),
- rcApplicable: z.boolean(),
- gyApplicable: z.boolean(),
- sysApplicable: z.boolean(),
- infraApplicable: z.boolean(),
-
file: z
.instanceof(File, { message: "파일을 업로드해주세요." })
.refine((file) => file.size <= 100 * 1024 * 1024, {
@@ -96,15 +56,6 @@ export const updateTemplateSchema = z.object({
{ message: "워드 파일(.doc, .docx)만 업로드 가능합니다." }
)
.optional(),
-}).refine((data) => {
- // 적어도 하나의 적용 범위는 선택되어야 함
- const hasAnyScope = BUSINESS_UNITS.some(unit =>
- data[unit.key as keyof typeof data] as boolean
- );
- return hasAnyScope;
-}, {
- message: "적어도 하나의 적용 범위를 선택해야 합니다.",
- path: ["shipBuildingApplicable"],
});
export type UpdateTemplateSchema = z.infer<typeof updateTemplateSchema>
@@ -122,16 +73,7 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
const form = useForm<UpdateTemplateSchema>({
resolver: zodResolver(updateTemplateSchema),
defaultValues: {
- templateName: template?.templateName as typeof TEMPLATE_NAME_OPTIONS[number] ?? "준법서약 (한글)",
legalReviewRequired: template?.legalReviewRequired ?? false,
- shipBuildingApplicable: template?.shipBuildingApplicable ?? false,
- windApplicable: template?.windApplicable ?? false,
- pcApplicable: template?.pcApplicable ?? false,
- nbApplicable: template?.nbApplicable ?? false,
- rcApplicable: template?.rcApplicable ?? false,
- gyApplicable: template?.gyApplicable ?? false,
- sysApplicable: template?.sysApplicable ?? false,
- infraApplicable: template?.infraApplicable ?? false,
},
mode: "onChange"
})
@@ -145,52 +87,23 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
}
};
- // 모든 적용 범위 선택/해제
- const handleSelectAllScopes = (checked: boolean | "indeterminate") => {
- const value = checked === true;
- BUSINESS_UNITS.forEach(unit => {
- form.setValue(unit.key as keyof UpdateTemplateSchema, value);
- });
- };
-
// 템플릿 변경 시 폼 값 업데이트
React.useEffect(() => {
if (template) {
form.reset({
- templateName: template.templateName as typeof TEMPLATE_NAME_OPTIONS[number],
legalReviewRequired: template.legalReviewRequired ?? false,
- shipBuildingApplicable: template.shipBuildingApplicable ?? false,
- windApplicable: template.windApplicable ?? false,
- pcApplicable: template.pcApplicable ?? false,
- nbApplicable: template.nbApplicable ?? false,
- rcApplicable: template.rcApplicable ?? false,
- gyApplicable: template.gyApplicable ?? false,
- sysApplicable: template.sysApplicable ?? false,
- infraApplicable: template.infraApplicable ?? false,
});
}
}, [template, form]);
- // 현재 선택된 적용 범위 수
- const selectedScopesCount = BUSINESS_UNITS.filter(unit =>
- form.watch(unit.key as keyof UpdateTemplateSchema)
- ).length;
-
function onSubmit(input: UpdateTemplateSchema) {
startUpdateTransition(async () => {
if (!template) return
// FormData 객체 생성하여 파일과 데이터를 함께 전송
const formData = new FormData();
- formData.append("templateName", input.templateName);
formData.append("legalReviewRequired", input.legalReviewRequired.toString());
- // 적용 범위 추가
- BUSINESS_UNITS.forEach(unit => {
- const value = input[unit.key as keyof UpdateTemplateSchema] as boolean;
- formData.append(unit.key, value.toString());
- });
-
if (input.file) {
formData.append("file", input.file);
}
@@ -221,24 +134,14 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
if (!template) return null;
- const scopeSelected = BUSINESS_UNITS.some(
- (unit) => form.watch(unit.key as keyof UpdateTemplateSchema)
- );
-
- const isDisabled =
- isUpdatePending ||
- !form.watch("templateName") ||
- !scopeSelected;
-
return (
<Sheet {...props}>
- <SheetContent className="sm:max-w-[600px] h-[100vh] flex flex-col p-0">
+ <SheetContent className="sm:max-w-[500px] h-[100vh] flex flex-col p-0">
{/* 고정된 헤더 */}
<SheetHeader className="p-6 pb-4 border-b">
<SheetTitle>템플릿 업데이트</SheetTitle>
<SheetDescription>
- 템플릿 정보를 수정하고 변경사항을 저장하세요
- <span className="text-red-500 mt-1 block text-sm">* 표시된 항목은 필수 입력사항입니다.</span>
+ 템플릿 파일을 업데이트하고 설정을 변경하세요
</SheetDescription>
</SheetHeader>
@@ -249,51 +152,49 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-6 py-4"
>
- {/* 기본 정보 */}
+ {/* 템플릿 정보 표시 */}
<Card>
<CardHeader>
- <CardTitle className="text-lg">기본 정보</CardTitle>
+ <CardTitle className="text-lg">템플릿 정보</CardTitle>
<CardDescription>
- 현재 리비전: <Badge variant="outline">v{template.revision}</Badge>
- <br />
- 현재 적용 범위: {scopeHelpers.getScopeDisplayText(template)}
+ 현재 템플릿의 기본 정보입니다
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 gap-4">
- <FormField
- control={form.control}
- name="templateName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>
- 템플릿 이름 <span className="text-red-500">*</span>
- </FormLabel>
- <Select onValueChange={field.onChange} defaultValue={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="템플릿 이름을 선택하세요" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectGroup>
- {TEMPLATE_NAME_OPTIONS.map((option) => (
- <SelectItem key={option} value={option}>
- {option}
- </SelectItem>
- ))}
- </SelectGroup>
- </SelectContent>
- </Select>
- <FormDescription>
- 미리 정의된 템플릿 중에서 선택
- </FormDescription>
- <FormMessage />
- </FormItem>
- )}
- />
+ <div className="space-y-2">
+ <label className="text-sm font-medium">템플릿 이름</label>
+ <div className="px-3 py-2 border rounded-md bg-gray-50">
+ {template.templateName}
+ </div>
+ </div>
+
+ <div className="space-y-2">
+ <label className="text-sm font-medium">현재 리비전</label>
+ <div className="px-3 py-2 border rounded-md bg-gray-50">
+ <Badge variant="outline">v{template.revision}</Badge>
+ </div>
+ </div>
+
+ <div className="space-y-2">
+ <label className="text-sm font-medium">현재 파일</label>
+ <div className="px-3 py-2 border rounded-md bg-gray-50">
+ {template.fileName}
+ </div>
+ </div>
</div>
+ </CardContent>
+ </Card>
+ {/* 설정 */}
+ <Card>
+ <CardHeader>
+ <CardTitle className="text-lg">설정</CardTitle>
+ <CardDescription>
+ 템플릿 관련 설정을 변경할 수 있습니다
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
<FormField
control={form.control}
name="legalReviewRequired"
@@ -317,69 +218,12 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
</CardContent>
</Card>
- {/* 적용 범위 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">
- 적용 범위 <span className="text-red-500">*</span>
- </CardTitle>
- <CardDescription>
- 이 템플릿이 적용될 사업부를 선택하세요. ({selectedScopesCount}개 선택됨)
- </CardDescription>
- </CardHeader>
- <CardContent className="space-y-4">
- <div className="flex items-center space-x-2">
- <Checkbox
- id="select-all"
- checked={selectedScopesCount === BUSINESS_UNITS.length}
- onCheckedChange={handleSelectAllScopes}
- />
- <label htmlFor="select-all" className="text-sm font-medium">
- 전체 선택
- </label>
- </div>
-
- <Separator />
-
- <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
- {BUSINESS_UNITS.map((unit) => (
- <FormField
- key={unit.key}
- control={form.control}
- name={unit.key as keyof UpdateTemplateSchema}
- render={({ field }) => (
- <FormItem className="flex flex-row items-start space-x-3 space-y-0">
- <FormControl>
- <Checkbox
- checked={field.value as boolean}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- <div className="space-y-1 leading-none">
- <FormLabel className="text-sm font-normal">
- {unit.label}
- </FormLabel>
- </div>
- </FormItem>
- )}
- />
- ))}
- </div>
-
- {form.formState.errors.shipBuildingApplicable && (
- <p className="text-sm text-destructive">
- {form.formState.errors.shipBuildingApplicable.message}
- </p>
- )}
- </CardContent>
- </Card>
-
{/* 파일 업데이트 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">파일 업데이트</CardTitle>
<CardDescription>
- 현재 파일: {template.fileName}
+ 새로운 템플릿 파일을 업로드하세요
</CardDescription>
</CardHeader>
<CardContent>
@@ -388,7 +232,7 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
name="file"
render={() => (
<FormItem>
- <FormLabel>템플릿 파일 (선택사항)</FormLabel>
+ <FormLabel>새 템플릿 파일 (선택사항)</FormLabel>
<FormControl>
<Dropzone
onDrop={handleFileChange}
@@ -402,7 +246,7 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
<DropzoneTitle>
{selectedFile
? selectedFile.name
- : "새 워드 파일을 드래그하세요 (선택사항)"}
+ : "새 워드 파일을 드래그하세요"}
</DropzoneTitle>
<DropzoneDescription>
{selectedFile
@@ -413,6 +257,9 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
</DropzoneZone>
</Dropzone>
</FormControl>
+ <FormDescription>
+ 파일을 업로드하지 않으면 기존 파일이 유지됩니다
+ </FormDescription>
<FormMessage />
</FormItem>
)}
@@ -433,12 +280,12 @@ export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTem
<Button
type="button"
onClick={form.handleSubmit(onSubmit)}
- disabled={isDisabled}
+ disabled={isUpdatePending}
>
{isUpdatePending && (
<Loader className="mr-2 size-4 animate-spin" aria-hidden="true" />
)}
- 저장
+ 업데이트
</Button>
</SheetFooter>
</SheetContent>