Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FilterMenu from "@/components/FilterMenu";
import Navbar from "@/components/Navbar";
import RecipeSummary from "@/components/RecipeSummary";
import DashboardCalendar from "@/components/DashboardCalendar";

export default function Home() {
const today = new Date();
Expand All @@ -18,6 +19,11 @@ export default function Home() {
<h1 className="text-3xl font-bold">Dashboard</h1>
<p className="mt-2 text-lg text-gray-600">{formattedDate}</p>
</div>
<div className="px-6">
<div className="max-w-lg">
<DashboardCalendar />
</div>
</div>
<h1>Dashboard</h1>
<h1 className="text-3xl font-bold underline">Hello world!</h1>
<RecipeSummary id={"recipe_test_001"} />
Expand Down
118 changes: 118 additions & 0 deletions src/components/DashboardCalendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"use client";

import { useState } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";

const DAY_HEADERS = ["SUN", "MON", "TUE", "WED", "THUR", "FRI", "SAT"];

function getDaysInMonth(year: number, month: number): number {
return new Date(year, month + 1, 0).getDate();
}

function getFirstDayOfMonth(year: number, month: number): number {
return new Date(year, month, 1).getDay();
}

function getWeekRange(date: Date): { start: Date; end: Date } {
const day = date.getDay();
const start = new Date(date);
start.setDate(date.getDate() - day);
const end = new Date(start);
end.setDate(start.getDate() + 6);
return { start, end };
}

function isSameDay(a: Date, b: Date): boolean {
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
}

function isInSameWeekWeekday(selected: Date, date: Date): boolean {
const { start, end } = getWeekRange(selected);
const dayOfWeek = date.getDay();
return date >= start && date <= end && dayOfWeek >= 1 && dayOfWeek <= 5;
}

export default function DashboardCalendar() {
const [currentMonth, setCurrentMonth] = useState(new Date());
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
const year = currentMonth.getFullYear();
const month = currentMonth.getMonth();
const daysInMonth = getDaysInMonth(year, month);
const firstDay = getFirstDayOfMonth(year, month);
const monthName = currentMonth.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
});

function goToPrevMonth() {
setCurrentMonth(new Date(year, month - 1, 1));
}

function goToNextMonth() {
setCurrentMonth(new Date(year, month + 1, 1));
}

function handleDateClick(day: number) {
setSelectedDate(new Date(year, month, day));
}

return (
<div className="w-full font-montserrat">
{/* Header */}
<div className="mb-6 flex items-center justify-between">
<h2 className="text-3xl font-bold">{monthName}</h2>
<div className="flex gap-2">
<button
onClick={goToPrevMonth}
className="rounded-full p-1 transition-colors hover:bg-gray-100"
aria-label="Previous month"
>
<ChevronLeft className="h-6 w-6 text-pepper" />
</button>
<button
onClick={goToNextMonth}
className="rounded-full p-1 transition-colors hover:bg-gray-100"
aria-label="Next month"
>
<ChevronRight className="h-6 w-6 text-pepper" />
</button>
</div>
</div>
{/* Day headers */}
<div className="mb-4 grid grid-cols-7">
{DAY_HEADERS.map((day) => (
<div key={day} className="text-sm font-bold">
{day}
</div>
))}
</div>
{/* Calendar grid */}
<div className="grid grid-cols-7 gap-y-6">
{Array.from({ length: firstDay }).map((_, i) => (
<div key={`empty-${i}`} />
))}
{Array.from({ length: daysInMonth }).map((_, i) => {
const day = i + 1;
const date = new Date(year, month, day);
const isSelected = selectedDate !== null && isSameDay(date, selectedDate);
const isSameWeek = selectedDate !== null && !isSelected && isInSameWeekWeekday(selectedDate, date);
return (
<button
key={day}
onClick={() => handleDateClick(day)}
className={`flex h-10 w-10 items-center justify-center rounded-full text-base transition-colors ${
isSelected
? "bg-radish-900 text-white"
: isSameWeek
? "bg-radish-100 text-radish-900"
: "text-pepper hover:bg-gray-100"
}`}
>
{day}
</button>
);
})}
</div>
</div>
);
}