diff options
Diffstat (limited to 'components/bidding/create')
| -rw-r--r-- | components/bidding/create/bidding-create-dialog.tsx | 451 |
1 files changed, 303 insertions, 148 deletions
diff --git a/components/bidding/create/bidding-create-dialog.tsx b/components/bidding/create/bidding-create-dialog.tsx index f298721b..bb7880f5 100644 --- a/components/bidding/create/bidding-create-dialog.tsx +++ b/components/bidding/create/bidding-create-dialog.tsx @@ -2,7 +2,7 @@ import * as React from 'react'
import { UseFormReturn } from 'react-hook-form'
-import { ChevronRight, Upload, FileText, Eye, User, Building, Calendar, DollarSign, Plus } from 'lucide-react'
+import { ChevronRight, Upload, FileText, Eye, User, Building, Calendar, DollarSign, Plus, Check, ChevronsUpDown } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
@@ -26,6 +26,20 @@ import { Textarea } from '@/components/ui/textarea' import { Switch } from '@/components/ui/switch'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from '@/components/ui/command'
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from '@/components/ui/popover'
+import { cn } from '@/lib/utils'
import type { CreateBiddingSchema } from '@/lib/bidding/validation'
import { contractTypeLabels, biddingTypeLabels, awardCountLabels, biddingNoticeTypeLabels } from '@/db/schema'
@@ -589,37 +603,62 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp control={form.control}
name="biddingConditions.paymentTerms"
render={({ field }) => (
- <FormItem>
+ <FormItem className="flex flex-col">
<FormLabel>SHI 지급조건 <span className="text-red-500">*</span></FormLabel>
- <FormControl>
- <Select
- value={biddingConditions.paymentTerms}
- onValueChange={(value) => {
- setBiddingConditions(prev => ({
- ...prev,
- paymentTerms: value
- }))
- field.onChange(value)
- }}
- >
- <SelectTrigger>
- <SelectValue placeholder="지급조건 선택" />
- </SelectTrigger>
- <SelectContent>
- {paymentTermsOptions.length > 0 ? (
- paymentTermsOptions.map((option) => (
- <SelectItem key={option.code} value={option.code}>
- {option.code} {option.description && `(${option.description})`}
- </SelectItem>
- ))
- ) : (
- <SelectItem value="loading" disabled>
- 데이터를 불러오는 중...
- </SelectItem>
- )}
- </SelectContent>
- </Select>
- </FormControl>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "justify-between",
+ !biddingConditions.paymentTerms && "text-muted-foreground"
+ )}
+ >
+ {biddingConditions.paymentTerms
+ ? paymentTermsOptions.find((option) => option.code === biddingConditions.paymentTerms)
+ ? `${paymentTermsOptions.find((option) => option.code === biddingConditions.paymentTerms)?.code} ${paymentTermsOptions.find((option) => option.code === biddingConditions.paymentTerms)?.description ? `(${paymentTermsOptions.find((option) => option.code === biddingConditions.paymentTerms)?.description})` : ''}`
+ : "지급조건 선택"
+ : "지급조건 선택"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-[400px] p-0">
+ <Command>
+ <CommandInput placeholder="지급조건 검색..." />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {paymentTermsOptions.map((option) => (
+ <CommandItem
+ key={option.code}
+ value={`${option.code} ${option.description || ''}`}
+ onSelect={() => {
+ setBiddingConditions(prev => ({
+ ...prev,
+ paymentTerms: option.code
+ }))
+ field.onChange(option.code)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ option.code === biddingConditions.paymentTerms
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ {option.code} {option.description && `(${option.description})`}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
<FormMessage />
</FormItem>
)}
@@ -632,37 +671,62 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp control={form.control}
name="biddingConditions.incoterms"
render={({ field }) => (
- <FormItem>
+ <FormItem className="flex flex-col">
<FormLabel>SHI 인도조건 <span className="text-red-500">*</span></FormLabel>
- <Select
- value={biddingConditions.incoterms}
- onValueChange={(value) => {
- setBiddingConditions(prev => ({
- ...prev,
- incoterms: value
- }))
- field.onChange(value)
- }}
- >
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="인코텀즈 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {incotermsOptions.length > 0 ? (
- incotermsOptions.map((option) => (
- <SelectItem key={option.code} value={option.code}>
- {option.code} {option.description && `(${option.description})`}
- </SelectItem>
- ))
- ) : (
- <SelectItem value="loading" disabled>
- 데이터를 불러오는 중...
- </SelectItem>
- )}
- </SelectContent>
- </Select>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "justify-between",
+ !biddingConditions.incoterms && "text-muted-foreground"
+ )}
+ >
+ {biddingConditions.incoterms
+ ? incotermsOptions.find((option) => option.code === biddingConditions.incoterms)
+ ? `${incotermsOptions.find((option) => option.code === biddingConditions.incoterms)?.code} ${incotermsOptions.find((option) => option.code === biddingConditions.incoterms)?.description ? `(${incotermsOptions.find((option) => option.code === biddingConditions.incoterms)?.description})` : ''}`
+ : "인코텀즈 선택"
+ : "인코텀즈 선택"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-[400px] p-0">
+ <Command>
+ <CommandInput placeholder="인코텀즈 검색..." />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {incotermsOptions.map((option) => (
+ <CommandItem
+ key={option.code}
+ value={`${option.code} ${option.description || ''}`}
+ onSelect={() => {
+ setBiddingConditions(prev => ({
+ ...prev,
+ incoterms: option.code
+ }))
+ field.onChange(option.code)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ option.code === biddingConditions.incoterms
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ {option.code} {option.description && `(${option.description})`}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
<FormMessage />
</FormItem>
)}
@@ -699,31 +763,60 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp control={form.control}
name="biddingConditions.taxConditions"
render={({ field }) => (
- <FormItem>
+ <FormItem className="flex flex-col">
<FormLabel>SHI 매입부가가치세 <span className="text-red-500">*</span></FormLabel>
- <FormControl>
- <Select
- value={biddingConditions.taxConditions}
- onValueChange={(value) => {
- setBiddingConditions(prev => ({
- ...prev,
- taxConditions: value
- }))
- field.onChange(value)
- }}
- >
- <SelectTrigger>
- <SelectValue placeholder="세금조건 선택" />
- </SelectTrigger>
- <SelectContent>
- {TAX_CONDITIONS.map((condition) => (
- <SelectItem key={condition.code} value={condition.code}>
- {condition.name}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- </FormControl>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "justify-between",
+ !biddingConditions.taxConditions && "text-muted-foreground"
+ )}
+ >
+ {biddingConditions.taxConditions
+ ? TAX_CONDITIONS.find((condition) => condition.code === biddingConditions.taxConditions)?.name
+ : "세금조건 선택"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-[400px] p-0">
+ <Command>
+ <CommandInput placeholder="세금조건 검색..." />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {TAX_CONDITIONS.map((condition) => (
+ <CommandItem
+ key={condition.code}
+ value={`${condition.code} ${condition.name}`}
+ onSelect={() => {
+ setBiddingConditions(prev => ({
+ ...prev,
+ taxConditions: condition.code
+ }))
+ field.onChange(condition.code)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ condition.code === biddingConditions.taxConditions
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ {condition.name}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
<FormMessage />
</FormItem>
)}
@@ -733,37 +826,62 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp control={form.control}
name="biddingConditions.shippingPort"
render={({ field }) => (
- <FormItem>
+ <FormItem className="flex flex-col">
<FormLabel>SHI 선적지</FormLabel>
- <Select
- value={biddingConditions.shippingPort}
- onValueChange={(value) => {
- setBiddingConditions(prev => ({
- ...prev,
- shippingPort: value
- }))
- field.onChange(value)
- }}
- >
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="선적지 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {shippingPlaces.length > 0 ? (
- shippingPlaces.map((place) => (
- <SelectItem key={place.code} value={place.code}>
- {place.code} {place.description && `(${place.description})`}
- </SelectItem>
- ))
- ) : (
- <SelectItem value="loading" disabled>
- 데이터를 불러오는 중...
- </SelectItem>
- )}
- </SelectContent>
- </Select>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "justify-between",
+ !biddingConditions.shippingPort && "text-muted-foreground"
+ )}
+ >
+ {biddingConditions.shippingPort
+ ? shippingPlaces.find((place) => place.code === biddingConditions.shippingPort)
+ ? `${shippingPlaces.find((place) => place.code === biddingConditions.shippingPort)?.code} ${shippingPlaces.find((place) => place.code === biddingConditions.shippingPort)?.description ? `(${shippingPlaces.find((place) => place.code === biddingConditions.shippingPort)?.description})` : ''}`
+ : "선적지 선택"
+ : "선적지 선택"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-[400px] p-0">
+ <Command>
+ <CommandInput placeholder="선적지 검색..." />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {shippingPlaces.map((place) => (
+ <CommandItem
+ key={place.code}
+ value={`${place.code} ${place.description || ''}`}
+ onSelect={() => {
+ setBiddingConditions(prev => ({
+ ...prev,
+ shippingPort: place.code
+ }))
+ field.onChange(place.code)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ place.code === biddingConditions.shippingPort
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ {place.code} {place.description && `(${place.description})`}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
<FormMessage />
</FormItem>
)}
@@ -776,43 +894,68 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp control={form.control}
name="biddingConditions.destinationPort"
render={({ field }) => (
- <FormItem>
+ <FormItem className="flex flex-col">
<FormLabel>SHI 하역지</FormLabel>
- <Select
- value={biddingConditions.destinationPort}
- onValueChange={(value) => {
- setBiddingConditions(prev => ({
- ...prev,
- destinationPort: value
- }))
- field.onChange(value)
- }}
- >
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="하역지 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {destinationPlaces.length > 0 ? (
- destinationPlaces.map((place) => (
- <SelectItem key={place.code} value={place.code}>
- {place.code} {place.description && `(${place.description})`}
- </SelectItem>
- ))
- ) : (
- <SelectItem value="loading" disabled>
- 데이터를 불러오는 중...
- </SelectItem>
- )}
- </SelectContent>
- </Select>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "justify-between",
+ !biddingConditions.destinationPort && "text-muted-foreground"
+ )}
+ >
+ {biddingConditions.destinationPort
+ ? destinationPlaces.find((place) => place.code === biddingConditions.destinationPort)
+ ? `${destinationPlaces.find((place) => place.code === biddingConditions.destinationPort)?.code} ${destinationPlaces.find((place) => place.code === biddingConditions.destinationPort)?.description ? `(${destinationPlaces.find((place) => place.code === biddingConditions.destinationPort)?.description})` : ''}`
+ : "하역지 선택"
+ : "하역지 선택"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-[400px] p-0">
+ <Command>
+ <CommandInput placeholder="하역지 검색..." />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {destinationPlaces.map((place) => (
+ <CommandItem
+ key={place.code}
+ value={`${place.code} ${place.description || ''}`}
+ onSelect={() => {
+ setBiddingConditions(prev => ({
+ ...prev,
+ destinationPort: place.code
+ }))
+ field.onChange(place.code)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ place.code === biddingConditions.destinationPort
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ {place.code} {place.description && `(${place.description})`}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
<FormMessage />
</FormItem>
)}
/>
- {/* <FormField
+ {/* <FormField
control={form.control}
name="biddingConditions.contractDeliveryDate"
render={({ field }) => (
@@ -829,6 +972,8 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp }))
field.onChange(e.target.value)
}}
+ min="1900-01-01"
+ max="2100-12-31"
/>
</FormControl>
<FormMessage />
@@ -849,7 +994,12 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp 계약기간 시작
</FormLabel>
<FormControl>
- <Input type="date" {...field} />
+ <Input
+ type="date"
+ {...field}
+ min="1900-01-01"
+ max="2100-12-31"
+ />
</FormControl>
<FormMessage />
</FormItem>
@@ -866,7 +1016,12 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp 계약기간 종료
</FormLabel>
<FormControl>
- <Input type="date" {...field} />
+ <Input
+ type="date"
+ {...field}
+ min="1900-01-01"
+ max="2100-12-31"
+ />
</FormControl>
<FormMessage />
</FormItem>
|
