260220:1228 20260220 TASK-BEFE-001 Fix Drawing Master Data Pages #2
All checks were successful
Build and Deploy / deploy (push) Successful in 2m22s

This commit is contained in:
admin
2026-02-20 12:28:49 +07:00
parent 21b48f7d32
commit 8223ae95ff
4 changed files with 117 additions and 118 deletions

View File

@@ -101,7 +101,12 @@ export default function ContractCategoriesPage() {
title="Contract Drawing Categories" title="Contract Drawing Categories"
description="Manage main categories (หมวดหมู่หลัก) for contract drawings" description="Manage main categories (หมวดหมู่หลัก) for contract drawings"
queryKey={['contract-drawing-categories', String(selectedProjectId)]} queryKey={['contract-drawing-categories', String(selectedProjectId)]}
fetchFn={() => drawingMasterDataService.getContractCategories(selectedProjectId)} fetchFn={async () => {
console.log(`Fetching Contract Categories for project ${selectedProjectId}`);
const data = await drawingMasterDataService.getContractCategories(selectedProjectId);
console.log('Contract Categories Data:', data);
return data;
}}
createFn={(data) => drawingMasterDataService.createContractCategory({ ...data, projectId: selectedProjectId })} createFn={(data) => drawingMasterDataService.createContractCategory({ ...data, projectId: selectedProjectId })}
updateFn={(id, data) => drawingMasterDataService.updateContractCategory(id, data)} updateFn={(id, data) => drawingMasterDataService.updateContractCategory(id, data)}
deleteFn={(id) => drawingMasterDataService.deleteContractCategory(id)} deleteFn={(id) => drawingMasterDataService.deleteContractCategory(id)}
@@ -259,21 +264,23 @@ function ManageMappings({ projectId }: { projectId: number }) {
<div className="p-4 text-center text-sm text-muted-foreground">No sub-categories mapped yet.</div> <div className="p-4 text-center text-sm text-muted-foreground">No sub-categories mapped yet.</div>
) : ( ) : (
<div className="divide-y"> <div className="divide-y">
{mappings.map((m: { id: number; subCategory: ContractSubCategory }) => ( {mappings
<div key={m.id} className="p-2 grid grid-cols-[1fr,auto] gap-2 items-center"> .filter((m: any) => m && m.subCategory)
<span className="text-sm"> .map((m: { id: number; subCategory: ContractSubCategory }) => (
{m.subCategory.subCatCode} - {m.subCategory.subCatName} <div key={m.id} className="p-2 grid grid-cols-[1fr,auto] gap-2 items-center">
</span> <span className="text-sm">
<Button {m.subCategory?.subCatCode ?? '?'} - {m.subCategory?.subCatName ?? 'Unknown'}
variant="ghost" </span>
size="sm" <Button
onClick={() => deleteMutation.mutate(m.id)} variant="ghost"
disabled={deleteMutation.isPending} size="sm"
> onClick={() => deleteMutation.mutate(m.id)}
<Trash2 className="h-4 w-4 text-red-500" /> disabled={deleteMutation.isPending}
</Button> >
</div> <Trash2 className="h-4 w-4 text-red-500" />
))} </Button>
</div>
))}
</div> </div>
)} )}
</div> </div>

View File

@@ -1,19 +1,13 @@
"use client"; 'use client';
import { useState } from "react"; import { useState } from 'react';
import { GenericCrudTable } from "@/components/admin/reference/generic-crud-table"; import { GenericCrudTable } from '@/components/admin/reference/generic-crud-table';
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from '@tanstack/react-table';
import { import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
Select, import { Loader2 } from 'lucide-react';
SelectContent, import { useProjects } from '@/hooks/use-master-data';
SelectItem, import { drawingMasterDataService } from '@/lib/services/drawing-master-data.service';
SelectTrigger, import { Badge } from '@/components/ui/badge';
SelectValue,
} from "@/components/ui/select";
import { Loader2 } from "lucide-react";
import { useProjects } from "@/hooks/use-master-data";
import { drawingMasterDataService } from "@/lib/services/drawing-master-data.service";
import { Badge } from "@/components/ui/badge";
interface SubCategory { interface SubCategory {
id: number; id: number;
@@ -29,33 +23,27 @@ export default function ContractSubCategoriesPage() {
const columns: ColumnDef<SubCategory>[] = [ const columns: ColumnDef<SubCategory>[] = [
{ {
accessorKey: "subCatCode", accessorKey: 'subCatCode',
header: "Code", header: 'Code',
cell: ({ row }) => ( cell: ({ row }) => (
<Badge variant="outline" className="font-mono"> <Badge variant="outline" className="font-mono">
{row.getValue("subCatCode")} {row.getValue('subCatCode')}
</Badge> </Badge>
), ),
}, },
{ {
accessorKey: "subCatName", accessorKey: 'subCatName',
header: "Sub-category Name", header: 'Sub-category Name',
}, },
{ {
accessorKey: "description", accessorKey: 'description',
header: "Description", header: 'Description',
cell: ({ row }) => ( cell: ({ row }) => <span className="text-muted-foreground text-sm">{row.getValue('description') || '-'}</span>,
<span className="text-muted-foreground text-sm">
{row.getValue("description") || "-"}
</span>
),
}, },
{ {
accessorKey: "sortOrder", accessorKey: 'sortOrder',
header: "Order", header: 'Order',
cell: ({ row }) => ( cell: ({ row }) => <span className="font-mono">{row.getValue('sortOrder')}</span>,
<span className="font-mono">{row.getValue("sortOrder")}</span>
),
}, },
]; ];
@@ -63,7 +51,7 @@ export default function ContractSubCategoriesPage() {
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span className="text-sm font-medium">Project:</span> <span className="text-sm font-medium">Project:</span>
<Select <Select
value={selectedProjectId?.toString() ?? ""} value={selectedProjectId?.toString() ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
@@ -89,9 +77,7 @@ export default function ContractSubCategoriesPage() {
<div className="p-6 space-y-6"> <div className="p-6 space-y-6">
<div> <div>
<h1 className="text-2xl font-bold">Contract Drawing Sub-categories</h1> <h1 className="text-2xl font-bold">Contract Drawing Sub-categories</h1>
<p className="text-muted-foreground mt-1"> <p className="text-muted-foreground mt-1">Manage sub-categories () for contract drawings</p>
Manage sub-categories () for contract drawings
</p>
</div> </div>
{projectFilter} {projectFilter}
<div className="text-center py-12 text-muted-foreground border rounded-lg border-dashed"> <div className="text-center py-12 text-muted-foreground border rounded-lg border-dashed">
@@ -107,17 +93,24 @@ export default function ContractSubCategoriesPage() {
entityName="Sub-category" entityName="Sub-category"
title="Contract Drawing Sub-categories" title="Contract Drawing Sub-categories"
description="Manage sub-categories (หมวดหมู่ย่อย) for contract drawings" description="Manage sub-categories (หมวดหมู่ย่อย) for contract drawings"
queryKey={["contract-drawing-sub-categories", String(selectedProjectId)]} queryKey={['contract-drawing-sub-categories', String(selectedProjectId)]}
fetchFn={() => drawingMasterDataService.getContractSubCategories(selectedProjectId)} fetchFn={async () => {
createFn={(data) => drawingMasterDataService.createContractSubCategory({ ...data, projectId: selectedProjectId })} console.log(`Fetching Contract Sub-Categories for project ${selectedProjectId}`);
const data = await drawingMasterDataService.getContractSubCategories(selectedProjectId);
console.log('Contract Sub-Categories Data:', data);
return data;
}}
createFn={(data) =>
drawingMasterDataService.createContractSubCategory({ ...data, projectId: selectedProjectId })
}
updateFn={(id, data) => drawingMasterDataService.updateContractSubCategory(id, data)} updateFn={(id, data) => drawingMasterDataService.updateContractSubCategory(id, data)}
deleteFn={(id) => drawingMasterDataService.deleteContractSubCategory(id)} deleteFn={(id) => drawingMasterDataService.deleteContractSubCategory(id)}
columns={columns} columns={columns}
fields={[ fields={[
{ name: "subCatCode", label: "Sub-category Code", type: "text", required: true }, { name: 'subCatCode', label: 'Sub-category Code', type: 'text', required: true },
{ name: "subCatName", label: "Sub-category Name", type: "text", required: true }, { name: 'subCatName', label: 'Sub-category Name', type: 'text', required: true },
{ name: "description", label: "Description", type: "textarea" }, { name: 'description', label: 'Description', type: 'textarea' },
{ name: "sortOrder", label: "Sort Order", type: "text", required: true }, { name: 'sortOrder', label: 'Sort Order', type: 'text', required: true },
]} ]}
filters={projectFilter} filters={projectFilter}
/> />

View File

@@ -1,19 +1,13 @@
"use client"; 'use client';
import { useState } from "react"; import { useState } from 'react';
import { GenericCrudTable } from "@/components/admin/reference/generic-crud-table"; import { GenericCrudTable } from '@/components/admin/reference/generic-crud-table';
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from '@tanstack/react-table';
import { import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
Select, import { Loader2, CheckCircle, XCircle } from 'lucide-react';
SelectContent, import { useProjects } from '@/hooks/use-master-data';
SelectItem, import { drawingMasterDataService } from '@/lib/services/drawing-master-data.service';
SelectTrigger, import { Badge } from '@/components/ui/badge';
SelectValue,
} from "@/components/ui/select";
import { Loader2, CheckCircle, XCircle } from "lucide-react";
import { useProjects } from "@/hooks/use-master-data";
import { drawingMasterDataService } from "@/lib/services/drawing-master-data.service";
import { Badge } from "@/components/ui/badge";
interface MainCategory { interface MainCategory {
id: number; id: number;
@@ -30,44 +24,37 @@ export default function ShopMainCategoriesPage() {
const columns: ColumnDef<MainCategory>[] = [ const columns: ColumnDef<MainCategory>[] = [
{ {
accessorKey: "mainCategoryCode", accessorKey: 'mainCategoryCode',
header: "Code", header: 'Code',
cell: ({ row }) => ( cell: ({ row }) => (
<Badge variant="outline" className="font-mono"> <Badge variant="outline" className="font-mono">
{row.getValue("mainCategoryCode")} {row.getValue('mainCategoryCode')}
</Badge> </Badge>
), ),
}, },
{ {
accessorKey: "mainCategoryName", accessorKey: 'mainCategoryName',
header: "Category Name", header: 'Category Name',
}, },
{ {
accessorKey: "description", accessorKey: 'description',
header: "Description", header: 'Description',
cell: ({ row }) => ( cell: ({ row }) => <span className="text-muted-foreground text-sm">{row.getValue('description') || '-'}</span>,
<span className="text-muted-foreground text-sm">
{row.getValue("description") || "-"}
</span>
),
}, },
{ {
accessorKey: "isActive", accessorKey: 'isActive',
header: "Active", header: 'Active',
cell: ({ row }) => ( cell: ({ row }) =>
row.getValue("isActive") ? ( row.getValue('isActive') ? (
<CheckCircle className="h-4 w-4 text-green-600" /> <CheckCircle className="h-4 w-4 text-green-600" />
) : ( ) : (
<XCircle className="h-4 w-4 text-red-600" /> <XCircle className="h-4 w-4 text-red-600" />
) ),
),
}, },
{ {
accessorKey: "sortOrder", accessorKey: 'sortOrder',
header: "Order", header: 'Order',
cell: ({ row }) => ( cell: ({ row }) => <span className="font-mono">{row.getValue('sortOrder')}</span>,
<span className="font-mono">{row.getValue("sortOrder")}</span>
),
}, },
]; ];
@@ -75,7 +62,7 @@ export default function ShopMainCategoriesPage() {
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span className="text-sm font-medium">Project:</span> <span className="text-sm font-medium">Project:</span>
<Select <Select
value={selectedProjectId?.toString() ?? ""} value={selectedProjectId?.toString() ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
@@ -101,9 +88,7 @@ export default function ShopMainCategoriesPage() {
<div className="p-6 space-y-6"> <div className="p-6 space-y-6">
<div> <div>
<h1 className="text-2xl font-bold">Shop Drawing Main Categories</h1> <h1 className="text-2xl font-bold">Shop Drawing Main Categories</h1>
<p className="text-muted-foreground mt-1"> <p className="text-muted-foreground mt-1">Manage main categories () for shop drawings</p>
Manage main categories () for shop drawings
</p>
</div> </div>
{projectFilter} {projectFilter}
<div className="text-center py-12 text-muted-foreground border rounded-lg border-dashed"> <div className="text-center py-12 text-muted-foreground border rounded-lg border-dashed">
@@ -119,25 +104,34 @@ export default function ShopMainCategoriesPage() {
entityName="Main Category" entityName="Main Category"
title="Shop Drawing Main Categories" title="Shop Drawing Main Categories"
description="Manage main categories (หมวดหมู่หลัก) for shop drawings" description="Manage main categories (หมวดหมู่หลัก) for shop drawings"
queryKey={["shop-drawing-main-categories", String(selectedProjectId)]} queryKey={['shop-drawing-main-categories', String(selectedProjectId)]}
fetchFn={() => drawingMasterDataService.getShopMainCategories(selectedProjectId)} fetchFn={async () => {
createFn={(data) => drawingMasterDataService.createShopMainCategory({ console.log(`Fetching Shop Main Categories for project ${selectedProjectId}`);
...data, const data = await drawingMasterDataService.getShopMainCategories(selectedProjectId);
projectId: selectedProjectId, console.log('Shop Main Categories Data:', data);
isActive: data.isActive === "true" || data.isActive === true return data;
})} }}
updateFn={(id, data) => drawingMasterDataService.updateShopMainCategory(id, { createFn={(data) =>
...data, drawingMasterDataService.createShopMainCategory({
isActive: data.isActive === "true" || data.isActive === true ...data,
})} projectId: selectedProjectId,
isActive: data.isActive === 'true' || data.isActive === true,
})
}
updateFn={(id, data) =>
drawingMasterDataService.updateShopMainCategory(id, {
...data,
isActive: data.isActive === 'true' || data.isActive === true,
})
}
deleteFn={(id) => drawingMasterDataService.deleteShopMainCategory(id)} deleteFn={(id) => drawingMasterDataService.deleteShopMainCategory(id)}
columns={columns} columns={columns}
fields={[ fields={[
{ name: "mainCategoryCode", label: "Category Code", type: "text", required: true }, { name: 'mainCategoryCode', label: 'Category Code', type: 'text', required: true },
{ name: "mainCategoryName", label: "Category Name", type: "text", required: true }, { name: 'mainCategoryName', label: 'Category Name', type: 'text', required: true },
{ name: "description", label: "Description", type: "textarea" }, { name: 'description', label: 'Description', type: 'textarea' },
{ name: "isActive", label: "Active", type: "checkbox" }, { name: 'isActive', label: 'Active', type: 'checkbox' },
{ name: "sortOrder", label: "Sort Order", type: "text", required: true }, { name: 'sortOrder', label: 'Sort Order', type: 'text', required: true },
]} ]}
filters={projectFilter} filters={projectFilter}
/> />

View File

@@ -107,7 +107,12 @@ export default function ShopSubCategoriesPage() {
title="Shop Drawing Sub-categories" title="Shop Drawing Sub-categories"
description="Manage sub-categories (หมวดหมู่ย่อย) for shop drawings" description="Manage sub-categories (หมวดหมู่ย่อย) for shop drawings"
queryKey={['shop-drawing-sub-categories', String(selectedProjectId)]} queryKey={['shop-drawing-sub-categories', String(selectedProjectId)]}
fetchFn={() => drawingMasterDataService.getShopSubCategories(selectedProjectId)} fetchFn={async () => {
console.log(`Fetching Shop Sub-Categories for project ${selectedProjectId}`);
const data = await drawingMasterDataService.getShopSubCategories(selectedProjectId);
console.log('Shop Sub-Categories Data:', data);
return data;
}}
createFn={(data) => createFn={(data) =>
drawingMasterDataService.createShopSubCategory({ drawingMasterDataService.createShopSubCategory({
...data, ...data,