chore: update

This commit is contained in:
TakahashiNg
2026-05-14 02:02:30 +00:00
parent 0c7818a974
commit 65c2a7bdc5
5 changed files with 34 additions and 65 deletions
+18 -43
View File
@@ -4,32 +4,6 @@ import type { ShiftEntity } from "@/lib/types";
import type { ShiftCardProps } from "./ShiftCard.types"; import type { ShiftCardProps } from "./ShiftCard.types";
const STATUS_STYLES: Record<
ShiftEntity["status"],
{ bg: string; text: string; label: string }
> = {
available: {
bg: "bg-blue-50 border-blue-200",
text: "text-blue-700",
label: "Còn trống",
},
registered: {
bg: "bg-blue-100 border-blue-400",
text: "text-blue-900",
label: "Đã đăng ký",
},
approved_leave: {
bg: "bg-purple-50 border-purple-300",
text: "text-purple-700",
label: "Nghỉ phép",
},
absent: {
bg: "bg-red-50 border-red-300",
text: "text-red-700",
label: "Vắng mặt",
},
};
function formatWage(wage: number): string { function formatWage(wage: number): string {
if (wage >= 1000) { if (wage >= 1000) {
return `${(wage / 1000).toFixed(0)}k`; return `${(wage / 1000).toFixed(0)}k`;
@@ -42,20 +16,20 @@ export default function ShiftCard({
compact = false, compact = false,
onClick, onClick,
}: ShiftCardProps) { }: ShiftCardProps) {
const style = STATUS_STYLES[shift.status]; console.log(shift);
if (compact) { if (compact) {
return ( return (
<button <button
type="button" type="button"
onClick={() => onClick?.(shift)} onClick={() => onClick?.(shift)}
className={`w-full cursor-pointer rounded-lg border px-2 py-1.5 text-left text-xs transition-shadow hover:shadow-sm ${style.bg} ${style.text}`} className={`w-full cursor-pointer rounded-lg border px-2 py-1.5 text-left text-xs transition-shadow hover:shadow-sm `}
> >
<p className="font-semibold"> <p className="font-semibold">
{shift.startTime} {shift.endTime} {shift.startTime} {shift.endTime}
</p> </p>
<p className="mt-0.5 opacity-75"> <p className="mt-0.5 opacity-75">
{shift.durationHours}h · {formatWage(shift.wage)} {}h · {formatWage(shift.wage)}
</p> </p>
</button> </button>
); );
@@ -65,7 +39,7 @@ export default function ShiftCard({
<button <button
type="button" type="button"
onClick={() => onClick?.(shift)} onClick={() => onClick?.(shift)}
className={`w-full cursor-pointer rounded-xl border p-3 text-left transition-shadow hover:shadow-md ${style.bg} ${style.text}`} className={`w-full cursor-pointer rounded-xl border p-3 text-left transition-shadow hover:shadow-md `}
> >
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div> <div>
@@ -73,25 +47,26 @@ export default function ShiftCard({
{shift.startTime} {shift.endTime} {shift.startTime} {shift.endTime}
</p> </p>
<p className="mt-1 text-xs opacity-75"> <p className="mt-1 text-xs opacity-75">
{shift.durationHours}h · {formatWage(shift.wage)} VND {}h · {formatWage(shift.wage)} VND
</p> </p>
</div> </div>
<span <span
className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${ className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${
shift.status === "available" // shift.status === "available"
? "bg-blue-200 text-blue-800" // ? "bg-blue-200 text-blue-800"
: shift.status === "registered" // : shift.status === "registered"
? "bg-blue-300 text-blue-900" // ? "bg-blue-300 text-blue-900"
: shift.status === "approved_leave" // : shift.status === "approved_leave"
? "bg-purple-200 text-purple-800" // ? "bg-purple-200 text-purple-800"
: "bg-red-200 text-red-800" // : "bg-red-200 text-red-800"
""
}`} }`}
> >
{style.label} {/* {style.label} */}
</span> </span>
</div> </div>
{shift.registeredStaff.length > 0 && ( {(shift.registeredStaff && shift.registeredStaff.length > 0) && (
<div className="mt-2 border-t border-current/10 pt-2"> <div className="mt-2 border-t border-current/10 pt-2">
<p className="text-[10px] font-medium tracking-wide uppercase opacity-60"> <p className="text-[10px] font-medium tracking-wide uppercase opacity-60">
Nhân viên ({shift.registeredStaff.length}/{shift.maxStaff}) Nhân viên ({shift.registeredStaff.length}/{shift.maxStaff})
@@ -102,18 +77,18 @@ export default function ShiftCard({
key={s.id} key={s.id}
className="rounded-full bg-white/60 px-2 py-0.5 text-[10px] font-medium" className="rounded-full bg-white/60 px-2 py-0.5 text-[10px] font-medium"
> >
{s.name} {s.staffId}
</span> </span>
))} ))}
</div> </div>
</div> </div>
)} )}
{shift.status === "available" && shift.registeredStaff.length === 0 && ( {/* {shift.status === "available" && shift.registeredStaff.length === 0 && (
<p className="mt-2 text-[10px] italic opacity-50"> <p className="mt-2 text-[10px] italic opacity-50">
{shift.maxStaff} vị trí còn trống {shift.maxStaff} vị trí còn trống
</p> </p>
)} )} */}
</button> </button>
); );
} }
@@ -218,9 +218,7 @@ export default function MobileShiftView({
) : ( ) : (
<div className="space-y-3"> <div className="space-y-3">
{DEPARTMENTS.map((dept) => { {DEPARTMENTS.map((dept) => {
const deptShifts = selectedShifts.filter( const deptShifts = selectedShifts;
(s) => s.department === dept.id,
);
if (deptShifts.length === 0) return null; if (deptShifts.length === 0) return null;
return ( return (
<div key={dept.id}> <div key={dept.id}>
@@ -67,7 +67,7 @@ export default function WeeklySchedule({
const map: Record<string, string[]> = {}; const map: Record<string, string[]> = {};
weekDates.forEach((date) => { weekDates.forEach((date) => {
const dateStr = formatDateISO(date); const dateStr = formatDateISO(date);
const dayShifts = getShiftsForDate(dateStr); const dayShifts = getShiftsForDate(date);
const dots: string[] = []; const dots: string[] = [];
if (dayShifts.some((s) => s.status === "available")) if (dayShifts.some((s) => s.status === "available"))
dots.push("bg-sky-300"); dots.push("bg-sky-300");
@@ -160,9 +160,10 @@ export default function WeeklySchedule({
<div className="space-y-3"> <div className="space-y-3">
{DEPARTMENTS.map((dept) => { {DEPARTMENTS.map((dept) => {
const deptShifts = getShiftsForDate(selectedDateStr).filter( const deptShifts = getShiftsForDate(selectedDateObj)
(s) => s.department === dept.id, // .filter(
); // (s) => s.department === dept.id,
// );
if (deptShifts.length === 0 && !onCreateShift) return null; if (deptShifts.length === 0 && !onCreateShift) return null;
return ( return (
<div <div
@@ -247,9 +248,10 @@ export default function WeeklySchedule({
</td> </td>
{weekDates.map((date, i) => { {weekDates.map((date, i) => {
const dateStr = formatDateISO(date); const dateStr = formatDateISO(date);
const shifts = getShiftsForDate(dateStr).filter( const shifts = getShiftsForDate(date)
(s) => s.department === dept.id, // .filter(
); // (s) => s.department === dept.id,
// );
return ( return (
<td <td
key={i} key={i}
+3 -1
View File
@@ -208,7 +208,9 @@ export function ShiftProvider({ children }: { children: ReactNode }) {
const getShiftsForDate = useCallback( const getShiftsForDate = useCallback(
(date: Date): ShiftEntity[] => { (date: Date): ShiftEntity[] => {
return shifts.filter((s) => s.date === date); return shifts.filter((s) => {
return new Date(s.date).getDate() === date.getDate();
});
}, },
[shifts], [shifts],
); );
+1 -9
View File
@@ -96,7 +96,7 @@ export interface ShiftRegistrationEntity {
export interface ShiftEntity { export interface ShiftEntity {
id: string; id: string;
date: Date; date: string;
startTime: string; startTime: string;
endTime: string; endTime: string;
wage: number; wage: number;
@@ -104,12 +104,6 @@ export interface ShiftEntity {
registeredStaff?: ShiftRegistrationEntity[]; registeredStaff?: ShiftRegistrationEntity[];
} }
export interface Department {
id: string;
name: string;
icon: string;
}
export interface MenuItemEntity { export interface MenuItemEntity {
id?: string; id?: string;
name: string; name: string;
@@ -120,8 +114,6 @@ export interface MenuItemEntity {
description: string; description: string;
} }
export interface ShiftEntity {}
export interface EateryEntity { export interface EateryEntity {
id: string; id: string;
ownerId: string; ownerId: string;