Project

General

Profile

Feature #26731 » Employee-Status-Icon-Spec.md

#kiro - Parujee Pangsriuthai, 04/28/2026 09:14 AM

 
1
# สรุปข้อกำหนด: ระบบแสดง Icon Status บนการ์ดพนักงาน
2

    
3
## ภาพรวม
4

    
5
พัฒนาระบบแสดงไอคอนและป้ายสถานะ (Status Icon & Label) บนการ์ดพนักงานในหน้าเลือกช่างซ่อมบำรุง (AssignMaintenanceSupportDrawer) แทนที่ placeholder "ICON" และ "STATUS" ที่มีอยู่ใน `EmployeeItem` component
6

    
7
## ที่มาของข้อมูลสถานะ
8

    
9
ข้อมูลสถานะมาจาก API (`/call-terminal/employee`) ซึ่ง query จาก DB โดยตรง:
10

    
11
- **is_available** (boolean): `true` = ไม่มีงาน `during work` ที่ active อยู่ (ว่างรับงานได้)
12
- **is_working** (boolean): `true` = มีงาน `during work` ที่ active และไม่ถูก suspend (กำลังทำงานอยู่)
13
- **Off Shift**: คำนวณจาก `ms_shift` — พนักงานไม่อยู่ในช่วงเวลากะที่ตั้งไว้ (`start_ts` / `end_ts`)
14

    
15
> ⚠️ ปัจจุบัน API ยังไม่มี field `is_off_shift` — ต้องเพิ่ม logic คำนวณจาก `ms_shift` (เทียบเวลาปัจจุบันกับ `start_ts`/`end_ts` ของกะที่ผูกกับพนักงานผ่าน `work_shift_id`)
16

    
17
### SQL Query ปัจจุบัน (employee.repository.ts)
18

    
19
```sql
20
-- is_available: ไม่มีงาน during work
21
NOT EXISTS (
22
  SELECT 1 FROM mp_request_work_worker mp
23
  JOIN request_work rw ON rw.id = mp.request_work_id
24
  WHERE mp.employee_id = me.id
25
    AND mp.worker_type = 'employee'
26
    AND mp.is_active = TRUE
27
    AND rw.current_status = 'during work'
28
) AS is_available
29

    
30
-- is_working: มีงาน during work ที่ไม่ถูก suspend
31
EXISTS (
32
  SELECT 1 FROM mp_request_work_worker mp
33
  JOIN request_work rw ON rw.id = mp.request_work_id
34
  WHERE mp.employee_id = me.id
35
    AND mp.worker_type = 'employee'
36
    AND mp.is_active = TRUE
37
    AND rw.current_status = 'during work'
38
    AND rw.is_suspension = FALSE
39
) AS is_working
40
```
41

    
42
### ตรรกะ Off Shift (ต้องเพิ่มใหม่)
43

    
44
```
45
Off Shift = เวลาปัจจุบัน ไม่อยู่ในช่วง ms_shift.start_ts ~ ms_shift.end_ts
46
            ของกะที่ผูกกับพนักงาน (ms_employee.work_shift_id → ms_shift.id)
47
```
48

    
49
## เลย์เอาต์การ์ดพนักงาน
50

    
51
### โครงสร้างทั่วไป
52

    
53
```
54
┌─────────────────────────────────┐
55
│  ชื่อ นามสกุล (bold)        ● ← จุดสี (Status Dot)
56
│                                 │
57
│  ⊙ Available                    │  ← ไอคอน + ข้อความสถานะ
58
└─────────────────────────────────┘
59
```
60

    
61
- **แถวบน**: ชื่อพนักงาน (ซ้าย) + วงกลมสีทึบ 16x16px (ขวา)
62
- **แถวล่าง**: ไอคอน 16x16px + ข้อความสถานะ (ชิดซ้าย, gap-2)
63

    
64
### ตัวอย่างการ์ดแต่ละสถานะ
65

    
66
#### ✅ Available (ว่าง) — สีเขียว
67

    
68
```
69
┌─────────────────────────────────┐
70
│                                 │
71
│  Anupong Chaiya             🟢  │  ← bg-green-500
72
│                                 │
73
│  ✓ Available                    │  ← CheckCircle + text-green-600
74
│                                 │
75
└─────────────────────────────────┘
76
  border: border-gray-300 (ปกติ)
77
  bg: bg-white
78
```
79

    
80
#### 🔧 Working (กำลังทำงาน) — สีน้ำเงิน
81

    
82
```
83
┌─────────────────────────────────┐
84
│                                 │
85
│  Chaiyong Siripong          🔵  │  ← bg-blue-500
86
│                                 │
87
│  🕐 Working                     │  ← Clock + text-blue-600
88
│                                 │
89
└─────────────────────────────────┘
90
  border: border-gray-300 (ปกติ)
91
  bg: bg-white
92
```
93

    
94
#### 🚫 Off Shift (ไม่อยู่กะ) — สีเทา
95

    
96
```
97
┌─────────────────────────────────┐
98
│                                 │
99
│  Somchai Three              ⚪  │  ← bg-gray-400
100
│                                 │
101
│  ⊘ Off Shift                    │  ← MinusCircle + text-gray-400
102
│                                 │
103
└─────────────────────────────────┘
104
  border: border-gray-300 (ปกติ)
105
  bg: bg-white
106
```
107

    
108
#### 🔲 เมื่อถูกเลือก (Selected) — ทุกสถานะเหมือนกัน
109

    
110
```
111
┌═════════════════════════════════┐
112
│                                 │  ← border-blue-600 (เส้นขอบน้ำเงิน)
113
│  Sakchai Rattana            🟢  │     bg-blue-50 (พื้นหลังฟ้าอ่อน)
114
│                                 │
115
│  ✓ Available                    │
116
│                                 │
117
└═════════════════════════════════┘
118
  border: border-blue-600 (เลือกแล้ว)
119
  bg: bg-blue-50
120
```
121

    
122
### ตัวอย่างหน้าจอรวม (Grid 4 คอลัมน์)
123

    
124
```
125
⚡ Electrician  12
126
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
127
│ Anupong Chaiya 🟢│  │ Ganya Ratchada 🟢│  │ Sakchai Rattan 🟢│  │ Chaiyong Siri  🔵│
128
│ ✓ Available      │  │ ✓ Available      │  │ ✓ Available      │  │ 🕐 Working       │
129
└──────────────────┘  └──────────────────┘  └──────────────────┘  └──────────────────┘
130

    
131
🔧 Mechanic  5
132
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
133
│ Somchai Three  ⚪│  │ User One       🟢│  │ Prasit Kaew    🔵│  │ Wichai Suk     ⚪│
134
│ ⊘ Off Shift      │  │ ✓ Available      │  │ 🕐 Working       │  │ ⊘ Off Shift      │
135
└──────────────────┘  └──────────────────┘  └──────────────────┘  └──────────────────┘
136
```
137

    
138
### ตัวอย่างปุ่มกรองสถานะ
139

    
140
```
141
┌───────────────────────────────────────────────────────────────────────────────────┐
142
│  🔍 Search maintenance staff...     [  All  ] [ Available ] [ Working ] [Off Shift]│
143
│                                      (red)     (green)       (blue)     (gray)    │
144
└───────────────────────────────────────────────────────────────────────────────────┘
145
```
146

    
147
- **All** (แดง): แสดงทุกคน
148
- **Available** (เขียว): แสดงเฉพาะ `is_available = true` AND `is_off_shift = false`
149
- **Working** (น้ำเงิน): แสดงเฉพาะ `is_working = true` AND `is_off_shift = false`
150
- **Off Shift** (เทา): แสดงเฉพาะ `is_off_shift = true`
151

    
152
## สถานะทั้ง 3 แบบ (Priority: Off Shift > Working > Available)
153

    
154
| สถานะ | เงื่อนไข | สี Dot | ไอคอน | ข้อความ | สีข้อความ/ไอคอน |
155
|---|---|---|---|---|---|
156
| Off Shift | ไม่อยู่ในเวลากะ (`is_off_shift = true`) | ⚪ bg-gray-400 | MinusCircle | "Off Shift" | text-gray-400 |
157
| Working | ถูก assign เครื่อง + งานเป็น `during work` (`is_working = true`) | 🔵 bg-blue-500 | Clock | "Working" | text-blue-600 |
158
| Available | อยู่ในกะ + ไม่ได้ทำงาน (`is_available = true` AND `is_off_shift = false`) | 🟢 bg-green-500 | CheckCircle | "Available" | text-green-600 |
159

    
160
> Priority: ถ้า Off Shift → แสดง Off Shift เสมอ (แม้จะมีงาน assign อยู่)
161

    
162
## ไฟล์ที่เกี่ยวข้อง
163

    
164
### Frontend (Web)
165

    
166
| ไฟล์ | สิ่งที่ต้องทำ |
167
|---|---|
168
| `EmployeeItem.tsx` | แทนที่ placeholder ด้วย status dot, icon, label จริง |
169
| `assign-maintenance.model.ts` | เพิ่ม `is_available`, `is_working`, `is_off_shift` ใน EmployeeRecordData interface |
170
| `useInteralAssignMaintenanceDrawer.ts` | เพิ่ม filter logic สำหรับ "offShift" โดยใช้ `is_off_shift` |
171

    
172
### Backend (API)
173

    
174
| ไฟล์ | สิ่งที่ต้องทำ |
175
|---|---|
176
| `employee.repository.ts` | เพิ่ม SQL คำนวณ `is_off_shift` จาก `ms_shift` (เทียบ `start_ts`/`end_ts` กับเวลาปัจจุบัน) |
177
| `employee.model.ts` | เพิ่ม `is_off_shift: boolean` ใน `EmployeeForGroupByWorkType` interface |
178

    
179
## รายการข้อกำหนด (8 ข้อ)
180

    
181
### 1. เพิ่ม is_off_shift ใน API (Backend)
182
- เพิ่ม SQL subquery ใน `employee.repository.ts` เพื่อคำนวณ `is_off_shift`
183
- เทียบเวลาปัจจุบันกับ `ms_shift.start_ts` / `ms_shift.end_ts` ผ่าน `ms_employee.work_shift_id`
184
- เพิ่ม `is_off_shift: boolean` ใน `EmployeeForGroupByWorkType` interface (API model)
185

    
186
### 2. ขยาย EmployeeRecordData Model (Frontend)
187
- เพิ่มฟิลด์ `is_available: boolean`, `is_working: boolean`, `is_off_shift: boolean` ใน interface
188
- ให้ EmployeeItem ใช้งานได้โดยไม่มี type error
189

    
190
### 3. ตรรกะคำนวณสถานะ (Status Derivation Logic)
191
- `is_off_shift = true` → "offShift" (priority สูงสุด)
192
- `is_working = true` → "working"
193
- `is_available = true` AND `is_off_shift = false` → "available"
194
- Working = ช่างที่ถูก assign เครื่องไว้ + สถานะงาน `during work`
195
- Off Shift = ไม่อยู่ในเวลาที่ตั้งไว้ใน `ms_shift`
196

    
197
### 4. วงกลมสีสถานะ (Status Dot)
198
- แสดงจุดกลมทึบ 16x16px ที่มุมขวาบนของการ์ด
199
- สี: เขียว (available), น้ำเงิน (working), เทา (offShift)
200

    
201
### 5. ไอคอนสถานะ (Status Icon)
202
- แสดงใต้ชื่อพนักงาน ฝั่งซ้าย ขนาด 16x16px
203
- ไอคอน: CheckCircle (available), Clock (working), MinusCircle (offShift)
204
- ใช้ lucide-react
205

    
206
### 6. ข้อความสถานะ (Status Label)
207
- แสดงคู่กับไอคอน: "Available", "Working", "Off Shift"
208
- สีตรงกับสถานะ
209

    
210
### 7. เลือกได้ทุกสถานะ — ไม่ล็อก
211
- พนักงานทุกสถานะ (available, working, offShift) กดเลือกได้หมด
212
- เมื่อเลือกแล้วแสดง border-blue-600, bg-blue-50 เหมือนกันทุกสถานะ
213

    
214
### 8. ตัวกรอง Off Shift
215
- เพิ่ม filter logic: เมื่อเลือก "Off Shift" → แสดงเฉพาะพนักงานที่ `is_off_shift = true`
216
- ปุ่มกรองที่มีอยู่แล้ว: All, Available, Working, Off Shift
(1-1/2)