690327:1611 Fixing Refactor ADR-019 Naming convention uuid #187
This commit is contained in:
+140
-780
File diff suppressed because it is too large
Load Diff
+140
-792
File diff suppressed because it is too large
Load Diff
@@ -12,16 +12,6 @@ import { projectService } from '@/lib/services/project.service';
|
|||||||
import { contractService } from '@/lib/services/contract.service';
|
import { contractService } from '@/lib/services/contract.service';
|
||||||
import { Contract } from '@/types/contract';
|
import { Contract } from '@/types/contract';
|
||||||
|
|
||||||
// Helper to extract array data from various API response formats (paginated vs direct)
|
|
||||||
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 [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const masterDataKeys = {
|
export const masterDataKeys = {
|
||||||
all: ['masterData'] as const,
|
all: ['masterData'] as const,
|
||||||
organizations: () => [...masterDataKeys.all, 'organizations'] as const,
|
organizations: () => [...masterDataKeys.all, 'organizations'] as const,
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Git Conventions
|
||||||
|
|
||||||
|
**Version:** 1.8.4
|
||||||
|
**Last Updated:** 2026-03-24
|
||||||
|
**Location:** `specs/05-Engineering-Guidelines/05-05-git-conventions.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit Message Format
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <description>
|
||||||
|
[optional body]
|
||||||
|
[optional footer: Refs #issue]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Types
|
||||||
|
|
||||||
|
| Type | When to Use |
|
||||||
|
| ---------- | ------------------------------------------- |
|
||||||
|
| `feat` | Add new feature |
|
||||||
|
| `fix` | Fix bug |
|
||||||
|
| `refactor` | Restructure code without behavior change |
|
||||||
|
| `docs` | Edit documentation |
|
||||||
|
| `test` | Add/modify tests |
|
||||||
|
| `chore` | Infra, config, dependency updates |
|
||||||
|
| `style` | Formatting, linting (no logic change) |
|
||||||
|
| `spec` | Edit specs/ documents |
|
||||||
|
| `adr` | Add/modify Architecture Decision Record |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(correspondence): add create correspondence endpoint
|
||||||
|
fix(uuid): remove parseInt on projectId in rfas/page.tsx
|
||||||
|
spec(requirements): update edge cases for drawing workflow
|
||||||
|
adr(019): add UUID serialization behavior notes
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Branch Naming
|
||||||
|
|
||||||
|
```
|
||||||
|
feature/<description> # New feature
|
||||||
|
fix/<issue-number>-<description> # Bug fix
|
||||||
|
spec/<category>/<description> # Spec changes
|
||||||
|
adr/<number>-<description> # New/modify ADR
|
||||||
|
refactor/<description> # Refactor
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
feature/correspondence-cc-support
|
||||||
|
fix/23-uuid-parseInt-rfas-page
|
||||||
|
spec/requirements/update-correspondence-workflow
|
||||||
|
adr/019-uuid-serialization-behavior
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [FullStack Guidelines](05-01-fullstack-js-guidelines.md)
|
||||||
|
- [Backend Guidelines](05-02-backend-guidelines.md)
|
||||||
|
- [Frontend Guidelines](05-03-frontend-guidelines.md)
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# Code Snippets
|
||||||
|
|
||||||
|
**Version:** 1.8.4
|
||||||
|
**Last Updated:** 2026-03-24
|
||||||
|
**Location:** `specs/05-Engineering-Guidelines/05-06-code-snippets.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend DTO Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [dto-new] → Create DTO with validator
|
||||||
|
@IsUUID()
|
||||||
|
@ApiProperty({ description: 'Project UUID (public)' })
|
||||||
|
projectUuid!: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@ApiProperty({ required: false, description: 'Internal project ID' })
|
||||||
|
projectId?: number; // resolved internally, never from client
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend Form Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [form-rhf-zod] → Create form schema + hook
|
||||||
|
const schema = z.object({
|
||||||
|
projectUuid: z.string().uuid('รหัสโครงการไม่ถูกต้อง'),
|
||||||
|
title: z.string().min(3, 'กรุณากรอกหัวข้ออย่างน้อย 3 ตัวอักษร'),
|
||||||
|
});
|
||||||
|
const form = useForm({ resolver: zodResolver(schema) });
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## UUID Safe Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [uuid-safe] → Check UUID before use
|
||||||
|
const safeUuid = (val: string | number): string => {
|
||||||
|
if (typeof val === 'number') {
|
||||||
|
Logger.warn(`UUID received as number: ${val}`);
|
||||||
|
return String(val); // or throw error per policy
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend Error Handling Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [backend-error] → Standard error handling
|
||||||
|
if (!entity) {
|
||||||
|
this.logger.warn(`Entity not found: ${uuid}`, 'Service.findOne');
|
||||||
|
throw new NotFoundException(`Resource with UUID ${uuid} not found`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend Query Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [frontend-query] → TanStack Query v5 standard
|
||||||
|
const { data, error, isLoading } = useQuery({
|
||||||
|
queryKey: ['correspondence', uuid],
|
||||||
|
queryFn: () => api.get(`/correspondences/${uuid}`),
|
||||||
|
});
|
||||||
|
// v5: onError removed from useQuery — handle error via return value
|
||||||
|
if (error) toast.error('ไม่สามารถโหลดข้อมูลได้');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Redis Cache Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// [redis-cache] → Cache-Aside Pattern
|
||||||
|
const cacheKey = `correspondence:${uuid}`;
|
||||||
|
const cached = await this.cacheManager.get(cacheKey);
|
||||||
|
if (cached) return cached;
|
||||||
|
const entity = await this.repo.findOneBy({ uuid });
|
||||||
|
if (entity) {
|
||||||
|
await this.cacheManager.set(cacheKey, entity, 300); // 5 minutes
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Backend Guidelines](05-02-backend-guidelines.md)
|
||||||
|
- [Frontend Guidelines](05-03-frontend-guidelines.md)
|
||||||
|
- [Testing Strategy](05-04-testing-strategy.md)
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# i18n Guidelines
|
||||||
|
|
||||||
|
**Version:** 1.8.4
|
||||||
|
**Last Updated:** 2026-03-24
|
||||||
|
**Location:** `specs/05-Engineering-Guidelines/05-08-i18n-guidelines.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Comments & Documentation
|
||||||
|
|
||||||
|
- ✅ **Comments:** Write in Thai (for team understanding)
|
||||||
|
- ✅ **JSDoc:** Use Thai to explain business logic
|
||||||
|
- ✅ **Error messages:** Store as keys in i18n files, not hardcoded
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## i18n Structure (Frontend)
|
||||||
|
|
||||||
|
```
|
||||||
|
locales/
|
||||||
|
├── th/
|
||||||
|
│ ├── common.json # General messages
|
||||||
|
│ ├── errors.json # Error messages
|
||||||
|
│ ├── forms.json # Form labels & validation
|
||||||
|
│ └── modules/
|
||||||
|
│ ├── correspondence.json
|
||||||
|
│ └── rfa.json
|
||||||
|
└── en/ # Reserved for future
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Validation Messages (Zod)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ CORRECT — Use reference key
|
||||||
|
z.string().min(3, { message: 'errors:min_length_3' });
|
||||||
|
// Then resolve in frontend via i18n hook
|
||||||
|
|
||||||
|
// ❌ WRONG — Hardcode Thai in schema
|
||||||
|
z.string().min(3, 'กรุณากรอกอย่างน้อย 3 ตัวอักษร'); // Makes testing difficult
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Language Rules Summary
|
||||||
|
|
||||||
|
| Context | Language |
|
||||||
|
| --------------- | ---------- |
|
||||||
|
| Code (variables, functions, classes) | English |
|
||||||
|
| Comments | Thai |
|
||||||
|
| JSDoc | Thai |
|
||||||
|
| Error messages | i18n keys |
|
||||||
|
| UI labels | i18n files |
|
||||||
|
| Documentation | Thai |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Frontend Guidelines](05-03-frontend-guidelines.md)
|
||||||
|
- [Glossary](../00-overview/00-02-glossary.md)
|
||||||
Reference in New Issue
Block a user