mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-28 17:29:36 +02:00
Add new dashboard
This commit is contained in:
parent
88dbd41b92
commit
a39e22b0a8
13 changed files with 181 additions and 11 deletions
|
@ -444,7 +444,6 @@
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
credentials: 'include',
|
|
||||||
body: JSON.stringify(adventure)
|
body: JSON.stringify(adventure)
|
||||||
});
|
});
|
||||||
let data = await res.json();
|
let data = await res.json();
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "um Ihre eigenen Fotos zu teilen. \nVeröffentlichen Sie sie im",
|
"join_discord_desc": "um Ihre eigenen Fotos zu teilen. \nVeröffentlichen Sie sie im",
|
||||||
"photo_by": "Foto von",
|
"photo_by": "Foto von",
|
||||||
"change_password_error": "Passwort kann nicht geändert werden. \nUngültiges aktuelles Passwort oder ungültiges neues Passwort.",
|
"change_password_error": "Passwort kann nicht geändert werden. \nUngültiges aktuelles Passwort oder ungültiges neues Passwort.",
|
||||||
"current_password": "Aktuelles Passwort"
|
"current_password": "Aktuelles Passwort",
|
||||||
|
"password_change_lopout_warning": "Nach der Passwortänderung werden Sie abgemeldet."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Artikel hinzufügen",
|
"add_item": "Artikel hinzufügen",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord": "Join the Discord",
|
"join_discord": "Join the Discord",
|
||||||
"join_discord_desc": "to share your own photos. Post them in the #travel-share channel.",
|
"join_discord_desc": "to share your own photos. Post them in the #travel-share channel.",
|
||||||
"current_password": "Current Password",
|
"current_password": "Current Password",
|
||||||
"change_password_error": "Unable to change password. Invalid current password or invalid new password."
|
"change_password_error": "Unable to change password. Invalid current password or invalid new password.",
|
||||||
|
"password_change_lopout_warning": "You will be logged out after changing your password."
|
||||||
},
|
},
|
||||||
"collection": {
|
"collection": {
|
||||||
"collection_created": "Collection created successfully!",
|
"collection_created": "Collection created successfully!",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "para compartir tus propias fotos. \nPublicarlos en el",
|
"join_discord_desc": "para compartir tus propias fotos. \nPublicarlos en el",
|
||||||
"photo_by": "Foto por",
|
"photo_by": "Foto por",
|
||||||
"change_password_error": "No se puede cambiar la contraseña. \nContraseña actual no válida o contraseña nueva no válida.",
|
"change_password_error": "No se puede cambiar la contraseña. \nContraseña actual no válida o contraseña nueva no válida.",
|
||||||
"current_password": "Contraseña actual"
|
"current_password": "Contraseña actual",
|
||||||
|
"password_change_lopout_warning": "Se cerrará su sesión después de cambiar su contraseña."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Agregar artículo",
|
"add_item": "Agregar artículo",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "pour partager vos propres photos. \nPostez-les dans le",
|
"join_discord_desc": "pour partager vos propres photos. \nPostez-les dans le",
|
||||||
"photo_by": "Photo par",
|
"photo_by": "Photo par",
|
||||||
"change_password_error": "Impossible de changer le mot de passe. \nMot de passe actuel invalide ou nouveau mot de passe invalide.",
|
"change_password_error": "Impossible de changer le mot de passe. \nMot de passe actuel invalide ou nouveau mot de passe invalide.",
|
||||||
"current_password": "Mot de passe actuel"
|
"current_password": "Mot de passe actuel",
|
||||||
|
"password_change_lopout_warning": "Vous serez déconnecté après avoir modifié votre mot de passe."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Ajouter un article",
|
"add_item": "Ajouter un article",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "per condividere le tue foto. \nPubblicateli in",
|
"join_discord_desc": "per condividere le tue foto. \nPubblicateli in",
|
||||||
"photo_by": "Foto di",
|
"photo_by": "Foto di",
|
||||||
"change_password_error": "Impossibile modificare la password. \nPassword attuale non valida o nuova password non valida.",
|
"change_password_error": "Impossibile modificare la password. \nPassword attuale non valida o nuova password non valida.",
|
||||||
"current_password": "password attuale"
|
"current_password": "password attuale",
|
||||||
|
"password_change_lopout_warning": "Verrai disconnesso dopo aver modificato la password."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Aggiungi articolo",
|
"add_item": "Aggiungi articolo",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "om uw eigen foto's te delen. \nPlaats ze in de",
|
"join_discord_desc": "om uw eigen foto's te delen. \nPlaats ze in de",
|
||||||
"photo_by": "Foto door",
|
"photo_by": "Foto door",
|
||||||
"change_password_error": "Kan wachtwoord niet wijzigen. \nOngeldig huidig wachtwoord of ongeldig nieuw wachtwoord.",
|
"change_password_error": "Kan wachtwoord niet wijzigen. \nOngeldig huidig wachtwoord of ongeldig nieuw wachtwoord.",
|
||||||
"current_password": "Huidig wachtwoord"
|
"current_password": "Huidig wachtwoord",
|
||||||
|
"password_change_lopout_warning": "Na het wijzigen van uw wachtwoord wordt u uitgelogd."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Artikel toevoegen",
|
"add_item": "Artikel toevoegen",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord": "Dołącz do Discorda",
|
"join_discord": "Dołącz do Discorda",
|
||||||
"join_discord_desc": "aby podzielić się swoimi zdjęciami. Zamieść je w kanale #travel-share.",
|
"join_discord_desc": "aby podzielić się swoimi zdjęciami. Zamieść je w kanale #travel-share.",
|
||||||
"change_password_error": "Nie można zmienić hasła. \nNieprawidłowe bieżące hasło lub nieprawidłowe nowe hasło.",
|
"change_password_error": "Nie można zmienić hasła. \nNieprawidłowe bieżące hasło lub nieprawidłowe nowe hasło.",
|
||||||
"current_password": "Aktualne hasło"
|
"current_password": "Aktualne hasło",
|
||||||
|
"password_change_lopout_warning": "Po zmianie hasła nastąpi wylogowanie."
|
||||||
},
|
},
|
||||||
"collection": {
|
"collection": {
|
||||||
"collection_created": "Kolekcja została pomyślnie utworzona!",
|
"collection_created": "Kolekcja została pomyślnie utworzona!",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "för att dela dina egna foton. \nLägg upp dem i",
|
"join_discord_desc": "för att dela dina egna foton. \nLägg upp dem i",
|
||||||
"photo_by": "Foto av",
|
"photo_by": "Foto av",
|
||||||
"change_password_error": "Det går inte att ändra lösenord. \nOgiltigt nuvarande lösenord eller ogiltigt nytt lösenord.",
|
"change_password_error": "Det går inte att ändra lösenord. \nOgiltigt nuvarande lösenord eller ogiltigt nytt lösenord.",
|
||||||
"current_password": "Aktuellt lösenord"
|
"current_password": "Aktuellt lösenord",
|
||||||
|
"password_change_lopout_warning": "Du kommer att loggas ut efter att du har ändrat ditt lösenord."
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "Lägg till objekt",
|
"add_item": "Lägg till objekt",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"join_discord_desc": "分享您自己的照片。\n将它们张贴在",
|
"join_discord_desc": "分享您自己的照片。\n将它们张贴在",
|
||||||
"photo_by": "摄影:",
|
"photo_by": "摄影:",
|
||||||
"change_password_error": "无法更改密码。\n当前密码无效或新密码无效。",
|
"change_password_error": "无法更改密码。\n当前密码无效或新密码无效。",
|
||||||
"current_password": "当前密码"
|
"current_password": "当前密码",
|
||||||
|
"password_change_lopout_warning": "更改密码后您将退出。"
|
||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"add_item": "添加项目",
|
"add_item": "添加项目",
|
||||||
|
|
53
frontend/src/routes/dashboard/+page.server.ts
Normal file
53
frontend/src/routes/dashboard/+page.server.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||||
|
import type { Adventure } from '$lib/types';
|
||||||
|
|
||||||
|
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||||
|
|
||||||
|
export const load = (async (event) => {
|
||||||
|
if (!event.locals.user) {
|
||||||
|
return redirect(302, '/login');
|
||||||
|
} else {
|
||||||
|
let adventures: Adventure[] = [];
|
||||||
|
|
||||||
|
let initialFetch = await event.fetch(`${serverEndpoint}/api/adventures/`, {
|
||||||
|
headers: {
|
||||||
|
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||||
|
},
|
||||||
|
credentials: 'include'
|
||||||
|
});
|
||||||
|
|
||||||
|
let stats = null;
|
||||||
|
|
||||||
|
let res = await event.fetch(`${serverEndpoint}/api/stats/counts/`, {
|
||||||
|
headers: {
|
||||||
|
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
console.error('Failed to fetch user stats');
|
||||||
|
} else {
|
||||||
|
stats = await res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialFetch.ok) {
|
||||||
|
let error_message = await initialFetch.json();
|
||||||
|
console.error(error_message);
|
||||||
|
console.error('Failed to fetch visited adventures');
|
||||||
|
return redirect(302, '/login');
|
||||||
|
} else {
|
||||||
|
let res = await initialFetch.json();
|
||||||
|
let visited = res.results as Adventure[];
|
||||||
|
// only get the first 3 adventures or less if there are less than 3
|
||||||
|
adventures = visited.slice(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
adventures,
|
||||||
|
stats
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}) satisfies PageServerLoad;
|
107
frontend/src/routes/dashboard/+page.svelte
Normal file
107
frontend/src/routes/dashboard/+page.svelte
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import AdventureCard from '$lib/components/AdventureCard.svelte';
|
||||||
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
|
export let data: PageData;
|
||||||
|
|
||||||
|
// Mock data
|
||||||
|
const user = data.user;
|
||||||
|
const recentAdventures = data.props.adventures;
|
||||||
|
const stats = data.props.stats;
|
||||||
|
console.log(stats);
|
||||||
|
|
||||||
|
const inspirationQuote = 'The world is a book, and those who do not travel read only one page.';
|
||||||
|
const inspirationImage = 'https://picsum.photos/seed/inspiration/800/400';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container mx-auto p-4">
|
||||||
|
<!-- Welcome Message -->
|
||||||
|
<div class="mb-8">
|
||||||
|
<h1 class="text-4xl font-extrabold">Welcome back, {user?.first_name}!</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Stats -->
|
||||||
|
<div class="stats shadow mb-8 w-full bg-neutral">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-primary">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="inline-block w-8 h-8 stroke-current"
|
||||||
|
><path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7"
|
||||||
|
></path></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="stat-title text-neutral-content">Countries Visited</div>
|
||||||
|
<div class="stat-value text-primary">{stats.country_count}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-secondary">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="inline-block w-8 h-8 stroke-current"
|
||||||
|
><path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||||
|
></path></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="stat-title text-neutral-content">Total Adventures</div>
|
||||||
|
<div class="stat-value text-secondary">{stats.adventure_count}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-success">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="inline-block w-8 h-8 stroke-current"
|
||||||
|
><path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||||
|
></path></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="stat-title text-neutral-content">Total Visited Regions</div>
|
||||||
|
<div class="stat-value text-success">{stats.visited_region_count}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recent Adventures -->
|
||||||
|
<h2 class="text-3xl font-semibold mb-4">Recent Adventures</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
||||||
|
{#each recentAdventures as adventure}
|
||||||
|
<AdventureCard {adventure} type="someType" user={data.user} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Inspiration -->
|
||||||
|
<div class="card lg:card-side bg-base-100 shadow-xl mb-8">
|
||||||
|
<figure class="lg:w-1/2">
|
||||||
|
<img src={inspirationImage} alt="Inspiration" class="w-full h-full object-cover" />
|
||||||
|
</figure>
|
||||||
|
<div class="card-body lg:w-1/2">
|
||||||
|
<h2 class="card-title">Get Inspired</h2>
|
||||||
|
<p class="text-lg italic">"{inspirationQuote}"</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<button class="btn btn-primary">Plan Your Next Adventure</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Dashboard | AdventureLog</title>
|
||||||
|
<meta name="description" content="Home dashboard for AdventureLog." />
|
||||||
|
</svelte:head>
|
|
@ -151,7 +151,9 @@
|
||||||
placeholder={$t('settings.confirm_new_password')}
|
placeholder={$t('settings.confirm_new_password')}
|
||||||
class="block mb-2 input input-bordered w-full max-w-xs"
|
class="block mb-2 input input-bordered w-full max-w-xs"
|
||||||
/>
|
/>
|
||||||
<button class="py-2 px-4 btn btn-primary mt-2">{$t('settings.password_change')}</button>
|
<div class="tooltip tooltip-warning" data-tip={$t('settings.password_change_lopout_warning')}>
|
||||||
|
<button class="py-2 px-4 btn btn-primary mt-2">{$t('settings.password_change')}</button>
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue