diff options
Diffstat (limited to 'ping/frontend/src/routes/dashboard/personnel')
| -rw-r--r-- | ping/frontend/src/routes/dashboard/personnel/+page.svelte | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/ping/frontend/src/routes/dashboard/personnel/+page.svelte b/ping/frontend/src/routes/dashboard/personnel/+page.svelte new file mode 100644 index 0000000..a1722c1 --- /dev/null +++ b/ping/frontend/src/routes/dashboard/personnel/+page.svelte @@ -0,0 +1,290 @@ +<script lang="ts"> + import Avatar from '$lib/components/Avatar.svelte'; + import UserItem from '$lib/components/UserItem.svelte'; + import { authFetch, getUpdatedUser, getUser, type IUser } from '$lib/stores/auth'; + import { addToast } from '$lib/stores/toast'; + import { onMount } from 'svelte'; + + let user = $state<IUser | null>(null); + let allUsers = $state<IUser[]>([]); + + let idValue = $state<string>(''); + let urlValue = $state<string>(''); + let nameValue = $state<string>(''); + let passwordValue = $state<string>(''); + + async function loadUser() { + try { + user = await getUser(); + if (!user) { + addToast({ title: 'Erreur', message: 'Utilisateur non trouvé.' }); + return null; + } + idValue = user.id; + urlValue = user.avatar || ''; + nameValue = user.displayName || ''; + return user; + } catch (error) { + user = null; + addToast({ title: 'Erreur', message: 'Impossible de charger les informations utilisateur.' }); + return null; + } + } + + async function loadAllUsers() { + try { + const response = await authFetch('/api/user/all'); + if (!response.ok) { + throw new Error('Erreur lors du chargement des utilisateurs'); + } + const users = await response.json(); + return users; + } catch (error) { + addToast({ title: 'Erreur', message: 'Impossible de charger la liste des utilisateurs.' }); + return []; + } + } + + function onEditUser(event: Event) { + event.preventDefault(); + const form = event.target as HTMLFormElement; + const formData = new FormData(form); + + const { id, avatar, username, password } = Object.fromEntries(formData.entries()); + + authFetch(`/api/user/${id}`, { + method: 'PUT', + body: JSON.stringify({ + avatar: avatar || user?.avatar, + displayName: username || user?.displayName, + password: password || undefined + }), + headers: { + 'Content-Type': 'application/json' + } + }) + .then((res) => res.json()) + .then((data) => { + getUpdatedUser().then((updatedUser) => { + user = updatedUser; + }); + console.log('Utilisateur mis à jour', data); + addToast({ + title: 'Succès', + message: 'Informations utilisateur mises à jour avec succès.', + color: 'green' + }); + }) + .catch((error) => { + addToast({ + title: 'Erreur', + message: 'Échec de la mise à jour des informations utilisateur.' + }); + }); + } + + function onCreateUser(event: Event) { + event.preventDefault(); + const form = event.target as HTMLFormElement; + const formData = new FormData(form); + const { login, password, isAdmin } = Object.fromEntries(formData.entries()); + + authFetch('/api/user', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + login, + password, + isAdmin: isAdmin === 'on' + }) + }) + .then(async (res) => { + if (!res.ok) { + addToast({ + title: 'Erreur', + message: "Impossible de créer l'utilisateur." + }); + throw new Error("Erreur lors de la création de l'utilisateur"); + } + const newUser = await res.json(); + allUsers = [...allUsers, newUser]; + addToast({ + title: 'Succès', + message: 'Nouvel utilisateur créé avec succès.', + color: 'green' + }); + form.reset(); + }) + .catch(() => { + addToast({ + title: 'Erreur', + message: "Impossible de créer l'utilisateur." + }); + }); + } + + onMount(async () => { + loadUser().then((user) => { + if (user && user.isAdmin) + loadAllUsers().then((users) => { + allUsers = users; + }); + }); + }); +</script> + +{#if user} + <div id="personnel"> + <div> + <section id="myUser" class="card"> + <h2>Mon compte</h2> + <Avatar username={user.displayName} url={user.avatar || '/img/default-avatar.png'} /> + <p><b>Nom</b>: {user.displayName}</p> + <p><b>Login</b>: {user.login}</p> + <p><b>Role</b>: {user.isAdmin ? 'ADMIN' : 'USER'}</p> + <p><b>Id</b>: {user.id}</p> + </section> + <section id="userEdit" class="card"> + <h2>Modifier</h2> + <i + >Laisser vide pour ne pas modifier<br /> + {#if user.isAdmin} + <p>Vous pouvez modifier les informations de n'importe quel utilisateur.</p> + {:else} + <p>Vous ne pouvez modifier que vos propres informations.</p> + {/if} + </i><br /> + <form onsubmit={onEditUser}> + {#if user.isAdmin} + <label for="id">ID de l'utilisateur</label> + <input type="text" placeholder="ID de l'utilisateur" name="id" bind:value={idValue} /> + {/if} + <label for="id">URL de l'avatar</label> + <input type="text" placeholder="URL de l'avatar" name="avatar" bind:value={urlValue} /> + <label for="id">Nom d'utilisateur</label> + <input + type="text" + placeholder="Nom d'utilisateur" + name="username" + bind:value={nameValue} + /> + <label for="id">Mot de passe</label> + <input + type="password" + placeholder="Mot de passe" + name="password" + bind:value={passwordValue} + /> + <button type="submit" class="btn">Modifier</button> + </form> + </section> + </div> + + {#if user.isAdmin} + <section id="adminActions"> + <div class="card"> + <h2>Créer un nouvel utilisateur</h2> + <form class="flex flex-col gap-2" onsubmit={onCreateUser}> + <label for="new-login">Login</label> + <input type="text" id="new-login" name="login" placeholder="Login" required /> + + <label for="new-password">Mot de passe</label> + <input + type="password" + id="new-password" + name="password" + placeholder="Mot de passe" + required + /> + + <label for="new-isAdmin"> + <input type="checkbox" id="new-isAdmin" name="isAdmin" /> + Administrateur + </label> + + <button type="submit" class="btn">Créer</button> + </form> + </div> + <div class="card"> + <h2>Liste des utilisateurs</h2> + <div> + {#each allUsers as u} + <UserItem + user={u} + onEdit={() => { + idValue = u.id; + urlValue = u.avatar || ''; + nameValue = u.displayName || ''; + }} + onDelete={() => { + authFetch(`/api/user/${u.id}`, { + method: 'DELETE' + }) + .then(async (res) => { + if (!res.ok) { + addToast({ + title: 'Erreur', + message: "Impossible de supprimer l'utilisateur." + }); + throw new Error("Erreur lors de la suppression de l'utilisateur"); + } + allUsers = allUsers.filter((user) => user.id !== u.id); + addToast({ + title: 'Succès', + message: 'Utilisateur supprimé avec succès.', + color: 'green' + }); + }) + .catch(() => { + addToast({ + title: 'Erreur', + message: "Impossible de supprimer l'utilisateur." + }); + }); + }} + /> + {/each} + </div> + </div> + </section> + {/if} + </div> +{:else} + <p>Chargement des informations utilisateur...</p> +{/if} + +<style> + * { + color: white; + } + + #personnel { + width: calc(100% - 32px); + display: flex; + gap: 16px; + } + + #personnel > * { + flex: 1; + } + + #myUser { + display: flex; + flex-direction: column; + } + + #userEdit form { + display: flex; + flex-direction: column; + gap: 8px; + } + + h2 { + margin: 0; + font-size: 1.5em; + font-weight: 600; + color: var(--text-lime); + } +</style> |
