"use server"; import { sql, SQL } from "drizzle-orm"; import db from "@/db/db"; import { materialSearchView } from "@/db/schema/items"; export interface MaterialSearchItem { materialGroupCode: string; materialGroupDesc: string; displayText: string; } export interface MaterialSearchResult { success: boolean; data: MaterialSearchItem[]; pagination: { page: number; perPage: number; total: number; pageCount: number; hasNextPage: boolean; hasPrevPage: boolean; }; } /** * 자재 검색 함수 - material_search_view에서 검색 */ export async function searchMaterialsForSelector( query: string, page: number = 1, perPage: number = 10 ): Promise { try { const offset = (page - 1) * perPage; // 검색 조건 let searchWhere: SQL | undefined; if (query.trim()) { const searchPattern = `%${query.trim()}%`; searchWhere = sql`( ${materialSearchView.materialGroupCode} ILIKE ${searchPattern} OR ${materialSearchView.materialGroupDesc} ILIKE ${searchPattern} OR ${materialSearchView.displayText} ILIKE ${searchPattern} )`; } const { data, total } = await db.transaction(async (tx) => { // 데이터 조회 const data = await tx .select() .from(materialSearchView) .where(searchWhere) .orderBy(materialSearchView.materialGroupCode, materialSearchView.materialGroupDesc) .limit(perPage) .offset(offset); // 총 개수 조회 const countResult = await tx .select({ count: sql`count(*)` }) .from(materialSearchView) .where(searchWhere); const total = countResult[0]?.count || 0; return { data: data.map((row) => ({ materialGroupCode: row.materialGroupCode, materialGroupDesc: row.materialGroupDesc, displayText: row.displayText, })), total, }; }); const pageCount = Math.ceil(total / perPage); return { success: true, data, pagination: { page, perPage, total, pageCount, hasNextPage: page < pageCount, hasPrevPage: page > 1, }, }; } catch (error) { console.error("자재 검색 오류:", error); return { success: false, data: [], pagination: { page: 1, perPage: 10, total: 0, pageCount: 0, hasNextPage: false, hasPrevPage: false, }, }; } }