264 lines
4.5 KiB
Markdown
264 lines
4.5 KiB
Markdown
You are a Senior Full Stack Engineer.
|
|
|
|
Project:
|
|
Training Management System (TMS)
|
|
|
|
Current task:
|
|
Change training hours storage and display from decimal hours to duration minutes.
|
|
|
|
Requirement:
|
|
Training duration must be stored and calculated as hours and minutes, not decimal hours.
|
|
|
|
Important constraints:
|
|
|
|
- Do NOT use AM/PM.
|
|
- Do NOT use clock TimePicker.
|
|
- Do NOT store Date object.
|
|
- Keep Thai UI.
|
|
- Keep responsive/mobile behavior.
|
|
- Minimal-impact changes only.
|
|
|
|
Business examples:
|
|
|
|
- 01:45 = 1 ชั่วโมง 45 นาที
|
|
- 00:15 = 15 นาที
|
|
- 02:00 = 2 ชั่วโมง
|
|
- 30:00 = 30 ชั่วโมง
|
|
|
|
Recommended storage:
|
|
Store duration as total minutes.
|
|
|
|
Examples:
|
|
|
|
- 01:45 -> 105
|
|
- 00:15 -> 15
|
|
- 02:00 -> 120
|
|
- 30:00 -> 1800
|
|
|
|
Part 1: Database
|
|
|
|
Check current fields:
|
|
|
|
- submittedHours
|
|
- approvedHours
|
|
- targetHours
|
|
- kHours
|
|
- sHours
|
|
- aHours
|
|
|
|
If current DB stores decimal hours, add new minute-based fields if needed:
|
|
|
|
training_records:
|
|
|
|
- submittedMinutes integer
|
|
- approvedMinutes integer
|
|
|
|
employee_training_targets:
|
|
|
|
- totalTargetMinutes integer
|
|
- kTargetMinutes integer
|
|
- sTargetMinutes integer
|
|
- aTargetMinutes integer
|
|
|
|
training_policy:
|
|
|
|
- totalTargetMinutes integer
|
|
- kTargetMinutes integer
|
|
- sTargetMinutes integer
|
|
- aTargetMinutes integer
|
|
|
|
Important:
|
|
Do not drop old decimal fields yet.
|
|
Keep old fields for compatibility during migration.
|
|
|
|
Migration:
|
|
|
|
- Convert old decimal hours to minutes:
|
|
minutes = ROUND(hours \* 60)
|
|
|
|
Part 2: Duration Picker UI
|
|
|
|
Create or update component:
|
|
|
|
src/components/ui/duration-picker.tsx
|
|
|
|
Props:
|
|
|
|
- valueMinutes: number | null
|
|
- onChange: (minutes: number | null) => void
|
|
- maxHours?: number
|
|
- minuteStep?: number
|
|
- disabled?: boolean
|
|
|
|
UI:
|
|
|
|
- Two dropdowns:
|
|
1. ชั่วโมง
|
|
2. นาที
|
|
|
|
Hour options:
|
|
|
|
- 00 to 30
|
|
|
|
Minute options:
|
|
|
|
- 00
|
|
- 15
|
|
- 30
|
|
- 45
|
|
|
|
Display:
|
|
|
|
- --:-- when empty
|
|
- 00:15
|
|
- 01:45
|
|
- 02:00
|
|
- 30:00
|
|
|
|
Do not display:
|
|
|
|
- AM
|
|
- PM
|
|
|
|
Part 3: Form Behavior
|
|
|
|
In Create/Edit Training Record form:
|
|
|
|
Field:
|
|
|
|
- จำนวนชั่วโมงอบรม \*
|
|
|
|
Use DurationPicker.
|
|
|
|
Save:
|
|
|
|
- submittedMinutes
|
|
|
|
Validation:
|
|
|
|
- required
|
|
- > 0 minutes
|
|
- <= 1800 minutes
|
|
|
|
Thai messages:
|
|
|
|
- กรุณาระบุจำนวนชั่วโมงอบรม
|
|
- จำนวนชั่วโมงอบรมต้องมากกว่า 0 นาที
|
|
- จำนวนชั่วโมงอบรมต้องไม่เกิน 30 ชั่วโมง
|
|
|
|
Part 4: Display Formatting
|
|
|
|
Create helper functions:
|
|
|
|
formatDurationThai(minutes: number): string
|
|
|
|
Examples:
|
|
|
|
- 15 -> 15 นาที
|
|
- 60 -> 1 ชั่วโมง
|
|
- 105 -> 1 ชั่วโมง 45 นาที
|
|
- 120 -> 2 ชั่วโมง
|
|
- 1800 -> 30 ชั่วโมง
|
|
|
|
formatDurationHHMM(minutes: number): string
|
|
|
|
Examples:
|
|
|
|
- 15 -> 00:15
|
|
- 105 -> 01:45
|
|
- 120 -> 02:00
|
|
|
|
Part 5: Calculations
|
|
|
|
All dashboard/report calculations should use minutes:
|
|
|
|
- approvedMinutes
|
|
- pendingMinutes
|
|
- rejectedMinutes
|
|
- targetMinutes
|
|
|
|
When summing:
|
|
|
|
- SUM(minutes)
|
|
|
|
Do not sum decimal hours.
|
|
|
|
Part 6: K/S/A Targets
|
|
|
|
Targets should support minutes too.
|
|
|
|
Examples:
|
|
|
|
- K = 12 ชั่วโมง 30 นาที -> 750 minutes
|
|
- S = 10 ชั่วโมง -> 600 minutes
|
|
- A = 7 ชั่วโมง 30 นาที -> 450 minutes
|
|
|
|
Part 7: Backward Compatibility
|
|
|
|
If minute field is null:
|
|
|
|
- fallback to old decimal hour field:
|
|
minutes = ROUND(hours \* 60)
|
|
|
|
Use helper:
|
|
getDurationMinutes(minutesField, legacyHoursField)
|
|
|
|
Part 8: Update all UI locations
|
|
|
|
Update:
|
|
|
|
- Training Record table
|
|
- Training Detail
|
|
- HRD Review
|
|
- Dashboard
|
|
- K/S/A Progress
|
|
- Employee Directory
|
|
- Reports
|
|
- Export Excel
|
|
- Export PDF
|
|
|
|
Display examples:
|
|
|
|
- 1 ชั่วโมง 45 นาที
|
|
- 15 นาที
|
|
- 2 ชั่วโมง
|
|
|
|
Part 9: Output Review File
|
|
|
|
Create:
|
|
docs/management-change-duration-minutes-review.md
|
|
|
|
Include:
|
|
|
|
1. Summary
|
|
2. Database Changes
|
|
3. Migration Strategy
|
|
4. Duration Picker UI
|
|
5. Storage Behavior
|
|
6. Display Formatting
|
|
7. Dashboard Impact
|
|
8. Reports Impact
|
|
9. Backward Compatibility
|
|
10. Manual Test Checklist
|
|
11. Known Limitations
|
|
|
|
Manual Test Checklist:
|
|
|
|
- 00:15 saves 15 minutes.
|
|
- 01:45 saves 105 minutes.
|
|
- 02:00 saves 120 minutes.
|
|
- 30:00 saves 1800 minutes.
|
|
- 00:00 is blocked.
|
|
- More than 30:00 is blocked.
|
|
- Training history shows 1 ชั่วโมง 45 นาที.
|
|
- Dashboard sums minutes correctly.
|
|
- Reports export minutes correctly.
|
|
- Legacy decimal hours still display correctly.
|
|
- No AM/PM appears anywhere.
|
|
|
|
Return:
|
|
|
|
- Complete code changes with file paths.
|
|
- Migration command if required.
|
|
- Review file.
|