From 32bde032543a511e465039993f3a713b3b9ddcbd Mon Sep 17 00:00:00 2001 From: Antoine Ordonneau Date: Fri, 19 Dec 2025 15:32:43 +0100 Subject: [PATCH] =?UTF-8?q?correction=20erreur=20et=20d=C3=A9coupage=20en?= =?UTF-8?q?=20composant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 36 ++-- package.json | 1 + pnpm-lock.yaml | 34 ++++ src/components/homePage/calendar.jsx | 146 ++++++++++++++++ src/components/homePage/calendar.module.css | 170 ++++++++++++++++++ src/components/homePage/eventList.jsx | 47 +++++ src/components/homePage/eventList.module.css | 64 +++++++ src/layout.jsx | 2 +- src/pages/Home/HomePage.jsx | 174 +------------------ src/pages/Home/HomePage.module.css | 168 +----------------- src/utils/date/formatDateLetter.js | 8 + src/utils/date/formatDateLetter.test.js | 9 + 12 files changed, 508 insertions(+), 351 deletions(-) create mode 100644 src/components/homePage/calendar.jsx create mode 100644 src/components/homePage/calendar.module.css create mode 100644 src/components/homePage/eventList.jsx create mode 100644 src/components/homePage/eventList.module.css create mode 100644 src/utils/date/formatDateLetter.js create mode 100644 src/utils/date/formatDateLetter.test.js diff --git a/package-lock.json b/package-lock.json index c714a7e..ee97185 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@vitejs/plugin-react": "^5.0.4", "@vitest/browser-playwright": "^4.0.8", "@vitest/coverage-v8": "^4.0.8", + "baseline-browser-mapping": "^2.9.8", "eslint": "^9.36.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", @@ -77,6 +78,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -286,7 +288,6 @@ "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1833,8 +1834,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -1933,6 +1933,7 @@ "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2162,6 +2163,7 @@ "integrity": "sha512-irO+aGxYx/rAhjEBLsGPO4JQ8dA+A43enIST0j4xQ2kYHatHi9tUcxkRRGpClGuUVU42mi+iQsFFzd4xxpoV3g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/mocker": "4.0.10", "@vitest/utils": "4.0.10", @@ -2185,6 +2187,7 @@ "integrity": "sha512-pm7Hl7BNyluox+uGJPnT7vCRDSI+ibHcWQRtnCACAZWxD6/b2gN+8pO0qTDPHpxDSTPKDS5sT2dKTHLcr+lsng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/browser": "4.0.10", "@vitest/mocker": "4.0.10", @@ -2359,6 +2362,7 @@ "integrity": "sha512-EXU2iSkKvNwtlL8L8doCpkyclw0mc/t4t9SeOnfOFPyqLmQwuceMPA4zJBa6jw0MKsZYbw7kAn+gl7HxrlB8UQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "4.0.10", "pathe": "^2.0.3" @@ -2412,6 +2416,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2559,9 +2564,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.16.tgz", - "integrity": "sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==", + "version": "2.9.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.8.tgz", + "integrity": "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2612,6 +2617,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -2696,6 +2702,7 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", + "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -2872,8 +2879,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", @@ -2920,6 +2926,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -2984,6 +2991,7 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3873,7 +3881,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -4342,7 +4349,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -4358,7 +4364,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -4371,8 +4376,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/prompts": { "version": "2.4.2", @@ -4436,6 +4440,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -4487,6 +4492,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -4641,6 +4647,7 @@ "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -4828,6 +4835,7 @@ "integrity": "sha512-vQMufKKA9TxgoEDHJv3esrqUkjszuuRiDkThiHxENFPdQawHhm2Dei+iwNRwH5W671zTDy9iRT9P1KDjcU5Iyw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^1.6.0", @@ -5306,6 +5314,7 @@ "integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -5381,6 +5390,7 @@ "integrity": "sha512-2Fqty3MM9CDwOVet/jaQalYlbcjATZwPYGcqpiYQqgQ/dLC7GuHdISKgTYIVF/kaishKxLzleKWWfbSDklyIKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.10", "@vitest/mocker": "4.0.10", diff --git a/package.json b/package.json index 996fc4e..8688856 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@vitejs/plugin-react": "^5.0.4", "@vitest/browser-playwright": "^4.0.8", "@vitest/coverage-v8": "^4.0.8", + "baseline-browser-mapping": "^2.9.8", "eslint": "^9.36.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6cc5fd..59042ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: react-router: specifier: ^7.9.4 version: 7.9.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react-router-dom: + specifier: ^7.10.1 + version: 7.10.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) devDependencies: '@chromatic-com/storybook': specifier: ^4.1.2 @@ -1553,6 +1556,23 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} + react-router-dom@7.10.1: + resolution: {integrity: sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.10.1: + resolution: {integrity: sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-router@7.9.4: resolution: {integrity: sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==} engines: {node: '>=20.0.0'} @@ -3315,6 +3335,20 @@ snapshots: react-refresh@0.17.0: {} + react-router-dom@7.10.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-router: 7.10.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + + react-router@7.10.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + cookie: 1.0.2 + react: 19.2.0 + set-cookie-parser: 2.7.1 + optionalDependencies: + react-dom: 19.2.0(react@19.2.0) + react-router@7.9.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: cookie: 1.0.2 diff --git a/src/components/homePage/calendar.jsx b/src/components/homePage/calendar.jsx new file mode 100644 index 0000000..f8ed8f2 --- /dev/null +++ b/src/components/homePage/calendar.jsx @@ -0,0 +1,146 @@ +import {useState} from "react"; +import styles from "./calendar.module.css"; +import formatDateLetter from "../../utils/date/formatDateLetter.js"; + +function Calendar() { + const events = { + "2025-11-07": ["Réunion de projet", "Anniversaire de Marie"], + "2025-11-10": ["Cours de React", "Rendez-vous médecin"], + "2025-11-14": ["Sortie cinéma"], + "2025-11-15": ["Sortie cinéma"], + "2025-11-17": ["Sortie cinéma"], + }; + const monthNames = [ + "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", + "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" + ]; + + const today = new Date(); + const [currentMonth, setCurrentMonth] = useState(today.getMonth()); + const [currentYear, setCurrentYear] = useState(today.getFullYear()); + const [selectedDay, setSelectedDay] = useState(() => { + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, "0"); + const day = String(today.getDate()).padStart(2, "0"); + const key = `${year}-${month}-${day}`; + return {date: key, events: events[key] || []}; + }); + + const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate(); + const firstDay = new Date(currentYear, currentMonth, 1).getDay(); + const startDay = (firstDay + 6) % 7; + + const days = []; + for (let i = 0; i < startDay; i++) days.push(null); + for (let i = 1; i <= daysInMonth; i++) days.push(i); + + const handlePrevMonth = () => { + let newMonth = currentMonth - 1; + let newYear = currentYear; + + if (newMonth < 0) { + newMonth = 11; + newYear--; + } + + setCurrentMonth(newMonth); + setCurrentYear(newYear); + + const key = `${newYear}-${String(newMonth + 1).padStart(2, "0")}-01`; + setSelectedDay({date: key, events: events[key] || []}); + }; + + const handleNextMonth = () => { + let newMonth = currentMonth + 1; + let newYear = currentYear; + + if (newMonth > 11) { + newMonth = 0; + newYear++; + } + + setCurrentMonth(newMonth); + setCurrentYear(newYear); + + const key = `${newYear}-${String(newMonth + 1).padStart(2, "0")}-01`; + setSelectedDay({date: key, events: events[key] || []}); + }; + + const handleDayClick = (day) => { + if (!day) return; + const key = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; + setSelectedDay({date: key, events: events[key] || []}); + }; + + return ( +
+
+
+ +

{monthNames[currentMonth]} {currentYear}

+ +
+ + + + + + + + + + + + + + + + {Array.from({length: Math.ceil(days.length / 7)}).map((_, weekIndex) => ( + + {days.slice(weekIndex * 7, weekIndex * 7 + 7).map((day, index) => { + const key = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; + const hasEvent = events[key]; + + return ( + + ); + })} + + ))} + +
LunMarMerJeuVenSamDim
handleDayClick(day)} + > + {day || ""} +
+ + {selectedDay && ( +
+

Événements du {formatDateLetter(selectedDay.date)}

+ + {selectedDay.events.length > 0 ? ( +
    + {selectedDay.events.map((ev, i) => ( +
  • {ev}
  • + ))} +
+ ) : ( +

Aucun événement ce jour-là.

+ )} +
+ )} +
+
+ ); +} + +export default Calendar; \ No newline at end of file diff --git a/src/components/homePage/calendar.module.css b/src/components/homePage/calendar.module.css new file mode 100644 index 0000000..5431a08 --- /dev/null +++ b/src/components/homePage/calendar.module.css @@ -0,0 +1,170 @@ +.calendarContainer { + padding: 20px; + font-family: Arial, sans-serif; + display: flex; + flex-direction: column; + align-items: center; +} + +.calendarHeader { + display: flex; + width: 100%; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 10px; +} + +.calendarHeader p { + width: auto; + text-align: center; + font-weight: bold; + font-size: 40px; +} + +.calendarHeader button { + top: 50%; + left: 50%; + width: 40px; + height: 40px; + border-radius: 50%; + border: none; + background: transparent; + box-shadow: + inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), + inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), + inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), + inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); + font-size: 15px; + color: #019AFF; + cursor: pointer; +} + +.calendar { + border-collapse: collapse; + width: 80%; + max-width: 500px; +} + +.calendar th, .calendar td { + border: none; + padding: 10px; + width: 14.2%; + line-height: 130%; + text-align: center; + cursor: pointer; +} + +.today { + color: #007bff; +} + +.hasEvent { + position: relative; +} + +.hasEvent::before { + content: ""; + position: absolute; + left: 50%; + bottom: 10px; + width: 20px; + height: 2px; + background-color: #007bff; + transform: translateX(-50%); + border-radius: 10px; +} + +.hasEvent.selected::before { + width: 25px; + height: 2px; + bottom: 10px; +} + +.selected { + position: relative; + font-size: 18px; + font-weight: 600; +} + +.selected::after { + content: ""; + position: absolute; + top: 50%; + left: 50%; + width: 40px; + height: 40px; + transform: translate(-50%, -50%); + border-radius: 38%; + pointer-events: none; + background: transparent; + box-shadow: + inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), + inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), + inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), + inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); +} + +.eventBox { + width: 100%; + border-radius: 20px; + padding: 15px; + margin-top: 16px; + border: none; + background: rgb(255, 255, 255, 0.25); + box-shadow: + inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), + inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), + inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), + inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); +} + +.eventBox ul { + list-style-type: disc; +} + +.eventGroup{ + border-radius: 20px; + padding: 15px; + margin-top: 16px; + border: none; + background: rgb(255, 255, 255, 0.25); + box-shadow: + inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), + inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), + inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), + inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); +} + +.glassCard { + width: 45%; + max-height: 475px; + margin: 16px 0px 16px 0px; + padding: 10px 20px 10px 20px; + height: fit-content; + background: rgba(255, 255, 255, 0.65); + backdrop-filter: blur(3px); + -webkit-backdrop-filter: blur(3px); + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.5), + inset 0 -1px 0 rgba(255, 255, 255, 0.1), + inset 0 0 8px 4px rgba(255, 255, 255, 0.4); + overflow: scroll; + +} + +.glassCard::-webkit-scrollbar{ + display: none; +} + +@media (max-width: 768px) { + .glassCard { + width: 100%; + margin: 0px; + margin-top: 16px; + margin-bottom: 16px; + display: flex; + } +} \ No newline at end of file diff --git a/src/components/homePage/eventList.jsx b/src/components/homePage/eventList.jsx new file mode 100644 index 0000000..1faf7e3 --- /dev/null +++ b/src/components/homePage/eventList.jsx @@ -0,0 +1,47 @@ +import {useMemo} from "react"; +import styles from "./eventList.module.css"; +import formatDateLetter from "../../utils/date/formatDateLetter.js"; +function eventList() { + const events = { + "2025-11-07": ["Réunion de projet", "Anniversaire de Marie"], + "2025-11-10": ["Cours de React", "Rendez-vous médecin"], + "2025-11-14": ["Sortie cinéma"], + "2025-11-15": ["Sortie cinéma"], + "2025-11-17": ["Sortie cinéma"], + }; + + const sortedEvents = useMemo(() => { + return Object.entries(events) + .map(([dateKey, eventList]) => ({date: dateKey, events: eventList})) + .sort((a, b) => new Date(a.date) - new Date(b.date)); + }, [events]); + + return ( +
+
+

Liste des événements à venir

+ {sortedEvents.length > 0 ? ( +
    + {sortedEvents.map((eventGroup) => ( +
  • +
    + {formatDateLetter(eventGroup.date)} +
    +
      + {eventGroup.events.map((event, i) => ( +
    • - {event}
    • + ))} +
    +
  • + ))} +
+ ) : ( +

Aucun événement planifié pour l'instant.

+ )} +
+
+ + ); +} + +export default eventList; \ No newline at end of file diff --git a/src/components/homePage/eventList.module.css b/src/components/homePage/eventList.module.css new file mode 100644 index 0000000..3288f5e --- /dev/null +++ b/src/components/homePage/eventList.module.css @@ -0,0 +1,64 @@ +.glassCard { + width: 45%; + max-height: 475px; + margin: 16px 0px 16px 0px; + padding: 10px 20px 10px 20px; + height: fit-content; + background: rgba(255, 255, 255, 0.65); + backdrop-filter: blur(3px); + -webkit-backdrop-filter: blur(3px); + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.5), + inset 0 -1px 0 rgba(255, 255, 255, 0.1), + inset 0 0 8px 4px rgba(255, 255, 255, 0.4); + overflow: scroll; + +} + +.glassCard::-webkit-scrollbar{ + display: none; +} + +.allContent{ + display: flex; + flex-direction: row; + justify-content: center; + gap: 76px; +} + +.eventList { + list-style: none; + padding: 0; + margin: 0; +} + +.eventDetails { + list-style: none; + padding: 0; + margin: 0; +} + +.dateSelected{ + font-size: 100px; +} + +h2{ + display: flex; + justify-content: center; +} + +.eventListContainer{ + width: 100%; +} + +@media (max-width: 768px) { + .glassCard { + width: 100%; + margin: 0px; + margin-top: 16px; + margin-bottom: 16px; + display: flex; + } +} \ No newline at end of file diff --git a/src/layout.jsx b/src/layout.jsx index 4689a4e..922f0e9 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -12,7 +12,7 @@ function Layout(){ const { user, loading } = useContext(AuthContext); if (loading) return

Loading

; - if (!user) return ; + //if (!user) return ; return (
diff --git a/src/pages/Home/HomePage.jsx b/src/pages/Home/HomePage.jsx index ae603b2..21b8881 100644 --- a/src/pages/Home/HomePage.jsx +++ b/src/pages/Home/HomePage.jsx @@ -1,179 +1,13 @@ -import { useState } from "react"; -import { useMemo } from "react"; import styles from "./HomePage.module.css"; +import Calendar from "../../components/homePage/calendar.jsx"; +import EventList from "../../components/homePage/eventList.jsx"; function HomePage() { - const events = { - "2025-11-07": ["Réunion de projet", "Anniversaire de Marie"], - "2025-11-10": ["Cours de React", "Rendez-vous médecin"], - "2025-11-14": ["Sortie cinéma"], - }; - - const monthNames = [ - "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", - "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" - ]; - - const today = new Date(); - const [currentMonth, setCurrentMonth] = useState(today.getMonth()); - const [currentYear, setCurrentYear] = useState(today.getFullYear()); - const [selectedDay, setSelectedDay] = useState(() => { - const year = today.getFullYear(); - const month = String(today.getMonth() + 1).padStart(2, "0"); - const day = String(today.getDate()).padStart(2, "0"); - const key = `${year}-${month}-${day}`; - return { date: key, events: events[key] || [] }; - }); - - const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate(); - const firstDay = new Date(currentYear, currentMonth, 1).getDay(); - const startDay = (firstDay + 6) % 7; - - const days = []; - for (let i = 0; i < startDay; i++) days.push(null); - for (let i = 1; i <= daysInMonth; i++) days.push(i); - - const handlePrevMonth = () => { - let newMonth = currentMonth - 1; - let newYear = currentYear; - - if (newMonth < 0) { - newMonth = 11; - newYear--; - } - - setCurrentMonth(newMonth); - setCurrentYear(newYear); - - const key = `${newYear}-${String(newMonth + 1).padStart(2, "0")}-01`; - setSelectedDay({ date: key, events: events[key] || [] }); - }; - - const handleNextMonth = () => { - let newMonth = currentMonth + 1; - let newYear = currentYear; - - if (newMonth > 11) { - newMonth = 0; - newYear++; - } - - setCurrentMonth(newMonth); - setCurrentYear(newYear); - - const key = `${newYear}-${String(newMonth + 1).padStart(2, "0")}-01`; - setSelectedDay({ date: key, events: events[key] || [] }); - }; - - const handleDayClick = (day) => { - if (!day) return; - const key = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; - setSelectedDay({ date: key, events: events[key] || [] }); - }; - - const sortedEvents = useMemo(() => { - return Object.entries(events) - .map(([dateKey, eventList]) => ({ date: dateKey, events: eventList })) - .sort((a, b) => new Date(a.date) - new Date(b.date)); - }, [events]); - - const formatDate = (dateString) => { - const [year, month, day] = dateString.split('-'); - return `${day} ${monthNames[parseInt(month) - 1]} ${year}`; - }; - return (
-
-
-
- -

{monthNames[currentMonth]} {currentYear}

- -
+ - - - - - - - - - - - - - - - {Array.from({ length: Math.ceil(days.length / 7) }).map((_, weekIndex) => ( - - {days.slice(weekIndex * 7, weekIndex * 7 + 7).map((day, index) => { - const key = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; - const hasEvent = events[key]; - - return ( - - ); - })} - - ))} - -
LunMarMerJeuVenSamDim
handleDayClick(day)} - > - {day || ""} -
- - {selectedDay && ( -
-

Événements du {formatDate(selectedDay.date)}

- - {selectedDay.events.length > 0 ? ( -
    - {selectedDay.events.map((ev, i) => ( -
  • {ev}
  • - ))} -
- ) : ( -

Aucun événement ce jour-là.

- )} -
- )} -
-
-
-
-

Liste des Événements à Venir

- {sortedEvents.length > 0 ? ( -
    - {sortedEvents.map((eventGroup) => ( -
  • -
    - {formatDate(eventGroup.date)} -
    -
      - {eventGroup.events.map((event, i) => ( -
    • - {event}
    • - ))} -
    -
  • - ))} -
- ) : ( -

Aucun événement planifié pour l'instant.

- )} -
-
+
); } diff --git a/src/pages/Home/HomePage.module.css b/src/pages/Home/HomePage.module.css index 7d6a67a..ddb110b 100644 --- a/src/pages/Home/HomePage.module.css +++ b/src/pages/Home/HomePage.module.css @@ -1,173 +1,7 @@ -.calendarContainer { - padding: 20px; - font-family: Arial, sans-serif; - display: flex; - flex-direction: column; - align-items: center; -} - -.calendarHeader { - display: flex; - width: 100%; - flex-direction: row; - justify-content: space-between; - align-items: center; - gap: 10px; -} - -.calendarHeader p { - width: auto; - text-align: center; - font-weight: bold; - font-size: 40px; -} - -.calendarHeader button { - top: 50%; - left: 50%; - width: 40px; - height: 40px; - border-radius: 50%; - border: none; - background: transparent; - box-shadow: - inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), - inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), - inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), - inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); - font-size: 15px; - color: #019AFF; - cursor: pointer; -} - -.calendar { - border-collapse: collapse; - width: 80%; - max-width: 500px; -} - -.calendar th, .calendar td { - border: none; - padding: 10px; - width: 14.2%; - line-height: 130%; - text-align: center; - cursor: pointer; -} - -.today { - color: #007bff; -} - -.hasEvent { - position: relative; -} - -.hasEvent::before { - content: ""; - position: absolute; - left: 50%; - bottom: 10px; - width: 20px; - height: 2px; - background-color: #007bff; - transform: translateX(-50%); - border-radius: 10px; -} - -.hasEvent.selected::before { - width: 25px; - height: 2px; - bottom: 10px; -} - -.selected { - position: relative; - font-size: 18px; - font-weight: 600; -} - -.selected::after { - content: ""; - position: absolute; - top: 50%; - left: 50%; - width: 40px; - height: 40px; - transform: translate(-50%, -50%); - border-radius: 38%; - pointer-events: none; - background: transparent; - box-shadow: - inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), - inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), - inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), - inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); -} - -.eventBox { - border-radius: 20px; - padding: 15px; - margin-top: 16px; - border: none; - background: rgb(255, 255, 255, 0.25); - box-shadow: - inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), - inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), - inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), - inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); -} - -.eventBox ul { - list-style-type: disc; -} - -.eventGroup{ - border-radius: 20px; - padding: 15px; - margin-top: 16px; - border: none; - background: rgb(255, 255, 255, 0.25); - box-shadow: - inset 1.25px 1.25px 1px rgba(255, 255, 255, 1), - inset -1.25px -1.25px 1px rgba(255, 255, 255, 1), - inset -0.25px 0.25px 1px rgba(0, 0, 0, 0.2), - inset 0.25px -0.25px 1px rgba(0, 0, 0, 0.2); -} - -.glassCard { - width: 45%; - margin: 16px; - padding: 10px 20px 10px 20px; - height: fit-content; - background: rgba(255, 255, 255, 0.65); - backdrop-filter: blur(3px); - -webkit-backdrop-filter: blur(3px); - border-radius: 20px; - border: 1px solid rgba(255, 255, 255, 0.3); - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), - inset 0 1px 0 rgba(255, 255, 255, 0.5), - inset 0 -1px 0 rgba(255, 255, 255, 0.1), - inset 0 0 8px 4px rgba(255, 255, 255, 0.4); - overflow: hidden; -} -.allContent{ - display: flex; - flex-direction: row; -} - @media (max-width: 768px) { - .glassCard { - width: 100%; - margin: 0px; - margin-top: 16px; - margin-bottom: 16px; - display: flex; - } - - .allContent{ display: flex; flex-direction: column; + gap: 0px; } } \ No newline at end of file diff --git a/src/utils/date/formatDateLetter.js b/src/utils/date/formatDateLetter.js new file mode 100644 index 0000000..8143337 --- /dev/null +++ b/src/utils/date/formatDateLetter.js @@ -0,0 +1,8 @@ +export default function formatDateLetter(d) { + const monthNames = [ + "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", + "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" + ]; + const [year, month, day] = d.split('-'); + return `${day} ${monthNames[parseInt(month) - 1]} ${year}`; +}; \ No newline at end of file diff --git a/src/utils/date/formatDateLetter.test.js b/src/utils/date/formatDateLetter.test.js new file mode 100644 index 0000000..3e52402 --- /dev/null +++ b/src/utils/date/formatDateLetter.test.js @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest'; +import formatDateLetter from './formatDateLetter'; + +const date = "2025-11-07" +const res = "07 Novembre 2025" + +test("Format Date Letter", () => { + expect(formatDateLetter(date)).toBe(res); +}) \ No newline at end of file