import { createSearchParamsCache, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum,parseAsBoolean } from "nuqs/server" import * as z from "zod" import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" export const searchParamsRFQDashboardCache = createSearchParamsCache({ // 공통 플래그 flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), // 페이징 page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), // 정렬 - rfqDashboardView 기반 sort: getSortingStateParser<{ rfqId: number; rfqCode: string; description: string; status: string; dueDate: Date; projectCode: string; projectName: string; packageNo: string; packageName: string; picName: string; totalAttachments: number; initialVendorCount: number; finalVendorCount: number; initialResponseRate: number; finalResponseRate: number; overallProgress: number; daysToDeadline: number; createdAt: Date; }>().withDefault([ { id: "createdAt", desc: true }, ]), // 고급 필터 filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), // 기본 필터 rfqBasicFilters: getFiltersStateParser().withDefault([]), rfqBasicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), basicFilters: getFiltersStateParser().withDefault([]), basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), // 검색 키워드 search: parseAsString.withDefault(""), // RFQ 특화 필터 rfqCode: parseAsString.withDefault(""), projectName: parseAsString.withDefault(""), projectCode: parseAsString.withDefault(""), picName: parseAsString.withDefault(""), packageNo: parseAsString.withDefault(""), status: parseAsStringEnum([ "DRAFT", "Doc. Received", "PIC Assigned", "Doc. Confirmed", "Init. RFQ Sent", "Init. RFQ Answered", "TBE started", "TBE finished", "Final RFQ Sent", "Quotation Received", "Vendor Selected" ]), dueDateFrom: parseAsString.withDefault(""), dueDateTo: parseAsString.withDefault(""), progressMin: parseAsInteger.withDefault(0), progressMax: parseAsInteger.withDefault(100), }); export type GetRFQDashboardSchema = Awaited> export const createRfqServerSchema = z.object({ projectId: z.number().min(1, "프로젝트를 선택해주세요"), // 필수로 변경 dueDate: z.date(), // Date 객체로 직접 받기 picCode: z.string().min(1, "구매 담당자 코드를 입력해주세요"), picName: z.string().optional(), engPicName: z.string().optional(), packageNo: z.string().min(1, "패키지 번호를 입력해주세요"), packageName: z.string().min(1, "패키지명을 입력해주세요"), remark: z.string().optional(), projectCompany: z.string().optional(), projectFlag: z.string().optional(), projectSite: z.string().optional(), createdBy: z.number(), updatedBy: z.number(), }) export type CreateRfqInput = z.infer export type RfqAttachment = { id: number attachmentType: string serialNo: string rfqId: number fileName: string originalFileName: string filePath: string fileSize: number | null fileType: string | null description: string | null createdBy: number createdAt: Date createdByName?: string responseStats?: { totalVendors: number respondedCount: number pendingCount: number waivedCount: number responseRate: number } } // RFQ Attachments용 검색 파라미터 캐시 export const searchParamsRfqAttachmentsCache = createSearchParamsCache({ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), sort: getSortingStateParser().withDefault([ { id: "createdAt", desc: true }, ]), // 기본 필터 attachmentType: parseAsArrayOf(z.string()).withDefault([]), fileType: parseAsArrayOf(z.string()).withDefault([]), search: parseAsString.withDefault(""), // advanced filter filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), }) // 스키마 타입들 export type GetRfqAttachmentsSchema = Awaited> // 첨부파일 레코드 타입 export const attachmentRecordSchema = z.object({ rfqId: z.number().positive(), attachmentType: z.enum(["구매", "설계"]), // serialNo: z.string().min(1), description: z.string().optional(), fileName: z.string(), originalFileName: z.string(), filePath: z.string(), fileSize: z.number(), fileType: z.string(), }) export type AttachmentRecord = z.infer export const deleteAttachmentsSchema = z.object({ ids: z.array(z.number()).min(1, "삭제할 첨부파일을 선택해주세요."), }) export type DeleteAttachmentsInput = z.infer