diff --git a/.env b/.env deleted file mode 100644 index 50dcc6e..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -VITE_API_URL=localhost:80 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c2d68f9..1ef73dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,6 +83,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", @@ -1640,8 +1641,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", @@ -1751,6 +1751,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1995,6 +1996,7 @@ "integrity": "sha512-lruSgrYPVAJzKmX6EJYCg9nY+0A4VkeTLpTzf1jRD/XMjNbzD9yy7D499xmVKglwJczANYJXBvZSPGcRlon+0w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/mocker": "4.0.13", "@vitest/utils": "4.0.13", @@ -2018,6 +2020,7 @@ "integrity": "sha512-oaRY+/pvwS4/sN2rE2aZh9jdli8EkXm5AidmXEbWRu2wW0omG9PmgChWCX2jsD9qRLQxXTSLl5oKezANNF6LnQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/browser": "4.0.13", "@vitest/mocker": "4.0.13", @@ -2192,6 +2195,7 @@ "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "4.0.13", "pathe": "^2.0.3" @@ -2245,6 +2249,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2479,6 +2484,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -2562,6 +2568,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" }, @@ -2775,8 +2782,17 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, + "license": "MIT" + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "license": "MIT", - "peer": true + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -2842,6 +2858,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -2905,6 +2922,7 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3814,7 +3832,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -4209,6 +4226,7 @@ "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "playwright-core": "1.56.1" }, @@ -4290,7 +4308,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -4306,7 +4323,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -4319,8 +4335,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", @@ -4396,6 +4411,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -4478,6 +4494,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" }, @@ -4651,6 +4668,7 @@ "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -4838,6 +4856,7 @@ "integrity": "sha512-vQMufKKA9TxgoEDHJv3esrqUkjszuuRiDkThiHxENFPdQawHhm2Dei+iwNRwH5W671zTDy9iRT9P1KDjcU5Iyw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^1.6.0", @@ -5341,6 +5360,7 @@ "integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -5410,12 +5430,28 @@ } } }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/vitest": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz", "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.13", "@vitest/mocker": "4.0.13", 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/Header/Header.jsx b/src/components/Header/Header.jsx index d467539..290cb24 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -55,9 +55,11 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles - {user.isAdmin && isActive ? styles.activeLink : styles.link}> - Administration - } + {/*{user?.isAdmin && ( + isActive ? styles.activeLink : styles.link}> + Administration + + )}*/} @@ -89,9 +91,11 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles - {user.isAdmin && isActive ? styles.activeLink : styles.link}> - Administration - } + {/*{user?.isAdmin && ( + isActive ? styles.activeLink : styles.link}> + Administration + + )}*/} 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..534d2c1 --- /dev/null +++ b/src/components/homePage/calendar.module.css @@ -0,0 +1,175 @@ +.calendarContainer { + padding: 20px; + 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: none; +} + +.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: 450px; + 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-top: 16px; + margin-bottom: 16px; + max-height: 450px; + } + + .calendarContainer { + padding: 20px; + display: flex; + flex-direction: column; + align-items: center; + } +} \ 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..be7e903 --- /dev/null +++ b/src/components/homePage/eventList.jsx @@ -0,0 +1,45 @@ +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 ? ( + + ) : ( +

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..0b27a64 --- /dev/null +++ b/src/components/homePage/eventList.module.css @@ -0,0 +1,75 @@ +.glassCard { + width: 45%; + max-height: 450px; + 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{ + font-size: 30px; + display: flex; + justify-content: center; +} + +.eventGroup{ + margin: 16px 0px 16px 0px; + padding: 10px 20px 10px 20px; + border-radius: 20px; + 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); +} + +@media (max-width: 768px) { + .glassCard { + width: 100%; + margin-top: 16px; + margin-bottom: 16px; + max-height: 450px; + display: flex; + flex-direction: column; + } +} \ No newline at end of file diff --git a/src/layout.jsx b/src/layout.jsx index 4fa0991..3e477a4 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -9,11 +9,11 @@ import { AuthContext } from "./contexts/auth/AuthContext.js"; function Layout(){ - const { user, loading } = useContext(AuthContext); + /*const { user, loading } = useContext(AuthContext); - if (loading) return

Loading

; + if (loading) return

Loading

; if (!user) return ; - if(user && user.validate === 0) return ; + if(user && user.validate === 0) return ;*/ return (
diff --git a/src/pages/Admin/AdminPage.jsx b/src/pages/Admin/AdminPage.jsx index da36ac4..7682bb1 100644 --- a/src/pages/Admin/AdminPage.jsx +++ b/src/pages/Admin/AdminPage.jsx @@ -15,7 +15,7 @@ function AdminPage() { const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); - if(!user.isAdmin) navigate("/"); + /*if(!user.isAdmin) navigate("/");*/ 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..8d3602d 100644 --- a/src/pages/Home/HomePage.module.css +++ b/src/pages/Home/HomePage.module.css @@ -1,173 +1,14 @@ -.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; + justify-content: center; + gap: 80px; } @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/pages/Profile/ProfilePage.jsx b/src/pages/Profile/ProfilePage.jsx index b2602d0..a47e87c 100644 --- a/src/pages/Profile/ProfilePage.jsx +++ b/src/pages/Profile/ProfilePage.jsx @@ -8,7 +8,6 @@ import SettingsModal from "../../components/SettingsModal/SettingsModal.jsx"; function ProfilePage() { const { user } = useContext(AuthContext); - return (
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