diff --git a/frontend/src/components/StatusBadge.jsx b/frontend/src/components/StatusBadge.jsx
index 6b2ca90..f0edc04 100644
--- a/frontend/src/components/StatusBadge.jsx
+++ b/frontend/src/components/StatusBadge.jsx
@@ -11,9 +11,13 @@ import { CheckCircle, AlertCircle, CalendarX, Palmtree, Briefcase } from 'lucide
* - normal → 正常 (green)
* - everything else (late/early/ot/abnormal/late_early/...) → 異常 (orange)
*
+ * If status_text carries a leave/holiday suffix (e.g. '+ SL2h', '🎉香港…'),
+ * a small secondary chip is rendered next to the main badge so the list page
+ * shows the underlying leave/holiday detail without expanding the row.
+ *
* Props:
* - code: status_code string
- * - text: status_text string (fallback signal)
+ * - text: status_text string (fallback signal + suffix source)
* - size: 'sm' | 'md' (default 'sm')
*/
export default function StatusBadge({ code = '', text = '', size = 'sm' }) {
@@ -28,32 +32,73 @@ export default function StatusBadge({ code = '', text = '', size = 'sm' }) {
)
- const c = String(code || '').toLowerCase()
+ // Extract leave/holiday suffix from status_text:
+ // '異常-遲到48分 + SL2h' → ['SL2h']
+ // '缺勤 (🎉香港特別行政區成立紀念日)' → ['🎉香港特別行政區成立紀念日']
+ // 'OT3分 + AL4h + SL3h' → ['AL4h', 'SL3h']
+ // '正常 + CL4h' → ['CL4h']
const t = String(text || '')
+ const noteParts = []
+ const split = t.split(' + ').map(s => s.trim())
+ if (split.length > 1) {
+ for (let i = 1; i < split.length; i++) {
+ noteParts.push(split[i].replace(/^\(|\)$/g, '').trim())
+ }
+ } else if (t.includes('🎉')) {
+ const m = t.match(/🎉[^)\s]+(?:\s[^)\s]+)*/)
+ if (m) noteParts.push(m[0])
+ }
+
+ const noteChips = noteParts.filter(Boolean).map((part, idx) => {
+ // Strip trailing ')'
+ const clean = part.replace(/\)+$/, '')
+ const isHoliday = clean.startsWith('🎉')
+ const cls = isHoliday
+ ? 'bg-indigo-50 text-indigo-600 border border-indigo-200'
+ : 'bg-violet-50 text-violet-600 border border-violet-200'
+ return (
+
+ {isHoliday ? clean : `+${clean}`}
+
+ )
+ })
+
+ const wrap = (content) => (
+
+ {content}
+ {noteChips}
+
+ )
+
+ const c = String(code || '').toLowerCase()
// 缺勤 (missing)
if (c === 'missing' || t === '缺勤') {
- return badge(, '缺勤', 'bg-gray-200 text-gray-700')
+ return wrap(badge(, '缺勤', 'bg-gray-200 text-gray-700'))
}
// 公假 (holiday)
if (c === 'holiday' || t.includes('公假') || t.includes('🏖️')) {
- return badge(, '公假', 'bg-indigo-100 text-indigo-700')
+ return wrap(badge(, '公假', 'bg-indigo-100 text-indigo-700'))
}
// 請假 (any leave type)
if (['al', 'sl', 'cl', 'mixed_leave'].includes(c)
|| t.includes('年假') || t.includes('病假') || t.includes('補鐘')
|| t.includes('混合假')) {
- return badge(, '請假', 'bg-violet-100 text-violet-700')
+ return wrap(badge(, '請假', 'bg-violet-100 text-violet-700'))
}
// 正常 (only when status_code is 'normal' — text suffix like '+ CL4h' is allowed,
// we still want to flag it as 正常 first since the employee did clock in/out normally)
if (c === 'normal') {
- return badge(, '正常', 'bg-green-100 text-green-700')
+ return wrap(badge(, '正常', 'bg-green-100 text-green-700'))
}
// 異常 (late/early/ot/abnormal/late_early/late_ot/early_ot/...)
- return badge(, '異常', 'bg-orange-100 text-orange-700')
+ return wrap(badge(, '異常', 'bg-orange-100 text-orange-700'))
}
\ No newline at end of file