Repository: jackkoskie/chill-pill
Pull request #54: Calendar interface
Author: login: ric-e
Labels: name: UX / Design
name: User Pages
description: Pages that allow the user to interact / configure / view with their data
name: Daily Flow
description: The main pages and actions involved in daily use. Not items that involve configuration
Created: 2025-04-08T12:56:42Z | Merged: 2025-04-08T15:58:56Z

dush's part

pull reqest to eventually squash and merge


Diff:
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index ec7e57d..5f4dfbc 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -78,7 +78,7 @@
 					<div class="flex-none gap-2">
 						<ul class="menu menu-horizontal p-1">
 							<li><a>{m.notifications()}</a></li>
-							<li><a>{m.calendar()}</a></li>
+							<li><a href="/calendar">{m.calendar()}</a></li>
 						</ul>
 					</div>
 					<div class="dropdown dropdown-end">
diff --git a/src/routes/calendar/+page.server.ts b/src/routes/calendar/+page.server.ts
new file mode 100644
index 0000000..f85ba98
--- /dev/null
+++ b/src/routes/calendar/+page.server.ts
@@ -0,0 +1,36 @@
+import { eq } from 'drizzle-orm';
+import type { PageServerLoad } from './$types';
+import { users } from '$lib/db/schema';
+import { redirect } from '@sveltejs/kit';
+
+export const load = (async ({ locals }) => {
+	const { db } = locals;
+
+	if (!locals.user) {
+		redirect(303, '/login');
+	}
+
+	const user = await db.query.users.findFirst({
+		where: eq(users.id, locals.user.id),
+		with: {
+			medications: {
+				with: {
+					history: {
+						orderBy: (posts, { desc }) => desc(posts.timestamp)
+					}
+				}
+			}
+		}
+	});
+
+	if (!user) {
+		redirect(303, '/login');
+	}
+
+	if (!user.medications) {
+		// If user has no medications, redirect to settings so they can add medications
+		redirect(303, '/settings');
+	}
+
+	return { user, medications: user.medications };
+}) satisfies PageServerLoad;
diff --git a/src/routes/calendar/+page.svelte b/src/routes/calendar/+page.svelte
new file mode 100644
index 0000000..6cb0653
--- /dev/null
+++ b/src/routes/calendar/+page.svelte
@@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<button
+					class="flex cursor-pointer flex-col justify-start rounded bg-white p-3 text-[#151e46] shadow-md transition-all duration-200 hover:bg-blue-200"
+					onclick={() => selectDate(day)}
+				>
+					<span class="text-sm font-bold">{day}</span>
+					{#if data.user.medications.some((med) => {
+						const weekday = getDayOfWeek(day);
+						const daysArray = intToDay(med.days);
+						return daysArray[weekday];
+					})}
+						<span class="mt-1 text-xs font-medium text-green-600">💊</span>
+					{/if}
+				</button>
+			{/each}
+		</div>
+	</div>
+
+	<!-- Medication Details Section (Right Panel) -->
+	<div class="flex-1 rounded-md bg-white p-4 text-[#151e46] shadow-lg">
+		<h3 class="mb-3 text-lg font-bold">
+			Medication for {selectedDate ? `${monthNames[month]} ${$selectedDate}` : ''}
+		</h3>
+
+		{#if $medicationsForSelectedDate.length > 0}
+			<ul class="space-y-3">
+				{#each $medicationsForSelectedDate as med}
+					<li class="border-l-4 border-blue-600 pl-3">
+						<div class="text-base font-semibold">{med.name}</div>
+						<div class="text-sm text-gray-700">{med.description}</div>
+						<div class="text-xs text-gray-500">
+							Time(s): {intToTime(med.time)
+								.map((t, i) => (t ? `${i.toString().padStart(2, '0')}:00` : null))
+								.filter(Boolean)
+								.join(', ')}
+						</div>
+						{#if med.dose}
+							<div class="text-xs text-gray-500">Dose: {med.dose} {med.units}</div>
+						{/if}
+					</li>
+				{/each}
+			</ul>
+		{:else}
+			<p class="text-gray-500">No medications for this day.</p>
+		{/if}
+	</div>
+</div>


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 1 out of 3 changed files in this pull request and generated 3 comments.

<details>
<summary>Files not reviewed (2)</summary>

* **src/routes/+layout.svelte**: Language not supported
* **src/routes/calendar/+page.svelte**: Language not supported
</details>



state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T15:18:40Z
user: login: jackkoskie
body: See comments, everything looks pretty good just a couple changes for accessibility and removing deprecated code before merging
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-04-08T15:32:52Z
user: login: jackkoskie
body: lgtm
state: DISMISSED
author_association: OWNER
submitted_at: 2025-04-08T15:50:36Z
user: login: jackkoskie
state: APPROVED
author_association: OWNER
submitted_at: 2025-04-08T15:58:48Z

Review comments:
diff_hunk: @@ -0,0 +1,36 @@
+import { eq } from 'drizzle-orm';
+import type { PageServerLoad } from './$types';
+import { users } from '$lib/db/schema';
+import { redirect } from '@sveltejs/kit';
+
+export const load = (async ({ locals }) => {
+	const { db } = locals;
+
+	if (!locals.user) {
+		redirect(303, '/login');
path: src/routes/calendar/+page.server.ts
user: login: Copilot
body: Redirects in SvelteKit load functions should be thrown to properly halt execution. Consider replacing 'redirect(303, '/login');' with 'throw redirect(303, '/login');' to align with expected SvelteKit behavior.
```suggestion
		throw redirect(303, '/login');
```
created_at: 2025-04-08T15:18:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,36 @@
+import { eq } from 'drizzle-orm';
+import type { PageServerLoad } from './$types';
+import { users } from '$lib/db/schema';
+import { redirect } from '@sveltejs/kit';
+
+export const load = (async ({ locals }) => {
+	const { db } = locals;
+
+	if (!locals.user) {
+		redirect(303, '/login');
+	}
+
+	const user = await db.query.users.findFirst({
+		where: eq(users.id, locals.user.id),
+		with: {
+			medications: {
+				with: {
+					history: {
+						orderBy: (posts, { desc }) => desc(posts.timestamp)
+					}
+				}
+			}
+		}
+	});
+
+	if (!user) {
+		redirect(303, '/login');
path: src/routes/calendar/+page.server.ts
user: login: Copilot
body: The redirect here should be thrown instead of simply called. Using 'throw redirect(303, '/login');' ensures the function exits as intended.
```suggestion
		throw redirect(303, '/login');
```
created_at: 2025-04-08T15:18:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,36 @@
+import { eq } from 'drizzle-orm';
+import type { PageServerLoad } from './$types';
+import { users } from '$lib/db/schema';
+import { redirect } from '@sveltejs/kit';
+
+export const load = (async ({ locals }) => {
+	const { db } = locals;
+
+	if (!locals.user) {
+		redirect(303, '/login');
+	}
+
+	const user = await db.query.users.findFirst({
+		where: eq(users.id, locals.user.id),
+		with: {
+			medications: {
+				with: {
+					history: {
+						orderBy: (posts, { desc }) => desc(posts.timestamp)
+					}
+				}
+			}
+		}
+	});
+
+	if (!user) {
+		redirect(303, '/login');
+	}
+
+	if (!user.medications) {
path: src/routes/calendar/+page.server.ts
user: login: Copilot
body: Similarly, use 'throw redirect(303, '/settings');' instead of calling 'redirect' to correctly halt further execution in the load function.
created_at: 2025-04-08T15:18:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<div
+					class="cursor-pointer rounded bg-white p-3 text-[#151e46] shadow-md transition-all duration-200 hover:bg-blue-200"
+					on:click={() => selectDate(day)}
+				>
+					<div class="text-sm font-bold">{day}</div>
+					{#if data.user.medications.some((med) => {
+						const weekday = getDayOfWeek(day);
+						const daysArray = intToDay(med.days);
+						return daysArray[weekday];
+					})}
+						<div class="mt-1 text-xs font-medium text-green-600">💊</div>
+					{/if}
+				</div>
+			{/each}
+		</div>
+	</div>
+
+	<!-- Medication Details Section (Right Panel) -->
+	<div class="flex-1 rounded-md bg-white p-4 text-[#151e46] shadow-lg">
+		<h3 class="mb-3 text-lg font-bold">
+			Todays Medications {selectedDate ? `- ${monthNames[month]} ${$selectedDate}` : ''}
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: Reword to not say "Today's Medications" unless on today's date. Could say something along the lines of Medication for April 4th...."
created_at: 2025-04-08T15:24:44Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<div
+					class="cursor-pointer rounded bg-white p-3 text-[#151e46] shadow-md transition-all duration-200 hover:bg-blue-200"
+					on:click={() => selectDate(day)}
+				>
+					<div class="text-sm font-bold">{day}</div>
+					{#if data.user.medications.some((med) => {
+						const weekday = getDayOfWeek(day);
+						const daysArray = intToDay(med.days);
+						return daysArray[weekday];
+					})}
+						<div class="mt-1 text-xs font-medium text-green-600">💊</div>
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: consider if possible indicating how many medications you have to take?
created_at: 2025-04-08T15:25:33Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<div
+					class="cursor-pointer rounded bg-white p-3 text-[#151e46] shadow-md transition-all duration-200 hover:bg-blue-200"
+					on:click={() => selectDate(day)}
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: depricated method of handling clicks

Use this instead:
```svelte
onclick={() => selectDate(day)}
```
created_at: 2025-04-08T15:28:39Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<div
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: div elements having click is not accessibility friendly, swap for a button element, shouldn't change anything
created_at: 2025-04-08T15:29:08Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
+		<div class="grid grid-cols-7 gap-2 text-center">
+			{#each ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as day}
+				<div class="font-semibold">{day}</div>
+			{/each}
+
+			<!-- Empty slots before the first day of the month -->
+			{#each Array(getFirstDayOffset(year, month)).fill(null) as _}
+				<div></div>
+			{/each}
+
+			<!-- Calendar days -->
+			{#each Array(getDaysInMonth(year, month))
+				.fill(0)
+				.map((_, i) => i + 1) as day}
+				<div
+					class="cursor-pointer rounded bg-white p-3 text-[#151e46] shadow-md transition-all duration-200 hover:bg-blue-200"
+					on:click={() => selectDate(day)}
+				>
+					<div class="text-sm font-bold">{day}</div>
+					{#if data.user.medications.some((med) => {
+						const weekday = getDayOfWeek(day);
+						const daysArray = intToDay(med.days);
+						return daysArray[weekday];
+					})}
+						<div class="mt-1 text-xs font-medium text-green-600">💊</div>
+					{/if}
+				</div>
+			{/each}
+		</div>
+	</div>
+
+	<!-- Medication Details Section (Right Panel) -->
+	<div class="flex-1 rounded-md bg-white p-4 text-[#151e46] shadow-lg">
+		<h3 class="mb-3 text-lg font-bold">
+			Todays Medications {selectedDate ? `- ${monthNames[month]} ${$selectedDate}` : ''}
+		</h3>
+
+		{#if $medicationsForSelectedDate.length > 0}
+			<ul class="space-y-3">
+				{#each $medicationsForSelectedDate as med}
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: see if there is a way to separate a medication into multiple instances for each time as it may make it easier for a user to be able to see all of their medications for the morning together and all of their medications for the evening together instead of having to look over the entire list
created_at: 2025-04-08T15:30:38Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,130 @@
+<script lang="ts">
+	import type { PageData } from './$types';
+	import { onMount } from 'svelte';
+	import { writable, derived } from 'svelte/store';
+	import { intToDay, intToTime } from '$lib/utils/converter';
+
+	let { data }: { data: PageData } = $props();
+
+	let selectedDate: Writable<number | null> = writable(null); // Store for selectedDate
+
+	const year = 2025;
+	const month = 3; // April (0-indexed)
+
+	const getDaysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();
+
+	const getFirstDayOffset = (year: number, month: number) => {
+		const jsDay = new Date(year, month, 1).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	const getDayOfWeek = (day: number) => {
+		const jsDay = new Date(year, month, day).getDay();
+		return (jsDay + 6) % 7;
+	};
+
+	// Derived store to get medications for the selected date
+	const medicationsForSelectedDate = derived(selectedDate, ($selectedDate) => {
+		if ($selectedDate === null) {
+			return [];
+		}
+		const weekday = getDayOfWeek($selectedDate);
+		return data.user.medications.filter((med) => {
+			const daysArray = intToDay(med.days);
+			return daysArray[weekday]; // Check if medication is scheduled for the selected day
+		});
+	});
+
+	// Handle date selection and update the selectedDate store
+	const selectDate = (day: number) => {
+		selectedDate.set(day);
+	};
+
+	onMount(() => {
+		// Select today's date if it's within the current month
+		const today = new Date();
+		if (today.getMonth() === month && today.getFullYear() === year) {
+			selectDate(today.getDate());
+		}
+	});
+
+	const monthNames = [
+		'January',
+		'February',
+		'March',
+		'April',
+		'May',
+		'June',
+		'July',
+		'August',
+		'September',
+		'October',
+		'November',
+		'December'
+	];
+</script>
+
+<div class="flex min-h-screen flex-col gap-6 bg-[#151e46] p-4 text-white md:flex-row">
+	<!-- Calendar section -->
+	<div class="flex-1">
+		<h2 class="mb-4 text-lg font-bold">Medication Schedule</h2>
path: src/routes/calendar/+page.svelte
user: login: jackkoskie
body: see if there is a way to have a medication stop showing on the calendar if by that point they will be out of the medication. not a necessity but a nice to have. potentially mark on the calendar that they will run out on that day so they can plan out when to go get a refill.
created_at: 2025-04-08T15:31:09Z
author_association: OWNER

PR comments:
user: login: ric-e
created_at: 2025-04-08T12:58:44Z
body: ok merge pull request ready
i need you both to take a look at the work before i get anything done

author_association: COLLABORATOR
user: login: cloudflare-workers-and-pages[bot]
created_at: 2025-04-08T15:50:11Z
body: ## Deploying chill-pill with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>53efdb9</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://e889ea1c.chill-pill.pages.dev'>https://e889ea1c.chill-pill.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://calendar-interface.chill-pill.pages.dev'>https://calendar-interface.chill-pill.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/cade74c6e5390b8462bb5fd578f0b904/pages/view/chill-pill/e889ea1c-0bdf-496d-8e39-8aae017f5e5b)

author_association: NONE