diff options
Diffstat (limited to 'lib/general-contracts_old/main')
5 files changed, 0 insertions, 1726 deletions
diff --git a/lib/general-contracts_old/main/create-general-contract-dialog.tsx b/lib/general-contracts_old/main/create-general-contract-dialog.tsx deleted file mode 100644 index 2c3fc8bc..00000000 --- a/lib/general-contracts_old/main/create-general-contract-dialog.tsx +++ /dev/null @@ -1,413 +0,0 @@ -"use client"
-
-import * as React from "react"
-import { useRouter } from "next/navigation"
-import { Plus } from "lucide-react"
-import { toast } from "sonner"
-import { Button } from "@/components/ui/button"
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog"
-import { Input } from "@/components/ui/input"
-import { Label } from "@/components/ui/label"
-import { Textarea } from "@/components/ui/textarea"
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
-import { Calendar } from "@/components/ui/calendar"
-import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
-import { CalendarIcon } from "lucide-react"
-import { format } from "date-fns"
-import { ko } from "date-fns/locale"
-import { cn } from "@/lib/utils"
-import { createContract, getVendors, getProjects } from "@/lib/general-contracts/service"
-import {
- GENERAL_CONTRACT_CATEGORIES,
- GENERAL_CONTRACT_TYPES,
- GENERAL_EXECUTION_METHODS
-} from "@/lib/general-contracts/types"
-import { useSession } from "next-auth/react"
-
-interface CreateContractForm {
- contractNumber: string
- name: string
- category: string
- type: string
- executionMethod: string
- vendorId: number | null
- projectId: number | null
- startDate: Date | undefined
- endDate: Date | undefined
- validityEndDate: Date | undefined
- notes: string
-}
-
-export function CreateGeneralContractDialog() {
- const router = useRouter()
- const { data: session } = useSession()
- const [open, setOpen] = React.useState(false)
- const [isLoading, setIsLoading] = React.useState(false)
- const [vendors, setVendors] = React.useState<Array<{ id: number; vendorName: string; vendorCode: string | null }>>([])
- const [projects, setProjects] = React.useState<Array<{ id: number; code: string; name: string; type: string }>>([])
-
- const [form, setForm] = React.useState<CreateContractForm>({
- contractNumber: '',
- name: '',
- category: '',
- type: '',
- executionMethod: '',
- vendorId: null,
- projectId: null,
- startDate: undefined,
- endDate: undefined,
- validityEndDate: undefined,
- notes: '',
- })
-
- // 업체 목록 조회
- React.useEffect(() => {
- const fetchVendors = async () => {
- try {
- const vendorList = await getVendors()
- setVendors(vendorList)
- } catch (error) {
- console.error('Error fetching vendors:', error)
- }
- }
- fetchVendors()
- }, [])
-
- // 프로젝트 목록 조회
- React.useEffect(() => {
- const fetchProjects = async () => {
- try {
- const projectList = await getProjects()
- console.log(projectList)
- setProjects(projectList)
- } catch (error) {
- console.error('Error fetching projects:', error)
- }
- }
- fetchProjects()
- }, [])
-
- const handleSubmit = async () => {
- // 필수 필드 검증
- if (!form.name || !form.category || !form.type || !form.executionMethod ||
- !form.vendorId || !form.startDate || !form.endDate) {
- toast.error("필수 항목을 모두 입력해주세요.")
- return
- }
-
- if (!form.validityEndDate) {
- setForm(prev => ({ ...prev, validityEndDate: form.endDate }))
- }
-
- try {
- setIsLoading(true)
-
- const contractData = {
- contractNumber: '',
- name: form.name,
- category: form.category,
- type: form.type,
- executionMethod: form.executionMethod,
- projectId: form.projectId,
- contractSourceType: 'manual',
- vendorId: form.vendorId!,
- startDate: form.startDate!.toISOString().split('T')[0],
- endDate: form.endDate!.toISOString().split('T')[0],
- validityEndDate: (form.validityEndDate || form.endDate!).toISOString().split('T')[0],
- status: 'Draft',
- registeredById: session?.user?.id || 1,
- lastUpdatedById: session?.user?.id || 1,
- notes: form.notes,
- }
-
- await createContract(contractData)
-
- toast.success("새 계약이 생성되었습니다.")
- setOpen(false)
- resetForm()
-
- // 상세 페이지로 이동
- router.refresh()
- } catch (error) {
- console.error('Error creating contract:', error)
- toast.error("계약 생성 중 오류가 발생했습니다.")
- } finally {
- setIsLoading(false)
- }
- }
-
- const resetForm = () => {
- setForm({
- contractNumber: '',
- name: '',
- category: '',
- type: '',
- executionMethod: '',
- vendorId: null,
- projectId: null,
- startDate: undefined,
- endDate: undefined,
- validityEndDate: undefined,
- notes: '',
- })
- }
-
- return (
- <Dialog open={open} onOpenChange={(newOpen) => {
- setOpen(newOpen)
- if (!newOpen) resetForm()
- }}>
- <DialogTrigger asChild>
- <Button size="sm">
- <Plus className="mr-2 h-4 w-4" />
- 신규등록
- </Button>
- </DialogTrigger>
- <DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
- <DialogHeader>
- <DialogTitle>새 계약 등록</DialogTitle>
- <DialogDescription>
- 새로운 계약의 기본 정보를 입력하세요.
- </DialogDescription>
- </DialogHeader>
-
- <div className="grid gap-4 py-4">
- <div className="grid grid-cols-1 gap-4">
- <div className="grid gap-2">
- <Label htmlFor="name">계약명 *</Label>
- <Input
- id="name"
- value={form.name}
- onChange={(e) => setForm(prev => ({ ...prev, name: e.target.value }))}
- placeholder="계약명을 입력하세요"
- />
- </div>
- </div>
-
- <div className="grid grid-cols-3 gap-4">
- <div className="grid gap-2">
- <Label htmlFor="category">계약구분 *</Label>
- <Select value={form.category} onValueChange={(value) => setForm(prev => ({ ...prev, category: value }))}>
- <SelectTrigger>
- <SelectValue placeholder="계약구분 선택" />
- </SelectTrigger>
- <SelectContent>
- {GENERAL_CONTRACT_CATEGORIES.map((category) => {
- const categoryLabels = {
- 'unit_price': '단가계약',
- 'general': '일반계약',
- 'sale': '매각계약'
- }
- return (
- <SelectItem key={category} value={category}>
- {category} - {categoryLabels[category as keyof typeof categoryLabels]}
- </SelectItem>
- )
- })}
- </SelectContent>
- </Select>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="type">계약종류 *</Label>
- <Select value={form.type} onValueChange={(value) => setForm(prev => ({ ...prev, type: value }))}>
- <SelectTrigger>
- <SelectValue placeholder="계약종류 선택" />
- </SelectTrigger>
- <SelectContent>
- {GENERAL_CONTRACT_TYPES.map((type) => {
- const typeLabels = {
- 'UP': '자재단가계약',
- 'LE': '임대차계약',
- 'IL': '개별운송계약',
- 'AL': '연간운송계약',
- 'OS': '외주용역계약',
- 'OW': '도급계약',
- 'IS': '검사계약',
- 'LO': 'LOI',
- 'FA': 'FA',
- 'SC': '납품합의계약',
- 'OF': '클레임상계계약',
- 'AW': '사전작업합의',
- 'AD': '사전납품합의',
- 'AM': '설계계약',
- 'SC_SELL': '폐기물매각계약'
- }
- return (
- <SelectItem key={type} value={type}>
- {type} - {typeLabels[type as keyof typeof typeLabels]}
- </SelectItem>
- )
- })}
- </SelectContent>
- </Select>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="executionMethod">체결방식 *</Label>
- <Select value={form.executionMethod} onValueChange={(value) => setForm(prev => ({ ...prev, executionMethod: value }))}>
- <SelectTrigger>
- <SelectValue placeholder="체결방식 선택" />
- </SelectTrigger>
- <SelectContent>
- {GENERAL_EXECUTION_METHODS.map((method) => (
- <SelectItem key={method} value={method}>
- {method}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- </div>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="project">프로젝트</Label>
- <Select value={form.projectId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, projectId: parseInt(value) }))}>
- <SelectTrigger>
- <SelectValue placeholder="프로젝트 선택 (선택사항)" />
- </SelectTrigger>
- <SelectContent>
- {projects.map((project) => (
- <SelectItem key={project.id} value={project.id.toString()}>
- {project.name} ({project.code})
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="vendor">협력업체 *</Label>
- <Select value={form.vendorId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, vendorId: parseInt(value) }))}>
- <SelectTrigger>
- <SelectValue placeholder="협력업체 선택" />
- </SelectTrigger>
- <SelectContent>
- {vendors.map((vendor) => (
- <SelectItem key={vendor.id} value={vendor.id.toString()}>
- {vendor.vendorName} ({vendor.vendorCode})
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- </div>
-
- <div className="grid grid-cols-3 gap-4">
- <div className="grid gap-2">
- <Label>계약시작일 *</Label>
- <Popover>
- <PopoverTrigger asChild>
- <Button
- variant="outline"
- className={cn(
- "justify-start text-left font-normal",
- !form.startDate && "text-muted-foreground"
- )}
- >
- <CalendarIcon className="mr-2 h-4 w-4" />
- {form.startDate ? format(form.startDate, "yyyy-MM-dd", { locale: ko }) : "날짜 선택"}
- </Button>
- </PopoverTrigger>
- <PopoverContent className="w-auto p-0">
- <Calendar
- mode="single"
- selected={form.startDate}
- onSelect={(date) => setForm(prev => ({ ...prev, startDate: date }))}
- initialFocus
- />
- </PopoverContent>
- </Popover>
- </div>
-
- <div className="grid gap-2">
- <Label>계약종료일 *</Label>
- <Popover>
- <PopoverTrigger asChild>
- <Button
- variant="outline"
- className={cn(
- "justify-start text-left font-normal",
- !form.endDate && "text-muted-foreground"
- )}
- >
- <CalendarIcon className="mr-2 h-4 w-4" />
- {form.endDate ? format(form.endDate, "yyyy-MM-dd", { locale: ko }) : "날짜 선택"}
- </Button>
- </PopoverTrigger>
- <PopoverContent className="w-auto p-0">
- <Calendar
- mode="single"
- selected={form.endDate}
- onSelect={(date) => setForm(prev => ({ ...prev, endDate: date }))}
- initialFocus
- />
- </PopoverContent>
- </Popover>
- </div>
-
- <div className="grid gap-2">
- <Label>유효기간종료일</Label>
- <Popover>
- <PopoverTrigger asChild>
- <Button
- variant="outline"
- className={cn(
- "justify-start text-left font-normal",
- !form.validityEndDate && "text-muted-foreground"
- )}
- >
- <CalendarIcon className="mr-2 h-4 w-4" />
- {form.validityEndDate ? format(form.validityEndDate, "yyyy-MM-dd", { locale: ko }) : "날짜 선택"}
- </Button>
- </PopoverTrigger>
- <PopoverContent className="w-auto p-0">
- <Calendar
- mode="single"
- selected={form.validityEndDate}
- onSelect={(date) => setForm(prev => ({ ...prev, validityEndDate: date }))}
- initialFocus
- />
- </PopoverContent>
- </Popover>
- </div>
- </div>
- <div className="grid gap-2">
- <Label htmlFor="notes">비고</Label>
- <Textarea
- id="notes"
- value={form.notes}
- onChange={(e) => setForm(prev => ({ ...prev, notes: e.target.value }))}
- placeholder="비고사항을 입력하세요"
- rows={3}
- />
- </div>
- </div>
-
- <DialogFooter>
- <Button
- type="button"
- variant="outline"
- onClick={() => setOpen(false)}
- >
- 취소
- </Button>
- <Button
- type="button"
- onClick={handleSubmit}
- disabled={isLoading}
- >
- {isLoading ? '생성 중...' : '생성'}
- </Button>
- </DialogFooter>
- </DialogContent>
- </Dialog>
- )
-}
diff --git a/lib/general-contracts_old/main/general-contract-update-sheet.tsx b/lib/general-contracts_old/main/general-contract-update-sheet.tsx deleted file mode 100644 index 54f4ae4e..00000000 --- a/lib/general-contracts_old/main/general-contract-update-sheet.tsx +++ /dev/null @@ -1,401 +0,0 @@ -"use client" - -import * as React from "react" -import { useForm } from "react-hook-form" -import { zodResolver } from "@hookform/resolvers/zod" -import { z } from "zod" -import { toast } from "sonner" -import { Button } from "@/components/ui/button" -import { - Sheet, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetTitle, -} from "@/components/ui/sheet" -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select" -import { Input } from "@/components/ui/input" -import { Textarea } from "@/components/ui/textarea" -import { - GENERAL_CONTRACT_CATEGORIES, - GENERAL_CONTRACT_TYPES, - GENERAL_EXECUTION_METHODS, -} from "@/lib/general-contracts/types" -import { updateContract } from "../service" -import { GeneralContractListItem } from "./general-contracts-table-columns" -import { useSession } from "next-auth/react" -const updateContractSchema = z.object({ - category: z.string().min(1, "계약구분을 선택해주세요"), - type: z.string().min(1, "계약종류를 선택해주세요"), - executionMethod: z.string().min(1, "체결방식을 선택해주세요"), - name: z.string().min(1, "계약명을 입력해주세요"), - startDate: z.string().min(1, "계약시작일을 선택해주세요"), - endDate: z.string().min(1, "계약종료일을 선택해주세요"), - validityEndDate: z.string().min(1, "유효기간종료일을 선택해주세요"), - contractScope: z.string().min(1, "계약확정범위를 선택해주세요"), - notes: z.string().optional(), - linkedRfqOrItb: z.string().optional(), - linkedPoNumber: z.string().optional(), - linkedBidNumber: z.string().optional(), -}) - -type UpdateContractFormData = z.infer<typeof updateContractSchema> - -interface GeneralContractUpdateSheetProps { - contract: GeneralContractListItem | null - open: boolean - onOpenChange: (open: boolean) => void - onSuccess?: () => void -} - -export function GeneralContractUpdateSheet({ - contract, - open, - onOpenChange, - onSuccess, -}: GeneralContractUpdateSheetProps) { - const [isSubmitting, setIsSubmitting] = React.useState(false) - const session = useSession() - const userId = session.data?.user?.id ? Number(session.data.user.id) : null - const form = useForm<UpdateContractFormData>({ - resolver: zodResolver(updateContractSchema), - defaultValues: { - category: "", - type: "", - executionMethod: "", - name: "", - startDate: "", - endDate: "", - validityEndDate: "", - contractScope: "", - notes: "", - linkedRfqOrItb: "", - linkedPoNumber: "", - linkedBidNumber: "", - }, - }) - - // 계약확정범위에 따른 품목정보 필드 비활성화 여부 - const watchedContractScope = form.watch("contractScope") - const isItemsDisabled = watchedContractScope === '단가' || watchedContractScope === '물량(실적)' - - // 계약 데이터가 변경될 때 폼 초기화 - React.useEffect(() => { - if (contract) { - console.log("Loading contract data:", contract) - const formData = { - category: contract.category || "", - type: contract.type || "", - executionMethod: contract.executionMethod || "", - name: contract.name || "", - startDate: contract.startDate || "", - endDate: contract.endDate || "", - validityEndDate: contract.validityEndDate || "", - contractScope: contract.contractScope || "", - notes: contract.notes || "", - linkedRfqOrItb: contract.linkedRfqOrItb || "", - linkedPoNumber: contract.linkedPoNumber || "", - linkedBidNumber: contract.linkedBidNumber || "", - } - console.log("Form data to reset:", formData) - form.reset(formData) - } - }, [contract, form]) - - const onSubmit = async (data: UpdateContractFormData) => { - if (!contract) return - - try { - setIsSubmitting(true) - - await updateContract(contract.id, { - category: data.category, - type: data.type, - executionMethod: data.executionMethod, - name: data.name, - startDate: data.startDate, - endDate: data.endDate, - validityEndDate: data.validityEndDate, - contractScope: data.contractScope, - notes: data.notes, - linkedRfqOrItb: data.linkedRfqOrItb, - linkedPoNumber: data.linkedPoNumber, - linkedBidNumber: data.linkedBidNumber, - vendorId: contract.vendorId, - lastUpdatedById: userId, - }) - - toast.success("계약 정보가 성공적으로 수정되었습니다.") - onOpenChange(false) - onSuccess?.() - } catch (error) { - console.error("Error updating contract:", error) - toast.error("계약 정보 수정 중 오류가 발생했습니다.") - } finally { - setIsSubmitting(false) - } - } - - return ( - <Sheet open={open} onOpenChange={onOpenChange}> - <SheetContent className="w-[800px] sm:max-w-[800px] flex flex-col" style={{width: 800, maxWidth: 800, height: '100vh'}}> - <SheetHeader className="flex-shrink-0"> - <SheetTitle>계약 정보 수정</SheetTitle> - <SheetDescription> - 계약의 기본 정보를 수정합니다. 변경사항은 즉시 저장됩니다. - </SheetDescription> - </SheetHeader> - - <div className="flex-1 overflow-y-auto min-h-0"> - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 h-full"> - <div className="grid gap-4 py-4"> - {/* 계약구분 */} - <FormField - control={form.control} - name="category" - render={({ field }) => ( - <FormItem> - <FormLabel>계약구분 *</FormLabel> - <Select onValueChange={field.onChange} value={field.value}> - <FormControl> - <SelectTrigger> - <SelectValue placeholder="계약구분을 선택하세요" /> - </SelectTrigger> - </FormControl> - <SelectContent> - {GENERAL_CONTRACT_CATEGORIES.map((category) => { - const categoryLabels = { - 'unit_price': '단가계약', - 'general': '일반계약', - 'sale': '매각계약' - } - return ( - <SelectItem key={category} value={category}> - {category} - {categoryLabels[category as keyof typeof categoryLabels]} - </SelectItem> - )})} - </SelectContent> - </Select> - <FormMessage /> - </FormItem> - )} - /> - - {/* 계약종류 */} - <FormField - control={form.control} - name="type" - render={({ field }) => ( - <FormItem> - <FormLabel>계약종류 *</FormLabel> - <Select onValueChange={field.onChange} value={field.value}> - <FormControl> - <SelectTrigger> - <SelectValue placeholder="계약종류를 선택하세요" /> - </SelectTrigger> - </FormControl> - <SelectContent> - {GENERAL_CONTRACT_TYPES.map((type) => { - const typeLabels = { - 'UP': '자재단가계약', - 'LE': '임대차계약', - 'IL': '개별운송계약', - 'AL': '연간운송계약', - 'OS': '외주용역계약', - 'OW': '도급계약', - 'IS': '검사계약', - 'LO': 'LOI', - 'FA': 'FA', - 'SC': '납품합의계약', - 'OF': '클레임상계계약', - 'AW': '사전작업합의', - 'AD': '사전납품합의', - 'AM': '설계계약', - 'SC_SELL': '폐기물매각계약' - } - return ( - <SelectItem key={type} value={type}> - {type} - {typeLabels[type as keyof typeof typeLabels]} - </SelectItem> - )})} - </SelectContent> - </Select> - <FormMessage /> - </FormItem> - )} - /> - - {/* 체결방식 */} - <FormField - control={form.control} - name="executionMethod" - render={({ field }) => ( - <FormItem> - <FormLabel>체결방식 *</FormLabel> - <Select onValueChange={field.onChange} value={field.value}> - <FormControl> - <SelectTrigger> - <SelectValue placeholder="체결방식을 선택하세요" /> - </SelectTrigger> - </FormControl> - <SelectContent> - {GENERAL_EXECUTION_METHODS.map((method) => { - const methodLabels = { - '전자계약': '전자계약', - '오프라인계약': '오프라인계약' - } - return ( - <SelectItem key={method} value={method}> - {method} - {methodLabels[method as keyof typeof methodLabels]} - </SelectItem> - )})} - </SelectContent> - </Select> - <FormMessage /> - </FormItem> - )} - /> - - {/* 계약명 */} - <FormField - control={form.control} - name="name" - render={({ field }) => ( - <FormItem> - <FormLabel>계약명 *</FormLabel> - <FormControl> - <Input placeholder="계약명을 입력하세요" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 계약시작일 */} - <FormField - control={form.control} - name="startDate" - render={({ field }) => ( - <FormItem> - <FormLabel>계약시작일 *</FormLabel> - <FormControl> - <Input type="date" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 계약종료일 */} - <FormField - control={form.control} - name="endDate" - render={({ field }) => ( - <FormItem> - <FormLabel>계약종료일 *</FormLabel> - <FormControl> - <Input type="date" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 유효기간종료일 */} - <FormField - control={form.control} - name="validityEndDate" - render={({ field }) => ( - <FormItem> - <FormLabel>유효기간종료일 *</FormLabel> - <FormControl> - <Input type="date" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 계약확정범위 */} - <FormField - control={form.control} - name="contractScope" - render={({ field }) => ( - <FormItem> - <FormLabel>계약확정범위 *</FormLabel> - <Select onValueChange={field.onChange} value={field.value}> - <FormControl> - <SelectTrigger> - <SelectValue placeholder="계약확정범위를 선택하세요" /> - </SelectTrigger> - </FormControl> - <SelectContent> - <SelectItem value="단가">단가</SelectItem> - <SelectItem value="금액">금액</SelectItem> - <SelectItem value="물량(실적)">물량(실적)</SelectItem> - </SelectContent> - </Select> - <FormMessage /> - <p className="text-sm text-muted-foreground"> - 해당 계약으로 확정되는 범위를 선택하세요. - </p> - </FormItem> - )} - /> - - {/* 비고 */} - <FormField - control={form.control} - name="notes" - render={({ field }) => ( - <FormItem> - <FormLabel>비고</FormLabel> - <FormControl> - <Textarea - placeholder="비고를 입력하세요" - className="min-h-[100px]" - {...field} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - - <SheetFooter className="flex-shrink-0 mt-6"> - <Button - type="button" - variant="outline" - onClick={() => onOpenChange(false)} - disabled={isSubmitting} - > - 취소 - </Button> - <Button type="submit" disabled={isSubmitting}> - {isSubmitting ? "수정 중..." : "수정"} - </Button> - </SheetFooter> - </form> - </Form> - </div> - </SheetContent> - </Sheet> - ) -} diff --git a/lib/general-contracts_old/main/general-contracts-table-columns.tsx b/lib/general-contracts_old/main/general-contracts-table-columns.tsx deleted file mode 100644 index a08d8b81..00000000 --- a/lib/general-contracts_old/main/general-contracts-table-columns.tsx +++ /dev/null @@ -1,571 +0,0 @@ -"use client"
-
-import * as React from "react"
-import { type ColumnDef } from "@tanstack/react-table"
-import { Checkbox } from "@/components/ui/checkbox"
-import { Badge } from "@/components/ui/badge"
-import { Button } from "@/components/ui/button"
-import {
- Eye, Edit, MoreHorizontal
-} from "lucide-react"
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
-import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
-import { DataTableRowAction } from "@/types/table"
-import { formatDate } from "@/lib/utils"
-
-// 일반계약 리스트 아이템 타입 정의
-export interface GeneralContractListItem {
- id: number
- contractNumber: string
- revision: number
- status: string
- category: string
- type: string
- executionMethod: string
- name: string
- contractSourceType?: string
- startDate: string
- endDate: string
- validityEndDate?: string
- contractScope?: string
- specificationType?: string
- specificationManualText?: string
- contractAmount?: number | string | null
- totalAmount?: number | string | null
- currency?: string
- registeredAt: string
- signedAt?: string
- linkedPoNumber?: string
- linkedRfqOrItb?: string
- linkedBidNumber?: string
- lastUpdatedAt: string
- notes?: string
- vendorId?: number
- vendorName?: string
- vendorCode?: string
- projectId?: number
- projectName?: string
- projectCode?: string
- managerName?: string
- lastUpdatedByName?: string
-}
-
-interface GetColumnsProps {
- setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<GeneralContractListItem> | null>>
-}
-
-// 상태별 배지 색상
-const getStatusBadgeVariant = (status: string) => {
- switch (status) {
- case 'Draft':
- return 'outline'
- case 'Request to Review':
- case 'Confirm to Review':
- return 'secondary'
- case 'Contract Accept Request':
- return 'default'
- case 'Complete the Contract':
- return 'default'
- case 'Reject to Accept Contract':
- case 'Contract Delete':
- return 'destructive'
- default:
- return 'outline'
- }
-}
-
-// 상태 텍스트 변환
-const getStatusText = (status: string) => {
- switch (status) {
- case 'Draft':
- return '임시저장'
- case 'Request to Review':
- return '조건검토요청'
- case 'Confirm to Review':
- return '조건검토완료'
- case 'Contract Accept Request':
- return '계약승인요청'
- case 'Complete the Contract':
- return '계약체결'
- case 'Reject to Accept Contract':
- return '계약승인거절'
- case 'Contract Delete':
- return '계약폐기'
- case 'PCR Request':
- return 'PCR요청'
- case 'VO Request':
- return 'VO요청'
- case 'PCR Accept':
- return 'PCR승인'
- case 'PCR Reject':
- return 'PCR거절'
- default:
- return status
- }
-}
-
-// 계약구분 텍스트 변환
-const getCategoryText = (category: string) => {
- switch (category) {
- case 'unit_price':
- return '단가계약'
- case 'general':
- return '일반계약'
- case 'sale':
- return '매각계약'
- default:
- return category
- }
-}
-
-// 계약종류 텍스트 변환
-const getTypeText = (type: string) => {
- switch (type) {
- case 'UP':
- return '자재단가계약'
- case 'LE':
- return '임대차계약'
- case 'IL':
- return '개별운송계약'
- case 'AL':
- return '연간운송계약'
- case 'OS':
- return '외주용역계약'
- case 'OW':
- return '도급계약'
- case 'IS':
- return '검사계약'
- case 'LO':
- return 'LOI'
- case 'FA':
- return 'FA'
- case 'SC':
- return '납품합의계약'
- case 'OF':
- return '클레임상계계약'
- case 'AW':
- return '사전작업합의'
- case 'AD':
- return '사전납품합의'
- case 'AM':
- return '설계계약'
- case 'SC_SELL':
- return '폐기물매각계약'
- default:
- return type
- }
-}
-
-// 체결방식 텍스트 변환
-const getExecutionMethodText = (method: string) => {
- switch (method) {
- case '전자계약':
- return '전자계약'
- case '오프라인계약':
- return '오프라인계약'
- default:
- return method
- }
-}
-
-// 업체선정방법 텍스트 변환
-const getcontractSourceTypeText = (method?: string) => {
- if (!method) return '-'
- switch (method) {
- case 'estimate':
- return '견적'
- case 'bid':
- return '입찰'
- case 'manual':
- return '자체생성'
- default:
- return method
- }
-}
-
-// 금액 포맷팅
-const formatCurrency = (amount: string | number | null | undefined, currency = 'KRW') => {
- if (!amount && amount !== 0) return '-'
-
- const numAmount = typeof amount === 'string' ? parseFloat(amount) : amount
- if (isNaN(numAmount)) return '-'
-
- // 통화 코드가 null이거나 유효하지 않은 경우 기본값 사용
- const safeCurrency = currency && typeof currency === 'string' ? currency : 'USD'
-
- return new Intl.NumberFormat('ko-KR', {
- style: 'currency',
- currency: safeCurrency,
- minimumFractionDigits: 0,
- maximumFractionDigits: 0,
- }).format(numAmount)
-}
-
-export function getGeneralContractsColumns({ setRowAction }: GetColumnsProps): ColumnDef<GeneralContractListItem>[] {
- return [
- // ═══════════════════════════════════════════════════════════════
- // 선택 및 기본 정보
- // ═══════════════════════════════════════════════════════════════
- {
- id: "select",
- header: ({ table }) => (
- <Checkbox
- checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate")}
- onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}
- aria-label="select all"
- className="translate-y-0.5"
- />
- ),
- cell: ({ row }) => (
- <Checkbox
- checked={row.getIsSelected()}
- onCheckedChange={(v) => row.toggleSelected(!!v)}
- aria-label="select row"
- className="translate-y-0.5"
- />
- ),
- size: 40,
- enableSorting: false,
- enableHiding: false,
- },
-
- // ░░░ 계약번호 ░░░
- {
- accessorKey: "contractNumber",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약번호 (Rev.)" />,
- cell: ({ row }) => (
- <div className="font-mono text-sm">
- {row.original.contractNumber}
- {row.original.revision > 0 && (
- <span className="ml-1 text-xs text-muted-foreground">
- Rev.{row.original.revision}
- </span>
- )}
- </div>
- ),
- size: 150,
- meta: { excelHeader: "계약번호 (Rev.)" },
- },
-
- // ░░░ 계약상태 ░░░
- {
- accessorKey: "status",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약상태" />,
- cell: ({ row }) => (
- <Badge variant={getStatusBadgeVariant(row.original.status)}>
- {getStatusText(row.original.status)}
- </Badge>
- ),
- size: 120,
- meta: { excelHeader: "계약상태" },
- },
-
- // ░░░ 계약명 ░░░
- {
- accessorKey: "name",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약명" />,
- cell: ({ row }) => (
- <div className="truncate max-w-[200px]" title={row.original.name}>
- <Button
- variant="link"
- className="p-0 h-auto text-left justify-start"
- onClick={() => setRowAction({ row, type: "view" })}
- >
- {row.original.name}
- </Button>
- </div>
- ),
- size: 200,
- meta: { excelHeader: "계약명" },
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 계약 정보
- // ═══════════════════════════════════════════════════════════════
- {
- header: "계약 정보",
- columns: [
- {
- accessorKey: "category",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약구분" />,
- cell: ({ row }) => (
- <Badge variant="outline">
- {getCategoryText(row.original.category)}
- </Badge>
- ),
- size: 100,
- meta: { excelHeader: "계약구분" },
- },
-
- {
- accessorKey: "type",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약종류" />,
- cell: ({ row }) => (
- <Badge variant="secondary">
- {getTypeText(row.original.type)}
- </Badge>
- ),
- size: 120,
- meta: { excelHeader: "계약종류" },
- },
-
- {
- accessorKey: "executionMethod",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="체결방식" />,
- cell: ({ row }) => (
- <Badge variant="outline">
- {getExecutionMethodText(row.original.executionMethod)}
- </Badge>
- ),
- size: 100,
- meta: { excelHeader: "체결방식" },
- },
-
- {
- accessorKey: "contractSourceType",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="업체선정방법" />,
- cell: ({ row }) => (
- <Badge variant="outline">
- {getcontractSourceTypeText(row.original.contractSourceType)}
- </Badge>
- ),
- size: 200,
- meta: { excelHeader: "업체선정방법" },
- },
- ]
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 협력업체 정보
- // ═══════════════════════════════════════════════════════════════
- {
- header: "협력업체",
- columns: [
- {
- accessorKey: "vendorName",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="협력업체명" />,
- cell: ({ row }) => (
- <div className="flex flex-col">
- <span className="font-medium">{row.original.vendorName || '-'}</span>
- <span className="text-xs text-muted-foreground">
- {row.original.vendorCode ? row.original.vendorCode : "-"}
- </span>
- </div>
- ),
- size: 150,
- meta: { excelHeader: "협력업체명" },
- },
-
- {
- accessorKey: "projectName",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="프로젝트명" />,
- cell: ({ row }) => (
- <div className="flex flex-col">
- <span className="font-medium">{row.original.projectName || '-'}</span>
- <span className="text-xs text-muted-foreground">
- {row.original.projectCode ? row.original.projectCode : "-"}
- </span>
- </div>
- ),
- size: 150,
- meta: { excelHeader: "프로젝트명" },
- },
-
- ]
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 기간 정보
- // ═══════════════════════════════════════════════════════════════
- {
- header: "계약기간",
- columns: [
- {
- id: "contractPeriod",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약기간" />,
- cell: ({ row }) => {
- const startDate = row.original.startDate
- const endDate = row.original.endDate
-
- if (!startDate || !endDate) return <span className="text-muted-foreground">-</span>
-
- const now = new Date()
- const isActive = now >= new Date(startDate) && now <= new Date(endDate)
- const isExpired = now > new Date(endDate)
-
- return (
- <div className="text-xs">
- <div className={`${isActive ? 'text-green-600 font-medium' : isExpired ? 'text-red-600' : 'text-gray-600'}`}>
- {formatDate(startDate, "KR")} ~ {formatDate(endDate, "KR")}
- </div>
- {isActive && (
- <Badge variant="default" className="text-xs mt-1">진행중</Badge>
- )}
- {isExpired && (
- <Badge variant="destructive" className="text-xs mt-1">만료</Badge>
- )}
- </div>
- )
- },
- size: 200,
- meta: { excelHeader: "계약기간" },
- },
- ]
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 금액 정보
- // ═══════════════════════════════════════════════════════════════
- {
- header: "금액 정보",
- columns: [
- {
- accessorKey: "currency",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="통화" />,
- cell: ({ row }) => (
- <span className="font-mono text-sm">{row.original.currency || 'KRW'}</span>
- ),
- size: 60,
- meta: { excelHeader: "통화" },
- },
-
- {
- accessorKey: "contractAmount",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약금액" />,
- cell: ({ row }) => (
- <span className="text-sm font-medium">
- {formatCurrency(row.original.contractAmount, row.original.currency)}
- </span>
- ),
- size: 200,
- meta: { excelHeader: "계약금액" },
- },
- ]
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 담당자 및 관리 정보
- // ═══════════════════════════════════════════════════════════════
- {
- header: "관리 정보",
- columns: [
- {
- accessorKey: "managerName",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약담당자" />,
- cell: ({ row }) => (
- <div className="truncate max-w-[100px]" title={row.original.managerName || ''}>
- {row.original.managerName || '-'}
- </div>
- ),
- size: 100,
- meta: { excelHeader: "계약담당자" },
- },
-
- {
- accessorKey: "registeredAt",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약등록일" />,
- cell: ({ row }) => (
- <span className="text-sm">{formatDate(row.original.registeredAt, "KR")}</span>
- ),
- size: 100,
- meta: { excelHeader: "계약등록일" },
- },
-
- {
- accessorKey: "signedAt",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약체결일" />,
- cell: ({ row }) => (
- <span className="text-sm">
- {row.original.signedAt ? formatDate(row.original.signedAt, "KR") : '-'}
- </span>
- ),
- size: 100,
- meta: { excelHeader: "계약체결일" },
- },
-
- {
- accessorKey: "linkedPoNumber",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="연계 PO번호" />,
- cell: ({ row }) => (
- <span className="font-mono text-sm">{row.original.linkedPoNumber || '-'}</span>
- ),
- size: 140,
- meta: { excelHeader: "연계 PO번호" },
- },
-
- {
- accessorKey: "lastUpdatedAt",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정일" />,
- cell: ({ row }) => (
- <span className="text-sm">{formatDate(row.original.lastUpdatedAt, "KR")}</span>
- ),
- size: 100,
- meta: { excelHeader: "최종수정일" },
- },
-
- {
- accessorKey: "lastUpdatedByName",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정자" />,
- cell: ({ row }) => (
- <span className="text-sm">{row.original.lastUpdatedByName || '-'}</span>
- ),
- size: 100,
- meta: { excelHeader: "최종수정자" },
- },
- ]
- },
-
- // ░░░ 비고 ░░░
- {
- accessorKey: "notes",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="비고" />,
- cell: ({ row }) => (
- <div className="truncate max-w-[150px]" title={row.original.notes || ''}>
- {row.original.notes || '-'}
- </div>
- ),
- size: 150,
- meta: { excelHeader: "비고" },
- },
-
- // ═══════════════════════════════════════════════════════════════
- // 액션
- // ═══════════════════════════════════════════════════════════════
- {
- id: "actions",
- header: "액션",
- cell: ({ row }) => (
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button variant="ghost" className="h-8 w-8 p-0">
- <span className="sr-only">메뉴 열기</span>
- <MoreHorizontal className="h-4 w-4" />
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align="end">
- {row.original.status !== 'Contract Delete' && (
- <>
- <DropdownMenuItem onClick={() => setRowAction({ row, type: "view" })}>
- <Eye className="mr-2 h-4 w-4" />
- 상세보기
- </DropdownMenuItem>
- <DropdownMenuItem onClick={() => setRowAction({ row, type: "update" })}>
- <Edit className="mr-2 h-4 w-4" />
- 수정
- </DropdownMenuItem>
- </>
- )}
- </DropdownMenuContent>
- </DropdownMenu>
- ),
- size: 50,
- enableSorting: false,
- enableHiding: false,
- },
- ]
-}
diff --git a/lib/general-contracts_old/main/general-contracts-table-toolbar-actions.tsx b/lib/general-contracts_old/main/general-contracts-table-toolbar-actions.tsx deleted file mode 100644 index f16b759a..00000000 --- a/lib/general-contracts_old/main/general-contracts-table-toolbar-actions.tsx +++ /dev/null @@ -1,124 +0,0 @@ -"use client"
-
-import * as React from "react"
-import { type Table } from "@tanstack/react-table"
-import {
- Download, FileSpreadsheet,
- Trash2,
-} from "lucide-react"
-import { deleteContract } from "../service"
-import { toast } from "sonner"
-import { exportTableToExcel } from "@/lib/export"
-import { Button } from "@/components/ui/button"
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
-import { GeneralContractListItem } from "./general-contracts-table-columns"
-import { CreateGeneralContractDialog } from "./create-general-contract-dialog"
-
-interface GeneralContractsTableToolbarActionsProps {
- table: Table<GeneralContractListItem>
-}
-
-export function GeneralContractsTableToolbarActions({ table }: GeneralContractsTableToolbarActionsProps) {
- const [isExporting, setIsExporting] = React.useState(false)
-
- // 선택된 계약들
- const selectedContracts = React.useMemo(() => {
- return table
- .getFilteredSelectedRowModel()
- .rows
- .map(row => row.original)
- }, [table.getFilteredSelectedRowModel().rows])
-
- const handleExport = async () => {
- try {
- setIsExporting(true)
- await exportTableToExcel(table, {
- filename: "general-contracts",
- excludeColumns: ["select", "actions"],
- })
- toast.success("계약 목록이 성공적으로 내보내졌습니다.")
- } catch (error) {
- toast.error("내보내기 중 오류가 발생했습니다.")
- } finally {
- setIsExporting(false)
- }
- }
-
-
- const handleDelete = async () => {
- if (selectedContracts.length === 0) {
- toast.error("계약폐기할 계약을 선택해주세요.")
- return
- }
-
- // // 계약폐기 확인
- // const confirmed = window.confirm(
- // `선택한 ${selectedContracts.length}개 계약을 폐기하시겠습니까?\n계약폐기 후에는 복구할 수 없습니다.`
- // )
-
- // if (!confirmed) return
-
- try {
- // 선택된 모든 계약을 폐기 처리
- const deletePromises = selectedContracts.map(contract =>
- deleteContract(contract.id)
- )
-
- await Promise.all(deletePromises)
-
- toast.success(`${selectedContracts.length}개 계약이 폐기되었습니다.`)
-
- // 테이블 새로고침
- } catch (error) {
- console.error('Error deleting contracts:', error)
- toast.error("계약폐기 중 오류가 발생했습니다.")
- }
- }
-
- return (
- <div className="flex items-center gap-2">
- {/* 신규 등록 */}
- <CreateGeneralContractDialog />
-
- {/* 계약폐기 */}
- <Button
- variant="outline"
- size="sm"
- onClick={handleDelete}
- disabled={selectedContracts.length === 0}
- className="text-red-600 hover:text-red-700 hover:bg-red-50"
- >
- <Trash2 className="mr-2 h-4 w-4" />
- 계약폐기
- </Button>
-
- {/* Export */}
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button
- variant="outline"
- size="sm"
- className="gap-2"
- disabled={isExporting}
- >
- <Download className="size-4" aria-hidden="true" />
- <span className="hidden sm:inline">
- {isExporting ? "내보내는 중..." : "Export"}
- </span>
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align="end">
- <DropdownMenuItem onClick={handleExport} disabled={isExporting}>
- <FileSpreadsheet className="mr-2 size-4" />
- <span>계약 목록 내보내기</span>
- </DropdownMenuItem>
- </DropdownMenuContent>
- </DropdownMenu>
- </div>
- )
-}
diff --git a/lib/general-contracts_old/main/general-contracts-table.tsx b/lib/general-contracts_old/main/general-contracts-table.tsx deleted file mode 100644 index e4c96ee3..00000000 --- a/lib/general-contracts_old/main/general-contracts-table.tsx +++ /dev/null @@ -1,217 +0,0 @@ -"use client"
-
-import * as React from "react"
-import { useRouter } from "next/navigation"
-import type {
- DataTableAdvancedFilterField,
- DataTableFilterField,
- DataTableRowAction,
-} from "@/types/table"
-
-import { useDataTable } from "@/hooks/use-data-table"
-import { DataTable } from "@/components/data-table/data-table"
-import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar"
-import { getGeneralContractsColumns, GeneralContractListItem } from "./general-contracts-table-columns"
-import { getGeneralContracts, getGeneralContractStatusCounts } from "@/lib/general-contracts/service"
-import { GeneralContractsTableToolbarActions } from "./general-contracts-table-toolbar-actions"
-import { GeneralContractUpdateSheet } from "./general-contract-update-sheet"
-import {
- GENERAL_EXECUTION_METHODS
-} from "@/lib/general-contracts/types"
-
-// 상태 라벨 매핑
-const contractStatusLabels = {
- 'Draft': '임시저장',
- 'Request to Review': '조건검토요청',
- 'Confirm to Review': '조건검토완료',
- 'Contract Accept Request': '계약승인요청',
- 'Complete the Contract': '계약체결',
- 'Reject to Accept Contract': '계약승인거절',
- 'Contract Delete': '계약폐기',
- 'PCR Request': 'PCR요청',
- 'VO Request': 'VO요청',
- 'PCR Accept': 'PCR승인',
- 'PCR Reject': 'PCR거절'
-}
-
-// 계약구분 라벨 매핑
-const contractCategoryLabels = {
- '단가계약': '단가계약',
- '일반계약': '일반계약',
- '매각계약': '매각계약'
-}
-
-// 계약종류 라벨 매핑
-const contractTypeLabels = {
- 'UP': '자재단가계약',
- 'LE': '임대차계약',
- 'IL': '개별운송계약',
- 'AL': '연간운송계약',
- 'OS': '외주용역계약',
- 'OW': '도급계약',
- 'IS': '검사계약',
- 'LO': 'LOI',
- 'FA': 'FA',
- 'SC': '납품합의계약',
- 'OF': '클레임상계계약',
- 'AW': '사전작업합의',
- 'AD': '사전납품합의',
- 'AM': '설계계약',
- 'SC_SELL': '폐기물매각계약'
-}
-
-interface GeneralContractsTableProps {
- promises: Promise<
- [
- Awaited<ReturnType<typeof getGeneralContracts>>,
- Awaited<ReturnType<typeof getGeneralContractStatusCounts>>
- ]
- >
-}
-
-export function GeneralContractsTable({ promises }: GeneralContractsTableProps) {
- const [{ data, pageCount }, statusCounts] = React.use(promises)
- const [isCompact, setIsCompact] = React.useState<boolean>(false)
- const [rowAction, setRowAction] = React.useState<DataTableRowAction<GeneralContractListItem> | null>(null)
- const [updateSheetOpen, setUpdateSheetOpen] = React.useState(false)
- const [selectedContract, setSelectedContract] = React.useState<GeneralContractListItem | null>(null)
-
- console.log(data, "data")
-
- const router = useRouter()
-
- const columns = React.useMemo(
- () => getGeneralContractsColumns({ setRowAction }),
- [setRowAction]
- )
-
- // rowAction 변경 감지하여 해당 액션 처리
- React.useEffect(() => {
- if (rowAction) {
- setSelectedContract(rowAction.row.original)
-
- switch (rowAction.type) {
- case "view":
- // 상세 페이지로 이동
- router.push(`/evcp/general-contracts/${rowAction.row.original.id}`)
- break
- case "update":
- // 수정 시트 열기
- setSelectedContract(rowAction.row.original)
- setUpdateSheetOpen(true)
- break
- default:
- break
- }
- }
- }, [rowAction, router])
-
- const filterFields: DataTableFilterField<GeneralContractListItem>[] = []
-
- const advancedFilterFields: DataTableAdvancedFilterField<GeneralContractListItem>[] = [
- { id: "name", label: "계약명", type: "text" },
- { id: "contractNumber", label: "계약번호", type: "text" },
- { id: "vendorName", label: "협력업체명", type: "text" },
- { id: "managerName", label: "계약담당자", type: "text" },
- {
- id: "status",
- label: "계약상태",
- type: "multi-select",
- options: Object.entries(contractStatusLabels).map(([value, label]) => ({
- label,
- value,
- count: statusCounts[value] || 0,
- })),
- },
- {
- id: "category",
- label: "계약구분",
- type: "select",
- options: Object.entries(contractCategoryLabels).map(([value, label]) => ({
- label,
- value,
- })),
- },
- {
- id: "type",
- label: "계약종류",
- type: "select",
- options: Object.entries(contractTypeLabels).map(([value, label]) => ({
- label,
- value,
- })),
- },
- {
- id: "executionMethod",
- label: "체결방식",
- type: "select",
- options: GENERAL_EXECUTION_METHODS.map(value => ({
- label: value,
- value: value,
- })),
- },
- {
- id: "contractSourceType",
- label: "업체선정방법",
- type: "select",
- options: [
- { label: "estimate", value: "견적" },
- { label: "bid", value: "입찰" },
- { label: "manual", value: "자체생성" },
- ],
- },
- { id: "registeredAt", label: "계약등록일", type: "date" },
- { id: "signedAt", label: "계약체결일", type: "date" },
- { id: "lastUpdatedAt", label: "최종수정일", type: "date" },
- ]
-
- const { table } = useDataTable({
- data,
- columns,
- pageCount,
- filterFields,
- enablePinning: true,
- enableAdvancedFilter: true,
- initialState: {
- sorting: [{ id: "registeredAt", desc: true }],
- columnPinning: { right: ["actions"] },
- },
- getRowId: (originalRow) => String(originalRow.id),
- shallow: false,
- clearOnDefault: true,
- })
-
- const handleCompactChange = React.useCallback((compact: boolean) => {
- setIsCompact(compact)
- }, [])
-
- return (
- <>
- <DataTable
- table={table}
- compact={isCompact}
- >
- <DataTableAdvancedToolbar
- table={table}
- filterFields={advancedFilterFields}
- shallow={false}
- enableCompactToggle={true}
- compactStorageKey="generalContractsTableCompact"
- onCompactChange={handleCompactChange}
- >
- <GeneralContractsTableToolbarActions table={table} />
- </DataTableAdvancedToolbar>
- </DataTable>
-
- <GeneralContractUpdateSheet
- contract={selectedContract}
- open={updateSheetOpen}
- onOpenChange={setUpdateSheetOpen}
- onSuccess={() => {
- // 테이블 새로고침 또는 상태 업데이트
- window.location.reload()
- }}
- />
- </>
- )
-}
|
