summaryrefslogtreecommitdiff
path: root/lib/b-rfq/initial/update-initial-rfq-sheet.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/b-rfq/initial/update-initial-rfq-sheet.tsx')
-rw-r--r--lib/b-rfq/initial/update-initial-rfq-sheet.tsx496
1 files changed, 0 insertions, 496 deletions
diff --git a/lib/b-rfq/initial/update-initial-rfq-sheet.tsx b/lib/b-rfq/initial/update-initial-rfq-sheet.tsx
deleted file mode 100644
index a19b5172..00000000
--- a/lib/b-rfq/initial/update-initial-rfq-sheet.tsx
+++ /dev/null
@@ -1,496 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { zodResolver } from "@hookform/resolvers/zod"
-import { CalendarIcon, Loader, ChevronsUpDown, Check } from "lucide-react"
-import { useForm } from "react-hook-form"
-import { toast } from "sonner"
-import { format } from "date-fns"
-import { ko } from "date-fns/locale"
-
-import { cn } from "@/lib/utils"
-import { Button } from "@/components/ui/button"
-import { Calendar } from "@/components/ui/calendar"
-import { Checkbox } from "@/components/ui/checkbox"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
- } from "@/components/ui/command"
-import { Input } from "@/components/ui/input"
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover"
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
-import {
- Sheet,
- SheetClose,
- SheetContent,
- SheetDescription,
- SheetFooter,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
-import { UpdateInitialRfqSchema, updateInitialRfqSchema } from "../validations"
-import { getIncotermsForSelection, modifyInitialRfq } from "../service"
-import { InitialRfqDetailView } from "@/db/schema"
-
-interface UpdateInitialRfqSheetProps
- extends React.ComponentPropsWithRef<typeof Sheet> {
- initialRfq: InitialRfqDetailView | null
-}
-
-interface Incoterm {
- id: number
- code: string
- description: string
-}
-
-export function UpdateInitialRfqSheet({ initialRfq, ...props }: UpdateInitialRfqSheetProps) {
- const [isUpdatePending, startUpdateTransition] = React.useTransition()
- const [incoterms, setIncoterms] = React.useState<Incoterm[]>([])
- const [incotermsLoading, setIncotermsLoading] = React.useState(false)
- const [incotermsSearchOpen, setIncotermsSearchOpen] = React.useState(false)
-
- const loadIncoterms = React.useCallback(async () => {
- setIncotermsLoading(true)
- try {
- const incotermsList = await getIncotermsForSelection()
- setIncoterms(incotermsList)
- } catch (error) {
- console.error("Failed to load incoterms:", error)
- toast.error("Incoterms 목록을 불러오는데 실패했습니다.")
- } finally {
- setIncotermsLoading(false)
- }
- }, [])
-
- React.useEffect(() => {
- if (incoterms.length === 0) {
- loadIncoterms()
- }
- }, [incoterms.length, loadIncoterms])
-
- const form = useForm<UpdateInitialRfqSchema>({
- resolver: zodResolver(updateInitialRfqSchema),
- defaultValues: {
- initialRfqStatus: initialRfq?.initialRfqStatus ?? "DRAFT",
- dueDate: initialRfq?.dueDate ?? new Date(),
- validDate: initialRfq?.validDate ?? undefined,
- incotermsCode: initialRfq?.incotermsCode ?? "",
- classification: initialRfq?.classification ?? "",
- sparepart: initialRfq?.sparepart ?? "",
- rfqRevision: initialRfq?.rfqRevision ?? 0,
- shortList: initialRfq?.shortList ?? false,
- returnYn: initialRfq?.returnYn ?? false,
- cpRequestYn: initialRfq?.cpRequestYn ?? false,
- prjectGtcYn: initialRfq?.prjectGtcYn ?? false,
- },
- })
-
- // initialRfq가 변경될 때 폼 값을 업데이트
- React.useEffect(() => {
- if (initialRfq) {
- form.reset({
- initialRfqStatus: initialRfq.initialRfqStatus ?? "DRAFT",
- dueDate: initialRfq.dueDate,
- validDate: initialRfq.validDate,
- incotermsCode: initialRfq.incotermsCode ?? "",
- classification: initialRfq.classification ?? "",
- sparepart: initialRfq.sparepart ?? "",
- shortList: initialRfq.shortList ?? false,
- returnYn: initialRfq.returnYn ?? false,
- rfqRevision: initialRfq.rfqRevision ?? 0,
- cpRequestYn: initialRfq.cpRequestYn ?? false,
- prjectGtcYn: initialRfq.prjectGtcYn ?? false,
- })
- }
- }, [initialRfq, form])
-
- function onSubmit(input: UpdateInitialRfqSchema) {
- startUpdateTransition(async () => {
- if (!initialRfq || !initialRfq.initialRfqId) {
- toast.error("유효하지 않은 RFQ입니다.")
- return
- }
-
- const { error } = await modifyInitialRfq({
- id: initialRfq.initialRfqId,
- ...input,
- })
-
- if (error) {
- toast.error(error)
- return
- }
-
- form.reset()
- props.onOpenChange?.(false)
- toast.success("초기 RFQ가 수정되었습니다")
- })
- }
-
- const selectedIncoterm = incoterms.find(incoterm => incoterm.code === form.watch("incotermsCode"))
-
- return (
- <Sheet {...props}>
- <SheetContent className="flex flex-col h-full sm:max-w-md">
- {/* 고정 헤더 */}
- <SheetHeader className="flex-shrink-0 text-left pb-6">
- <SheetTitle>초기 RFQ 수정</SheetTitle>
- <SheetDescription>
- 초기 RFQ 정보를 수정하고 변경사항을 저장하세요
- </SheetDescription>
- </SheetHeader>
-
- {/* 스크롤 가능한 폼 영역 */}
- <div className="flex-1 overflow-y-auto">
- <Form {...form}>
- <form
- onSubmit={form.handleSubmit(onSubmit)}
- className="flex flex-col gap-4 pr-2"
- >
- {/* RFQ 리비전 */}
- <FormField
- control={form.control}
- name="rfqRevision"
- render={({ field }) => (
- <FormItem>
- <FormLabel>RFQ 리비전</FormLabel>
- <FormControl>
- <Input
- type="number"
- min="0"
- placeholder="0"
- {...field}
- onChange={(e) => field.onChange(parseInt(e.target.value) || 0)}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 마감일 */}
- <FormField
- control={form.control}
- name="dueDate"
- render={({ field }) => (
- <FormItem className="flex flex-col">
- <FormLabel>마감일 *</FormLabel>
- <Popover>
- <PopoverTrigger asChild>
- <FormControl>
- <Button
- variant={"outline"}
- className={cn(
- "w-full pl-3 text-left font-normal",
- !field.value && "text-muted-foreground"
- )}
- >
- {field.value ? (
- format(field.value, "PPP", { locale: ko })
- ) : (
- <span>날짜를 선택하세요</span>
- )}
- <CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
- </Button>
- </FormControl>
- </PopoverTrigger>
- <PopoverContent className="w-auto p-0" align="start">
- <Calendar
- mode="single"
- selected={field.value}
- onSelect={field.onChange}
- disabled={(date) =>
- date < new Date("1900-01-01")
- }
- initialFocus
- />
- </PopoverContent>
- </Popover>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 유효일 */}
- <FormField
- control={form.control}
- name="validDate"
- render={({ field }) => (
- <FormItem className="flex flex-col">
- <FormLabel>유효일</FormLabel>
- <Popover>
- <PopoverTrigger asChild>
- <FormControl>
- <Button
- variant={"outline"}
- className={cn(
- "w-full pl-3 text-left font-normal",
- !field.value && "text-muted-foreground"
- )}
- >
- {field.value ? (
- format(field.value, "PPP", { locale: ko })
- ) : (
- <span>날짜를 선택하세요</span>
- )}
- <CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
- </Button>
- </FormControl>
- </PopoverTrigger>
- <PopoverContent className="w-auto p-0" align="start">
- <Calendar
- mode="single"
- selected={field.value}
- onSelect={field.onChange}
- disabled={(date) =>
- date < new Date("1900-01-01")
- }
- initialFocus
- />
- </PopoverContent>
- </Popover>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* Incoterms 코드 */}
- <FormField
- control={form.control}
- name="incotermsCode"
- render={({ field }) => (
- <FormItem className="flex flex-col">
- <FormLabel>Incoterms</FormLabel>
- <Popover open={incotermsSearchOpen} onOpenChange={setIncotermsSearchOpen}>
- <PopoverTrigger asChild>
- <FormControl>
- <Button
- variant="outline"
- role="combobox"
- aria-expanded={incotermsSearchOpen}
- className="justify-between"
- disabled={incotermsLoading}
- >
- {selectedIncoterm ? (
- <div className="flex items-center gap-2">
- <span className="truncate">
- {selectedIncoterm.code} - {selectedIncoterm.description}
- </span>
- </div>
- ) : (
- <span className="text-muted-foreground">
- {incotermsLoading ? "로딩 중..." : "인코텀즈를 선택하세요"}
- </span>
- )}
- <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
- </Button>
- </FormControl>
- </PopoverTrigger>
- <PopoverContent className="w-full p-0" align="start">
- <Command>
- <CommandInput
- placeholder="코드 또는 내용으로 검색..."
- className="h-9"
- />
- <CommandList>
- <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
- <CommandGroup>
- {incoterms.map((incoterm) => (
- <CommandItem
- key={incoterm.id}
- value={`${incoterm.code} ${incoterm.description}`}
- onSelect={() => {
- field.onChange(incoterm.code)
- setIncotermsSearchOpen(false)
- }}
- >
- <div className="flex items-center gap-2 w-full">
- <div className="flex-1 min-w-0">
- <div className="font-medium truncate">
- {incoterm.code} - {incoterm.description}
- </div>
- </div>
- <Check
- className={cn(
- "ml-auto h-4 w-4",
- incoterm.code === field.value ? "opacity-100" : "opacity-0"
- )}
- />
- </div>
- </CommandItem>
- ))}
- </CommandGroup>
- </CommandList>
- </Command>
- </PopoverContent>
- </Popover>
- <FormMessage />
- </FormItem>
- )}
- />
- {/* 체크박스 옵션들 */}
- <div className="space-y-3">
- <FormField
- control={form.control}
- name="shortList"
- render={({ field }) => (
- <FormItem className="flex flex-row items-start space-x-3 space-y-0">
- <FormControl>
- <Checkbox
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- <div className="space-y-1 leading-none ml-2">
- <FormLabel>Short List</FormLabel>
- </div>
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="returnYn"
- render={({ field }) => (
- <FormItem className="flex flex-row items-start space-x-3 space-y-0">
- <FormControl>
- <Checkbox
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- <div className="space-y-1 leading-none ml-2">
- <FormLabel>회신 여부</FormLabel>
- </div>
- </FormItem>
- )}
- />
-
- {/* 선급 */}
- <FormField
- control={form.control}
- name="classification"
- render={({ field }) => (
- <FormItem>
- <FormLabel>선급</FormLabel>
- <FormControl>
- <Input
- placeholder="선급"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 예비부품 */}
- <FormField
- control={form.control}
- name="sparepart"
- render={({ field }) => (
- <FormItem>
- <FormLabel>예비부품</FormLabel>
- <FormControl>
- <Input
- placeholder="O1, O2"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
-
-
-
- <FormField
- control={form.control}
- name="cpRequestYn"
- render={({ field }) => (
- <FormItem className="flex flex-row items-start space-x-3 space-y-0">
- <FormControl>
- <Checkbox
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- <div className="space-y-1 leading-none ml-2">
- <FormLabel>CP 요청</FormLabel>
- </div>
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="prjectGtcYn"
- render={({ field }) => (
- <FormItem className="flex flex-row items-start space-x-3 space-y-0">
- <FormControl>
- <Checkbox
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- <div className="space-y-1 leading-none ml-2">
- <FormLabel>프로젝트 GTC</FormLabel>
- </div>
- </FormItem>
- )}
- />
- </div>
-
- {/* 하단 여백 */}
- <div className="h-4" />
- </form>
- </Form>
- </div>
-
- {/* 고정 푸터 */}
- <SheetFooter className="flex-shrink-0 gap-2 pt-6 sm:space-x-0">
- <SheetClose asChild>
- <Button type="button" variant="outline">
- 취소
- </Button>
- </SheetClose>
- <Button
- onClick={form.handleSubmit(onSubmit)}
- disabled={isUpdatePending}
- >
- {isUpdatePending && (
- <Loader
- className="mr-2 size-4 animate-spin"
- aria-hidden="true"
- />
- )}
- 저장
- </Button>
- </SheetFooter>
- </SheetContent>
- </Sheet>
- )
-} \ No newline at end of file