Refactor AttendanceCalendar component for improved UI and code clarity. Remove unused status markup, streamline button components, and enhance badge styling for attendance statuses. Update CSS for better responsiveness and maintainability.

This commit is contained in:
Yoga Pangestu 2026-06-11 19:37:06 +07:00
parent f8322566da
commit f01a8a11a4

View File

@ -94,16 +94,11 @@ function renderEventContent(arg: EventContentArg) {
? `<span class="attendance-event__name">${escapeHtml(attendance.employee_name)}</span>`
: '';
const statusMarkup = isComplete
? ''
: '<span class="attendance-event__status">Belum pulang</span>';
return {
html: `
<div class="attendance-event__inner">
${nameMarkup}
<span class="attendance-event__time">${escapeHtml(timeLabel)}</span>
${statusMarkup}
</div>
`,
};
@ -212,39 +207,21 @@ watch(
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div class="flex flex-wrap items-center gap-2">
<div class="bg-muted/50 flex items-center rounded-lg border p-1 shadow-xs">
<Button
variant="ghost"
size="icon-sm"
aria-label="Bulan sebelumnya"
@click="navigatePrev"
>
<Button variant="ghost" size="icon-sm" aria-label="Bulan sebelumnya" @click="navigatePrev">
<ChevronLeft class="size-4" />
</Button>
<Button
variant="ghost"
size="sm"
class="px-3"
@click="navigateToday"
>
<Button variant="ghost" size="sm" class="px-3" @click="navigateToday">
Hari ini
</Button>
<Button
variant="ghost"
size="icon-sm"
aria-label="Bulan berikutnya"
@click="navigateNext"
>
<Button variant="ghost" size="icon-sm" aria-label="Bulan berikutnya" @click="navigateNext">
<ChevronRight class="size-4" />
</Button>
</div>
<DatePicker
v-model="pickerDate"
class="w-auto min-w-[13rem] sm:min-w-[15rem]"
placeholder="Pilih bulan"
/>
<DatePicker v-model="pickerDate" class="w-auto min-w-[13rem] sm:min-w-[15rem]"
placeholder="Pilih bulan" />
</div>
<div class="flex flex-wrap items-center gap-2">
@ -252,29 +229,25 @@ watch(
{{ calendarTitle }}
</span>
<Badge variant="outline" class="border-chart-2/50 bg-chart-2/15 text-chart-2 font-normal dark:text-chart-2">
<Badge variant="outline"
class="border-emerald-600/50 bg-emerald-500/15 font-normal text-emerald-700 dark:text-emerald-400">
Selesai
</Badge>
<Badge variant="outline" class="border-amber-500/50 bg-amber-400 font-normal text-amber-950">
<Badge variant="outline" class="border-primary/50 bg-primary/20 font-normal text-primary-foreground">
Belum pulang
</Badge>
</div>
</div>
<div
:class="cn(
'overflow-hidden rounded-xl border bg-background shadow-xs transition-opacity',
isNavigating && 'pointer-events-none opacity-60',
)"
>
<div :class="cn(
'overflow-hidden rounded-xl border bg-background shadow-xs transition-opacity',
isNavigating && 'pointer-events-none opacity-60',
)">
<FullCalendar ref="calendarRef" :options="calendarOptions" />
</div>
</div>
<AttendanceDetailDialog
v-model:open="detailOpen"
:attendance="selectedAttendance"
/>
<AttendanceDetailDialog v-model:open="detailOpen" :attendance="selectedAttendance" />
</template>
<style>
@ -293,7 +266,7 @@ watch(
border-radius: 0;
}
.attendance-calendar .fc .fc-scrollgrid-section > td {
.attendance-calendar .fc .fc-scrollgrid-section>td {
border: 0;
}
@ -406,16 +379,16 @@ watch(
.attendance-calendar .fc .attendance-event--complete,
.attendance-calendar .fc .attendance-event--complete .fc-event-main {
background-color: var(--chart-2) !important;
border-color: color-mix(in oklch, var(--chart-2) 70%, var(--foreground)) !important;
background-color: oklch(0.59 0.14 152) !important;
border-color: oklch(0.52 0.12 152) !important;
color: oklch(0.99 0 0) !important;
}
.attendance-calendar .fc .attendance-event--active,
.attendance-calendar .fc .attendance-event--active .fc-event-main {
background-color: oklch(0.79 0.16 75) !important;
border-color: oklch(0.7 0.14 70) !important;
color: oklch(0.32 0.07 55) !important;
background-color: var(--primary) !important;
border-color: color-mix(in oklch, var(--primary) 80%, var(--foreground)) !important;
color: var(--primary-foreground) !important;
}
.attendance-calendar .fc .attendance-event__inner {
@ -460,21 +433,27 @@ watch(
.attendance-calendar .fc .attendance-event--active .attendance-event__time,
.attendance-calendar .fc .attendance-event--active .attendance-event__name,
.attendance-calendar .fc .attendance-event--active .attendance-event__status {
color: oklch(0.32 0.07 55);
color: var(--primary-foreground);
opacity: 0.95;
}
.dark .attendance-calendar .fc .attendance-event--complete,
.dark .attendance-calendar .fc .attendance-event--complete .fc-event-main {
background-color: oklch(0.55 0.13 152) !important;
border-color: oklch(0.48 0.11 152) !important;
}
.dark .attendance-calendar .fc .attendance-event--active,
.dark .attendance-calendar .fc .attendance-event--active .fc-event-main {
background-color: oklch(0.72 0.14 75) !important;
border-color: oklch(0.64 0.12 70) !important;
color: oklch(0.28 0.06 55) !important;
background-color: var(--primary) !important;
border-color: color-mix(in oklch, var(--primary) 75%, var(--foreground)) !important;
color: var(--primary-foreground) !important;
}
.dark .attendance-calendar .fc .attendance-event--active .attendance-event__time,
.dark .attendance-calendar .fc .attendance-event--active .attendance-event__name,
.dark .attendance-calendar .fc .attendance-event--active .attendance-event__status {
color: oklch(0.28 0.06 55);
color: var(--primary-foreground);
}
@media (max-width: 640px) {