Dashboard Verbessert
This commit is contained in:
BIN
public/images/profile-placeholder.png
Normal file
BIN
public/images/profile-placeholder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
@@ -46,9 +46,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
||||||
<div class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-10 rounded-lg select-none">
|
<!--
|
||||||
|
TODO: Storniert Feld hinzufügen
|
||||||
|
{#if ausweis.storniert}
|
||||||
|
<div class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none">
|
||||||
<h1 class="absolute -rotate-[25deg] text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]">Storniert</h1>
|
<h1 class="absolute -rotate-[25deg] text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]">Storniert</h1>
|
||||||
</div>
|
</div>
|
||||||
|
{/if} -->
|
||||||
<figure class="lg:w-1/2">
|
<figure class="lg:w-1/2">
|
||||||
<img
|
<img
|
||||||
src={(ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.gebaeude_bilder && ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.gebaeude_bilder[0]?.url) || "/images/placeholder.jpg"}
|
src={(ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.gebaeude_bilder && ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.gebaeude_bilder[0]?.url) || "/images/placeholder.jpg"}
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
import { addNotification } from "#components/NotificationProvider/shared";
|
import { addNotification } from "#components/NotificationProvider/shared";
|
||||||
import { notifications } from "#components/NotificationProvider/shared";
|
import { notifications } from "#components/NotificationProvider/shared";
|
||||||
import ThemeController from "#components/ThemeController.svelte";
|
import ThemeController from "#components/ThemeController.svelte";
|
||||||
|
import { BenutzerClient } from "#components/Ausweis/types";
|
||||||
|
|
||||||
export let lightTheme: boolean;
|
export let lightTheme: boolean;
|
||||||
|
export let benutzer: BenutzerClient;
|
||||||
|
|
||||||
const rippleOptions: RippleOptions = {
|
const rippleOptions: RippleOptions = {
|
||||||
center: false,
|
center: false,
|
||||||
@@ -66,6 +68,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</details></li>
|
</details></li>
|
||||||
|
{#if benutzer.rolle === "ADMIN"}
|
||||||
<li><details>
|
<li><details>
|
||||||
<summary class="button-tab w-full outline-0 hover:outline-0">
|
<summary class="button-tab w-full outline-0 hover:outline-0">
|
||||||
<LockClosed width={22} height={22} />
|
<LockClosed width={22} height={22} />
|
||||||
@@ -88,6 +91,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</details></li>
|
</details></li>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-auto flex flex-col gap-4 px-8">
|
<div class="mt-auto flex flex-col gap-4 px-8">
|
||||||
<div class="flex flex-row justify-between items-center">
|
<div class="flex flex-row justify-between items-center">
|
||||||
@@ -114,24 +118,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider px-8"></div>
|
<div class="divider px-8"></div>
|
||||||
<button
|
<a
|
||||||
|
href="/dashboard/einstellungen"
|
||||||
use:ripple={rippleOptions}
|
use:ripple={rippleOptions}
|
||||||
class="btn btn-ghost no-animation focus:shadow-none justify-start py-4 h-auto hover:bg-base-200 px-8 rounded-none w-full flex flex-row gap-4"
|
class="btn btn-ghost no-animation focus:shadow-none justify-start py-4 h-auto hover:bg-base-200 px-8 rounded-none w-full flex flex-row gap-4"
|
||||||
>
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<div class="w-12 rounded-full">
|
<div class="w-12 rounded-full">
|
||||||
<img
|
<img
|
||||||
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"
|
src={benutzer.profilbild || "/images/profile-placeholder.png"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-base-content font-semibold"
|
<span class="text-base-content font-semibold text-left"
|
||||||
>Gertrude McKenzie</span
|
>{benutzer.vorname} {benutzer.name}</span
|
||||||
>
|
>
|
||||||
<span class="text-base-content">uve@rehkenban.bo</span>
|
<span class="text-base-content">{benutzer.email}</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!--<header class="md:hidden flex flex-row justify-between items-center px-8 sticky top-0 z-50 h-20 bg-base-100 border-b border-b-base-300">
|
<!--<header class="md:hidden flex flex-row justify-between items-center px-8 sticky top-0 z-50 h-20 bg-base-100 border-b border-b-base-300">
|
||||||
|
|||||||
@@ -6,7 +6,20 @@ import "../../svelte-dialogs.config"
|
|||||||
import "svelte-ripple-action/ripple.css"
|
import "svelte-ripple-action/ripple.css"
|
||||||
import DashboardSidebar from "../components/Dashboard/DashboardSidebar.svelte"
|
import DashboardSidebar from "../components/Dashboard/DashboardSidebar.svelte"
|
||||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
import { validateAccessTokenServer } from "src/server/lib/validateAccessToken";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { createCaller } from "#lib/caller";
|
||||||
|
|
||||||
|
const valid = validateAccessTokenServer(Astro)
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
Astro.redirect("/auth/login", 302)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const caller = createCaller(Astro)
|
||||||
|
|
||||||
|
const benutzer = await caller.v1.benutzer.self()
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -91,7 +104,7 @@ let lightTheme = Astro.cookies.get("theme").value === "light";
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="min-h-screen grid md:grid-cols-[300px_1fr]">
|
<body class="min-h-screen grid md:grid-cols-[300px_1fr]">
|
||||||
<DashboardSidebar lightTheme={lightTheme} client:load></DashboardSidebar>
|
<DashboardSidebar lightTheme={lightTheme} benutzer={benutzer} client:load></DashboardSidebar>
|
||||||
<main class="p-8 overflow-auto h-screen bg-base-100">
|
<main class="p-8 overflow-auto h-screen bg-base-100">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -7,14 +7,57 @@
|
|||||||
} from "radix-svelte-icons";
|
} from "radix-svelte-icons";
|
||||||
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs";
|
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs";
|
||||||
import { dialogs } from "../../../svelte-dialogs.config";
|
import { dialogs } from "../../../svelte-dialogs.config";
|
||||||
|
import { BenutzerClient } from "#components/Ausweis/types";
|
||||||
|
import { client } from "src/trpc";
|
||||||
|
import { exclude } from "#lib/exclude";
|
||||||
|
|
||||||
function profilSpeichern() {
|
export let benutzer: BenutzerClient;
|
||||||
dialogs.confirm({
|
|
||||||
|
let passwort: string | undefined = undefined;
|
||||||
|
let passwortVerify: string | undefined = undefined;
|
||||||
|
async function profilSpeichern(e: SubmitEvent) {
|
||||||
|
e.preventDefault()
|
||||||
|
if (!passwort) {
|
||||||
|
passwort = undefined
|
||||||
|
} else {
|
||||||
|
if (passwort.length < 8) {
|
||||||
|
dialogs.alert({
|
||||||
|
title: "Passwort zu kurz",
|
||||||
|
text: "Das Passwort muss mindestens 8 Zeichen lang sein.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
} else if (passwort !== passwortVerify) {
|
||||||
|
dialogs.alert({
|
||||||
|
title: "Passwörter stimmen nicht überein",
|
||||||
|
text: "Die eingegebenen Passwörter stimmen nicht überein.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await dialogs.confirm({
|
||||||
title: "Profil speichern",
|
title: "Profil speichern",
|
||||||
text: "Möchtest du deine Änderungen speichern?",
|
text: "Möchtest du deine Änderungen speichern?",
|
||||||
confirmButtonText: "Speichern",
|
confirmButtonText: "Speichern",
|
||||||
declineButtonText: "Abbrechen",
|
declineButtonText: "Abbrechen",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!response) return;
|
||||||
|
|
||||||
|
const benutzerObjekt = exclude({
|
||||||
|
...benutzer,
|
||||||
|
passwort
|
||||||
|
}, ["rolle"])
|
||||||
|
|
||||||
|
// Wir wollen die Rolle nicht mit übertragen.
|
||||||
|
// Diese wird zwar sowieso rausgeschmissen aber sonst kommen wir nicht durch die Validation durch...
|
||||||
|
await client.v1.benutzer.update.mutate(benutzerObjekt)
|
||||||
|
|
||||||
|
dialogs.success({
|
||||||
|
title: "Profil gespeichert",
|
||||||
|
text: "Deine Änderungen wurden erfolgreich gespeichert.",
|
||||||
|
dismissButtonClass: "btn btn-success"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -62,34 +105,51 @@
|
|||||||
>
|
>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<h2 class="text-2xl font-medium">Profil</h2>
|
<h2 class="text-2xl font-medium">Profil</h2>
|
||||||
<div class="flex flex-col gap-4 my-4 max-w-2xl">
|
<form class="flex flex-col gap-4 my-4 max-w-2xl" on:submit={profilSpeichern}>
|
||||||
<div class="flex flex-row gap-4">
|
<div class="flex flex-row gap-4">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="whitespace-nowrap">Vorname</span>
|
<span class="whitespace-nowrap">Vorname</span>
|
||||||
<input type="password" class="input text-base-content font-medium" placeholder="Max">
|
<input type="text" class="input text-base-content font-medium" placeholder="Max" bind:value={benutzer.vorname}>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="whitespace-nowrap">Nachname</span>
|
<span class="whitespace-nowrap">Nachname</span>
|
||||||
<input type="password" class="input text-base-content font-medium" placeholder="Müller">
|
<input type="text" class="input text-base-content font-medium" placeholder="Müller" bind:value={benutzer.name}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="whitespace-nowrap">Email Adresse</span>
|
<span class="whitespace-nowrap">Email Adresse</span>
|
||||||
<input type="text" class="input text-base-content font-medium" placeholder="name@email.com" value="zobhusdi@wo.tk">
|
<input type="email" class="input text-base-content font-medium" placeholder="name@email.com" bind:value={benutzer.email}>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="whitespace-nowrap">Telefonnummer</span>
|
||||||
|
<input type="phone" class="input text-base-content font-medium" placeholder="040 12345678" bind:value={benutzer.telefon}>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row gap-4">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="whitespace-nowrap">Adresse</span>
|
||||||
|
<input type="text" class="input text-base-content font-medium" placeholder="Musterstraße 123" bind:value={benutzer.adresse}>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="whitespace-nowrap">PLZ</span>
|
||||||
|
<input type="text" class="input text-base-content font-medium" placeholder="12345" bind:value={benutzer.plz}>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="whitespace-nowrap">Ort</span>
|
||||||
|
<input type="text" class="input text-base-content font-medium" placeholder="Musterhausen" bind:value={benutzer.ort}>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row gap-4">
|
<div class="flex flex-row gap-4">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="whitespace-nowrap">Passwort</span>
|
<span class="whitespace-nowrap">Passwort</span>
|
||||||
<input type="password" class="input text-base-content font-medium" placeholder="*********">
|
<input type="password" class="input text-base-content font-medium" placeholder="*********" bind:value={passwort}>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="whitespace-nowrap">Passwort bestätigen</span>
|
<span class="whitespace-nowrap">Passwort bestätigen</span>
|
||||||
<input type="password" class="input text-base-content font-medium" placeholder="*********">
|
<input type="password" class="input text-base-content font-medium" placeholder="*********" bind:value={passwortVerify}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<button class="btn btn-primary" type="submit">Speichern</button>
|
||||||
|
</form>
|
||||||
<button class="btn btn-primary" on:click={profilSpeichern}>Speichern</button>
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<h1>Panel Two</h1>
|
<h1>Panel Two</h1>
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
---
|
---
|
||||||
import UserLayout from "#layouts/UserLayout.astro";
|
import UserLayout from "#layouts/UserLayout.astro";
|
||||||
|
import { createCaller } from "#lib/caller";
|
||||||
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
|
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
|
||||||
|
import { validateAccessTokenServer } from "src/server/lib/validateAccessToken";
|
||||||
|
|
||||||
|
const valid = await validateAccessTokenServer(Astro);
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
return Astro.redirect("/auth/login", 302);
|
||||||
|
}
|
||||||
|
|
||||||
|
const caller = createCaller(Astro);
|
||||||
|
const benutzer = await caller.v1.benutzer.self();
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<UserLayout title="Einstellungen">
|
<UserLayout title="Einstellungen">
|
||||||
<DashboardEinstellungenModule client:load />
|
<DashboardEinstellungenModule benutzer={benutzer} client:load />
|
||||||
</UserLayout>
|
</UserLayout>
|
||||||
@@ -9,6 +9,10 @@ dialogs.config({
|
|||||||
titleClass: "text-base-content text-xl font-medium",
|
titleClass: "text-base-content text-xl font-medium",
|
||||||
dividerClass: "hidden",
|
dividerClass: "hidden",
|
||||||
footerClass: "bg-base-100 justify-center gap-4 mt-4",
|
footerClass: "bg-base-100 justify-center gap-4 mt-4",
|
||||||
|
closeButtonClass: "btn btn-primary",
|
||||||
|
closeButtonText: "Schließen",
|
||||||
|
dismissButtonClass: "btn btn-primary",
|
||||||
|
dismissButtonText: "Schließen",
|
||||||
closeOnBg: true,
|
closeOnBg: true,
|
||||||
closeOnEsc: true
|
closeOnEsc: true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user