summaryrefslogtreecommitdiff
path: root/lib/docu-list-rule/code-groups
diff options
context:
space:
mode:
Diffstat (limited to 'lib/docu-list-rule/code-groups')
-rw-r--r--lib/docu-list-rule/code-groups/service.ts48
-rw-r--r--lib/docu-list-rule/code-groups/table/code-groups-add-dialog.tsx61
-rw-r--r--lib/docu-list-rule/code-groups/table/code-groups-edit-sheet.tsx4
-rw-r--r--lib/docu-list-rule/code-groups/table/code-groups-table-columns.tsx13
-rw-r--r--lib/docu-list-rule/code-groups/table/code-groups-table-toolbar.tsx6
-rw-r--r--lib/docu-list-rule/code-groups/table/code-groups-table.tsx34
-rw-r--r--lib/docu-list-rule/code-groups/table/delete-code-groups-dialog.tsx4
7 files changed, 140 insertions, 30 deletions
diff --git a/lib/docu-list-rule/code-groups/service.ts b/lib/docu-list-rule/code-groups/service.ts
index c99588a5..843bafa2 100644
--- a/lib/docu-list-rule/code-groups/service.ts
+++ b/lib/docu-list-rule/code-groups/service.ts
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache"
import db from "@/db/db"
import { codeGroups, comboBoxSettings } from "@/db/schema/docu-list-rule"
-import { eq, sql, count } from "drizzle-orm"
+import { projects } from "@/db/schema/projects"
+import { eq, sql, count, and } from "drizzle-orm"
import { unstable_noStore } from "next/cache"
// Code Groups 목록 조회
@@ -24,7 +25,8 @@ export async function getCodeGroups(input: any) {
${codeGroups.groupId} ILIKE ${searchTerm} OR
${codeGroups.description} ILIKE ${searchTerm} OR
${codeGroups.codeFormat} ILIKE ${searchTerm} OR
- ${codeGroups.controlType} ILIKE ${searchTerm}
+ ${codeGroups.controlType} ILIKE ${searchTerm} OR
+ ${projects.code} ILIKE ${searchTerm}
)`
}
@@ -68,14 +70,20 @@ export async function getCodeGroups(input: any) {
if (input.sort && input.sort.length > 0) {
const sortField = input.sort[0]
// 안전성 체크: 필드가 실제 테이블에 존재하는지 확인
- if (sortField && sortField.id && typeof sortField.id === "string" && sortField.id in codeGroups) {
+ if (sortField && sortField.id && typeof sortField.id === "string") {
const direction = sortField.desc ? sql`DESC` : sql`ASC`
- const col = codeGroups[sortField.id as keyof typeof codeGroups]
- orderBy = sql`${col} ${direction}`
+
+ // 프로젝트 코드 정렬 처리
+ if (sortField.id === "projectCode") {
+ orderBy = sql`${projects.code} ${direction}`
+ } else if (sortField.id in codeGroups) {
+ const col = codeGroups[sortField.id as keyof typeof codeGroups]
+ orderBy = sql`${col} ${direction}`
+ }
}
}
- // 데이터 조회
+ // 데이터 조회 (프로젝트 정보 포함)
const data = await db
.select({
id: codeGroups.id,
@@ -87,38 +95,44 @@ export async function getCodeGroups(input: any) {
isActive: codeGroups.isActive,
createdAt: codeGroups.createdAt,
updatedAt: codeGroups.updatedAt,
+ projectId: codeGroups.projectId,
+ projectCode: projects.code,
+ projectName: projects.name,
})
.from(codeGroups)
+ .leftJoin(projects, eq(codeGroups.projectId, projects.id))
.where(whereConditions)
.orderBy(orderBy)
.limit(perPage)
.offset(offset)
- // 총 개수 조회 (Document Class 제외)
- const [{ count: total }] = await db
- .select({ count: count() })
+ // 총 개수 조회 (프로젝트 정보 포함)
+ const totalCountResult = await db
+ .select({ count: sql<number>`count(*)` })
.from(codeGroups)
+ .leftJoin(projects, eq(codeGroups.projectId, projects.id))
.where(whereConditions)
- const pageCount = Math.ceil(total / perPage)
+ const totalCount = totalCountResult[0]?.count || 0
return {
data,
- pageCount,
- total,
+ totalCount,
+ pageCount: Math.ceil(totalCount / perPage),
}
} catch (error) {
console.error("Error fetching code groups:", error)
return {
data: [],
+ totalCount: 0,
pageCount: 0,
- total: 0,
}
}
}
// Code Group 생성
export async function createCodeGroup(input: {
+ projectId: number // projectCode를 projectId로 변경
description: string
codeFormat?: string
expressions?: string
@@ -126,11 +140,14 @@ export async function createCodeGroup(input: {
isActive?: boolean
}) {
try {
- // 마지막 Code Group의 groupId를 찾아서 다음 번호 생성 (DOC_CLASS 제외)
+ // 해당 프로젝트의 마지막 Code Group의 groupId를 찾아서 다음 번호 생성 (DOC_CLASS 제외)
const lastCodeGroup = await db
.select({ groupId: codeGroups.groupId })
.from(codeGroups)
- .where(sql`${codeGroups.groupId} != 'DOC_CLASS'`)
+ .where(and(
+ eq(codeGroups.projectId, input.projectId), // projectId로 변경
+ sql`${codeGroups.groupId} != 'DOC_CLASS'`
+ ))
.orderBy(sql`CAST(SUBSTRING(${codeGroups.groupId}, 6) AS INTEGER) DESC`)
.limit(1)
@@ -148,6 +165,7 @@ export async function createCodeGroup(input: {
const [newCodeGroup] = await db
.insert(codeGroups)
.values({
+ projectId: input.projectId, // projectId로 변경
groupId: newGroupId,
description: input.description,
codeFormat: input.codeFormat,
diff --git a/lib/docu-list-rule/code-groups/table/code-groups-add-dialog.tsx b/lib/docu-list-rule/code-groups/table/code-groups-add-dialog.tsx
index bf044f1a..a0143239 100644
--- a/lib/docu-list-rule/code-groups/table/code-groups-add-dialog.tsx
+++ b/lib/docu-list-rule/code-groups/table/code-groups-add-dialog.tsx
@@ -33,10 +33,12 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
-import { createCodeGroup } from "../service"
+import { createCodeGroup } from "@/lib/docu-list-rule/code-groups/service"
+import { getProjectLists } from "@/lib/projects/service"
import { z } from "zod"
const createCodeGroupSchema = z.object({
+ projectId: z.string().min(1, "프로젝트는 필수입니다."),
description: z.string().min(1, "Description은 필수입니다."),
codeFormat: z.string().optional().refine((val) => {
if (!val) return true; // 빈 값은 허용
@@ -54,16 +56,44 @@ interface CodeGroupsAddDialogProps {
export function CodeGroupsAddDialog({ onSuccess }: CodeGroupsAddDialogProps) {
const [open, setOpen] = React.useState(false)
const [isLoading, setIsLoading] = React.useState(false)
+ const [projects, setProjects] = React.useState<Array<{ id: number; code: string; name: string }>>([])
const form = useForm<CreateCodeGroupFormValues>({
resolver: zodResolver(createCodeGroupSchema),
defaultValues: {
+ projectId: "",
description: "",
codeFormat: "",
controlType: "",
},
})
+ // 프로젝트 목록 로드
+ React.useEffect(() => {
+ if (open) {
+ const loadProjects = async () => {
+ try {
+ const result = await getProjectLists({
+ page: 1,
+ perPage: 1000,
+ search: "",
+ sort: [],
+ filters: [],
+ joinOperator: "and",
+ flags: []
+ })
+ if (result.data) {
+ setProjects(result.data)
+ }
+ } catch (error) {
+ console.error("Failed to load projects:", error)
+ toast.error("프로젝트 목록을 불러오는데 실패했습니다.")
+ }
+ }
+ loadProjects()
+ }
+ }, [open])
+
// Code Format을 기반으로 정규식 자동 생성 함수
const generateExpression = (codeFormat: string): string => {
if (!codeFormat) return ''
@@ -121,6 +151,7 @@ export function CodeGroupsAddDialog({ onSuccess }: CodeGroupsAddDialogProps) {
const expressions = generateExpression(data.codeFormat || "")
const result = await createCodeGroup({
+ projectId: parseInt(data.projectId),
description: data.description,
codeFormat: data.codeFormat,
expressions: expressions,
@@ -156,6 +187,7 @@ export function CodeGroupsAddDialog({ onSuccess }: CodeGroupsAddDialogProps) {
<DialogTitle>Code Group 생성</DialogTitle>
<DialogDescription>
새로운 Code Group을 생성합니다.
+ <span className="text-red-500 mt-1 block text-sm">* 표시된 항목은 필수 입력사항입니다.</span>
</DialogDescription>
</DialogHeader>
@@ -163,10 +195,35 @@ export function CodeGroupsAddDialog({ onSuccess }: CodeGroupsAddDialogProps) {
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
+ name="projectId"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>프로젝트 *</FormLabel>
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
+ <FormControl>
+ <SelectTrigger>
+ <SelectValue placeholder="프로젝트를 선택하세요" />
+ </SelectTrigger>
+ </FormControl>
+ <SelectContent>
+ {projects.map((project) => (
+ <SelectItem key={project.id} value={project.id.toString()}>
+ {project.code} - {project.name}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ <FormField
+ control={form.control}
name="description"
render={({ field }) => (
<FormItem>
- <FormLabel>Description</FormLabel>
+ <FormLabel>Description *</FormLabel>
<FormControl>
<Input placeholder="예: PROJECT NO" {...field} />
</FormControl>
diff --git a/lib/docu-list-rule/code-groups/table/code-groups-edit-sheet.tsx b/lib/docu-list-rule/code-groups/table/code-groups-edit-sheet.tsx
index 74ebc05a..7dc714a7 100644
--- a/lib/docu-list-rule/code-groups/table/code-groups-edit-sheet.tsx
+++ b/lib/docu-list-rule/code-groups/table/code-groups-edit-sheet.tsx
@@ -34,8 +34,8 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
-import { updateCodeGroup } from "../service"
-import { codeGroups } from "@/db/schema/codeGroups"
+import { updateCodeGroup } from "@/lib/docu-list-rule/code-groups/service"
+import { codeGroups } from "@/db/schema/docu-list-rule"
import { z } from "zod"
const updateCodeGroupSchema = z.object({
diff --git a/lib/docu-list-rule/code-groups/table/code-groups-table-columns.tsx b/lib/docu-list-rule/code-groups/table/code-groups-table-columns.tsx
index c15dd676..01047c50 100644
--- a/lib/docu-list-rule/code-groups/table/code-groups-table-columns.tsx
+++ b/lib/docu-list-rule/code-groups/table/code-groups-table-columns.tsx
@@ -103,6 +103,19 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<typeof
// ----------------------------------------------------------------
const dataColumns: ColumnDef<typeof codeGroups.$inferSelect>[] = [
{
+ accessorKey: "projectCode",
+ enableResizing: true,
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="프로젝트 코드" />
+ ),
+ meta: {
+ excelHeader: "프로젝트 코드",
+ type: "text",
+ },
+ cell: ({ row }) => row.getValue("projectCode") ?? "",
+ minSize: 120
+ },
+ {
accessorKey: "groupId",
enableResizing: true,
header: ({ column }) => (
diff --git a/lib/docu-list-rule/code-groups/table/code-groups-table-toolbar.tsx b/lib/docu-list-rule/code-groups/table/code-groups-table-toolbar.tsx
index d2d9efb4..4dc3334c 100644
--- a/lib/docu-list-rule/code-groups/table/code-groups-table-toolbar.tsx
+++ b/lib/docu-list-rule/code-groups/table/code-groups-table-toolbar.tsx
@@ -3,9 +3,9 @@
import * as React from "react"
import { type Table } from "@tanstack/react-table"
-import { DeleteCodeGroupsDialog } from "./delete-code-groups-dialog"
-import { CodeGroupsAddDialog } from "./code-groups-add-dialog"
-import { codeGroups } from "@/db/schema/codeGroups"
+import { DeleteCodeGroupsDialog } from "@/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog"
+import { CodeGroupsAddDialog } from "@/lib/docu-list-rule/code-groups/table/code-groups-add-dialog"
+import { codeGroups } from "@/db/schema/docu-list-rule"
interface CodeGroupsTableToolbarActionsProps<TData> {
table: Table<TData>
diff --git a/lib/docu-list-rule/code-groups/table/code-groups-table.tsx b/lib/docu-list-rule/code-groups/table/code-groups-table.tsx
index 8873c34c..0029ed91 100644
--- a/lib/docu-list-rule/code-groups/table/code-groups-table.tsx
+++ b/lib/docu-list-rule/code-groups/table/code-groups-table.tsx
@@ -9,10 +9,10 @@ import type {
DataTableFilterField,
DataTableRowAction,
} from "@/types/table"
-import { getColumns } from "./code-groups-table-columns";
-import { DeleteCodeGroupsDialog } from "./delete-code-groups-dialog";
-import { CodeGroupsEditSheet } from "./code-groups-edit-sheet";
-import { CodeGroupsTableToolbarActions } from "./code-groups-table-toolbar";
+import { getColumns } from "@/lib/docu-list-rule/code-groups/table/code-groups-table-columns";
+import { DeleteCodeGroupsDialog } from "@/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog";
+import { CodeGroupsEditSheet } from "@/lib/docu-list-rule/code-groups/table/code-groups-edit-sheet";
+import { CodeGroupsTableToolbarActions } from "@/lib/docu-list-rule/code-groups/table/code-groups-table-toolbar";
import { codeGroups } from "@/db/schema/docu-list-rule";
interface CodeGroupsTableProps {
@@ -68,12 +68,34 @@ export function CodeGroupsTable({ promises }: CodeGroupsTableProps) {
enableAdvancedFilter: true,
initialState: {
columnPinning: { right: ["actions"] },
+ expanded: {},
},
- getRowId: (originalRow) => String(originalRow.groupId),
+ getRowId: (originalRow) => String(originalRow.id),
shallow: false,
- clearOnDefault: true,
+ clearOnDefault: false,
})
+ // 컴포넌트 마운트 후 그룹핑 설정
+ React.useEffect(() => {
+ if (data && table.getState().grouping.length === 0) {
+ table.setGrouping(["projectCode"])
+ }
+ }, [table, data])
+
+ // 정렬 시 펼쳐진 상태 유지
+ React.useEffect(() => {
+ const currentExpanded = table.getState().expanded
+ if (Object.keys(currentExpanded).length > 0) {
+ // 약간의 지연 후 현재 펼쳐진 상태를 다시 설정
+ const timer = setTimeout(() => {
+ table.setExpanded(currentExpanded)
+ }, 100)
+ return () => clearTimeout(timer)
+ }
+ }, [table.getState().sorting, table])
+
+
+
return (
<>
<DataTable table={table}>
diff --git a/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog.tsx b/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog.tsx
index 66a8d7c2..6f2217bd 100644
--- a/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog.tsx
+++ b/lib/docu-list-rule/code-groups/table/delete-code-groups-dialog.tsx
@@ -27,8 +27,8 @@ import {
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
-import { codeGroups } from "@/db/schema/codeGroups"
-import { deleteCodeGroup } from "../service"
+import { codeGroups } from "@/db/schema/docu-list-rule"
+import { deleteCodeGroup } from "@/lib/docu-list-rule/code-groups/service"
interface DeleteCodeGroupsDialogProps
extends React.ComponentPropsWithoutRef<typeof Dialog> {