import { createSearchParamsCache, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, } from "nuqs/server"; import * as z from "zod"; import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers"; // ============= 메인 검색 파라미터 스키마 ============= export const searchParamsEvaluationTargetsCache = createSearchParamsCache({ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), sort: getSortingStateParser().withDefault([ { id: "createdAt", desc: true }, ]), // 기본 필터들 evaluationYear: parseAsInteger.withDefault(new Date().getFullYear()), division: parseAsString.withDefault(""), status: parseAsString.withDefault(""), domesticForeign: parseAsString.withDefault(""), materialType: parseAsString.withDefault(""), consensusStatus: parseAsString.withDefault(""), // 고급 필터 filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), // 베이직 필터 (커스텀 필터 패널용) basicFilters: getFiltersStateParser().withDefault([]), basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), // 검색 search: parseAsString.withDefault(""), }); // ============= 타입 정의 ============= export type GetEvaluationTargetsSchema = Awaited< ReturnType >; export type EvaluationTargetStatus = "PENDING" | "CONFIRMED" | "EXCLUDED"; export type Division = "PLANT" | "SHIP"; export type MaterialType = "EQUIPMENT" | "BULK" | "EQUIPMENT_BULK"; export type DomesticForeign = "DOMESTIC" | "FOREIGN"; // ============= 필터 옵션 상수들 ============= export const EVALUATION_TARGET_FILTER_OPTIONS = { DIVISIONS: [ { value: "PLANT", label: "해양" }, { value: "SHIP", label: "조선" }, ], STATUSES: [ { value: "PENDING", label: "검토 중" }, { value: "CONFIRMED", label: "확정" }, { value: "EXCLUDED", label: "제외" }, ], DOMESTIC_FOREIGN: [ { value: "DOMESTIC", label: "내자" }, { value: "FOREIGN", label: "외자" }, ], MATERIAL_TYPES: [ { value: "EQUIPMENT", label: "기자재" }, { value: "BULK", label: "벌크" }, { value: "EQUIPMENT_BULK", label: "기자재/벌크" }, ], CONSENSUS_STATUS: [ { value: "true", label: "의견 일치" }, { value: "false", label: "의견 불일치" }, { value: "null", label: "검토 중" }, ], } as const; // ============= 유효성 검사 함수들 ============= export function validateEvaluationYear(year: number): boolean { const currentYear = new Date().getFullYear(); return year >= 2020 && year <= currentYear + 1; } export function validateDivision(division: string): division is Division { return ["PLANT", "SHIP"].includes(division); } export function validateStatus(status: string): status is EvaluationTargetStatus { return ["PENDING", "CONFIRMED", "EXCLUDED"].includes(status); } export function validateMaterialType(materialType: string): materialType is MaterialType { return ["EQUIPMENT", "BULK", "EQUIPMENT_BULK"].includes(materialType); } export function validateDomesticForeign(domesticForeign: string): domesticForeign is DomesticForeign { return ["DOMESTIC", "FOREIGN"].includes(domesticForeign); } // ============= 기본값 제공 함수들 ============= export function getDefaultEvaluationYear(): number { return new Date().getFullYear(); } export function getDefaultSearchParams(): GetEvaluationTargetsSchema { return { flags: [], page: 1, perPage: 10, sort: [{ id: "createdAt", desc: true }], evaluationYear: getDefaultEvaluationYear(), division: "", status: "", domesticForeign: "", materialType: "", consensusStatus: "", filters: [], joinOperator: "and", basicFilters: [], basicJoinOperator: "and", search: "", }; } // ============= 편의 함수들 ============= // 상태별 라벨 반환 export function getStatusLabel(status: EvaluationTargetStatus): string { const statusMap = { PENDING: "검토 중", CONFIRMED: "확정", EXCLUDED: "제외" }; return statusMap[status] || status; } // 구분별 라벨 반환 export function getDivisionLabel(division: Division): string { const divisionMap = { PLANT: "해양", SHIP: "조선" }; return divisionMap[division] || division; } // 자재구분별 라벨 반환 export function getMaterialTypeLabel(materialType: MaterialType): string { const materialTypeMap = { EQUIPMENT: "기자재", BULK: "벌크", EQUIPMENT_BULK: "기자재/벌크" }; return materialTypeMap[materialType] || materialType; } // 내외자별 라벨 반환 export function getDomesticForeignLabel(domesticForeign: DomesticForeign): string { const domesticForeignMap = { DOMESTIC: "내자", FOREIGN: "외자" }; return domesticForeignMap[domesticForeign] || domesticForeign; }