260316:1437 Refactor to NestJS 11 #6
Build and Deploy / deploy (push) Successful in 5m37s

This commit is contained in:
admin
2026-03-16 14:37:04 +07:00
parent 75314980d4
commit 1843ed8cf7
7 changed files with 33 additions and 35 deletions
@@ -26,7 +26,7 @@ interface Category {
} }
export default function ContractCategoriesPage() { export default function ContractCategoriesPage() {
const [selectedProjectId, setSelectedProjectId] = useState<number | undefined>(undefined); const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
const { data: projects = [], isLoading: isLoadingProjects } = useProjects(); const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
const columns: ColumnDef<Category>[] = [ const columns: ColumnDef<Category>[] = [
@@ -59,8 +59,8 @@ export default function ContractCategoriesPage() {
<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 ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v || undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
{isLoadingProjects ? ( {isLoadingProjects ? (
@@ -160,7 +160,7 @@ class MappingErrorBoundary extends React.Component<
} }
} }
function CategoryMappingSection({ projectId }: { projectId: number }) { function CategoryMappingSection({ projectId }: { projectId: string }) {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<h2 className="text-xl font-semibold">Category Mappings (Map Sub-categories to Categories)</h2> <h2 className="text-xl font-semibold">Category Mappings (Map Sub-categories to Categories)</h2>
@@ -174,7 +174,7 @@ function CategoryMappingSection({ projectId }: { projectId: number }) {
); );
} }
function ManageMappings({ projectId }: { projectId: number }) { function ManageMappings({ projectId }: { projectId: string }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [selectedCat, setSelectedCat] = useState<string>(''); const [selectedCat, setSelectedCat] = useState<string>('');
const [selectedSubCat, setSelectedSubCat] = useState<string>(''); const [selectedSubCat, setSelectedSubCat] = useState<string>('');
@@ -210,7 +210,7 @@ function ManageMappings({ projectId }: { projectId: number }) {
const mappings = Array.isArray(rawMappings) ? rawMappings : []; const mappings = Array.isArray(rawMappings) ? rawMappings : [];
const createMutation = useMutation({ const createMutation = useMutation({
mutationFn: (data: { projectId: number; categoryId: number; subCategoryId: number }) => mutationFn: (data: { projectId: number | string; categoryId: number; subCategoryId: number }) =>
drawingMasterDataService.createContractMapping(data), drawingMasterDataService.createContractMapping(data),
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['contract-mappings'] }); queryClient.invalidateQueries({ queryKey: ['contract-mappings'] });
@@ -18,7 +18,7 @@ interface SubCategory {
} }
export default function ContractSubCategoriesPage() { export default function ContractSubCategoriesPage() {
const [selectedProjectId, setSelectedProjectId] = useState<number | undefined>(undefined); const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
const { data: projects = [], isLoading: isLoadingProjects } = useProjects(); const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
const columns: ColumnDef<SubCategory>[] = [ const columns: ColumnDef<SubCategory>[] = [
@@ -51,8 +51,8 @@ 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 ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v || undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
{isLoadingProjects ? ( {isLoadingProjects ? (
@@ -24,7 +24,7 @@ interface Volume {
} }
export default function ContractVolumesPage() { export default function ContractVolumesPage() {
const [selectedProjectId, setSelectedProjectId] = useState<number | undefined>(undefined); const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
const { data: projects = [], isLoading: isLoadingProjects } = useProjects(); const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
const columns: ColumnDef<Volume>[] = [ const columns: ColumnDef<Volume>[] = [
@@ -63,8 +63,8 @@ export default function ContractVolumesPage() {
<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 ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v || undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
{isLoadingProjects ? ( {isLoadingProjects ? (
@@ -19,7 +19,7 @@ interface MainCategory {
} }
export default function ShopMainCategoriesPage() { export default function ShopMainCategoriesPage() {
const [selectedProjectId, setSelectedProjectId] = useState<number | undefined>(undefined); const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
const { data: projects = [], isLoading: isLoadingProjects } = useProjects(); const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
const columns: ColumnDef<MainCategory>[] = [ const columns: ColumnDef<MainCategory>[] = [
@@ -62,8 +62,8 @@ 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 ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v || undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
{isLoadingProjects ? ( {isLoadingProjects ? (
@@ -19,7 +19,7 @@ interface SubCategory {
} }
export default function ShopSubCategoriesPage() { export default function ShopSubCategoriesPage() {
const [selectedProjectId, setSelectedProjectId] = useState<number | undefined>(undefined); const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
const { data: projects = [], isLoading: isLoadingProjects } = useProjects(); const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
console.log('Projects Data:', projects); console.log('Projects Data:', projects);
@@ -64,8 +64,8 @@ export default function ShopSubCategoriesPage() {
<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 ?? ''}
onValueChange={(v) => setSelectedProjectId(v ? parseInt(v) : undefined)} onValueChange={(v) => setSelectedProjectId(v || undefined)}
> >
<SelectTrigger className="w-[300px]"> <SelectTrigger className="w-[300px]">
{isLoadingProjects ? ( {isLoadingProjects ? (
@@ -14,7 +14,7 @@ export default function TagsPage() {
}); });
const projectOptions = [ const projectOptions = [
{ label: "Global (All Projects)", value: "" }, { label: "Global (All Projects)", value: "__none__" },
...(projectsData || []).map((p: Record<string, unknown>) => ({ ...(projectsData || []).map((p: Record<string, unknown>) => ({
label: p.project_name || p.project_code || `Project ${p.id}`, label: p.project_name || p.project_code || `Project ${p.id}`,
value: String(p.id), value: String(p.id),
@@ -57,11 +57,9 @@ export default function TagsPage() {
const formatPayload = (data: Record<string, unknown>) => { const formatPayload = (data: Record<string, unknown>) => {
const payload = { ...data }; const payload = { ...data };
// Backend entity uses project_id (underscore) per ADR-017/018 schema // ADR-019: project_id is now a UUID string or '__none__' for global
if (!payload.project_id || payload.project_id === "") { if (!payload.project_id || payload.project_id === "__none__") {
payload.project_id = null; payload.project_id = null;
} else {
payload.project_id = Number(payload.project_id);
} }
return payload; return payload;
}; };
@@ -14,7 +14,7 @@ export interface ContractVolume {
} }
export interface CreateContractVolumeDto { export interface CreateContractVolumeDto {
projectId: number; projectId: number | string;
volumeCode: string; volumeCode: string;
volumeName: string; volumeName: string;
description?: string; description?: string;
@@ -34,7 +34,7 @@ export interface ContractCategory {
} }
export interface CreateContractCategoryDto { export interface CreateContractCategoryDto {
projectId: number; projectId: number | string;
catCode: string; catCode: string;
catName: string; catName: string;
description?: string; description?: string;
@@ -54,7 +54,7 @@ export interface ContractSubCategory {
} }
export interface CreateContractSubCategoryDto { export interface CreateContractSubCategoryDto {
projectId: number; projectId: number | string;
subCatCode: string; subCatCode: string;
subCatName: string; subCatName: string;
description?: string; description?: string;
@@ -75,7 +75,7 @@ export interface ShopMainCategory {
} }
export interface CreateShopMainCategoryDto { export interface CreateShopMainCategoryDto {
projectId: number; projectId: number | string;
mainCategoryCode: string; mainCategoryCode: string;
mainCategoryName: string; mainCategoryName: string;
description?: string; description?: string;
@@ -97,7 +97,7 @@ export interface ShopSubCategory {
} }
export interface CreateShopSubCategoryDto { export interface CreateShopSubCategoryDto {
projectId: number; projectId: number | string;
subCategoryCode: string; subCategoryCode: string;
subCategoryName: string; subCategoryName: string;
description?: string; description?: string;
@@ -110,7 +110,7 @@ export interface CreateShopSubCategoryDto {
// =========================== // ===========================
export const drawingMasterDataService = { export const drawingMasterDataService = {
// --- Contract Volumes --- // --- Contract Volumes ---
async getContractVolumes(projectId: number): Promise<ContractVolume[]> { async getContractVolumes(projectId: number | string): Promise<ContractVolume[]> {
const response = await apiClient.get(`/drawings/master-data/contract/volumes`, { const response = await apiClient.get(`/drawings/master-data/contract/volumes`, {
params: { projectId }, params: { projectId },
}); });
@@ -132,7 +132,7 @@ export const drawingMasterDataService = {
}, },
// --- Contract Categories --- // --- Contract Categories ---
async getContractCategories(projectId: number): Promise<ContractCategory[]> { async getContractCategories(projectId: number | string): Promise<ContractCategory[]> {
const response = await apiClient.get(`/drawings/master-data/contract/categories`, { const response = await apiClient.get(`/drawings/master-data/contract/categories`, {
params: { projectId }, params: { projectId },
}); });
@@ -154,7 +154,7 @@ export const drawingMasterDataService = {
}, },
// --- Contract Sub-categories --- // --- Contract Sub-categories ---
async getContractSubCategories(projectId: number): Promise<ContractSubCategory[]> { async getContractSubCategories(projectId: number | string): Promise<ContractSubCategory[]> {
const response = await apiClient.get(`/drawings/master-data/contract/sub-categories`, { const response = await apiClient.get(`/drawings/master-data/contract/sub-categories`, {
params: { projectId }, params: { projectId },
}); });
@@ -180,7 +180,7 @@ export const drawingMasterDataService = {
// --- Contract Category Mappings --- // --- Contract Category Mappings ---
async getContractMappings( async getContractMappings(
projectId: number, projectId: number | string,
categoryId?: number categoryId?: number
): Promise<{ id: number; subCategory: ContractSubCategory; category: ContractCategory }[]> { ): Promise<{ id: number; subCategory: ContractSubCategory; category: ContractCategory }[]> {
const response = await apiClient.get(`/drawings/master-data/contract/mappings`, { const response = await apiClient.get(`/drawings/master-data/contract/mappings`, {
@@ -190,7 +190,7 @@ export const drawingMasterDataService = {
}, },
async createContractMapping(data: { async createContractMapping(data: {
projectId: number; projectId: number | string;
categoryId: number; categoryId: number;
subCategoryId: number; subCategoryId: number;
}): Promise<{ id: number }> { }): Promise<{ id: number }> {
@@ -203,7 +203,7 @@ export const drawingMasterDataService = {
}, },
// --- Shop Main Categories --- // --- Shop Main Categories ---
async getShopMainCategories(projectId: number): Promise<ShopMainCategory[]> { async getShopMainCategories(projectId: number | string): Promise<ShopMainCategory[]> {
const response = await apiClient.get(`/drawings/master-data/shop/main-categories`, { const response = await apiClient.get(`/drawings/master-data/shop/main-categories`, {
params: { projectId }, params: { projectId },
}); });
@@ -225,7 +225,7 @@ export const drawingMasterDataService = {
}, },
// --- Shop Sub-categories --- // --- Shop Sub-categories ---
async getShopSubCategories(projectId: number, mainCategoryId?: number): Promise<ShopSubCategory[]> { async getShopSubCategories(projectId: number | string, mainCategoryId?: number): Promise<ShopSubCategory[]> {
const response = await apiClient.get(`/drawings/master-data/shop/sub-categories`, { const response = await apiClient.get(`/drawings/master-data/shop/sub-categories`, {
params: { projectId, mainCategoryId }, params: { projectId, mainCategoryId },
}); });