690327:0024 Fixing Refactor ADR-019 Naming convention uuid #11
This commit is contained in:
@@ -17,7 +17,7 @@ import { Organization } from '../../organization/entities/organization.entity';
|
|||||||
import { UserAssignment } from './user-assignment.entity';
|
import { UserAssignment } from './user-assignment.entity';
|
||||||
import { UserPreference } from './user-preference.entity';
|
import { UserPreference } from './user-preference.entity';
|
||||||
import { UuidBaseEntity } from '../../../common/entities/uuid-base.entity';
|
import { UuidBaseEntity } from '../../../common/entities/uuid-base.entity';
|
||||||
import { Exclude } from 'class-transformer';
|
import { Exclude, Expose } from 'class-transformer';
|
||||||
|
|
||||||
@Entity('users')
|
@Entity('users')
|
||||||
export class User extends UuidBaseEntity {
|
export class User extends UuidBaseEntity {
|
||||||
@@ -57,12 +57,19 @@ export class User extends UuidBaseEntity {
|
|||||||
|
|
||||||
// Relation กับ Organization (สังกัดหลัก)
|
// Relation กับ Organization (สังกัดหลัก)
|
||||||
@Column({ name: 'primary_organization_id', nullable: true })
|
@Column({ name: 'primary_organization_id', nullable: true })
|
||||||
|
@Exclude() // INT ID - never expose, use primaryOrganizationPublicId instead (ADR-019)
|
||||||
primaryOrganizationId?: number;
|
primaryOrganizationId?: number;
|
||||||
|
|
||||||
@ManyToOne(() => Organization, { nullable: true, onDelete: 'SET NULL' })
|
@ManyToOne(() => Organization, { nullable: true, onDelete: 'SET NULL' })
|
||||||
@JoinColumn({ name: 'primary_organization_id' })
|
@JoinColumn({ name: 'primary_organization_id' })
|
||||||
organization?: Organization;
|
organization?: Organization;
|
||||||
|
|
||||||
|
// ADR-019: Expose UUID instead of INT ID
|
||||||
|
@Expose({ name: 'primaryOrganizationId' })
|
||||||
|
get primaryOrganizationPublicId(): string | undefined {
|
||||||
|
return this.organization?.publicId;
|
||||||
|
}
|
||||||
|
|
||||||
// Relation กับ Assignments (RBAC)
|
// Relation กับ Assignments (RBAC)
|
||||||
@OneToMany(() => UserAssignment, (assignment) => assignment.user)
|
@OneToMany(() => UserAssignment, (assignment) => assignment.user)
|
||||||
assignments?: UserAssignment[];
|
assignments?: UserAssignment[];
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export class UserService {
|
|||||||
.leftJoinAndSelect('user.preference', 'preference') // Optional
|
.leftJoinAndSelect('user.preference', 'preference') // Optional
|
||||||
.leftJoinAndSelect('user.assignments', 'assignments')
|
.leftJoinAndSelect('user.assignments', 'assignments')
|
||||||
.leftJoinAndSelect('assignments.role', 'role')
|
.leftJoinAndSelect('assignments.role', 'role')
|
||||||
|
.leftJoinAndSelect('user.organization', 'organization') // [FIX] Required for primaryOrganizationPublicId getter (ADR-019)
|
||||||
.select([
|
.select([
|
||||||
'user.user_id',
|
'user.user_id',
|
||||||
'user.publicId',
|
'user.publicId',
|
||||||
@@ -92,13 +93,13 @@ export class UserService {
|
|||||||
'user.firstName',
|
'user.firstName',
|
||||||
'user.lastName',
|
'user.lastName',
|
||||||
'user.lineId',
|
'user.lineId',
|
||||||
'user.primaryOrganizationId',
|
|
||||||
'user.isActive',
|
'user.isActive',
|
||||||
'user.createdAt',
|
'user.createdAt',
|
||||||
'user.updatedAt',
|
'user.updatedAt',
|
||||||
'assignments.id',
|
'assignments.id',
|
||||||
'role.roleId',
|
'role.roleId',
|
||||||
'role.roleName',
|
'role.roleName',
|
||||||
|
'organization.publicId', // [FIX] Expose org UUID for getter (ADR-019)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Apply Filters
|
// Apply Filters
|
||||||
@@ -146,6 +147,7 @@ export class UserService {
|
|||||||
'assignments',
|
'assignments',
|
||||||
'assignments.role',
|
'assignments.role',
|
||||||
'assignments.role.permissions', // [FIX] Required for RBAC AbilityFactory
|
'assignments.role.permissions', // [FIX] Required for RBAC AbilityFactory
|
||||||
|
'organization', // [FIX] Required for primaryOrganizationPublicId getter (ADR-019)
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -164,6 +166,7 @@ export class UserService {
|
|||||||
'assignments',
|
'assignments',
|
||||||
'assignments.role',
|
'assignments.role',
|
||||||
'assignments.role.permissions',
|
'assignments.role.permissions',
|
||||||
|
'organization', // [FIX] Required for primaryOrganizationPublicId getter (ADR-019)
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import { SearchContractDto, CreateContractDto, UpdateContractDto } from '@/types
|
|||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
|
||||||
interface _Project {
|
interface _Project {
|
||||||
id: string; // ADR-019: uuid exposed as 'id' (string)
|
publicId: string; // ADR-019: uuid exposed as 'publicId' (string)
|
||||||
projectCode: string;
|
projectCode: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
}
|
}
|
||||||
@@ -206,8 +206,8 @@ export default function ContractsPage() {
|
|||||||
|
|
||||||
const handleEdit = (contract: Contract) => {
|
const handleEdit = (contract: Contract) => {
|
||||||
setEditingUuid(contract.id);
|
setEditingUuid(contract.id);
|
||||||
// ADR-019: project.id is the project's UUID (exposed via @Expose)
|
// ADR-019: project.publicId is the project's UUID
|
||||||
const pId = contract.project?.id || '';
|
const pId = contract.project?.publicId || '';
|
||||||
reset({
|
reset({
|
||||||
contractCode: contract.contractCode,
|
contractCode: contract.contractCode,
|
||||||
contractName: contract.contractName,
|
contractName: contract.contractName,
|
||||||
@@ -299,8 +299,8 @@ export default function ContractsPage() {
|
|||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{projects?.map((p) => (
|
{projects?.map((p) => (
|
||||||
// ADR-019: Project exposes UUID as 'id' (string)
|
// ADR-019: Project exposes UUID as 'publicId'
|
||||||
<SelectItem key={p.id} value={p.id}>
|
<SelectItem key={p.publicId} value={p.publicId}>
|
||||||
{p.projectCode} - {p.projectName}
|
{p.projectCode} - {p.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ export default function ContractCategoriesPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects as { id?: number; uuid?: string; projectCode: string; projectName: string }[]).map((project) => (
|
{(projects as { id?: number; publicId?: string; projectCode: string; projectName: string }[]).map((project) => (
|
||||||
<SelectItem key={project.uuid || project.id} value={String(project.id || project.uuid)}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ export default function ContractSubCategoriesPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects as { id?: number; uuid?: string; projectCode: string; projectName: string }[]).map((project) => (
|
{(projects as { id?: number; publicId?: string; projectCode: string; projectName: string }[]).map((project) => (
|
||||||
<SelectItem key={project.uuid || project.id} value={String(project.id || project.uuid)}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ export default function ContractVolumesPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects as { id?: number; uuid?: string; projectCode: string; projectName: string }[]).map((project) => (
|
{(projects as { id?: number; publicId?: string; projectCode: string; projectName: string }[]).map((project) => (
|
||||||
<SelectItem key={project.uuid || project.id} value={String(project.id || project.uuid)}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ export default function ShopMainCategoriesPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects as { id?: number; uuid?: string; projectCode: string; projectName: string }[]).map((project) => (
|
{(projects as { id?: number; publicId?: string; projectCode: string; projectName: string }[]).map((project) => (
|
||||||
<SelectItem key={project.uuid || project.id} value={String(project.id || project.uuid)}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ export default function ShopSubCategoriesPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects as { id?: number; uuid?: string; projectCode: string; projectName: string }[]).map((project) => (
|
{(projects as { id?: number; publicId?: string; projectCode: string; projectName: string }[]).map((project) => (
|
||||||
<SelectItem key={project.uuid || project.id} value={String(project.id || project.uuid)}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -24,12 +24,15 @@ export default function EditTemplatePage() {
|
|||||||
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
||||||
const { data: projects = [] } = useProjects();
|
const { data: projects = [] } = useProjects();
|
||||||
const projectId = template?.projectId || 1;
|
const projectId = template?.projectId || 1;
|
||||||
const { data: contracts = [] } = useContracts(projectId);
|
const { data: contractsData } = useContracts(projectId);
|
||||||
const contractId = contracts[0]?.id;
|
const contracts = Array.isArray(contractsData) ? contractsData : [];
|
||||||
|
const firstContract = contracts[0] as { id?: number; publicId?: string } | undefined;
|
||||||
|
const contractId = firstContract?.publicId ?? firstContract?.id;
|
||||||
const { data: disciplines = [] } = useDisciplines(contractId);
|
const { data: disciplines = [] } = useDisciplines(contractId);
|
||||||
|
|
||||||
const selectedProjectName =
|
const selectedProjectName =
|
||||||
projects.find((p: { id?: number; uuid?: string; projectCode: string; projectName: string }) => p.id === projectId)
|
projects.find((p: { id?: number; publicId?: string; projectCode: string; projectName: string }) =>
|
||||||
|
String(p.publicId ?? p.id) === String(projectId))
|
||||||
?.projectName || 'LCBP3';
|
?.projectName || 'LCBP3';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -14,12 +14,15 @@ export default function NewTemplatePage() {
|
|||||||
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
||||||
const { data: projects = [] } = useProjects();
|
const { data: projects = [] } = useProjects();
|
||||||
const projectId = 1; // Default or sync with selection
|
const projectId = 1; // Default or sync with selection
|
||||||
const { data: contracts = [] } = useContracts(projectId);
|
const { data: contractsData } = useContracts(projectId);
|
||||||
const contractId = contracts[0]?.id;
|
const contracts = Array.isArray(contractsData) ? contractsData : [];
|
||||||
|
const firstContract = contracts[0] as { id?: number; publicId?: string } | undefined;
|
||||||
|
const contractId = firstContract?.publicId ?? firstContract?.id;
|
||||||
const { data: disciplines = [] } = useDisciplines(contractId);
|
const { data: disciplines = [] } = useDisciplines(contractId);
|
||||||
|
|
||||||
const selectedProjectName =
|
const selectedProjectName =
|
||||||
projects.find((p: { id: number; projectName: string }) => p.id === projectId)?.projectName || 'LCBP3';
|
projects.find((p: { id?: number; publicId?: string; projectName: string }) =>
|
||||||
|
String(p.publicId ?? p.id) === String(projectId))?.projectName || 'LCBP3';
|
||||||
|
|
||||||
const handleSave = async (data: Partial<NumberingTemplate>) => {
|
const handleSave = async (data: Partial<NumberingTemplate>) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ export default function NumberingPage() {
|
|||||||
|
|
||||||
// Master Data
|
// Master Data
|
||||||
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
|
||||||
const { data: contracts = [] } = useContracts(selectedProjectId);
|
const { data: contractsData } = useContracts(selectedProjectId);
|
||||||
|
const contracts = Array.isArray(contractsData) ? contractsData : [];
|
||||||
const firstContract = contracts[0] as { id?: number; publicId?: string } | undefined;
|
const firstContract = contracts[0] as { id?: number; publicId?: string } | undefined;
|
||||||
const contractId = firstContract?.publicId ?? firstContract?.id;
|
const contractId = firstContract?.publicId ?? firstContract?.id;
|
||||||
const { data: disciplines = [] } = useDisciplines(contractId);
|
const { data: disciplines = [] } = useDisciplines(contractId);
|
||||||
@@ -147,8 +148,7 @@ export default function NumberingPage() {
|
|||||||
.filter(
|
.filter(
|
||||||
(t) =>
|
(t) =>
|
||||||
!t.projectId ||
|
!t.projectId ||
|
||||||
String(t.project?.id ?? t.project?.publicId) === selectedProjectId ||
|
String(t.project?.publicId) === selectedProjectId
|
||||||
t.project?.publicId === selectedProjectId
|
|
||||||
)
|
)
|
||||||
.map((template) => (
|
.map((template) => (
|
||||||
<Card key={template.id} className="p-6 hover:shadow-md transition-shadow">
|
<Card key={template.id} className="p-6 hover:shadow-md transition-shadow">
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import {
|
|||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
id: string; // ADR-019: uuid exposed as 'id'
|
publicId: string; // ADR-019: uuid exposed as 'publicId'
|
||||||
projectCode: string;
|
projectCode: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
@@ -71,7 +71,7 @@ export default function ProjectsPage() {
|
|||||||
|
|
||||||
const confirmDelete = () => {
|
const confirmDelete = () => {
|
||||||
if (projectToDelete) {
|
if (projectToDelete) {
|
||||||
deleteProject.mutate(projectToDelete.id, {
|
deleteProject.mutate(projectToDelete.publicId, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setDeleteDialogOpen(false);
|
setDeleteDialogOpen(false);
|
||||||
setProjectToDelete(null);
|
setProjectToDelete(null);
|
||||||
@@ -145,7 +145,7 @@ export default function ProjectsPage() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const handleEdit = (project: Project) => {
|
const handleEdit = (project: Project) => {
|
||||||
setEditingUuid(project.id);
|
setEditingUuid(project.publicId);
|
||||||
reset({
|
reset({
|
||||||
projectCode: project.projectCode,
|
projectCode: project.projectCode,
|
||||||
projectName: project.projectName,
|
projectName: project.projectName,
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ export default function TagsPage() {
|
|||||||
accessorKey: 'project_id',
|
accessorKey: 'project_id',
|
||||||
header: 'Project',
|
header: 'Project',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const item = row.original as Tag & { project?: { id?: number | string; projectName?: string; projectCode?: string } };
|
const item = row.original as Tag & { project?: { id?: number | string; publicId?: string; projectName?: string; projectCode?: string } };
|
||||||
const project = item.project;
|
const project = item.project;
|
||||||
if (!project) return <span className="text-muted-foreground italic">Global</span>;
|
if (!project) return <span className="text-muted-foreground italic">Global</span>;
|
||||||
return (project.projectName || project.projectCode || `Project ${project.id}`) as React.ReactNode;
|
return (project.projectName || project.projectCode || `Project ${project.publicId || project.id}`) as React.ReactNode;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,10 +75,10 @@ export default function TagsPage() {
|
|||||||
const items = await masterDataService.getTags();
|
const items = await masterDataService.getTags();
|
||||||
// ADR-019: Map project_id INT → project UUID for edit mode select matching
|
// ADR-019: Map project_id INT → project UUID for edit mode select matching
|
||||||
return items.map((item) => {
|
return items.map((item) => {
|
||||||
const rec = item as Tag & { project?: { id?: number | string; uuid?: string }; project_id?: number | string };
|
const rec = item as Tag & { project?: { id?: number | string; publicId?: string }; project_id?: number | string };
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
project_id: rec.project?.id || rec.project?.uuid || (rec.project_id ? String(rec.project_id) : null),
|
project_id: rec.project?.publicId || rec.project?.id || (rec.project_id ? String(rec.project_id) : null),
|
||||||
} as Tag;
|
} as Tag;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export default function DrawingsPage() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{projects.map((project: { id: string; projectName: string; projectCode: string }) => (
|
{projects.map((project: { id?: number; publicId?: string; projectName: string; projectCode: string }) => (
|
||||||
<SelectItem key={project.id} value={project.id}>
|
<SelectItem key={project.publicId || project.id} value={String(project.publicId || project.id)}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -25,6 +25,16 @@ import { useState, useEffect } from 'react';
|
|||||||
import { Loader2 } from 'lucide-react';
|
import { Loader2 } from 'lucide-react';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
|
||||||
|
// Helper to extract array data from various API response formats
|
||||||
|
const extractArrayData = <T,>(value: unknown): T[] => {
|
||||||
|
if (Array.isArray(value)) return value as T[];
|
||||||
|
if (value && typeof value === 'object' && 'data' in value) {
|
||||||
|
const data = (value as { data?: unknown }).data;
|
||||||
|
if (Array.isArray(data)) return data as T[];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
// Base Schema
|
// Base Schema
|
||||||
const baseSchema = z.object({
|
const baseSchema = z.object({
|
||||||
drawingType: z.enum(['CONTRACT', 'SHOP', 'AS_BUILT']),
|
drawingType: z.enum(['CONTRACT', 'SHOP', 'AS_BUILT']),
|
||||||
@@ -79,7 +89,8 @@ export function DrawingUploadForm() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// Project list
|
// Project list
|
||||||
const { data: projects = [], isLoading: isLoadingProjects } = useProjects();
|
const { data: projectsData, isLoading: isLoadingProjects } = useProjects();
|
||||||
|
const projects = extractArrayData<{ id?: number; publicId?: string; projectName: string; projectCode: string }>(projectsData);
|
||||||
|
|
||||||
// Selected project for category fetching
|
// Selected project for category fetching
|
||||||
const [selectedProjectId, setSelectedProjectId] = useState<number | string | undefined>(undefined);
|
const [selectedProjectId, setSelectedProjectId] = useState<number | string | undefined>(undefined);
|
||||||
@@ -119,9 +130,9 @@ export function DrawingUploadForm() {
|
|||||||
}
|
}
|
||||||
// Try to resolve UUID→INT from projects list, or pass UUID directly
|
// Try to resolve UUID→INT from projects list, or pass UUID directly
|
||||||
const project = projects.find(
|
const project = projects.find(
|
||||||
(p: { id: string; uuid?: string }) => p.id === watchedProjectId || p.uuid === watchedProjectId
|
(p: { id?: number; publicId?: string }) => String(p.publicId ?? p.id) === watchedProjectId
|
||||||
) as { id: string; uuid?: string } | undefined;
|
) as { id?: number; publicId?: string } | undefined;
|
||||||
setSelectedProjectId(project?.id ?? watchedProjectId);
|
setSelectedProjectId(project?.publicId ?? project?.id ?? watchedProjectId);
|
||||||
}, [watchedProjectId, projects]);
|
}, [watchedProjectId, projects]);
|
||||||
|
|
||||||
const onSubmit = (data: DrawingFormData) => {
|
const onSubmit = (data: DrawingFormData) => {
|
||||||
@@ -181,11 +192,14 @@ export function DrawingUploadForm() {
|
|||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{projects.map((project: { id: string; projectName: string; projectCode: string }) => (
|
{projects.map((project) => {
|
||||||
<SelectItem key={project.id} value={project.id}>
|
const projectValue = String(project.publicId ?? project.id ?? '');
|
||||||
|
return (
|
||||||
|
<SelectItem key={projectValue} value={projectValue}>
|
||||||
{project.projectCode} - {project.projectName}
|
{project.projectCode} - {project.projectName}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
{errors.projectId && <p className="text-sm text-destructive">{errors.projectId.message}</p>}
|
{errors.projectId && <p className="text-sm text-destructive">{errors.projectId.message}</p>}
|
||||||
|
|||||||
Reference in New Issue
Block a user