54d5d6150c
Release package / release (pull_request) Successful in 3m23s
- Translated payment page text from Vietnamese to English. - Updated staff creation page with English labels and messages. - Changed staff schedule page labels and navigation items to English. - Modified shift card and search bar components to use English text. - Updated delete confirmation and product modal components with English messages. - Translated product management tab and category sidebar to English. - Changed shift schedule components to display English text for shifts and actions. - Updated header logo alt text to improve accessibility.
111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
"use client";
|
||
|
||
import type { ShiftCardProps } from "./ShiftCard.types";
|
||
|
||
function formatWage(wage: number): string {
|
||
if (wage >= 1_000_000) return `${(wage / 1_000_000).toFixed(1)}M`;
|
||
if (wage >= 1000) return `${(wage / 1000).toFixed(0)}k`;
|
||
return wage.toLocaleString("vi-VN");
|
||
}
|
||
|
||
function getShiftPeriod(startTime: string): "morning" | "afternoon" | "evening" {
|
||
const h = parseInt(startTime.split(":")[0] ?? "0", 10);
|
||
if (h < 12) return "morning";
|
||
if (h < 18) return "afternoon";
|
||
return "evening";
|
||
}
|
||
|
||
const PERIOD_STYLES = {
|
||
morning: {
|
||
border: "border-l-indigo-500",
|
||
text: "text-indigo-700",
|
||
badge: "bg-indigo-100 text-indigo-700",
|
||
dot: "bg-indigo-400",
|
||
},
|
||
afternoon: {
|
||
border: "border-l-amber-500",
|
||
text: "text-amber-700",
|
||
badge: "bg-amber-100 text-amber-700",
|
||
dot: "bg-amber-400",
|
||
},
|
||
evening: {
|
||
border: "border-l-violet-500",
|
||
text: "text-violet-700",
|
||
badge: "bg-violet-100 text-violet-700",
|
||
dot: "bg-violet-400",
|
||
},
|
||
};
|
||
|
||
export default function ShiftCard({ shift, compact = false, onClick }: ShiftCardProps) {
|
||
const registeredCount = shift.registeredStaff?.length ?? 0;
|
||
const period = getShiftPeriod(shift.startTime);
|
||
const s = PERIOD_STYLES[period];
|
||
|
||
if (compact) {
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={() => onClick?.(shift)}
|
||
className={`group w-full cursor-pointer rounded-xl border-l-[3px] bg-white text-left shadow-sm transition hover:-translate-y-px hover:shadow-md ${s.border}`}
|
||
>
|
||
<div className="px-2.5 py-2">
|
||
<p className={`text-xs font-bold leading-tight ${s.text}`}>
|
||
{shift.startTime}–{shift.endTime}
|
||
</p>
|
||
<div className="mt-1 flex items-center justify-between gap-1">
|
||
<p className="text-[10px] text-(--color-text-muted)">{formatWage(shift.wage ?? 0)}đ</p>
|
||
<span className={`rounded-full px-1.5 py-px text-[9px] font-semibold ${s.badge}`}>
|
||
{registeredCount}/{shift.maxStaff}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</button>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={() => onClick?.(shift)}
|
||
className={`group w-full cursor-pointer rounded-2xl border-l-[4px] bg-white text-left shadow-sm transition hover:-translate-y-0.5 hover:shadow-lg ${s.border}`}
|
||
>
|
||
<div className="p-4">
|
||
<div className="flex items-start justify-between gap-3">
|
||
<div className="min-w-0">
|
||
<div className="flex items-center gap-2">
|
||
<span className={`h-2 w-2 shrink-0 rounded-full ${s.dot}`} />
|
||
<p className={`text-base font-bold ${s.text}`}>
|
||
{shift.startTime} – {shift.endTime}
|
||
</p>
|
||
</div>
|
||
<p className="mt-1 text-xs text-(--color-text-muted)">
|
||
{(shift.wage ?? 0).toLocaleString("vi-VN")} VND/ca
|
||
</p>
|
||
</div>
|
||
<span className={`shrink-0 rounded-full px-2.5 py-1 text-xs font-semibold ${s.badge}`}>
|
||
{registeredCount}/{shift.maxStaff} staff
|
||
</span>
|
||
</div>
|
||
|
||
{registeredCount > 0 && (
|
||
<div className="mt-3 border-t border-gray-100 pt-3">
|
||
<p className="mb-2 text-[10px] font-semibold tracking-wider text-(--color-text-muted) uppercase">
|
||
Registered staff
|
||
</p>
|
||
<div className="flex flex-wrap gap-1.5">
|
||
{shift.registeredStaff!.map((staff) => (
|
||
<span
|
||
key={staff.id}
|
||
className="rounded-full bg-gray-100 px-2.5 py-0.5 text-[11px] font-medium text-(--color-text-secondary)"
|
||
>
|
||
{staff.staffId}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</button>
|
||
);
|
||
}
|