@@ -4,14 +4,27 @@ import dayGridPlugin from '@fullcalendar/daygrid';
44import timeGridPlugin from ' @fullcalendar/timegrid' ;
55import interactionPlugin from ' @fullcalendar/interaction' ;
66import type { DatesSetArg , EventClickArg , EventDropArg , EventChangeArg } from ' @fullcalendar/core' ;
7- import { computed , ref , watch , inject , type ComputedRef } from ' vue' ;
7+ import {
8+ computed ,
9+ ref ,
10+ watch ,
11+ inject ,
12+ type ComputedRef ,
13+ nextTick ,
14+ onMounted ,
15+ onActivated ,
16+ } from ' vue' ;
817import chroma from ' chroma-js' ;
918import { useCssVariable } from ' @/utils/useCssVariable' ;
1019import { getDayJsInstance , getLocalizedDayJs } from ' ../utils/time' ;
1120import { getUserTimezone , getWeekStart } from ' ../utils/settings' ;
1221import { LoadingSpinner , TimeEntryCreateModal , TimeEntryEditModal } from ' ..' ;
1322import FullCalendarEventContent from ' ./FullCalendarEventContent.vue' ;
1423import FullCalendarDayHeader from ' ./FullCalendarDayHeader.vue' ;
24+ import activityStatusPlugin , {
25+ type ActivityPeriod ,
26+ renderActivityStatusBoxes ,
27+ } from ' ./idleStatusPlugin' ;
1528import type {
1629 TimeEntry ,
1730 Project ,
@@ -37,6 +50,7 @@ const props = defineProps<{
3750 tasks: Task [];
3851 clients: Client [];
3952 tags: Tag [];
53+ activityPeriods? : ActivityPeriod [];
4054 loading? : boolean ;
4155
4256 // Permissions / feature flags
@@ -165,6 +179,8 @@ const dailyTotals = computed(() => {
165179
166180function emitDatesChange(arg : DatesSetArg ) {
167181 emit (' dates-change' , { start: arg .start , end: arg .end });
182+ // Render activity boxes after calendar view has been rendered
183+ renderActivityBoxes ();
168184}
169185
170186function handleDateSelect(arg : { start: Date ; end: Date }) {
@@ -234,7 +250,7 @@ async function handleEventResize(arg: EventChangeArg) {
234250}
235251
236252const calendarOptions = computed (() => ({
237- plugins: [dayGridPlugin , timeGridPlugin , interactionPlugin ],
253+ plugins: [dayGridPlugin , timeGridPlugin , interactionPlugin , activityStatusPlugin ],
238254 initialView: ' timeGridWeek' ,
239255 headerToolbar: {
240256 left: ' prev,next today' ,
@@ -265,6 +281,7 @@ const calendarOptions = computed(() => ({
265281 datesSet: emitDatesChange ,
266282
267283 events: events .value ,
284+ activityPeriods: props .activityPeriods || [],
268285}));
269286
270287watch (showCreateTimeEntryModal , (value ) => {
@@ -283,6 +300,48 @@ watch(showEditTimeEntryModal, (value) => {
283300 emit (' refresh' );
284301 }
285302});
303+
304+ // Render activity status boxes after FullCalendar has rendered
305+ const renderActivityBoxes = () => {
306+ if (! calendarRef .value || ! props .activityPeriods ) return ;
307+
308+ const calendarEl = calendarRef .value .$el as HTMLElement ;
309+ if (calendarEl && props .activityPeriods .length > 0 ) {
310+ renderActivityStatusBoxes (calendarEl , props .activityPeriods );
311+ }
312+ };
313+
314+ // Watch for activity periods changes - re-render when data changes
315+ watch (
316+ () => props .activityPeriods ,
317+ () => {
318+ renderActivityBoxes ();
319+ }
320+ );
321+
322+ const scrollToCurrentTime = () => {
323+ nextTick (() => {
324+ if (calendarRef .value ) {
325+ const now = getDayJsInstance ()();
326+ const oneHourBefore = now .subtract (1 , ' hour' );
327+
328+ // If subtracting 1 hour keeps us on the same day, scroll to 1 hour before
329+ const scrollTime = now .isSame (oneHourBefore , ' day' )
330+ ? oneHourBefore .format (' HH:mm:ss' )
331+ : now .format (' HH:mm:ss' );
332+
333+ calendarRef .value .getApi ().scrollToTime (scrollTime );
334+ }
335+ });
336+ };
337+
338+ onMounted (() => {
339+ scrollToCurrentTime ();
340+ });
341+
342+ onActivated (() => {
343+ scrollToCurrentTime ();
344+ });
286345 </script >
287346
288347<template >
@@ -377,11 +436,11 @@ watch(showEditTimeEntryModal, (value) => {
377436}
378437
379438.fullcalendar :deep(.fc-timegrid-slot-label ) {
380- background-color : var (--theme-color-default- background );
439+ background-color : var (--background );
381440}
382441
383442.fullcalendar :deep(.fc-toolbar ) {
384- background-color : var (--theme-color-default- background );
443+ background-color : var (--background );
385444 padding : 0.5rem ;
386445 margin-bottom : 0 ;
387446}
@@ -463,7 +522,7 @@ watch(showEditTimeEntryModal, (value) => {
463522
464523.fullcalendar :deep(.fc-event ) {
465524 border-radius : var (--radius );
466- padding : 0.45 rem 0.25 rem ;
525+ padding : 0 ;
467526 font-size : 0.75rem ;
468527 cursor : pointer ;
469528 box-shadow : var (--theme-shadow-card );
@@ -525,7 +584,7 @@ watch(showEditTimeEntryModal, (value) => {
525584}
526585
527586.fullcalendar :deep(.fc-highlight ) {
528- background-color : var (--theme-color-default-background );
587+ background-color : var (--primary );
529588}
530589
531590.fullcalendar :deep(.fc-select-mirror ) {
@@ -543,7 +602,7 @@ watch(showEditTimeEntryModal, (value) => {
543602}
544603
545604.fullcalendar :deep(.fc-timegrid-body ) {
546- background-color : var (--theme-color-default- background );
605+ background-color : var (--background );
547606}
548607
549608.fullcalendar :deep(.fc-timegrid-col ) {
@@ -610,4 +669,34 @@ watch(showEditTimeEntryModal, (value) => {
610669.fullcalendar :deep(.fc-event-main ) {
611670 padding : 0.125rem 0.25rem ;
612671}
672+
673+ /* Activity status plugin styles */
674+ .fullcalendar :deep(.activity-status-box ) {
675+ transition : opacity 0.2s ease ;
676+ }
677+
678+ .fullcalendar :deep(.activity-status-box.idle ) {
679+ background-color : rgba (239 , 68 , 68 , 0.3 ) !important ;
680+ }
681+
682+ .fullcalendar :deep(.activity-status-box.idle ):hover {
683+ background-color : rgba (239 , 68 , 68 , 1 ) !important ;
684+ }
685+
686+ .fullcalendar :deep(.activity-status-box.active ) {
687+ background-color : rgba (34 , 197 , 94 , 0.3 ) !important ;
688+ }
689+
690+ .fullcalendar :deep(.activity-status-box.active ):hover {
691+ background-color : rgba (34 , 197 , 94 , 1 ) !important ;
692+ }
693+
694+ /* Add left margin to events only on days with activity status data */
695+ .fullcalendar :deep(.has-activity-status .fc-timegrid-event-harness ) {
696+ margin-left : 15px !important ;
697+ }
698+
699+ .fullcalendar :deep(.fc-timegrid-event ) {
700+ margin-left : 0 !important ;
701+ }
613702 </style >
0 commit comments