import { createSearchParamsCache, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, } from "nuqs/server" import * as z from "zod" import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" import { vendorInvestigationsView } from "@/db/schema" export const searchParamsInvestigationCache = createSearchParamsCache({ // Common flags flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), // Paging page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), // Sorting - adjusting for vendorInvestigationsView sort: getSortingStateParser().withDefault([ { id: "createdAt", desc: true }, ]), // Advanced filter filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), // Global search search: parseAsString.withDefault(""), // ----------------------------------------------------------------- // Fields specific to vendor investigations // ----------------------------------------------------------------- // investigationStatus: PLANNED, IN_PROGRESS, COMPLETED, CANCELED, RESULT_SENT investigationStatus: parseAsStringEnum(["PLANNED", "IN_PROGRESS", "COMPLETED", "CANCELED", "RESULT_SENT"]), // In case you also want to filter by vendorName, vendorCode, etc. vendorName: parseAsString.withDefault(""), vendorCode: parseAsString.withDefault(""), // If you need to filter by vendor status (e.g., PQ_SUBMITTED, ACTIVE, etc.), // you can include it here too. Example: // vendorStatus: parseAsStringEnum([ // "PENDING_REVIEW", // "IN_REVIEW", // "REJECTED", // "IN_PQ", // "PQ_SUBMITTED", // "PQ_FAILED", // "PQ_APPROVED", // "APPROVED", // "ACTIVE", // "INACTIVE", // "BLACKLISTED", // ]).optional(), }) // Finally, export the type you can use in your server action: export type GetVendorsInvestigationSchema = Awaited> // 실사 진행 관리용 스키마 export const updateVendorInvestigationProgressSchema = z .object({ investigationId: z.number({ required_error: "Investigation ID is required", }), investigationAddress: z .string({ required_error: "실사 주소는 필수입니다." }) .min(1, "실사 주소는 필수입니다."), investigationMethod: z.enum([ "PURCHASE_SELF_EVAL", "DOCUMENT_EVAL", "PRODUCT_INSPECTION", "SITE_VISIT_EVAL", ], { required_error: "실사 방법은 필수입니다." }), // 날짜 필드들 forecastedAt: z.union([ z.date(), z.string().transform((str) => (str ? new Date(str) : undefined)), ]), confirmedAt: z.union([ z.date(), z.string().transform((str) => (str ? new Date(str) : undefined)), ], { required_error: "실사 계획 확정일은 필수입니다." }), }) .superRefine((data, ctx) => { // 방문/제품 평가일 경우 forecastedAt은 필수 아님, 그 외에는 필수 const method = data.investigationMethod const requiresForecast = method !== "PRODUCT_INSPECTION" && method !== "SITE_VISIT_EVAL" if (requiresForecast && !data.forecastedAt) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["forecastedAt"], message: "실사 수행 예정일은 필수입니다.", }) } }) export type UpdateVendorInvestigationProgressSchema = z.infer // 실사 결과 입력용 스키마 export const updateVendorInvestigationResultSchema = z.object({ investigationId: z.number({ required_error: "Investigation ID is required", }), // 날짜 필드들 completedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]), evaluationScore: z.number() .int("평가 점수는 정수여야 합니다.") .min(0, "평가 점수는 0점 이상이어야 합니다.") .max(100, "평가 점수는 100점 이하여야 합니다."), evaluationResult: z.enum(["APPROVED", "SUPPLEMENT", "SUPPLEMENT_REINSPECT", "SUPPLEMENT_DOCUMENT", "REJECTED", "RESULT_SENT"]), investigationNotes: z.string().max(1000, "QM 의견은 1000자 이내로 입력해주세요.").optional(), attachments: z.any({ required_error: "첨부파일은 필수입니다." }), }) export type UpdateVendorInvestigationResultSchema = z.infer // 기존 호환성을 위한 통합 스키마 export const updateVendorInvestigationSchema = z.object({ investigationId: z.number({ required_error: "Investigation ID is required", }), investigationStatus: z.enum(["PLANNED", "IN_PROGRESS", "COMPLETED", "CANCELED", "SUPPLEMENT_REQUIRED", "RESULT_SENT"], { required_error: "실사 상태를 선택해주세요.", }), investigationAddress: z.string().optional(), investigationMethod: z.enum(["PURCHASE_SELF_EVAL", "DOCUMENT_EVAL", "PRODUCT_INSPECTION", "SITE_VISIT_EVAL"]).optional(), // 날짜 필드들 forecastedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]).optional(), requestedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]).optional(), confirmedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]).optional(), completedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]).optional(), evaluationScore: z.number() .int("평가 점수는 정수여야 합니다.") .min(0, "평가 점수는 0점 이상이어야 합니다.") .max(100, "평가 점수는 100점 이하여야 합니다.") .optional(), evaluationResult: z.enum(["APPROVED", "SUPPLEMENT", "SUPPLEMENT_REINSPECT", "SUPPLEMENT_DOCUMENT", "REJECTED", "RESULT_SENT"]).optional(), investigationNotes: z.string().max(1000, "QM 의견은 1000자 이내로 입력해주세요.").optional(), attachments: z.any().optional(), // File 업로드를 위한 필드 }) export type UpdateVendorInvestigationSchema = z.infer