Can update profile information
This commit is contained in:
		@@ -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>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user