diff --git a/geneit_app/package-lock.json b/geneit_app/package-lock.json index e06e236..184a50f 100644 --- a/geneit_app/package-lock.json +++ b/geneit_app/package-lock.json @@ -22,6 +22,7 @@ "@types/node": "^16.18.34", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", + "date-and-time": "^3.0.1", "jotai": "^2.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -6846,6 +6847,11 @@ "node": ">=10" } }, + "node_modules/date-and-time": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.0.1.tgz", + "integrity": "sha512-Az1hy3IPuh7LR4duPGlgkUzZXtjoWH8pd+XVLpLXMNd+DD48sRdcsWIPbqdHCXg4izb9lPzrKtqUXPXevS9g4Q==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -22546,6 +22552,11 @@ "whatwg-url": "^8.0.0" } }, + "date-and-time": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.0.1.tgz", + "integrity": "sha512-Az1hy3IPuh7LR4duPGlgkUzZXtjoWH8pd+XVLpLXMNd+DD48sRdcsWIPbqdHCXg4izb9lPzrKtqUXPXevS9g4Q==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/geneit_app/package.json b/geneit_app/package.json index f978bad..e3620a9 100644 --- a/geneit_app/package.json +++ b/geneit_app/package.json @@ -17,6 +17,7 @@ "@types/node": "^16.18.34", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", + "date-and-time": "^3.0.1", "jotai": "^2.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/geneit_app/src/api/ApiClient.ts b/geneit_app/src/api/ApiClient.ts index 4975624..78bf5b4 100644 --- a/geneit_app/src/api/ApiClient.ts +++ b/geneit_app/src/api/ApiClient.ts @@ -47,8 +47,7 @@ export class APIClient { // Handle expired tokens if (res.status === 412) { AuthApi.RemoveAuthToken(); - // eslint-disable-next-line no-self-assign - window.location.href = window.location.href; + window.location.href = "/"; } if (!args.allowFail && !res.ok) diff --git a/geneit_app/src/api/UserApi.ts b/geneit_app/src/api/UserApi.ts index 85fb373..3e49be0 100644 --- a/geneit_app/src/api/UserApi.ts +++ b/geneit_app/src/api/UserApi.ts @@ -23,4 +23,17 @@ export class UserApi { }) ).data; } + + /** + * Update user profile + */ + static async UpdateProfile(name: string): Promise { + await APIClient.exec({ + uri: "/user/update_profile", + method: "POST", + jsonData: { + name: name, + }, + }); + } } diff --git a/geneit_app/src/routes/ProfileRoute.tsx b/geneit_app/src/routes/ProfileRoute.tsx index 664c2bd..06724e7 100644 --- a/geneit_app/src/routes/ProfileRoute.tsx +++ b/geneit_app/src/routes/ProfileRoute.tsx @@ -1,25 +1,129 @@ import React, { useRef } from "react"; import { AsyncWidget } from "../widgets/AsyncWidget"; import { User, UserApi } from "../api/UserApi"; +import { + Alert, + Box, + Button, + Card, + CardActions, + CardContent, + Checkbox, + FormControlLabel, + TextField, + Typography, +} from "@mui/material"; +import { TimeWidget, formatDate } from "../widgets/TimeWidget"; +import { ServerApi } from "../api/ServerApi"; export function ProfileRoute(): React.ReactElement { const [user, setUser] = React.useState(null); + const [newName, setNewName] = React.useState(""); + + const [error, setError] = React.useState(null); + const [success, setSuccess] = React.useState(null); const load = async () => { - setUser(await UserApi.GetUserInfo()); + const u = await UserApi.GetUserInfo(); + setUser(u); + setNewName(u.name); }; const counter = useRef(0); + const updateProfile = async () => { + try { + setSuccess(null); + setError(null); + + await UserApi.UpdateProfile(newName); + + counter.current += 1; + setSuccess("Informations du profil mises à jour avec succès !"); + } catch (e) { + console.error(e); + setError("Echec de la mise à jour du profil !"); + } + }; + return ( ( - <> -

ready !!! {user!.name}

- +
+ Profil + + {error && {error}} + {success && {success}} + + + + + Paramètres du compte + + + + + + + + + + + + setNewName(e.target.value)} + inputProps={{ + maxLength: ServerApi.Config.constraints.user_name_len.max, + }} + /> + + } + label="Compte administrateur" + /> + + + + + + +
)} /> ); diff --git a/geneit_app/src/widgets/TimeWidget.tsx b/geneit_app/src/widgets/TimeWidget.tsx new file mode 100644 index 0000000..f72b72a --- /dev/null +++ b/geneit_app/src/widgets/TimeWidget.tsx @@ -0,0 +1,63 @@ +import { Tooltip } from "@mui/material"; +import date from "date-and-time"; + +export function formatDate(time: number): string { + const t = new Date(); + t.setTime(1000 * time); + return date.format(t, "DD/MM/YYYY HH:mm:ss"); +} + +export function timeDiff(a: number, b: number): string { + let diff = b - a; + + if (diff === 0) return "maintenant"; + if (diff === 1) return "1 seconde"; + + if (diff < 60) { + return `${diff} secondes`; + } + + diff = Math.floor(diff / 60); + + if (diff === 1) return "1 minute"; + if (diff < 24) { + return `${diff} minutes`; + } + + diff = Math.floor(diff / 60); + + if (diff === 1) return "1 heure"; + if (diff < 24) { + return `${diff} heures`; + } + + const diffDays = Math.floor(diff / 24); + + if (diffDays === 1) return "1 jour"; + if (diffDays < 31) { + return `${diffDays} jours`; + } + + diff = Math.floor(diffDays / 31); + + if (diff < 12) { + return `${diff} mois`; + } + + const diffYears = Math.floor(diffDays / 365); + + if (diffYears === 1) return "1 an"; + return `${diffYears} ans`; +} + +export function timeDiffFromNow(time: number): string { + return timeDiff(time, Math.floor(new Date().getTime() / 1000)); +} + +export function TimeWidget(p: { time: number }): React.ReactElement { + return ( + + {timeDiffFromNow(p.time)} + + ); +}