mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-25 07:49:37 +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: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(adventure)
|
||||
});
|
||||
let data = await res.json();
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "um Ihre eigenen Fotos zu teilen. \nVeröffentlichen Sie sie im",
|
||||
"photo_by": "Foto von",
|
||||
"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": {
|
||||
"add_item": "Artikel hinzufügen",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord": "Join the Discord",
|
||||
"join_discord_desc": "to share your own photos. Post them in the #travel-share channel.",
|
||||
"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_created": "Collection created successfully!",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "para compartir tus propias fotos. \nPublicarlos en el",
|
||||
"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.",
|
||||
"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": {
|
||||
"add_item": "Agregar artículo",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "pour partager vos propres photos. \nPostez-les dans le",
|
||||
"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.",
|
||||
"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": {
|
||||
"add_item": "Ajouter un article",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "per condividere le tue foto. \nPubblicateli in",
|
||||
"photo_by": "Foto di",
|
||||
"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": {
|
||||
"add_item": "Aggiungi articolo",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "om uw eigen foto's te delen. \nPlaats ze in de",
|
||||
"photo_by": "Foto door",
|
||||
"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": {
|
||||
"add_item": "Artikel toevoegen",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord": "Dołącz do Discorda",
|
||||
"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.",
|
||||
"current_password": "Aktualne hasło"
|
||||
"current_password": "Aktualne hasło",
|
||||
"password_change_lopout_warning": "Po zmianie hasła nastąpi wylogowanie."
|
||||
},
|
||||
"collection": {
|
||||
"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",
|
||||
"photo_by": "Foto av",
|
||||
"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": {
|
||||
"add_item": "Lägg till objekt",
|
||||
|
|
|
@ -294,7 +294,8 @@
|
|||
"join_discord_desc": "分享您自己的照片。\n将它们张贴在",
|
||||
"photo_by": "摄影:",
|
||||
"change_password_error": "无法更改密码。\n当前密码无效或新密码无效。",
|
||||
"current_password": "当前密码"
|
||||
"current_password": "当前密码",
|
||||
"password_change_lopout_warning": "更改密码后您将退出。"
|
||||
},
|
||||
"checklist": {
|
||||
"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')}
|
||||
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 />
|
||||
</form>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue