diff options
Diffstat (limited to 'lib/form-list')
| -rw-r--r-- | lib/form-list/repository.ts | 24 | ||||
| -rw-r--r-- | lib/form-list/service.ts | 151 | ||||
| -rw-r--r-- | lib/form-list/table/formLists-table-columns.tsx | 14 | ||||
| -rw-r--r-- | lib/form-list/table/formLists-table-toolbar-actions.tsx | 4 | ||||
| -rw-r--r-- | lib/form-list/table/formLists-table.tsx | 8 | ||||
| -rw-r--r-- | lib/form-list/table/meta-sheet.tsx | 5 | ||||
| -rw-r--r-- | lib/form-list/validation.ts | 10 |
7 files changed, 95 insertions, 121 deletions
diff --git a/lib/form-list/repository.ts b/lib/form-list/repository.ts index 9c7f6891..ef8000c5 100644 --- a/lib/form-list/repository.ts +++ b/lib/form-list/repository.ts @@ -1,7 +1,7 @@ import db from "@/db/db"; import { projects } from "@/db/schema"; import { Item, items } from "@/db/schema/items"; -import { tagTypeClassFormMappings } from "@/db/schema/vendorData"; +import { formListsView, tagTypeClassFormMappings } from "@/db/schema/vendorData"; import { eq, inArray, @@ -29,23 +29,8 @@ export async function selectFormLists( const { where, orderBy, offset = 0, limit = 10 } = params; return tx - .select({ - id: tagTypeClassFormMappings.id, - projectId: tagTypeClassFormMappings.projectId, - tagTypeLabel: tagTypeClassFormMappings.tagTypeLabel, - classLabel: tagTypeClassFormMappings.classLabel, - formCode: tagTypeClassFormMappings.formCode, - formName: tagTypeClassFormMappings.formName, - ep: tagTypeClassFormMappings.ep, - remark: tagTypeClassFormMappings.remark, - createdAt: tagTypeClassFormMappings.createdAt, - updatedAt: tagTypeClassFormMappings.updatedAt, - // 프로젝트 정보 추가 - projectCode: projects.code, - projectName: projects.name - }) - .from(tagTypeClassFormMappings) - .innerJoin(projects, eq(tagTypeClassFormMappings.projectId, projects.id)) + .select() + .from(formListsView) .where(where) .orderBy(...(orderBy ?? [])) .offset(offset) @@ -59,8 +44,7 @@ export async function selectFormLists( ) { const res = await tx .select({ count: count() }) - .from(tagTypeClassFormMappings) - .leftJoin(projects, eq(tagTypeClassFormMappings.projectId, projects.id)) + .from(formListsView) .where(where); return res[0]?.count ?? 0; }
\ No newline at end of file diff --git a/lib/form-list/service.ts b/lib/form-list/service.ts index 9887609f..d49dc5fc 100644 --- a/lib/form-list/service.ts +++ b/lib/form-list/service.ts @@ -5,94 +5,87 @@ import db from "@/db/db"; import { unstable_cache } from "@/lib/unstable-cache"; import { GetFormListsSchema } from "./validation"; import { filterColumns } from "@/lib/filter-columns"; -import { tagTypeClassFormMappings } from "@/db/schema/vendorData"; +import { formListsView } from "@/db/schema/vendorData"; import { asc, desc, ilike, inArray, and, gte, lte, not, or } from "drizzle-orm"; import { countFormLists, selectFormLists } from "./repository"; import { projects } from "@/db/schema"; export async function getFormLists(input: GetFormListsSchema) { + return unstable_cache( + async () => { + try { + const offset = (input.page - 1) * input.perPage; + const advancedTable = true; - return unstable_cache( - async () => { - try { - const offset = (input.page - 1) * input.perPage; - - // const advancedTable = input.flags.includes("advancedTable"); - const advancedTable = true; - - // advancedTable 모드면 filterColumns()로 where 절 구성 - const advancedWhere = filterColumns({ - table: tagTypeClassFormMappings, - filters: input.filters, - joinOperator: input.joinOperator, - }); - - - let globalWhere - if (input.search) { - const s = `%${input.search}%` - globalWhere = or(ilike(tagTypeClassFormMappings.formCode, s), ilike(tagTypeClassFormMappings.formName, s) - , ilike(tagTypeClassFormMappings.tagTypeLabel, s) , ilike(tagTypeClassFormMappings.classLabel, s), - ilike(projects.name, s), - ilike(projects.code, s), - ) - // 필요시 여러 칼럼 OR조건 (status, priority, etc) - } - - const finalWhere = and( - // advancedWhere or your existing conditions - advancedWhere, - globalWhere // and()함수로 결합 or or() 등으로 결합 - ) - - - // 아니면 ilike, inArray, gte 등으로 where 절 구성 - const where = finalWhere - - - const orderBy = + + // advancedTable 모드면 filterColumns()로 where 절 구성 + const advancedWhere = filterColumns({ + table: formListsView, // 뷰 테이블 사용 + filters: input.filters, + joinOperator: input.joinOperator, + }); + + let globalWhere; + if (input.search) { + const s = `%${input.search}%`; + globalWhere = or( + ilike(formListsView.formCode, s), + ilike(formListsView.formName, s), + ilike(formListsView.tagTypeLabel, s), + ilike(formListsView.classLabel, s), + ilike(formListsView.projectName, s), // 뷰 테이블의 projectName 사용 + ilike(formListsView.projectCode, s), // 뷰 테이블의 projectCode 사용 + ); + } + + const finalWhere = and( + advancedWhere, + globalWhere + ); + + const where = finalWhere; + + const orderBy = input.sort.length > 0 ? input.sort.map((item) => { - // 프로젝트 관련 필드 정렬 처리 - if (item.id === 'projectCode') { - return item.desc ? desc(projects.code) : asc(projects.code); - } else if (item.id === 'projectName') { - return item.desc ? desc(projects.name) : asc(projects.name); - } else { - // 기존 필드 정렬 - return item.desc - ? desc(tagTypeClassFormMappings[item.id]) - : asc(tagTypeClassFormMappings[item.id]); - } + // 뷰 테이블은 모든 필드가 포함되어 있으므로 간단하게 처리 + return item.desc + ? desc(formListsView[item.id]) + : asc(formListsView[item.id]); }) - : [asc(tagTypeClassFormMappings.createdAt)]; - // 트랜잭션 내부에서 Repository 호출 - const { data, total } = await db.transaction(async (tx) => { - const data = await selectFormLists(tx, { - where, - orderBy, - offset, - limit: input.perPage, - }); + : [asc(formListsView.createdAt)]; - console.log("dbdata") - - const total = await countFormLists(tx, where); - return { data, total }; + // 트랜잭션 내부에서 Repository 호출 + const { data, total } = await db.transaction(async (tx) => { + // 뷰 테이블을 사용하는 새로운 select 함수 + const data = await selectFormLists(tx, { + where, + orderBy, + offset, + limit: input.perPage, }); - - const pageCount = Math.ceil(total / input.perPage); - - return { data, pageCount }; - } catch (err) { - // 에러 발생 시 디폴트 - return { data: [], pageCount: 0 }; - } - }, - [JSON.stringify(input)], // 캐싱 키 - { - revalidate: 3600, - tags: ["form-lists"], + + + + // 뷰 테이블을 사용하는 새로운 count 함수 + const total = await countFormLists(tx, where); + return { data, total }; + }); + + const pageCount = Math.ceil(total / input.perPage); + + + return { data, pageCount }; + } catch (err) { + console.log(err) + // 에러 발생 시 디폴트 + return { data: [], pageCount: 0 }; } - )(); - }
\ No newline at end of file + }, + [JSON.stringify(input)], // 캐싱 키 + { + revalidate: 3600, + tags: ["form-lists"], + } + )(); +}
\ No newline at end of file diff --git a/lib/form-list/table/formLists-table-columns.tsx b/lib/form-list/table/formLists-table-columns.tsx index 647a8af1..5b120796 100644 --- a/lib/form-list/table/formLists-table-columns.tsx +++ b/lib/form-list/table/formLists-table-columns.tsx @@ -17,16 +17,16 @@ import { import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { formListsColumnsConfig } from "@/config/formListsColumnsConfig" -import { ExtendedFormMappings } from "../validation" +import { FormListsView } from "@/db/schema" interface GetColumnsProps { - setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<ExtendedFormMappings> | null>> + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<FormListsView> | null>> } /** * tanstack table 컬럼 정의 (중첩 헤더 버전) */ -export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<ExtendedFormMappings>[] { +export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<FormListsView>[] { // ---------------------------------------------------------------- // 1) select 컬럼 (체크박스) // ---------------------------------------------------------------- @@ -35,7 +35,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Extende // ---------------------------------------------------------------- // 2) actions 컬럼 (단일 버튼 - Meta Info 바로 보기) // ---------------------------------------------------------------- - const actionsColumn: ColumnDef<ExtendedFormMappings> = { + const actionsColumn: ColumnDef<FormListsView> = { id: "actions", enableHiding: false, cell: function Cell({ row }) { @@ -65,7 +65,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Extende // 3) 일반 컬럼들을 "그룹"별로 묶어 중첩 columns 생성 // ---------------------------------------------------------------- // 3-1) groupMap: { [groupName]: ColumnDef<TagTypeClassFormMappings>[] } - const groupMap: Record<string, ColumnDef<ExtendedFormMappings>[]> = {} + const groupMap: Record<string, ColumnDef<FormListsView>[]> = {} formListsColumnsConfig.forEach((cfg) => { // 만약 group가 없으면 "_noGroup" 처리 @@ -76,7 +76,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Extende } // child column 정의 - const childCol: ColumnDef<ExtendedFormMappings> = { + const childCol: ColumnDef<FormListsView> = { accessorKey: cfg.id, enableResizing: true, header: ({ column }) => ( @@ -104,7 +104,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Extende // ---------------------------------------------------------------- // 3-2) groupMap에서 실제 상위 컬럼(그룹)을 만들기 // ---------------------------------------------------------------- - const nestedColumns: ColumnDef<ExtendedFormMappings>[] = [] + const nestedColumns: ColumnDef<FormListsView>[] = [] // 순서를 고정하고 싶다면 group 순서를 미리 정의하거나 sort해야 함 // 여기서는 그냥 Object.entries 순서 diff --git a/lib/form-list/table/formLists-table-toolbar-actions.tsx b/lib/form-list/table/formLists-table-toolbar-actions.tsx index 97db9a91..fc1e9c80 100644 --- a/lib/form-list/table/formLists-table-toolbar-actions.tsx +++ b/lib/form-list/table/formLists-table-toolbar-actions.tsx @@ -7,10 +7,10 @@ import { toast } from "sonner" import { exportTableToExcel } from "@/lib/export" import { Button } from "@/components/ui/button" -import { ExtendedFormMappings } from "../validation" +import { FormListsView } from "@/db/schema" interface ItemsTableToolbarActionsProps { - table: Table<ExtendedFormMappings> + table: Table<FormListsView> } export function FormListsTableToolbarActions({ table }: ItemsTableToolbarActionsProps) { diff --git a/lib/form-list/table/formLists-table.tsx b/lib/form-list/table/formLists-table.tsx index 9f35db03..a9a56338 100644 --- a/lib/form-list/table/formLists-table.tsx +++ b/lib/form-list/table/formLists-table.tsx @@ -16,7 +16,7 @@ import { getFormLists } from "../service" import { getColumns } from "./formLists-table-columns" import { FormListsTableToolbarActions } from "./formLists-table-toolbar-actions" import { ViewMetas } from "./meta-sheet" -import { ExtendedFormMappings } from "../validation" +import { FormListsView } from "@/db/schema" interface ItemsTableProps { promises: Promise< @@ -33,7 +33,7 @@ export function FormListsTable({ promises }: ItemsTableProps) { React.use(promises) const [rowAction, setRowAction] = - React.useState<DataTableRowAction<ExtendedFormMappings> | null>(null) + React.useState<DataTableRowAction<FormListsView> | null>(null) const columns = React.useMemo( () => getColumns({ setRowAction }), @@ -51,7 +51,7 @@ export function FormListsTable({ promises }: ItemsTableProps) { * @prop {React.ReactNode} [icon] - An optional icon to display next to the label. * @prop {boolean} [withCount] - An optional boolean to display the count of the filter option. */ - const filterFields: DataTableFilterField<ExtendedFormMappings>[] = [ + const filterFields: DataTableFilterField<FormListsView>[] = [ ] @@ -66,7 +66,7 @@ export function FormListsTable({ promises }: ItemsTableProps) { * 3. Used with DataTableAdvancedToolbar: Enables a more sophisticated filtering UI. * 4. Date and boolean types: Adds support for filtering by date ranges and boolean values. */ - const advancedFilterFields: DataTableAdvancedFilterField<ExtendedFormMappings>[] = [ + const advancedFilterFields: DataTableAdvancedFilterField<FormListsView>[] = [ { id: "projectCode", label: "Project Code", diff --git a/lib/form-list/table/meta-sheet.tsx b/lib/form-list/table/meta-sheet.tsx index 03e7d257..24140a95 100644 --- a/lib/form-list/table/meta-sheet.tsx +++ b/lib/form-list/table/meta-sheet.tsx @@ -32,8 +32,8 @@ import { CardHeader, CardTitle } from "@/components/ui/card" -import type { TagTypeClassFormMappings } from "@/db/schema/vendorData" // or your actual type import { fetchFormMetadata, FormColumn } from "@/lib/forms/services" +import { FormListsView } from "@/db/schema" // 옵션을 표시하기 위한 새로운 컴포넌트 const CollapsibleOptions = ({ options }: { options?: string[] }) => { @@ -89,7 +89,7 @@ const CollapsibleOptions = ({ options }: { options?: string[] }) => { interface ViewMetasProps { open: boolean onOpenChange: (open: boolean) => void - form: TagTypeClassFormMappings | null + form: FormListsView | null } export function ViewMetas({ open, onOpenChange, form }: ViewMetasProps) { @@ -124,6 +124,7 @@ export function ViewMetas({ open, onOpenChange, form }: ViewMetasProps) { React.useEffect(() => { async function fetchMeta() { if (!form || !open) return + if (form.formCode === null || form.projectId === null) return setLoading(true) try { diff --git a/lib/form-list/validation.ts b/lib/form-list/validation.ts index 497ec871..78ed6b72 100644 --- a/lib/form-list/validation.ts +++ b/lib/form-list/validation.ts @@ -8,13 +8,9 @@ import { import * as z from "zod" import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" -import { TagTypeClassFormMappings } from "@/db/schema/vendorData"; +import { FormListsView } from "@/db/schema/vendorData"; + -export type ExtendedFormMappings = TagTypeClassFormMappings & { - projectCode: string; - projectName: string; - }; - export const searchParamsCache = createSearchParamsCache({ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault( @@ -22,7 +18,7 @@ export const searchParamsCache = createSearchParamsCache({ ), page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), - sort: getSortingStateParser<ExtendedFormMappings>().withDefault([ + sort: getSortingStateParser<FormListsView>().withDefault([ { id: "createdAt", desc: true }, ]), |
