diff --git a/.env.exemple b/.env.exemple new file mode 100644 index 0000000..3452b5c --- /dev/null +++ b/.env.exemple @@ -0,0 +1 @@ +VITE_API_URL= \ No newline at end of file diff --git a/.gitignore b/.gitignore index f52343a..bd7187d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ dist-ssr *storybook.log storybook-static + +.env \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index dc53079..4b8ff7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,9 @@ "name": "sae-front", "version": "0.0.0", "dependencies": { + "chart.js": "^4.5.1", "react": "^19.1.1", + "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4" }, diff --git a/package.json b/package.json index d2aa97d..c86a179 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,13 @@ "lint": "eslint .", "preview": "vite preview", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "storybook build", + "test": "vitest" }, "dependencies": { + "chart.js": "^4.5.1", "react": "^19.1.1", + "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4" }, @@ -26,17 +29,17 @@ "@types/react": "^19.1.16", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^5.0.4", + "@vitest/browser-playwright": "^4.0.8", + "@vitest/coverage-v8": "^4.0.8", "eslint": "^9.36.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", "eslint-plugin-storybook": "^10.0.6", "globals": "^16.4.0", + "playwright": "^1.56.1", "prop-types": "^15.8.1", "storybook": "^10.0.6", "vite": "^7.1.7", - "vitest": "^4.0.8", - "playwright": "^1.56.1", - "@vitest/browser-playwright": "^4.0.8", - "@vitest/coverage-v8": "^4.0.8" + "vitest": "^4.0.8" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f9b236..c6cc5fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,15 @@ importers: .: dependencies: + chart.js: + specifier: ^4.5.1 + version: 4.5.1 react: specifier: ^19.1.1 version: 19.2.0 + react-chartjs-2: + specifier: ^5.3.1 + version: 5.3.1(chart.js@4.5.1)(react@19.2.0) react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) @@ -436,6 +442,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@kurkle/color@0.3.4': + resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} + '@mdx-js/react@3.1.1': resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} peerDependencies: @@ -949,6 +958,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chart.js@4.5.1: + resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} + engines: {pnpm: '>=8'} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -1510,6 +1523,12 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-chartjs-2@5.3.1: + resolution: {integrity: sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==} + peerDependencies: + chart.js: ^4.1.1 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-docgen-typescript@2.4.0: resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==} peerDependencies: @@ -2186,6 +2205,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@kurkle/color@0.3.4': {} + '@mdx-js/react@3.1.1(@types/react@19.2.2)(react@19.2.0)': dependencies: '@types/mdx': 2.0.13 @@ -2738,6 +2759,10 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chart.js@4.5.1: + dependencies: + '@kurkle/color': 0.3.4 + check-error@2.1.1: {} chromatic@12.2.0: {} @@ -3255,6 +3280,11 @@ snapshots: queue-microtask@1.2.3: {} + react-chartjs-2@5.3.1(chart.js@4.5.1)(react@19.2.0): + dependencies: + chart.js: 4.5.1 + react: 19.2.0 + react-docgen-typescript@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 diff --git a/public/icons/pen.svg b/public/icons/pen.svg new file mode 100644 index 0000000..b13361f --- /dev/null +++ b/public/icons/pen.svg @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/src/components/Event/Event.jsx b/src/components/Event/Event.jsx index f3941b5..6a75fd1 100644 --- a/src/components/Event/Event.jsx +++ b/src/components/Event/Event.jsx @@ -1,9 +1,12 @@ import styles from "./Event.module.css"; -import {useState, useEffect} from "react"; -import {Link} from "react-router"; +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router"; import Button from "/src/components/ui/button/button.jsx" function Event({event}){ + + const navigate = useNavigate(); + const [eventMenu, seteventMenu] = useState(false); const [windowSize, setWindowSize] = useState({ width: null, @@ -31,7 +34,7 @@ function Event({event}){
+
) : (
{task.description}
+{formatDate(task.start)}
+{date}
-Role : Président
-Membre depuis : 2019
+Role : {user.role}
+Membre depuis : {formatDate(user.created_at)}
Mail : mailpro@gmail.com
-Téléphone : 08 67 87 32 21
+Mail : {user.email}
+Téléphone : {user.phone}
Aucune tâche pour le moment.
+ )} +{event.tasks}
+{member.name}
+Rôle : {user?.role}
+Membre depuis : {user?.created_at && formatDate(user.created_at)}
+Rôle : {user?.role}
+Membre depuis : {user?.created_at && formatDate(user.created_at)}
+Email : {user?.email}
+ {user?.phone &&Téléphone : {user.phone}
} +Rôle : {role}
-Membre depuis : {since}
-Rôle : {role}
-Membre depuis : {since}
-Email : {email}
-Téléphone : {phone}
-Lorem Ipsum...
, +}; diff --git a/src/utils/auth/logout.js b/src/utils/auth/logout.js new file mode 100644 index 0000000..fa34b2f --- /dev/null +++ b/src/utils/auth/logout.js @@ -0,0 +1,28 @@ +import getXSRFToken from "../getXSRF.js"; + +export default async function logout() { + + const csrfToken = await getXSRFToken(); + + try { + const response = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/logout`, { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-XSRF-TOKEN': csrfToken + }, + }); + + console.log('Code HTTP :', response.status); + + if (!response.ok) { + throw new Error(`Erreur HTTP ${response.status}`); + } + + return { status: response.status }; + } catch (error) { + return error; + } +} diff --git a/src/utils/date/formatDate.js b/src/utils/date/formatDate.js new file mode 100644 index 0000000..3fd1371 --- /dev/null +++ b/src/utils/date/formatDate.js @@ -0,0 +1,9 @@ +export default function formatDate(d) { + const date = new Date(d); + + const jj = String(date.getUTCDate()).padStart(2, '0'); + const mm = String(date.getUTCMonth() + 1).padStart(2, '0'); + const aaaa = date.getUTCFullYear(); + + return `${jj}/${mm}/${aaaa}`; +} \ No newline at end of file diff --git a/src/utils/date/formatDate.test.js b/src/utils/date/formatDate.test.js new file mode 100644 index 0000000..97179dc --- /dev/null +++ b/src/utils/date/formatDate.test.js @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest'; +import formatDate from './formatDate'; + +const date = "2025-11-28T11:26:45.000000Z" +const res = "28/11/2025" + +test("Format Date", () => { + expect(formatDate(date)).toBe(res); +}) \ No newline at end of file diff --git a/src/utils/event/getAllEvents.js b/src/utils/event/getAllEvents.js new file mode 100644 index 0000000..f5e37c5 --- /dev/null +++ b/src/utils/event/getAllEvents.js @@ -0,0 +1,23 @@ +export default async function getAllEvents() { + + try { + const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/events/`, { + method: 'GET', + credentials: 'include', + headers: { + 'Accept': 'application/json' + } + }); + + if (!res.ok) { + throw new Error(`Erreur serveur : ${res.status}`); + } + + const data = await res.json(); + return data; + } catch (err) { + console.error('Erreur :', err); + return null; + } + +} \ No newline at end of file diff --git a/src/utils/event/getEventById.js b/src/utils/event/getEventById.js new file mode 100644 index 0000000..8d09b78 --- /dev/null +++ b/src/utils/event/getEventById.js @@ -0,0 +1,23 @@ +export default async function GetEventById(id) { + + try { + const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/events/${id}`, { + method: 'GET', + credentials: 'include', + headers: { + 'Accept': 'application/json' + } + }); + + if (!res.ok) { + throw new Error(`Erreur serveur : ${res.status}`); + } + + const data = await res.json(); + return data; + } catch (err) { + console.error('Erreur :', err); + return null; + } + +} \ No newline at end of file diff --git a/src/utils/getUser.js b/src/utils/getUser.js index b5c817d..24297ca 100644 --- a/src/utils/getUser.js +++ b/src/utils/getUser.js @@ -1,6 +1,6 @@ export default async function getUser() { try { - const res = await fetch('http://localhost:80/api/users/me', { + const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/me`, { method: 'GET', credentials: 'include', headers: { diff --git a/src/utils/getXSRF.js b/src/utils/getXSRF.js index 46a9415..0c78e40 100644 --- a/src/utils/getXSRF.js +++ b/src/utils/getXSRF.js @@ -1,5 +1,5 @@ export default async function getXSRFToken() { - const response = await fetch('http://localhost:80/sanctum/csrf-cookie', { + const response = await fetch(`http://${import.meta.env.VITE_API_URL}/sanctum/csrf-cookie`, { method: 'GET', credentials: 'include' }); diff --git a/src/utils/login.js b/src/utils/login.js index 6107185..161268c 100644 --- a/src/utils/login.js +++ b/src/utils/login.js @@ -4,7 +4,7 @@ export default async function login(email, password) { const csrfToken = await getXSRFToken(); try { - const response = await fetch('http://localhost:80/api/users/login', { + const response = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/login`, { method: 'POST', credentials: 'include', headers: { diff --git a/src/utils/register.js b/src/utils/register.js index 2cdacf6..313df77 100644 --- a/src/utils/register.js +++ b/src/utils/register.js @@ -4,7 +4,7 @@ export default async function register(email, password, name, lastname) { const csrfToken = await getXSRFToken(); try { - const response = await fetch('http://localhost:80/api/users/register', { + const response = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/register`, { method: 'POST', credentials: 'include', headers: { diff --git a/src/utils/users/getAllUsers.js b/src/utils/users/getAllUsers.js new file mode 100644 index 0000000..c9c383e --- /dev/null +++ b/src/utils/users/getAllUsers.js @@ -0,0 +1,21 @@ +export default async function getAllUser() { + try { + const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users`, { + method: 'GET', + credentials: 'include', + headers: { + 'Accept': 'application/json' + } + }); + + if (!res.ok) { + throw new Error(`Erreur serveur : ${res.status}`); + } + + const data = await res.json(); + return data; + } catch (err) { + console.error('Erreur :', err); + return null; + } +} diff --git a/src/utils/users/getUserById.js b/src/utils/users/getUserById.js new file mode 100644 index 0000000..59af94a --- /dev/null +++ b/src/utils/users/getUserById.js @@ -0,0 +1,20 @@ +export default async function getUserById (id) { + try { + const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/${id}`, { + method: 'GET', + credentials: 'include', + headers: { + 'Accept': 'application/json' + } + }); + + if (!res.ok) { + throw new Error(`Erreur serveur : ${res.status}`); + } + + return await res.json(); + } catch (err) { + console.error('Erreur :', err); + return null; + } +} \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 59b0166..3277a15 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,39 +1,48 @@ +// vite.config.js ///