Calendar component

This commit is contained in:
2025-06-02 20:52:49 +03:00
parent 7d4d50848b
commit c83e4ff00b
4 changed files with 127 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
.calendarGrid {
display: grid;
gap: 1rem;
grid-template-columns: auto auto auto auto auto auto auto;
text-align: center;
margin-bottom: 2rem;
}
.monthNavigation {
display: flex;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
}
.monthTitle {
text-align: center;
}
.monthNavBtn {
background-color: #d4f0dd;
}
.emptyBtn {
background-color: #d4f0dd;
}
.calendarCell {
background-color: #d4f0dd;
border: 1px solid #ccc;
padding: 0.5rem;
cursor: pointer;
height: 3rem;
width: 3rem;
border-radius: 0.5rem;
}
.firstWeekPaddingCell {
height: 3rem;
width: 3rem;
}

View File

@@ -0,0 +1,72 @@
import { JSX, useEffect, useState } from "react";
import styles from "./Calendar.module.css";
import { getMonthName, daysInMonth } from "../utils/dateUtils";
const generateFirstWeekPadding = (month: number) => {
const firstDay = new Date(new Date().getFullYear(), month, 1).getDay();
const padding = Array.from({ length: firstDay === 0 ? 6 : firstDay - 1 }, (_, index) => (
<div key={index} className={`${styles.firstWeekPaddingCell}`}>
&nbsp;
</div>
));
return padding;
}
const generateCalendarCells = (month: number) => {
const monthDays = daysInMonth[month];
const calendarCells = Array.from({ length: monthDays }, (_, index) => {
const day = index + 1;
const date = new Date(new Date().getFullYear(), month, day);
return (
<div key={index} className={`${styles.calendarCell}`}>
{date.toLocaleDateString("fi-FI", {
day: "2-digit",
month: "2-digit",
})}
</div>
);
});
return calendarCells;
}
export default function Calendar() {
const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
const [calendarCells, setCalendarCells] = useState<JSX.Element[]>([]);
const [firstWeekPadding, setFirstWeekPadding] = useState<JSX.Element[]>([]);
useEffect(() => {
setCalendarCells(generateCalendarCells(selectedMonth));
setFirstWeekPadding(generateFirstWeekPadding(selectedMonth));
}, [selectedMonth]);
return (
<>
<h2 className={styles.monthTitle}>
{getMonthName(selectedMonth)} {new Date().getFullYear()}
</h2>
<div className={styles.monthNavigation}>
<button onClick={() => setSelectedMonth((prev) => (prev - 1 + 12) % 12)} className={styles.monthNavBtn}>
&lt; Edellinen kuukausi
</button>
<button onClick={() => setSelectedMonth((prev) => (prev + 1) % 12)} className={styles.monthNavBtn}>
Seuraava kuukausi &gt;
</button>
</div>
<div className={styles.calendarGrid}>
<span>Ma</span>
<span>Ti</span>
<span>Ke</span>
<span>To</span>
<span>Pe</span>
<span>La</span>
<span>Su</span>
{firstWeekPadding}
{calendarCells}
</div>
</>
);
}

View File

@@ -1,3 +1,6 @@
'use client'
import { use } from "react";
import Calendar from "./components/Calendar";
import styles from "./page.module.css"; import styles from "./page.module.css";
export default function Home() { export default function Home() {
@@ -5,6 +8,7 @@ export default function Home() {
<div className={styles.page}> <div className={styles.page}>
<span className={styles.companyName}>Livonsaaren Osuuspuutarhan</span> <span className={styles.companyName}>Livonsaaren Osuuspuutarhan</span>
<h1 className={styles.title}>Satolaatikko kalenteri</h1> <h1 className={styles.title}>Satolaatikko kalenteri</h1>
<Calendar />
</div> </div>
); );
} }

10
app/utils/dateUtils.ts Normal file
View File

@@ -0,0 +1,10 @@
export const getMonthName = (month: number): string => {
const monthNames = [
"Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu",
"Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu",
"Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu"
];
return monthNames[month];
}
export const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];