Add basic frontend structure

This commit is contained in:
Oliver Traber 2025-03-18 17:23:26 +00:00 committed by Bluemedia
parent 486977f828
commit 25b7c24c65
Signed by: Bluemedia
GPG key ID: C0674B105057136C
29 changed files with 4659 additions and 3811 deletions

View file

@ -0,0 +1,97 @@
<script lang="ts">
import { goto } from '$app/navigation'
import { persistentSettings } from '$lib/persistent-store'
import i18n from '$lib/i18n'
let { children } = $props()
if (!$persistentSettings.loggedIn) {
goto('/login')
}
let drawerOpen = $state(false)
</script>
<div class="w-full h-full p-4 flex flex-col bg-base-200">
<div class="navbar w-auto mb-4 pr-4 bg-base-100 shadow-md rounded-md">
<div class="drawer navbar-start">
<input bind:checked={drawerOpen} id="nav-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content">
<label for="nav-drawer" class="btn btn-ghost btn-circle drawer-button">
<i class="bi bi-list text-2xl"></i>
</label>
</div>
<div class="drawer-side z-10">
<label for="nav-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
<ul class="menu bg-base-100 text-base min-h-full w-80 p-4">
<li class="mb-4">
<a class="btn btn-ghost text-xl" href="/">LibreCharge</a>
</li>
<li>
<a
onclick={() => {
drawerOpen = !drawerOpen
}}
href="/"
>
<i class="bi bi-graph-up text-xl"></i>
<span>Dashboard</span>
</a>
</li>
<li>
<a
onclick={() => {
drawerOpen = !drawerOpen
}}
href="/idtoken"
>
<i class="bi bi-credit-card-fill text-xl"></i>
<span>{$i18n.t('common:navbar.link.idtoken')}</span>
</a>
</li>
<li>
<a
onclick={() => {
drawerOpen = !drawerOpen
}}
href="/transaction"
>
<i class="bi bi-battery-charging text-xl"></i>
<span>{$i18n.t('common:navbar.link.transaction')}</span>
</a>
</li>
<li>
<a
onclick={() => {
drawerOpen = !drawerOpen
}}
href="/chargepoint"
>
<i class="bi bi-plug-fill text-xl"></i>
<span>{$i18n.t('common:navbar.link.chargepoint')}</span>
</a>
</li>
</ul>
</div>
</div>
<div class="navbar-center">
<a class="btn btn-ghost text-xl" href="/">LibreCharge</a>
</div>
<div class="navbar-end">
<div class="dropdown dropdown-end">
<div tabindex="0" role="button" class="btn btn-ghost btn-circle">
<i class="bi bi-person-circle text-2xl"></i>
</div>
<ul
tabindex="-1"
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-52 p-2 shadow"
>
<li><a href="/profile">{$i18n.t('common:navbar.link.profile')}</a></li>
<li><a href="/login?logout">{$i18n.t('common:navbar.link.logout')}</a></li>
</ul>
</div>
</div>
</div>
<div class="w-full h-full flex flex-col">
{@render children()}
</div>
</div>

View file

@ -0,0 +1,121 @@
<script lang="ts">
import { persistentSettings } from '$lib/persistent-store'
import { currentDaytime } from '$lib/util'
import i18n from '$lib/i18n'
import DashboardCard from '$lib/component/DashboardCard.svelte'
import TransactionTable from '$lib/component/TransactionTable.svelte'
$i18n.loadNamespaces('dashboard')
let hasActiveTransaction = $state(true)
</script>
<div class="w-full h-full mt-10 flex flex-col">
<p class="w-full text-2xl font-bold">
{$i18n.t('dashboard:greeting.' + currentDaytime(), { name: $persistentSettings.friendlyName })}
</p>
<div class="w-full mt-5 flex gap-x-4">
<div class="card bg-base-100 shadow rounded-md basis-0 grow">
<div class="card-body gap-2">
<div class="flex items-start justify-between gap-2 text-sm">
<div>
<p class="text-base-content/80 font-medium">
{$i18n.t('dashboard:cards.currentTransaction')}
</p>
<div class="mt-3 flex items-center gap-2">
{#if hasActiveTransaction}
<div class="inline-grid *:[grid-area:1/1]">
<div class="status status-success animate-ping"></div>
<div class="status status-success"></div>
</div>
{/if}
<p class="text-2xl font-semibold">
{#if hasActiveTransaction}0,25 kWh{:else}-{/if}
</p>
{#if hasActiveTransaction}
<div class="badge badge-soft badge-success badge-sm gap-0.5 px-1 font-medium">
2,30 €
</div>
{/if}
</div>
</div>
<i class="bi bi-plug-fill text-primary text-4xl"></i>
</div>
<div class="w-full flex flex-row items-center">
<p class="text-base-content/60 text-sm">
{#if hasActiveTransaction}
{$i18n.t('dashboard:cards.chargepoint', { name: 'DE-EXMPL-0001' })}
{:else}
{$i18n.t('dashboard:cards.noCurrentTransaction')}
{/if}
</p>
{#if hasActiveTransaction}
<button class="btn btn-xs btn-primary">
{$i18n.t('dashboard:cards.toCurrentTransactionButton')}
<i class="bi bi-arrow-right"></i>
</button>
{/if}
</div>
</div>
</div>
<DashboardCard
title={$i18n.t('dashboard:cards.transactionCount')}
icon={'bi-battery-charging'}
value={3}
previousValue={1}
/>
<DashboardCard
title={$i18n.t('dashboard:cards.transactionEnergyTotal')}
icon={'bi-lightning-charge-fill'}
value={180}
previousValue={50}
unit={'kWh'}
/>
<DashboardCard
title={$i18n.t('dashboard:cards.transactionCostTotal')}
icon={'bi-currency-exchange'}
value={30.56}
previousValue={30.56}
unit={'€'}
/>
</div>
<div class="w-full flex flex-col mt-10">
<p class="text-xl font-bold">{$i18n.t('dashboard:table.title')}</p>
<TransactionTable
transactions={[
{
id: '1',
begin: new Date(Date.UTC(2025, 3, 15, 14, 12, 23)),
end: new Date(Date.UTC(2025, 3, 15, 16, 18, 46)),
chargepoint: { name: 'DE-EXMPL-0001', id: '1' },
energyAmmount: 58.65,
cost: 36.45,
},
{
id: '2',
begin: new Date(Date.UTC(2025, 3, 15, 14, 12, 23)),
end: new Date(Date.UTC(2025, 3, 15, 16, 18, 46)),
chargepoint: { name: 'DE-EXMPL-0001', id: '1' },
energyAmmount: 58.65,
cost: 36.45,
},
{
id: '3',
begin: new Date(Date.UTC(2025, 3, 15, 14, 12, 23)),
end: new Date(Date.UTC(2025, 3, 15, 16, 18, 46)),
chargepoint: { name: 'DE-EXMPL-0001', id: '1' },
energyAmmount: 58.65,
cost: 36.45,
},
{
id: '4',
begin: new Date(Date.UTC(2025, 3, 15, 14, 12, 23)),
end: new Date(Date.UTC(2025, 3, 15, 16, 18, 46)),
chargepoint: { name: 'DE-EXMPL-0001', id: '1' },
energyAmmount: 58.65,
cost: 36.45,
},
]}
/>
</div>
</div>