diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-30 01:54:09 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-30 01:54:09 +0000 |
| commit | d59a5175210c18fcc675cde93865339abf37a406 (patch) | |
| tree | 085834900e7b65c60364602432c38f3030d456e2 | |
| parent | 3bdd648ad4cb863043db181291ddaebbc025965b (diff) | |
(최겸) 기술영업 아이템리스트 filter, sort 적용
| -rw-r--r-- | app/[lng]/evcp/(evcp)/items-tech/page.tsx | 23 | ||||
| -rw-r--r-- | lib/items-tech/service.ts | 70 | ||||
| -rw-r--r-- | lib/items-tech/table/hull/offshore-hull-table.tsx | 19 | ||||
| -rw-r--r-- | lib/items-tech/table/ship/Items-ship-table.tsx | 29 | ||||
| -rw-r--r-- | lib/items-tech/table/top/offshore-top-table.tsx | 18 | ||||
| -rw-r--r-- | lib/items-tech/validations.ts | 57 |
6 files changed, 141 insertions, 75 deletions
diff --git a/app/[lng]/evcp/(evcp)/items-tech/page.tsx b/app/[lng]/evcp/(evcp)/items-tech/page.tsx index 52ff519d..55ac9c63 100644 --- a/app/[lng]/evcp/(evcp)/items-tech/page.tsx +++ b/app/[lng]/evcp/(evcp)/items-tech/page.tsx @@ -3,7 +3,7 @@ import { type SearchParams } from "@/types/table" import { getValidFilters } from "@/lib/data-table"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { searchParamsCache } from "@/lib/items-tech/validations"
+import { shipbuildingSearchParamsCache, offshoreTopSearchParamsCache, offshoreHullSearchParamsCache } from "@/lib/items-tech/validations"
import { getShipbuildingItems, getOffshoreTopItems, getOffshoreHullItems } from "@/lib/items-tech/service"
import { OffshoreTopTable } from "@/lib/items-tech/table/top/offshore-top-table"
import { OffshoreHullTable } from "@/lib/items-tech/table/hull/offshore-hull-table"
@@ -17,8 +17,13 @@ interface IndexPageProps { export default async function IndexPage({ searchParams }: IndexPageProps) {
const params = await searchParams
- const search = searchParamsCache.parse(params)
- const validFilters = getValidFilters(search.filters || [])
+ const shipbuildingSearch = shipbuildingSearchParamsCache.parse(params)
+ const offshoreTopSearch = offshoreTopSearchParamsCache.parse(params)
+ const offshoreHullSearch = offshoreHullSearchParamsCache.parse(params)
+ const validShipbuildingFilters = getValidFilters(shipbuildingSearch.filters || [])
+ const validOffshoreTopFilters = getValidFilters(offshoreTopSearch.filters || [])
+ const validOffshoreHullFilters = getValidFilters(offshoreHullSearch.filters || [])
+
// URL에서 아이템 타입 가져오기
const itemType = params.type || "ship"
@@ -29,8 +34,8 @@ export default async function IndexPage({ searchParams }: IndexPageProps) { <ItemsShipTable
promises={Promise.all([
getShipbuildingItems({
- ...search,
- filters: validFilters,
+ ...shipbuildingSearch,
+ filters: validShipbuildingFilters,
}),
]).then(([result]) => result)}
/>
@@ -40,8 +45,8 @@ export default async function IndexPage({ searchParams }: IndexPageProps) { <OffshoreTopTable
promises={Promise.all([
getOffshoreTopItems({
- ...search,
- filters: validFilters,
+ ...offshoreTopSearch,
+ filters: validOffshoreTopFilters,
}),
]).then(([result]) => result)}
/>
@@ -51,8 +56,8 @@ export default async function IndexPage({ searchParams }: IndexPageProps) { <OffshoreHullTable
promises={Promise.all([
getOffshoreHullItems({
- ...search,
- filters: validFilters,
+ ...offshoreHullSearch,
+ filters: validOffshoreHullFilters,
}),
]).then(([result]) => result)}
/>
diff --git a/lib/items-tech/service.ts b/lib/items-tech/service.ts index 9fa35148..6047552f 100644 --- a/lib/items-tech/service.ts +++ b/lib/items-tech/service.ts @@ -9,7 +9,7 @@ import { unstable_cache } from "@/lib/unstable-cache"; import { getErrorMessage } from "@/lib/handle-error";
import { asc, desc, ilike, and, or, eq, count, inArray, sql } from "drizzle-orm";
-import { GetItemsSchema, UpdateItemSchema, ShipbuildingItemCreateData, TypedItemCreateData, OffshoreTopItemCreateData, OffshoreHullItemCreateData } from "./validations";
+import { GetShipbuildingSchema, GetOffshoreTopSchema, GetOffshoreHullSchema, UpdateItemSchema, ShipbuildingItemCreateData, TypedItemCreateData, OffshoreTopItemCreateData, OffshoreHullItemCreateData } from "./validations";
import { Item, items, itemShipbuilding, itemOffshoreTop, itemOffshoreHull, ItemOffshoreTop, ItemOffshoreHull } from "@/db/schema/items";
import { findAllItems } from "./repository";
import { findAllOffshoreItems } from "./repository";
@@ -23,7 +23,7 @@ import { findAllOffshoreItems } from "./repository"; * 총 개수에 따라 pageCount를 계산해서 리턴.
* Next.js의 unstable_cache를 사용해 일정 시간 캐시.
*/
-export async function getShipbuildingItems(input: GetItemsSchema) {
+export async function getShipbuildingItems(input: GetShipbuildingSchema) {
return unstable_cache(
async () => {
try {
@@ -34,6 +34,12 @@ export async function getShipbuildingItems(input: GetItemsSchema) { table: items,
filters: input.filters,
joinOperator: input.joinOperator,
+ joinedTables: { itemShipbuilding },
+ customColumnMapping: {
+ workType: { table: itemShipbuilding, column: "workType" },
+ shipTypes: { table: itemShipbuilding, column: "shipTypes" },
+ itemList: { table: itemShipbuilding, column: "itemList" },
+ },
});
let globalWhere;
@@ -41,8 +47,7 @@ export async function getShipbuildingItems(input: GetItemsSchema) { const s = `%${input.search}%`;
globalWhere = or(
ilike(items.itemCode, s),
- ilike(items.itemName, s),
- ilike(items.description, s)
+ ilike(itemShipbuilding.itemList, s)
);
}
@@ -55,10 +60,13 @@ export async function getShipbuildingItems(input: GetItemsSchema) { const orderBy =
input.sort.length > 0
- ? input.sort.map((item) =>
- item.desc ? desc(items[item.id]) : asc(items[item.id])
- )
- : [asc(items.createdAt)];
+ ? input.sort.map((item) => {
+ const column = item.id === "workType" || item.id === "shipTypes" || item.id === "itemList"
+ ? itemShipbuilding[item.id]
+ : items[item.id];
+ return item.desc ? desc(column) : asc(column);
+ })
+ : [desc(items.createdAt)];
// 조선 아이템 테이블과 기본 아이템 테이블 조인하여 조회
const result = await db.select({
@@ -103,7 +111,7 @@ export async function getShipbuildingItems(input: GetItemsSchema) { )();
}
-export async function getOffshoreTopItems(input: GetItemsSchema) {
+export async function getOffshoreTopItems(input: GetOffshoreTopSchema) {
return unstable_cache(
async () => {
try {
@@ -114,6 +122,12 @@ export async function getOffshoreTopItems(input: GetItemsSchema) { table: items,
filters: input.filters,
joinOperator: input.joinOperator,
+ joinedTables: { itemOffshoreTop },
+ customColumnMapping: {
+ workType: { table: itemOffshoreTop, column: "workType" },
+ itemList: { table: itemOffshoreTop, column: "itemList" },
+ subItemList: { table: itemOffshoreTop, column: "subItemList" },
+ },
});
let globalWhere;
@@ -121,8 +135,8 @@ export async function getOffshoreTopItems(input: GetItemsSchema) { const s = `%${input.search}%`;
globalWhere = or(
ilike(items.itemCode, s),
- ilike(items.itemName, s),
- ilike(items.description, s)
+ ilike(itemOffshoreTop.itemList, s),
+ ilike(itemOffshoreTop.subItemList, s)
);
}
@@ -135,10 +149,13 @@ export async function getOffshoreTopItems(input: GetItemsSchema) { const orderBy =
input.sort.length > 0
- ? input.sort.map((item) =>
- item.desc ? desc(items[item.id]) : asc(items[item.id])
- )
- : [asc(items.createdAt)];
+ ? input.sort.map((item) => {
+ const column = item.id === "workType" || item.id === "itemList" || item.id === "subItemList"
+ ? itemOffshoreTop[item.id]
+ : items[item.id];
+ return item.desc ? desc(column) : asc(column);
+ })
+ : [desc(items.createdAt)];
// 해양 TOP 아이템 테이블과 기본 아이템 테이블 조인하여 조회
const result = await db.select({
@@ -183,7 +200,7 @@ export async function getOffshoreTopItems(input: GetItemsSchema) { )();
}
-export async function getOffshoreHullItems(input: GetItemsSchema) {
+export async function getOffshoreHullItems(input: GetOffshoreHullSchema) {
return unstable_cache(
async () => {
try {
@@ -194,6 +211,12 @@ export async function getOffshoreHullItems(input: GetItemsSchema) { table: items,
filters: input.filters,
joinOperator: input.joinOperator,
+ joinedTables: { itemOffshoreHull },
+ customColumnMapping: {
+ workType: { table: itemOffshoreHull, column: "workType" },
+ itemList: { table: itemOffshoreHull, column: "itemList" },
+ subItemList: { table: itemOffshoreHull, column: "subItemList" },
+ },
});
let globalWhere;
@@ -201,8 +224,8 @@ export async function getOffshoreHullItems(input: GetItemsSchema) { const s = `%${input.search}%`;
globalWhere = or(
ilike(items.itemCode, s),
- ilike(items.itemName, s),
- ilike(items.description, s)
+ ilike(itemOffshoreHull.itemList, s),
+ ilike(itemOffshoreHull.subItemList, s)
);
}
@@ -215,10 +238,13 @@ export async function getOffshoreHullItems(input: GetItemsSchema) { const orderBy =
input.sort.length > 0
- ? input.sort.map((item) =>
- item.desc ? desc(items[item.id]) : asc(items[item.id])
- )
- : [asc(items.createdAt)];
+ ? input.sort.map((item) => {
+ const column = item.id === "workType" || item.id === "itemList" || item.id === "subItemList"
+ ? itemOffshoreHull[item.id]
+ : items[item.id];
+ return item.desc ? desc(column) : asc(column);
+ })
+ : [desc(items.createdAt)];
// 해양 HULL 아이템 테이블과 기본 아이템 테이블 조인하여 조회
const result = await db.select({
diff --git a/lib/items-tech/table/hull/offshore-hull-table.tsx b/lib/items-tech/table/hull/offshore-hull-table.tsx index 00f2c466..2a6f3173 100644 --- a/lib/items-tech/table/hull/offshore-hull-table.tsx +++ b/lib/items-tech/table/hull/offshore-hull-table.tsx @@ -70,19 +70,16 @@ export function OffshoreHullTable({ promises }: OffshoreHullTableProps) { type: "text",
},
{
- id: "itemName",
- label: "Item Name",
- type: "text",
- },
- {
- id: "description",
- label: "Description",
- type: "text",
- },
- {
id: "workType",
label: "기능(공종)",
- type: "text",
+ type: "select",
+ options: [
+ { label: "HA", value: "HA" },
+ { label: "HE", value: "HE" },
+ { label: "HH", value: "HH" },
+ { label: "HM", value: "HM" },
+ { label: "NC", value: "NC" },
+ ],
},
{
id: "itemList",
diff --git a/lib/items-tech/table/ship/Items-ship-table.tsx b/lib/items-tech/table/ship/Items-ship-table.tsx index 29ad8f8a..61e8d8b4 100644 --- a/lib/items-tech/table/ship/Items-ship-table.tsx +++ b/lib/items-tech/table/ship/Items-ship-table.tsx @@ -81,24 +81,29 @@ export function ItemsShipTable({ promises }: ItemsTableProps) { type: "text",
},
{
- id: "itemName",
- label: "Item Name",
- type: "text",
- },
- {
- id: "description",
- label: "Description",
- type: "text",
- },
- {
id: "workType",
label: "기능(공종)",
- type: "text",
+ type: "select",
+ options: [
+ { label: "기장", value: "기장" },
+ { label: "전장", value: "전장" },
+ { label: "선실", value: "선실" },
+ { label: "배관", value: "배관" },
+ { label: "철의", value: "철의" },
+ ],
},
{
id: "shipTypes",
label: "선종",
- type: "text",
+ type: "select",
+ options: [
+ { label: "A-MAX", value: "A-MAX" },
+ { label: "S-MAX", value: "S-MAX" },
+ { label: "LNGC", value: "LNGC" },
+ { label: "VLCC", value: "VLCC" },
+ { label: "CONT", value: "CONT" },
+ { label: "OPTION", value: "OPTION" },
+ ],
},
{
id: "itemList",
diff --git a/lib/items-tech/table/top/offshore-top-table.tsx b/lib/items-tech/table/top/offshore-top-table.tsx index 689f1db3..c038de13 100644 --- a/lib/items-tech/table/top/offshore-top-table.tsx +++ b/lib/items-tech/table/top/offshore-top-table.tsx @@ -66,19 +66,15 @@ export function OffshoreTopTable({ promises }: OffshoreTopTableProps) { type: "text",
},
{
- id: "itemName",
- label: "Item Name",
- type: "text",
- },
- {
- id: "description",
- label: "Description",
- type: "text",
- },
- {
id: "workType",
label: "기능(공종)",
- type: "text",
+ type: "select",
+ options: [
+ { label: "TM", value: "TM" },
+ { label: "TS", value: "TS" },
+ { label: "TE", value: "TE" },
+ { label: "TP", value: "TP" },
+ ],
},
{
id: "itemList",
diff --git a/lib/items-tech/validations.ts b/lib/items-tech/validations.ts index 399193b2..09c7878b 100644 --- a/lib/items-tech/validations.ts +++ b/lib/items-tech/validations.ts @@ -8,25 +8,59 @@ import { import * as z from "zod"
import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers"
-import { Item } from "@/db/schema/items";
+import { ItemOffshoreTop, ItemOffshoreHull, ItemShipbuilding } from "@/db/schema/items";
-export const searchParamsCache = createSearchParamsCache({
- flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault(
- []
- ),
+// 조선 아이템 검색 파라미터 캐시
+export const shipbuildingSearchParamsCache = createSearchParamsCache({
+ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]),
page: parseAsInteger.withDefault(1),
perPage: parseAsInteger.withDefault(10),
- sort: getSortingStateParser<Item>().withDefault([
+ sort: getSortingStateParser<ItemShipbuilding>().withDefault([
{ id: "createdAt", desc: true },
]),
itemCode: parseAsString.withDefault(""),
- itemName: parseAsString.withDefault(""),
- description: parseAsString.withDefault(""),
+ workType: parseAsString.withDefault(""),
+ shipTypes: parseAsString.withDefault(""),
+ itemList: parseAsString.withDefault(""),
+ filters: getFiltersStateParser().withDefault([]),
+ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
+ search: parseAsString.withDefault(""),
+
+})
+
+// 해양 TOP 아이템 검색 파라미터 캐시
+export const offshoreTopSearchParamsCache = createSearchParamsCache({
+ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]),
+ page: parseAsInteger.withDefault(1),
+ perPage: parseAsInteger.withDefault(10),
+ sort: getSortingStateParser<ItemOffshoreTop>().withDefault([
+ { id: "createdAt", desc: true },
+ ]),
+ itemCode: parseAsString.withDefault(""),
+ workType: parseAsString.withDefault(""),
+ itemList: parseAsString.withDefault(""),
+ subItemList: parseAsString.withDefault(""),
+ filters: getFiltersStateParser().withDefault([]),
+ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
+ search: parseAsString.withDefault(""),
+})
- // advanced filter
+// 해양 HULL 아이템 검색 파라미터 캐시
+export const offshoreHullSearchParamsCache = createSearchParamsCache({
+ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]),
+ page: parseAsInteger.withDefault(1),
+ perPage: parseAsInteger.withDefault(10),
+ sort: getSortingStateParser<ItemOffshoreHull>().withDefault([
+ { id: "createdAt", desc: true },
+ ]),
+ itemCode: parseAsString.withDefault(""),
+ workType: parseAsString.withDefault(""),
+ itemList: parseAsString.withDefault(""),
+ subItemList: parseAsString.withDefault(""),
filters: getFiltersStateParser().withDefault([]),
joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
search: parseAsString.withDefault(""),
+
})
export const createItemSchema = z.object({
@@ -51,7 +85,10 @@ export const updateShipbuildingItemSchema = z.object({ itemList: z.string().optional(),
})
-export type GetItemsSchema = Awaited<ReturnType<typeof searchParamsCache.parse>>
+export type GetShipbuildingSchema = Awaited<ReturnType<typeof shipbuildingSearchParamsCache.parse>>
+export type GetOffshoreTopSchema = Awaited<ReturnType<typeof offshoreTopSearchParamsCache.parse>>
+export type GetOffshoreHullSchema = Awaited<ReturnType<typeof offshoreHullSearchParamsCache.parse>>
+
export type CreateItemSchema = z.infer<typeof createItemSchema>
export type UpdateItemSchema = z.infer<typeof updateItemSchema>
export type UpdateShipbuildingItemSchema = z.infer<typeof updateShipbuildingItemSchema>
|
