summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/form-data/form-data-table.tsx11
-rw-r--r--components/ship-vendor-document/add-attachment-dialog.tsx6
-rw-r--r--components/ship-vendor-document/new-revision-dialog.tsx5
-rw-r--r--components/signup/tech-vendor-join-form.tsx45
-rw-r--r--components/tech-vendors/tech-vendor-container.tsx103
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