PHP Classes

File: resources/js/pages/WeeklyPlanner.vue

Recommend this page to a friend!
  Packages of Niko Peikrishvili   Ticker   resources/js/pages/WeeklyPlanner.vue   Download  
File: resources/js/pages/WeeklyPlanner.vue
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Ticker
Application to track and manage to do tasks
Author: By
Last change:
Date: 3 months ago
Size: 7,357 bytes
 

Contents

Class file image Download
<script setup> import { ref, computed, onMounted, onUnmounted } from 'vue'; import { Head } from '@inertiajs/vue3'; import { useWeeklyPlanner } from '@/composables/useWeeklyPlanner'; import { useTodos } from '@/composables/useTodos'; import { useSettings } from '@/composables/useSettings'; import AppSidebar from '@/components/AppSidebar.vue'; import DayColumn from '@/components/Weekly/DayColumn.vue'; import BacklogColumn from '@/components/Weekly/BacklogColumn.vue'; import CarryOverModal from '@/components/Weekly/CarryOverModal.vue'; import SettingsModal from '@/components/SettingsModal.vue'; import { SidebarProvider, SidebarInset, SidebarTrigger } from '@/components/ui/sidebar'; import { Separator } from '@/components/ui/separator'; const props = defineProps({ initialWeekKey: { type: String, default: null, }, }); const { fetchWeekData, navigateWeek, loading, currentWeekKey, weekDisplay, isCurrentWeek, } = useWeeklyPlanner(); const { fetchSettings, appearance, updateSetting, applyTheme } = useSettings(); const showSettingsModal = ref(false); // Dynamic CSS variables based on settings const cssVars = computed(() => ({ '--dot-opacity': appearance.value.dotOpacity, '--primary-color': appearance.value.primaryColor, '--bg-color': appearance.value.backgroundColor, '--text-color': appearance.value.textColor, '--secondary-text-color': appearance.value.secondaryTextColor, '--border-color': appearance.value.borderColor, })); const { updateTodo: updateTodoApi } = useTodos(); const showCarryOverModal = ref(false); const handleTaskDropped = async () => { await fetchWeekData(currentWeekKey.value); }; const handleToggleComplete = async (data) => { try { await updateTodoApi(data.id, { is_completed: data.is_completed }); await fetchWeekData(currentWeekKey.value); } catch (err) { console.error('Failed to toggle task:', err); } }; const handleSidebarAction = (action) => { switch (action) { case 'prevWeek': navigateWeek(-1); break; case 'currentWeek': navigateWeek(0); break; case 'nextWeek': navigateWeek(1); break; case 'carryOver': showCarryOverModal.value = true; break; } }; const toggleDarkMode = async () => { const newTheme = appearance.value.theme === 'dark' ? 'light' : 'dark'; await updateSetting('appearance.theme', newTheme); applyTheme(newTheme); }; const handleKeyDown = (e) => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') { return; } if (e.altKey) { if (e.key === 'ArrowLeft') { e.preventDefault(); navigateWeek(-1); } else if (e.key === 'ArrowRight') { e.preventDefault(); navigateWeek(1); } return; } if (e.key === 'Escape') { if (showCarryOverModal.value) { showCarryOverModal.value = false; } else if (showSettingsModal.value) { showSettingsModal.value = false; } return; } if (showCarryOverModal.value || showSettingsModal.value) { return; } // Ignore shortcuts when modifier keys are pressed (allow browser shortcuts like Ctrl+R) if (e.ctrlKey || e.metaKey) { return; } if (e.key === 'c' || e.key === 'C') { e.preventDefault(); navigateWeek(0); } else if (e.key === 'w' || e.key === 'W') { e.preventDefault(); window.location.href = '/'; } else if (e.key === 'm' || e.key === 'M') { e.preventDefault(); showCarryOverModal.value = true; } else if (e.key === ',') { e.preventDefault(); showSettingsModal.value = true; } else if (e.key === 'd' || e.key === 'D') { e.preventDefault(); toggleDarkMode(); } }; onMounted(async () => { document.addEventListener('keydown', handleKeyDown, true); await Promise.all([ fetchWeekData(props.initialWeekKey), fetchSettings(), ]); }); onUnmounted(() => { document.removeEventListener('keydown', handleKeyDown, true); }); const handleCarriedOver = () => { // Data is already refreshed by the carryOver function }; </script> <template> <Head title="?????? ????????" /> <SidebarProvider :style="{ '--sidebar-width': '16rem', ...cssVars }"> <AppSidebar current-page="weekly" :show-settings="() => showSettingsModal = true" @action="handleSidebarAction" /> <SidebarInset> <header class="flex h-14 shrink-0 items-center gap-2 border-b px-4"> <SidebarTrigger class="-ml-1" /> <Separator orientation="vertical" class="mr-2 h-4" /> <div class="flex items-center gap-2"> <span class="font-medium">{{ weekDisplay }}</span> <span v-if="isCurrentWeek" class="px-2 py-0.5 text-xs rounded-full bg-primary text-primary-foreground" > ????????? </span> </div> </header> <div class="flex-1 p-4"> <!-- Loading Overlay --> <div v-if="loading" class="fixed inset-0 bg-background/50 z-40 flex items-center justify-center" > <div class="flex items-center gap-3 bg-card rounded-lg shadow-lg px-6 py-4 border"> <svg class="w-6 h-6 animate-spin text-primary" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> <span class="text-foreground">?????????...</span> </div> </div> <!-- Main Grid: 5 Days + Backlog --> <div class="grid grid-cols-6 gap-4 h-[calc(100vh-88px)]"> <!-- Day Columns (Mon-Fri) --> <DayColumn v-for="day in 5" :key="day" :day-of-week="day" @task-dropped="handleTaskDropped" @toggle-complete="handleToggleComplete" /> <!-- Backlog Column --> <BacklogColumn @task-dropped="handleTaskDropped" /> </div> </div> </SidebarInset> <!-- Carry Over Modal --> <CarryOverModal :show="showCarryOverModal" @close="showCarryOverModal = false" @carried-over="handleCarriedOver" /> <!-- Settings Modal --> <SettingsModal :show="showSettingsModal" @close="showSettingsModal = false" /> </SidebarProvider> </template> <style scoped> kbd { font-family: monospace; } </style>