diff --git a/resources/js/Components/Timesheet/RemoveRowDialog.vue b/resources/js/Components/Timesheet/RemoveRowDialog.vue new file mode 100644 index 00000000..65623f26 --- /dev/null +++ b/resources/js/Components/Timesheet/RemoveRowDialog.vue @@ -0,0 +1,46 @@ + + + diff --git a/resources/js/Components/Timesheet/TimesheetCell.vue b/resources/js/Components/Timesheet/TimesheetCell.vue new file mode 100644 index 00000000..31556672 --- /dev/null +++ b/resources/js/Components/Timesheet/TimesheetCell.vue @@ -0,0 +1,65 @@ + + + diff --git a/resources/js/Components/Timesheet/TimesheetFooterActions.vue b/resources/js/Components/Timesheet/TimesheetFooterActions.vue new file mode 100644 index 00000000..b5a73cf2 --- /dev/null +++ b/resources/js/Components/Timesheet/TimesheetFooterActions.vue @@ -0,0 +1,50 @@ + + + diff --git a/resources/js/Components/Timesheet/TimesheetGrid.vue b/resources/js/Components/Timesheet/TimesheetGrid.vue new file mode 100644 index 00000000..df54539a --- /dev/null +++ b/resources/js/Components/Timesheet/TimesheetGrid.vue @@ -0,0 +1,159 @@ + + + diff --git a/resources/js/Components/Timesheet/TimesheetHeader.vue b/resources/js/Components/Timesheet/TimesheetHeader.vue new file mode 100644 index 00000000..8ce79740 --- /dev/null +++ b/resources/js/Components/Timesheet/TimesheetHeader.vue @@ -0,0 +1,60 @@ + + + diff --git a/resources/js/Components/Timesheet/TimesheetRow.vue b/resources/js/Components/Timesheet/TimesheetRow.vue new file mode 100644 index 00000000..26ceb7ec --- /dev/null +++ b/resources/js/Components/Timesheet/TimesheetRow.vue @@ -0,0 +1,132 @@ + + + diff --git a/resources/js/Layouts/AppLayout.vue b/resources/js/Layouts/AppLayout.vue index da7135b8..4f878468 100644 --- a/resources/js/Layouts/AppLayout.vue +++ b/resources/js/Layouts/AppLayout.vue @@ -17,6 +17,7 @@ import { UserGroupIcon, XMarkIcon, DocumentTextIcon, + TableCellsIcon, } from '@heroicons/vue/20/solid'; import { PanelLeft } from 'lucide-vue-next'; import NavigationSidebarItem from '@/Components/NavigationSidebarItem.vue'; @@ -135,7 +136,7 @@ const page = usePage<{ ? 'max-lg:translate-x-0 max-lg:shadow-xl' : 'max-lg:-translate-x-full', ]" - class="flex-shrink-0 h-screen fixed w-[280px] px-2.5 py-4 hidden lg:flex flex-col justify-between bg-background border-r border-default-background-separator max-lg:z-50 max-lg:transition-transform max-lg:duration-200 max-lg:ease-in-out lg:w-[230px] 2xl:w-[250px] 2xl:px-3 lg:border-r-0" + class="flex-shrink-0 h-screen fixed w-[280px] px-2.5 py-4 hidden lg:flex flex-col justify-between bg-background border-r border-default-background-separator max-lg:z-50 max-lg:transition-transform max-lg:duration-200 max-lg:ease-in-out lg:w-[230px] lg:border-r-0" :style="showSidebarMenu ? { display: 'flex' } : undefined">
+
-
+
(undefined); -const calendarEnd = ref(undefined); +const calendarStart = ref(undefined); +const calendarEnd = ref(undefined); // Test-injectable activity periods (for E2E testing). // These hooks are no-ops in production — they only take effect when test code @@ -99,7 +100,7 @@ const { tags } = useTagsQuery(); const queryClient = useQueryClient(); -function onDatesChange({ start, end }: { start: Date; end: Date }) { +function onDatesChange({ start, end }: { start: Dayjs; end: Dayjs }) { calendarStart.value = start; calendarEnd.value = end; } diff --git a/resources/js/Pages/Timesheet.vue b/resources/js/Pages/Timesheet.vue new file mode 100644 index 00000000..5a9e6c62 --- /dev/null +++ b/resources/js/Pages/Timesheet.vue @@ -0,0 +1,199 @@ + + + diff --git a/resources/js/packages/ui/src/FullCalendar/TimeEntryCalendar.vue b/resources/js/packages/ui/src/FullCalendar/TimeEntryCalendar.vue index df5f212a..a7e9cf5d 100644 --- a/resources/js/packages/ui/src/FullCalendar/TimeEntryCalendar.vue +++ b/resources/js/packages/ui/src/FullCalendar/TimeEntryCalendar.vue @@ -57,7 +57,7 @@ import type { import type { Dayjs } from 'dayjs'; const emit = defineEmits<{ - (e: 'dates-change', payload: { start: Date; end: Date }): void; + (e: 'dates-change', payload: { start: Dayjs; end: Dayjs }): void; (e: 'refresh'): void; }>(); diff --git a/resources/js/packages/ui/src/FullCalendar/useCalendarNavigation.ts b/resources/js/packages/ui/src/FullCalendar/useCalendarNavigation.ts index a1fd79b5..af16d54c 100644 --- a/resources/js/packages/ui/src/FullCalendar/useCalendarNavigation.ts +++ b/resources/js/packages/ui/src/FullCalendar/useCalendarNavigation.ts @@ -1,27 +1,17 @@ import { computed, ref } from 'vue'; import type { Dayjs } from 'dayjs'; import { getLocalizedDayJs } from '../utils/time'; -import { getWeekStart } from '../utils/settings'; +import { getWeekStartDayNumber } from '../utils/settings'; export function useCalendarNavigation(callbacks: { - onDatesChange: (payload: { start: Date; end: Date }) => void; + onDatesChange: (payload: { start: Dayjs; end: Dayjs }) => void; scrollToCurrentTime: () => void; }) { const activeView = ref('timeGridWeek'); const currentDate = ref(getLocalizedDayJs()); function getFirstDay(): number { - const weekStart = getWeekStart(); - const weekStartMap: Record = { - sunday: 0, - monday: 1, - tuesday: 2, - wednesday: 3, - thursday: 4, - friday: 5, - saturday: 6, - }; - return weekStartMap[weekStart] ?? 1; + return getWeekStartDayNumber(); } const viewDays = computed(() => { @@ -67,8 +57,8 @@ export function useCalendarNavigation(callbacks: { const days = viewDays.value; if (days.length === 0) return; - const start = days[0]!.toDate(); - const end = days[days.length - 1]!.add(1, 'day').toDate(); + const start = days[0]!; + const end = days[days.length - 1]!.add(1, 'day'); callbacks.onDatesChange({ start, end }); } diff --git a/resources/js/packages/ui/src/Input/DurationSecondsInput.vue b/resources/js/packages/ui/src/Input/DurationSecondsInput.vue new file mode 100644 index 00000000..4042f00b --- /dev/null +++ b/resources/js/packages/ui/src/Input/DurationSecondsInput.vue @@ -0,0 +1,145 @@ + + + diff --git a/resources/js/packages/ui/src/Input/EstimatedTimeInput.vue b/resources/js/packages/ui/src/Input/EstimatedTimeInput.vue index cf927843..ff11e88c 100644 --- a/resources/js/packages/ui/src/Input/EstimatedTimeInput.vue +++ b/resources/js/packages/ui/src/Input/EstimatedTimeInput.vue @@ -1,12 +1,6 @@ - - diff --git a/resources/js/packages/ui/src/Input/TextInput.vue b/resources/js/packages/ui/src/Input/TextInput.vue index 33669f71..3c767191 100644 --- a/resources/js/packages/ui/src/Input/TextInput.vue +++ b/resources/js/packages/ui/src/Input/TextInput.vue @@ -1,11 +1,15 @@