feat(dashboard): show runners via selfservice count

This commit is contained in:
Philipp Dormann 2025-03-28 22:01:02 +01:00
parent f4542adf3b
commit 0ee43f80a6
Signed by: philipp
GPG Key ID: 3BB9ADD52DCA4314
3 changed files with 243 additions and 223 deletions

View File

@ -1,228 +1,246 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { StatsService } from "@odit/lfk-client-js"; import { StatsService } from "@odit/lfk-client-js";
import store from "../../store"; import store from "../../store";
import StatCard from "./StatCard.svelte"; import StatCard from "./StatCard.svelte";
const stats_promise = StatsService.statsControllerGet(); const stats_promise = StatsService.statsControllerGet();
</script> </script>
<div class="p-2 md:p-5 overflow-x-hidden"> <div class="p-2 md:p-5 overflow-x-hidden">
<h4 class="mb-1 text-3xl font-extrabold leading-tight"> <h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("dashboard-greeting")} <span class="text-blue-500" {$_("dashboard-greeting")}
>{store.state.jwtinfo.userdetails.firstname} <span class="text-blue-500"
{store.state.jwtinfo.userdetails.lastname}</span >{store.state.jwtinfo.userdetails.firstname}
> {store.state.jwtinfo.userdetails.lastname}</span
</h4> >
{#await stats_promise} </h4>
<div {#await stats_promise}
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" <div
role="alert" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
> role="alert"
<p class="font-bold">{$_("stats-are-being-loaded")}</p> >
<p class="text-sm">{$_("this-might-take-a-moment")}</p> <p class="font-bold">{$_("stats-are-being-loaded")}</p>
</div> <p class="text-sm">{$_("this-might-take-a-moment")}</p>
{:then stats} </div>
<div {:then stats}
class="grid gap-1 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4" <div
> class="grid gap-1 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4"
<StatCard >
title={$_("runners")} <StatCard
value={stats.total_runners} title={$_("runners")}
href="/runners/" value={stats.total_runners}
> href="/runners/"
<svg >
height="24" <svg
width="24" height="24"
fill="currentColor" width="24"
xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
><path d="M0 0h24v24H0z" fill="none" /> viewBox="0 0 24 24"
<path ><path d="M0 0h24v24H0z" fill="none" />
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" <path
/></svg d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("total-scans")} <StatCard
value={stats.total_scans} title={$_("total-scans")}
href="/scans/" value={stats.total_scans}
> href="/scans/"
<svg >
fill="currentColor" <svg
width="24" fill="currentColor"
height="24" width="24"
xmlns="http://www.w3.org/2000/svg" height="24"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
><path fill="none" d="M0 0h24v24H0z" /> viewBox="0 0 24 24"
<path ><path fill="none" d="M0 0h24v24H0z" />
fill="currentColor" <path
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z" fill="currentColor"
/></svg d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("total-donors")} <StatCard
value={stats.total_donors} title={$_("total-donors")}
href="/donors/" value={stats.total_donors}
> href="/donors/"
<svg >
fill="currentColor" <svg
xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
width="24" viewBox="0 0 24 24"
height="24" width="24"
><path fill="none" d="M0 0h24v24H0z" /> height="24"
<path ><path fill="none" d="M0 0h24v24H0z" />
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z" <path
/></svg d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("total-donation-count")} <StatCard
value={stats.total_donations} title={$_("total-donation-count")}
href="/donations/" value={stats.total_donations}
> href="/donations/"
<svg >
fill="currentColor" <svg
xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
width="24" viewBox="0 0 24 24"
height="24" width="24"
><path fill="none" d="M0 0h24v24H0z" /> height="24"
<path ><path fill="none" d="M0 0h24v24H0z" />
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z" <path
/></svg d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("average-donation")} <StatCard
value={`${parseFloat(stats.average_donation / 100).toLocaleString( title={$_("average-donation")}
undefined, value={`${parseFloat(stats.average_donation / 100).toLocaleString(
{ undefined,
minimumFractionDigits: 2, {
maximumFractionDigits: 2, minimumFractionDigits: 2,
} maximumFractionDigits: 2,
)}`} }
href="/donations/" )}`}
> href="/donations/"
<svg >
xmlns="http://www.w3.org/2000/svg" <svg
height="24" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" height="24"
width="24" fill="currentColor"
><path d="M0 0h24v24H0z" fill="none" /> width="24"
<path ><path d="M0 0h24v24H0z" fill="none" />
d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" <path
/></svg d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("total-donations")} <StatCard
value={`${parseFloat(stats.total_donation / 100).toLocaleString( title={$_("total-donations")}
undefined, value={`${parseFloat(stats.total_donation / 100).toLocaleString(
{ undefined,
minimumFractionDigits: 2, {
maximumFractionDigits: 2, minimumFractionDigits: 2,
} maximumFractionDigits: 2,
)}`} }
href="/donations/" )}`}
> href="/donations/"
<svg >
xmlns="http://www.w3.org/2000/svg" <svg
height="24" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" height="24"
width="24" fill="currentColor"
><path d="M0 0h24v24H0z" fill="none" /> width="24"
<path ><path d="M0 0h24v24H0z" fill="none" />
d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" <path
/></svg d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("total-distance")} <StatCard
value={`${stats.total_distance / 1000}km`} title={$_("total-distance")}
href="/scans/" value={`${stats.total_distance / 1000}km`}
> href="/scans/"
<svg >
fill="currentColor" <svg
xmlns="http://www.w3.org/2000/svg" fill="currentColor"
height="24" xmlns="http://www.w3.org/2000/svg"
width="24" height="24"
><path d="M0 0h24v24H0z" fill="none" /> width="24"
<path ><path d="M0 0h24v24H0z" fill="none" />
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" <path
/></svg d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("average-distance")} <StatCard
value={`${parseFloat(stats.average_distance / 1000).toLocaleString( title={$_("average-distance")}
undefined, value={`${parseFloat(stats.average_distance / 1000).toLocaleString(
{ undefined,
minimumFractionDigits: 2, {
maximumFractionDigits: 2, minimumFractionDigits: 2,
} maximumFractionDigits: 2,
)}km`} }
href="/scans/" )}km`}
> href="/scans/"
<svg >
fill="currentColor" <svg
xmlns="http://www.w3.org/2000/svg" fill="currentColor"
height="24" xmlns="http://www.w3.org/2000/svg"
width="24" height="24"
><path d="M0 0h24v24H0z" fill="none" /> width="24"
<path ><path d="M0 0h24v24H0z" fill="none" />
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" <path
/></svg d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
> /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("count_teams")} <StatCard
value={stats.total_teams} title={$_("count_teams")}
href="/teams/" value={stats.total_teams}
> href="/teams/"
<svg >
stroke="currentColor" <svg
fill="none" stroke="currentColor"
stroke-width="2" fill="none"
viewBox="0 0 24 24" stroke-width="2"
stroke-linecap="round" viewBox="0 0 24 24"
stroke-linejoin="round" stroke-linecap="round"
size="24" stroke-linejoin="round"
class="stroke-current text-grey-500" size="24"
height="24" class="stroke-current text-grey-500"
width="24" height="24"
xmlns="http://www.w3.org/2000/svg" width="24"
><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /> xmlns="http://www.w3.org/2000/svg"
<circle cx="9" cy="7" r="4" /> ><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
<path d="M23 21v-2a4 4 0 0 0-3-3.87" /> <circle cx="9" cy="7" r="4" />
<path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg <path d="M23 21v-2a4 4 0 0 0-3-3.87" />
> <path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg
</StatCard> >
<StatCard </StatCard>
title={$_("count_organizations")} <StatCard
value={stats.total_orgs} title={$_("count_organizations")}
href="/orgs/" value={stats.total_orgs}
> href="/orgs/"
<svg >
height="24" <svg
fill="currentColor" height="24"
width="24" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" width="24"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
><path fill="none" d="M0 0h24v24H0z" /> viewBox="0 0 24 24"
<path ><path fill="none" d="M0 0h24v24H0z" />
d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z" <path
/></svg d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z"
> /></svg
</StatCard> >
</div> </StatCard>
{:catch error} <StatCard
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500"> title={$_("runner_via_selfservice")}
<span class="inline-block align-middle mr-8"> value={stats.runnersViaSelfservice}
<b class="capitalize">{$_("general_promise_error")}</b> href="/runners/"
{error} >
</span> <svg
</div> height="24"
{/await} width="24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path d="M0 0h24v24H0z" fill="none" />
<path
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
/></svg
>
</StatCard>
</div>
{:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_("general_promise_error")}</b>
{error}
</span>
</div>
{/await}
</div> </div>

View File

@ -375,6 +375,7 @@
"runner-import": "Läufer Import", "runner-import": "Läufer Import",
"runner-is-being-added": "Läufer wird hinzugefügt...", "runner-is-being-added": "Läufer wird hinzugefügt...",
"runner-updated": "Läufer aktualisiert!", "runner-updated": "Läufer aktualisiert!",
"runner_via_selfservice": "Läufer via Selfservice",
"runnercards": "Laeuferkarten", "runnercards": "Laeuferkarten",
"runnerimport_verify_runners_org": "Bitte die Läufer für den Import in die Organisation \"{org_name}\" bestätigen", "runnerimport_verify_runners_org": "Bitte die Läufer für den Import in die Organisation \"{org_name}\" bestätigen",
"runners": "Läufer", "runners": "Läufer",

View File

@ -375,6 +375,7 @@
"runner-import": "Runner Import", "runner-import": "Runner Import",
"runner-is-being-added": "Runner is being added...", "runner-is-being-added": "Runner is being added...",
"runner-updated": "Runner updated!", "runner-updated": "Runner updated!",
"runner_via_selfservice": "Runner via Selfservice",
"runnercards": "Runnercards", "runnercards": "Runnercards",
"runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"", "runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"",
"runners": "Runners", "runners": "Runners",