| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- <template>
- <Section
- title="Example Calendar"
- padding
- >
- <template #toolbar>
- <button @click="goToToday">Today</button>
- <button @click="previousMonth">‹</button>
- <div class="date-picker-container">
- <input
- id="goto-date"
- type="month"
- v-model="selectedDate"
- @change="goToSelectedDate"
- class="date-picker-input"
- />
- </div>
- <button @click="nextMonth">›</button>
- </template>
- <Calendar
- :section="true"
- :events="events"
- :loading="loading"
- :error="error"
- :show-navigation="false"
- :current-month="currentMonthIndex"
- :current-year="currentYear"
- @event-click="handleEventClick"
- @date-click="handleDateClick"
- @month-change="handleMonthChange"
- />
- </Section>
- </template>
- <script setup>
- import { ref, onMounted } from 'vue'
- import Calendar from '../components/Calendar.vue'
- import Section from '../components/Section.vue'
- const events = ref([])
- const loading = ref(false)
- const error = ref(null)
- const currentMonth = ref('?')
- const currentMonthIndex = ref(new Date().getMonth())
- const currentYear = ref(new Date().getFullYear())
- // Date picker state - using native HTML5 month input
- const selectedDate = ref('')
- // Generate dummy events for the current month
- function generateDummyEvents() {
- const now = new Date()
- const currentMonth = now.getMonth()
- const currentYear = now.getFullYear()
-
- // Get the number of days in the current month
- const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate()
-
- const dummyEvents = []
-
- // Add some recurring events
- for (let day = 1; day <= daysInMonth; day++) {
- const date = new Date(currentYear, currentMonth, day)
- const dayOfWeek = date.getDay()
-
- // Add weekend events (Saturday and Sunday)
- if (dayOfWeek === 0 || dayOfWeek === 6) {
- dummyEvents.push({
- id: `weekend-${day}`,
- title: 'Weekend Activity',
- date: new Date(currentYear, currentMonth, day, 10, 0),
- description: 'Relaxing weekend activity'
- })
- }
-
- // Add some random events
- if (Math.random() > 0.7) {
- const eventTypes = [
- { title: 'Team Meeting', time: [9, 0], duration: 1 },
- { title: 'Client Call', time: [14, 30], duration: 0.5 },
- { title: 'Project Review', time: [16, 0], duration: 2 },
- { title: 'Lunch Break', time: [12, 0], duration: 1 },
- { title: 'Code Review', time: [10, 0], duration: 1.5 }
- ]
-
- const eventType = eventTypes[Math.floor(Math.random() * eventTypes.length)]
- const [hours, minutes] = eventType.time
-
- dummyEvents.push({
- id: `event-${day}-${Math.random().toString(36).substr(2, 9)}`,
- title: eventType.title,
- date: new Date(currentYear, currentMonth, day, hours, minutes),
- description: `Scheduled ${eventType.title.toLowerCase()}`
- })
- }
- }
-
- // Add some multi-day events
- dummyEvents.push({
- id: 'conference-1',
- title: 'Tech Conference',
- startDate: new Date(currentYear, currentMonth, 5, 9, 0),
- endDate: new Date(currentYear, currentMonth, 7, 17, 0),
- description: 'Annual technology conference'
- })
-
- dummyEvents.push({
- id: 'vacation-1',
- title: 'Vacation',
- startDate: new Date(currentYear, currentMonth, 15, 0, 0),
- endDate: new Date(currentYear, currentMonth, 18, 23, 59),
- description: 'Family vacation time'
- })
-
- // Add some all-day events
- dummyEvents.push({
- id: 'holiday-1',
- title: 'Public Holiday',
- date: new Date(currentYear, currentMonth, 1, 0, 0),
- description: 'National holiday - office closed'
- })
-
- if (daysInMonth >= 25) {
- dummyEvents.push({
- id: 'deadline-1',
- title: 'Project Deadline',
- date: new Date(currentYear, currentMonth, 25, 0, 0),
- description: 'Important project deadline'
- })
- }
-
- return dummyEvents
- }
- function handleEventClick(event) {
- console.log('Event clicked:', event)
- alert(`Event: ${event.title}\nDescription: ${event.description || 'No description'}`)
- }
- function handleDateClick(date) {
- console.log('Date clicked:', date)
- alert(`Date selected: ${date.toLocaleDateString()}`)
- }
- // Helper function to update the date picker value
- function updateDatePicker(monthIndex, year) {
- const month = String(monthIndex + 1).padStart(2, '0')
- selectedDate.value = `${year}-${month}`
- }
- // Navigation functions - using the same fast path as internal calendar navigation
- function previousMonth() {
- const newMonth = currentMonthIndex.value === 0 ? 11 : currentMonthIndex.value - 1
- const newYear = currentMonthIndex.value === 0 ? currentYear.value - 1 : currentYear.value
-
- // Update state directly (fast path)
- currentMonthIndex.value = newMonth
- currentYear.value = newYear
-
- // Update title
- const date = new Date(newYear, newMonth, 1)
- currentMonth.value = date.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
-
- // Update date picker
- updateDatePicker(newMonth, newYear)
- }
- function nextMonth() {
- const newMonth = currentMonthIndex.value === 11 ? 0 : currentMonthIndex.value + 1
- const newYear = currentMonthIndex.value === 11 ? currentYear.value + 1 : currentYear.value
-
- // Update state directly (fast path)
- currentMonthIndex.value = newMonth
- currentYear.value = newYear
-
- // Update title
- const date = new Date(newYear, newMonth, 1)
- currentMonth.value = date.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
-
- // Update date picker
- updateDatePicker(newMonth, newYear)
- }
- function goToToday() {
- const now = new Date()
- const newMonth = now.getMonth()
- const newYear = now.getFullYear()
-
- // Update state directly (fast path)
- currentMonthIndex.value = newMonth
- currentYear.value = newYear
-
- // Update title
- currentMonth.value = now.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
-
- // Update date picker
- updateDatePicker(newMonth, newYear)
- }
- function goToSelectedDate() {
- if (!selectedDate.value) return
-
- // Parse the YYYY-MM format from the native date picker
- const [year, month] = selectedDate.value.split('-').map(Number)
- const monthIndex = month - 1 // Convert to 0-based month index
-
- // Update state directly (fast path)
- currentMonthIndex.value = monthIndex
- currentYear.value = year
-
- // Update title
- const date = new Date(year, monthIndex, 1)
- currentMonth.value = date.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
- }
- function handleMonthChange(month, year) {
- console.log('Month changed:', month, year)
- // In a real app, you might fetch events for the new month
- loading.value = true
-
- // Update current month and year state
- currentMonthIndex.value = month
- currentYear.value = year
-
- // Use native JavaScript to format month and year
- const date = new Date(year, month, 1)
- currentMonth.value = date.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
-
- // Update date picker to reflect the new month
- updateDatePicker(month, year)
-
- setTimeout(() => {
- // Simulate loading delay
- events.value = generateDummyEvents()
- loading.value = false
- }, 500)
- }
- onMounted(() => {
- // Generate initial events for current month
- events.value = generateDummyEvents()
-
- // Set initial month title using native JavaScript
- const now = new Date()
- currentMonthIndex.value = now.getMonth()
- currentYear.value = now.getFullYear()
- currentMonth.value = now.toLocaleDateString('en-US', {
- month: 'long',
- year: 'numeric'
- })
-
- // Initialize the native date picker with current month/year
- const year = now.getFullYear()
- const month = String(now.getMonth() + 1).padStart(2, '0')
- selectedDate.value = `${year}-${month}`
- })
- </script>
- <style scoped>
- .date-picker-container {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- }
- .date-picker-label {
- font-size: 0.875rem;
- font-weight: 500;
- color: #374151;
- }
- .date-picker-input {
- padding: 0.5rem;
- border: 1px solid #d1d5db;
- border-radius: 4px;
- font-size: 0.875rem;
- background: white;
- cursor: pointer;
- transition: all 0.2s;
- }
- .date-picker-input:hover {
- border-color: #9ca3af;
- }
- .date-picker-input:focus {
- outline: none;
- border-color: #3b82f6;
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
- }
- /* Dark theme support */
- @media (prefers-color-scheme: dark) {
- .date-picker-label {
- color: #d1d5db;
- }
-
- .date-picker-input {
- background: #374151;
- border-color: #4b5563;
- color: #f9fafb;
- }
-
- .date-picker-input:hover {
- border-color: #6b7280;
- }
-
- .date-picker-input:focus {
- border-color: #60a5fa;
- box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.1);
- }
- }
- </style>
|