|
|
@@ -0,0 +1,128 @@
|
|
|
+<script lang="ts">
|
|
|
+ import { onMount } from 'svelte';
|
|
|
+
|
|
|
+ let currentDate: Date = new Date();
|
|
|
+ let days: Array<{ day: number; isActive: boolean, isAvailable: boolean }> = [];
|
|
|
+ let currentMonth: string = '';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Updates the calendar display by calculating the days of the current month.
|
|
|
+ */
|
|
|
+ const renderCalendar = (): void => {
|
|
|
+ const year: number = currentDate.getFullYear();
|
|
|
+ const month: number = currentDate.getMonth();
|
|
|
+ currentMonth = currentDate.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
|
|
|
+
|
|
|
+ const firstDayOfMonth: Date = new Date(year, month, 1);
|
|
|
+ const lastDayOfMonth: Date = new Date(year, month + 1, 0);
|
|
|
+ const firstDayIndex: number = firstDayOfMonth.getDay();
|
|
|
+ const daysInMonth: number = lastDayOfMonth.getDate();
|
|
|
+
|
|
|
+ // Reset days array
|
|
|
+ days = [];
|
|
|
+
|
|
|
+ // Add empty cells for days before the first of the month
|
|
|
+ for (let i = 0; i < firstDayIndex; i++) {
|
|
|
+ days.push({ day: 0, isActive: false, isAvailable: false });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add days of the month
|
|
|
+ for (let day = 1; day <= daysInMonth; day++) {
|
|
|
+ days.push({ day, isActive: day === 20, isAvailable: day / 2 == 5.5 }); // Example: Make day 20 active
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Changes the current month by a given offset and re-renders the calendar.
|
|
|
+ * @param offset - The number of months to move forward or backward.
|
|
|
+ */
|
|
|
+ const changeMonth = (offset: number): void => {
|
|
|
+ currentDate.setMonth(currentDate.getMonth() + offset);
|
|
|
+ renderCalendar();
|
|
|
+ };
|
|
|
+
|
|
|
+ onMount(() => {
|
|
|
+ renderCalendar();
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handles the selection of a day in the calendar.
|
|
|
+ * @param selectedDay - The day number that was clicked.
|
|
|
+ */
|
|
|
+ const selectDay = (selectedDay: number): void => {
|
|
|
+ days = days.map((d) => ({ ...d, isActive: d.day === selectedDay}));
|
|
|
+ };
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <style>
|
|
|
+ .date-picker {
|
|
|
+ border: 1px solid var(--border-color);
|
|
|
+ border-radius: var(--border-radius);
|
|
|
+ padding: 1rem;
|
|
|
+ max-width: 600px;
|
|
|
+ background: var(--background);
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ }
|
|
|
+ .date-picker-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 1rem;
|
|
|
+ }
|
|
|
+ .date-picker-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(7, 1fr);
|
|
|
+ gap: 0.5rem;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .date-picker-day {
|
|
|
+ font-weight: bold;
|
|
|
+ color: var(--secondary);
|
|
|
+ }
|
|
|
+ .date-picker-cell {
|
|
|
+ padding: 0.5rem;
|
|
|
+ border-radius: var(--border-radius);
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none;
|
|
|
+ }
|
|
|
+ .date-picker-cell:hover {
|
|
|
+ background-color: var(--hover-background);
|
|
|
+ }
|
|
|
+ .date-picker-cell.active {
|
|
|
+ background-color: var(--primary);
|
|
|
+ color: var(--background);
|
|
|
+ }
|
|
|
+ .empty {
|
|
|
+ pointer-events: none;
|
|
|
+ visibility: hidden;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+
|
|
|
+
|
|
|
+<div class="date-picker border center">
|
|
|
+ <div class="date-picker-header">
|
|
|
+ <button class="button square secondary medium" on:click={() => changeMonth(-1)}><</button>
|
|
|
+ <h4 id="currentMonth" class="small wrap center-align">{currentMonth}</h4>
|
|
|
+ <button class="button square secondary medium" on:click={() => changeMonth(1)}>></button>
|
|
|
+ </div>
|
|
|
+ <div class="date-picker-grid">
|
|
|
+ <!-- Days of the week -->
|
|
|
+ <div class="date-picker-day">Sun</div>
|
|
|
+ <div class="date-picker-day">Mon</div>
|
|
|
+ <div class="date-picker-day">Tue</div>
|
|
|
+ <div class="date-picker-day">Wed</div>
|
|
|
+ <div class="date-picker-day">Thu</div>
|
|
|
+ <div class="date-picker-day">Fri</div>
|
|
|
+ <div class="date-picker-day">Sat</div>
|
|
|
+
|
|
|
+ <!-- Render days -->
|
|
|
+ {#each days as { day, isActive, isAvailable }, index}
|
|
|
+ <div
|
|
|
+ class="date-picker-cell {isAvailable && !isActive ? 'secondary': ''} {isActive ? 'active' : ''} {day === 0 ? 'empty' : ''}"
|
|
|
+ on:click={() => day && selectDay(day)}
|
|
|
+ >
|
|
|
+ {day || ''}
|
|
|
+ </div>
|
|
|
+ {/each}
|
|
|
+ </div>
|
|
|
+</div>
|