StatusBadge: surface leave/holiday suffix as secondary chip
status_text fields like '異常-遲到48分 + SL2h' or '缺勤 (🎉香港特區…)' carried important leave/holiday context that the simplified badge was dropping on the list page — the user had no way to tell an abnormal record was partly covered by sick leave. Extract the suffix from status_text and render a small secondary chip next to the basic-status badge (violet for leave types, indigo for holidays). Detail page picks this up automatically since the component is shared. Example: '異常 +SL2h' / '缺勤 🎉香港特區成立紀念日'
This commit is contained in:
@@ -11,9 +11,13 @@ import { CheckCircle, AlertCircle, CalendarX, Palmtree, Briefcase } from 'lucide
|
|||||||
* - normal → 正常 (green)
|
* - normal → 正常 (green)
|
||||||
* - everything else (late/early/ot/abnormal/late_early/...) → 異常 (orange)
|
* - 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:
|
* Props:
|
||||||
* - code: status_code string
|
* - code: status_code string
|
||||||
* - text: status_text string (fallback signal)
|
* - text: status_text string (fallback signal + suffix source)
|
||||||
* - size: 'sm' | 'md' (default 'sm')
|
* - size: 'sm' | 'md' (default 'sm')
|
||||||
*/
|
*/
|
||||||
export default function StatusBadge({ code = '', text = '', size = 'sm' }) {
|
export default function StatusBadge({ code = '', text = '', size = 'sm' }) {
|
||||||
@@ -28,32 +32,73 @@ export default function StatusBadge({ code = '', text = '', size = 'sm' }) {
|
|||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
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 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 (
|
||||||
|
<span
|
||||||
|
key={idx}
|
||||||
|
className={`inline-flex items-center ${sizeCls} rounded-full font-normal ${cls}`}
|
||||||
|
title={clean}
|
||||||
|
>
|
||||||
|
{isHoliday ? clean : `+${clean}`}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const wrap = (content) => (
|
||||||
|
<span className="inline-flex items-center gap-1 flex-wrap">
|
||||||
|
{content}
|
||||||
|
{noteChips}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
|
||||||
|
const c = String(code || '').toLowerCase()
|
||||||
|
|
||||||
// 缺勤 (missing)
|
// 缺勤 (missing)
|
||||||
if (c === 'missing' || t === '缺勤') {
|
if (c === 'missing' || t === '缺勤') {
|
||||||
return badge(<CalendarX size={12} />, '缺勤', 'bg-gray-200 text-gray-700')
|
return wrap(badge(<CalendarX size={12} />, '缺勤', 'bg-gray-200 text-gray-700'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 公假 (holiday)
|
// 公假 (holiday)
|
||||||
if (c === 'holiday' || t.includes('公假') || t.includes('🏖️')) {
|
if (c === 'holiday' || t.includes('公假') || t.includes('🏖️')) {
|
||||||
return badge(<Palmtree size={12} />, '公假', 'bg-indigo-100 text-indigo-700')
|
return wrap(badge(<Palmtree size={12} />, '公假', 'bg-indigo-100 text-indigo-700'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 請假 (any leave type)
|
// 請假 (any leave type)
|
||||||
if (['al', 'sl', 'cl', 'mixed_leave'].includes(c)
|
if (['al', 'sl', 'cl', 'mixed_leave'].includes(c)
|
||||||
|| t.includes('年假') || t.includes('病假') || t.includes('補鐘')
|
|| t.includes('年假') || t.includes('病假') || t.includes('補鐘')
|
||||||
|| t.includes('混合假')) {
|
|| t.includes('混合假')) {
|
||||||
return badge(<Briefcase size={12} />, '請假', 'bg-violet-100 text-violet-700')
|
return wrap(badge(<Briefcase size={12} />, '請假', 'bg-violet-100 text-violet-700'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正常 (only when status_code is 'normal' — text suffix like '+ CL4h' is allowed,
|
// 正常 (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)
|
// we still want to flag it as 正常 first since the employee did clock in/out normally)
|
||||||
if (c === 'normal') {
|
if (c === 'normal') {
|
||||||
return badge(<CheckCircle size={12} />, '正常', 'bg-green-100 text-green-700')
|
return wrap(badge(<CheckCircle size={12} />, '正常', 'bg-green-100 text-green-700'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 異常 (late/early/ot/abnormal/late_early/late_ot/early_ot/...)
|
// 異常 (late/early/ot/abnormal/late_early/late_ot/early_ot/...)
|
||||||
return badge(<AlertCircle size={12} />, '異常', 'bg-orange-100 text-orange-700')
|
return wrap(badge(<AlertCircle size={12} />, '異常', 'bg-orange-100 text-orange-700'))
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user