diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-25 07:51:15 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-25 07:51:15 +0000 |
| commit | 2650b7c0bb0ea12b68a58c0439f72d61df04b2f1 (patch) | |
| tree | 17156183fd74b69d78178065388ac61a18ac07b4 /components | |
| parent | d32acea05915bd6c1ed4b95e56c41ef9204347bc (diff) | |
(대표님) 정기평가 대상, 미들웨어 수정, nextauth 토큰 처리 개선, GTC 등
(최겸) 기술영업
Diffstat (limited to 'components')
| -rw-r--r-- | components/form-data/form-data-table.tsx | 11 | ||||
| -rw-r--r-- | components/ship-vendor-document/add-attachment-dialog.tsx | 6 | ||||
| -rw-r--r-- | components/ship-vendor-document/new-revision-dialog.tsx | 5 | ||||
| -rw-r--r-- | components/signup/tech-vendor-join-form.tsx | 45 | ||||
| -rw-r--r-- | components/tech-vendors/tech-vendor-container.tsx | 103 |
5 files changed, 52 insertions, 118 deletions
diff --git a/components/form-data/form-data-table.tsx b/components/form-data/form-data-table.tsx index 90c8490b..9936e870 100644 --- a/components/form-data/form-data-table.tsx +++ b/components/form-data/form-data-table.tsx @@ -231,6 +231,12 @@ export default function DynamicTable({ const [tempCount, setTempCount] = React.useState(0); const [addTagDialogOpen, setAddTagDialogOpen] = React.useState(false); + // TAG_NO가 있는 첫 번째 행의 shi 값 확인 + const isAddTagDisabled = React.useMemo(() => { + const firstRowWithTagNo = tableData.find(row => row.TAG_NO); + return firstRowWithTagNo?.shi === true; + }, [tableData]); + // Clean up polling on unmount React.useEffect(() => { return () => { @@ -743,7 +749,10 @@ export default function DynamicTable({ Get Tags </DropdownMenuItem> )} - <DropdownMenuItem onClick={() => setAddTagDialogOpen(true)} disabled={isAnyOperationPending}> + <DropdownMenuItem + onClick={() => setAddTagDialogOpen(true)} + disabled={isAnyOperationPending || isAddTagDisabled} + > <Plus className="mr-2 h-4 w-4" /> Add Tags </DropdownMenuItem> diff --git a/components/ship-vendor-document/add-attachment-dialog.tsx b/components/ship-vendor-document/add-attachment-dialog.tsx index a285b4de..8357c0b6 100644 --- a/components/ship-vendor-document/add-attachment-dialog.tsx +++ b/components/ship-vendor-document/add-attachment-dialog.tsx @@ -38,7 +38,7 @@ import { useSession } from "next-auth/react" * -----------------------------------------------------------------------------------------------*/ // 파일 검증 스키마 -const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB +const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 50MB const ACCEPTED_FILE_TYPES = [ 'application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', @@ -56,7 +56,7 @@ const attachmentUploadSchema = z.object({ attachments: z .array(z.instanceof(File)) .min(1, "Please upload at least 1 file") - .max(10, "Maximum 10 files can be uploaded") + // .max(10, "Maximum 10 files can be uploaded") .refine( (files) => files.every((file) => file.size <= MAX_FILE_SIZE), "File size must be 50MB or less" @@ -131,7 +131,7 @@ function FileUploadArea({ Drag files to add here or click to select </p> <p className="text-xs text-gray-500"> - Supports PDF, Word, Excel, Image, Text, ZIP files (max 50MB) + Supports PDF, Word, Excel, Image, Text, ZIP files (max 1GB) </p> <input ref={fileInputRef} diff --git a/components/ship-vendor-document/new-revision-dialog.tsx b/components/ship-vendor-document/new-revision-dialog.tsx index 7adc0b3a..8ca6d533 100644 --- a/components/ship-vendor-document/new-revision-dialog.tsx +++ b/components/ship-vendor-document/new-revision-dialog.tsx @@ -50,7 +50,7 @@ import { useSession } from "next-auth/react" * -----------------------------------------------------------------------------------------------*/ // 파일 검증 스키마 -const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB +const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 50MB const ACCEPTED_FILE_TYPES = [ 'application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', @@ -73,7 +73,6 @@ const createRevisionUploadSchema = (drawingKind: string) => { attachments: z .array(z.instanceof(File)) .min(1, "Please upload at least 1 file") - .max(10, "Maximum 10 files can be uploaded") .refine( (files) => files.every((file) => file.size <= MAX_FILE_SIZE), "File size must be 50MB or less" @@ -219,7 +218,7 @@ function FileUploadArea({ Drag files here or click to select </p> <p className="text-xs text-gray-500"> - Supports PDF, Word, Excel, Image, Text, ZIP files (max 50MB) + Supports PDF, Word, Excel, Image, Text, ZIP files (max 1GB) </p> <input ref={fileInputRef} diff --git a/components/signup/tech-vendor-join-form.tsx b/components/signup/tech-vendor-join-form.tsx index 4d17398d..d554079f 100644 --- a/components/signup/tech-vendor-join-form.tsx +++ b/components/signup/tech-vendor-join-form.tsx @@ -171,6 +171,8 @@ export function TechVendorJoinForm() { {
contactName: "",
contactPosition: "",
+ contactTitle: "",
+ contactCountry: "",
contactEmail: "",
contactPhone: "",
},
@@ -269,9 +271,9 @@ export function TechVendorJoinForm() { }
const isFormValid = form.formState.isValid
- // console.log("Form errors:", form.formState.errors);
- // console.log("Form values:", form.getValues());
- // console.log("Form valid:", form.formState.isValid);
+ console.log("Form errors:", form.formState.errors);
+ console.log("Form values:", form.getValues());
+ console.log("Form valid:", form.formState.isValid);
// Dropzone handlers
const handleDropAccepted = (acceptedFiles: File[]) => {
@@ -297,11 +299,11 @@ export function TechVendorJoinForm() { form.setValue("files", updated, { shouldValidate: true })
}
- const handleItemsSelected = (itemCodes: string[]) => {
- setSelectedItemCodes(itemCodes)
- // 선택된 아이템 코드들을 콤마로 구분하여 items 필드에 설정
- const itemsString = itemCodes.join(", ")
- form.setValue("items", itemsString)
+ type SelectedItem = { type: "SHIP" | "TOP" | "HULL", id: number, code: string, name: string };
+
+ const handleItemsSelected = (items: SelectedItem[]) => {
+ setSelectedItemCodes(items.map(item => item.code));
+ form.setValue("items", JSON.stringify(items));
}
// Submit
@@ -805,6 +807,33 @@ export function TechVendorJoinForm() { </FormItem>
)}
/>
+ <FormField
+ control={form.control}
+ name={`contacts.${index}.contactTitle`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>직위</FormLabel>
+ <FormControl>
+ <Input placeholder="직위를 입력하세요" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ <FormField
+ control={form.control}
+ name={`contacts.${index}.contactCountry`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>국가</FormLabel>
+ <FormControl>
+ <Input placeholder="국가를 입력하세요" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
<FormField
control={form.control}
diff --git a/components/tech-vendors/tech-vendor-container.tsx b/components/tech-vendors/tech-vendor-container.tsx deleted file mode 100644 index 8c89d3e4..00000000 --- a/components/tech-vendors/tech-vendor-container.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"
-
-import * as React from "react"
-import { useRouter, usePathname, useSearchParams } from "next/navigation"
-import { ChevronDown } from "lucide-react"
-
-import { Button } from "@/components/ui/button"
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
-import { InformationButton } from "@/components/information/information-button"
-interface VendorType {
- id: string
- name: string
- value: string
-}
-
-interface TechVendorContainerProps {
- vendorTypes: VendorType[]
- children: React.ReactNode
-}
-
-export function TechVendorContainer({
- vendorTypes,
- children,
-}: TechVendorContainerProps) {
- const router = useRouter()
- const pathname = usePathname()
- const searchParamsObj = useSearchParams()
-
- // useSearchParams를 메모이제이션하여 안정적인 참조 생성
- const searchParams = React.useMemo(
- () => searchParamsObj || new URLSearchParams(),
- [searchParamsObj]
- )
-
- // URL에서 현재 선택된 벤더 타입 가져오기
- const vendorType = searchParams.get("vendorType") || "all"
-
- // // 선택한 벤더 타입에 해당하는 이름 찾기
- // const selectedVendor = vendorTypes.find((vendor) => vendor.id === vendorType)?.name || "전체"
-
- // // 벤더 타입 변경 핸들러
- // const handleVendorTypeChange = React.useCallback((value: string) => {
- // const params = new URLSearchParams(searchParams.toString())
- // if (value === "all") {
- // params.delete("vendorType")
- // } else {
- // params.set("vendorType", value)
- // }
-
- // router.push(`${pathname}?${params.toString()}`)
- // }, [router, pathname, searchParams])
-
- return (
- <>
- {/* 상단 영역: 제목 왼쪽 / 벤더 타입 선택기 오른쪽 */}
- <div className="flex items-center justify-between">
- {/* 왼쪽: 타이틀 & 설명 */}
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">기술영업 협력업체 리스트</h2>
- <InformationButton pagePath="evcp/tech-vendors" />
- </div>
- {/* <p className="text-muted-foreground">
- 기술영업 벤더에 대한 요약 정보를 확인하고 관리할 수 있습니다.
- </p> */}
- </div>
-
- {/* 오른쪽: 벤더 타입 드롭다운
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button variant="outline" className="min-w-[150px]">
- {selectedVendor}
- <ChevronDown className="ml-2 h-4 w-4" />
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align="end" className="w-[200px]">
- {vendorTypes.map((vendor) => (
- <DropdownMenuItem
- key={vendor.id}
- onClick={() => handleVendorTypeChange(vendor.id)}
- className={vendor.id === vendorType ? "bg-muted" : ""}
- >
- {vendor.name}
- </DropdownMenuItem>
- ))}
- </DropdownMenuContent>
- </DropdownMenu> */}
- </div>
-
- {/* 컨텐츠 영역 */}
- <section className="overflow-hidden">
- <div>
- {children}
- </div>
- </section>
- </>
- )
-}
\ No newline at end of file |
