|
|
@@ -1,132 +1,176 @@
|
|
|
<script lang="ts">
|
|
|
- import { onMount } from 'svelte';
|
|
|
-
|
|
|
- let currentDate: Date = new Date();
|
|
|
- let days: Array<{ day: number; isActive: boolean, isAvailable: boolean }> = [];
|
|
|
- let currentMonth: string = '';
|
|
|
+ import type { AppointmentDateTimes } from '$lib/dbdata';
|
|
|
+ import { isSameDate } from '$lib/funcs';
|
|
|
+ import moment, { type Moment } from 'moment';
|
|
|
+ import { onMount } from 'svelte';
|
|
|
|
|
|
- export let selectedDate: Date;
|
|
|
-
|
|
|
- /**
|
|
|
- * 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(() => {
|
|
|
+ let currentDate: Date = new Date();
|
|
|
+ let days: Array<{ day: number; isActive: boolean; isAvailable: boolean }> = [];
|
|
|
+
|
|
|
+ let currentMonth: string = '';
|
|
|
+ export let selectedDate: Date;
|
|
|
+ export let appointmentDateTimes: AppointmentDateTimes[];
|
|
|
+
|
|
|
+ $: {
|
|
|
+ if (appointmentDateTimes.length > 0) {
|
|
|
+ console.log(appointmentDateTimes);
|
|
|
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}));
|
|
|
- const selectedDateValue = new Date(currentDate.getFullYear(), currentDate.getMonth(), selectedDay);
|
|
|
- selectedDate = selectedDateValue;
|
|
|
- };
|
|
|
- </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;
|
|
|
+ }
|
|
|
+
|
|
|
+ function isDayAvailable(year: number, month: number, day: number) {
|
|
|
+ const dateStr = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
|
|
|
+ const testDate: Date = moment(dateStr).toDate();
|
|
|
+
|
|
|
+ return appointmentDateTimes.some(date => isSameDate(testDate, date.date));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Updates the calendar display by calculating the days of the current month.
|
|
|
+ */
|
|
|
+ const renderCalendar = (): void => {
|
|
|
+ console.log(currentDate);
|
|
|
+ const mDate: Moment = moment(currentDate);
|
|
|
+ const year: number = currentDate.getFullYear();
|
|
|
+ const month: number = mDate.month() + 1;
|
|
|
+ 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: false, isAvailable: isDayAvailable(year, month, day) }); // 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);
|
|
|
+ if (offset === -1) {
|
|
|
+ currentDate = moment(currentDate).subtract(1, "month").toDate();
|
|
|
+ } else {
|
|
|
+ currentDate = moment(currentDate).add(1, "month").toDate();
|
|
|
}
|
|
|
- </style>
|
|
|
-
|
|
|
+
|
|
|
+ renderCalendar();
|
|
|
+ };
|
|
|
+
|
|
|
+ onMount(() => {
|
|
|
+ currentDate = new Date();
|
|
|
+ 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 }));
|
|
|
+ const selectedDateValue = new Date(
|
|
|
+ currentDate.getFullYear(),
|
|
|
+ currentDate.getMonth(),
|
|
|
+ selectedDay
|
|
|
+ );
|
|
|
+ selectedDate = selectedDateValue;
|
|
|
+ };
|
|
|
+</script>
|
|
|
|
|
|
<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>
|
|
|
+ <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>
|
|
|
+ <!-- Render days -->
|
|
|
+ {#each days as { day, isActive, isAvailable }, index}
|
|
|
+ {#if isAvailable}
|
|
|
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
|
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
|
+ <div
|
|
|
+ class="date-picker-cell {!isActive ? 'secondary' : ''} {isActive
|
|
|
+ ? 'active'
|
|
|
+ : ''} {day === 0 ? 'empty' : ''}"
|
|
|
+ on:click={() => day && selectDay(day)}
|
|
|
+ >
|
|
|
+ {day || ''}
|
|
|
+ </div>
|
|
|
+ {:else}
|
|
|
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
|
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
|
+ <div
|
|
|
+ class="date-picker-cell"
|
|
|
+ >
|
|
|
+ {day || ''}
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+ {/each}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+
|
|
|
+<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>
|