Can update profile information
This commit is contained in:
parent
b64bc8fb6d
commit
e3bec527f0
11
geneit_app/package-lock.json
generated
11
geneit_app/package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -23,4 +23,17 @@ export class UserApi {
|
||||
})
|
||||
).data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user profile
|
||||
*/
|
||||
static async UpdateProfile(name: string): Promise<void> {
|
||||
await APIClient.exec({
|
||||
uri: "/user/update_profile",
|
||||
method: "POST",
|
||||
jsonData: {
|
||||
name: name,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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 | User>(null);
|
||||
const [newName, setNewName] = React.useState("");
|
||||
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
const [success, setSuccess] = React.useState<string | null>(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 (
|
||||
<AsyncWidget
|
||||
loadKey={counter.current}
|
||||
load={load}
|
||||
errMsg="Echec du chargement des informations du compte utilisateur !"
|
||||
build={() => (
|
||||
<>
|
||||
<p>ready !!! {user!.name}</p>
|
||||
</>
|
||||
<div style={{ maxWidth: "500px", margin: "auto" }}>
|
||||
<Typography variant="h3">Profil</Typography>
|
||||
|
||||
{error && <Alert severity="error">{error}</Alert>}
|
||||
{success && <Alert severity="success">{success}</Alert>}
|
||||
|
||||
<Card style={{ marginTop: "10px" }}>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
Paramètres du compte
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
component="form"
|
||||
sx={{
|
||||
"& .MuiTextField-root": { m: 1 },
|
||||
}}
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
>
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label="Identifiant"
|
||||
value={user?.id}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label="Création du compte"
|
||||
value={formatDate(user!.time_create)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label="Activation du compte"
|
||||
value={formatDate(user!.time_activate)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label="Adresse mail"
|
||||
value={user?.email}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Nom d'utilisateur"
|
||||
value={newName}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
inputProps={{
|
||||
maxLength: ServerApi.Config.constraints.user_name_len.max,
|
||||
}}
|
||||
/>
|
||||
|
||||
<FormControlLabel
|
||||
disabled
|
||||
control={<Checkbox checked={user!.admin} />}
|
||||
label="Compte administrateur"
|
||||
/>
|
||||
</Box>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button onClick={updateProfile} style={{ marginLeft: "auto" }}>
|
||||
Enregistrer
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
63
geneit_app/src/widgets/TimeWidget.tsx
Normal file
63
geneit_app/src/widgets/TimeWidget.tsx
Normal file
@ -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 (
|
||||
<Tooltip title={formatDate(p.time)}>
|
||||
<span>{timeDiffFromNow(p.time)}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user