Improve UI

- Add metrics table  to sidebar after schedule generation
- Add scheduler status indicator to sidebar
- Refactor report() to consume `ResidentMetrics`
- Delete unused preview component
- Beautify css across wizard steps
This commit is contained in:
2026-03-14 19:44:29 +02:00
parent 3ecdc91802
commit 756c1cdc47
14 changed files with 363 additions and 269 deletions

View File

@@ -2,38 +2,38 @@
import Basic from "./components/configurations/basic.svelte";
import Residents from "./components/configurations/residents.svelte";
import Advanced from "./components/configurations/advanced.svelte";
import Preview from "./components/schedule/preview.svelte";
import { rota, steps } from "./state.svelte.js";
import { EngineStatus, rota, steps } from "./state.svelte.js";
import Generate from "./components/schedule/generate.svelte";
</script>
<main
class="grid h-screen w-full grid-cols-5 overflow-hidden bg-zinc-200/50 font-sans tracking-tight antialiased"
class="bg-zinc-200/ grid h-screen w-full grid-cols-5 overflow-hidden font-sans tracking-tight antialiased"
>
<aside
class="col-span-1 flex flex-col border-r border-zinc-200 bg-zinc-50/50 font-sans antialiased"
>
<div class="flex justify-center border p-3 font-sans">
<h1 class="text-xl font-black tracking-tight uppercase">Rota Scheduler</h1>
<div class="flex justify-center p-2 font-sans">
<h1 class="text-xl font-black tracking-tighter text-slate-900 uppercase">
Rota <span class="text-emerald-600">Scheduler</span>
</h1>
</div>
<div class="h-px w-full bg-zinc-200"></div>
<nav class="relative flex-1 p-6">
<div class="absolute top-10 bottom-10 left-9.75 w-0.5 bg-zinc-200"></div>
<div class="relative flex h-full flex-col justify-between">
<nav class="relative flex flex-col p-4">
<div class="flex flex-col gap-2">
{#each steps as step}
<button
onclick={() => (rota.currentStep = step.id)}
class="group relative z-10 flex items-center gap-4 py-4 transition-all"
class="group relative z-10 flex items-center gap-4 rounded-xl p-4 transition-all
{rota.currentStep === step.id ? 'bg-zinc-200/80 shadow-inner' : 'hover:bg-zinc-100/50'}"
>
<div
class="flex size-8 items-center justify-center rounded-full border-2 transition-all duration-300
class="flex size-8 items-center justify-center rounded-lg transition-all duration-300
{rota.currentStep === step.id
? 'bg-slate-800 text-white'
? 'bg-slate-800 text-white shadow-md'
: rota.currentStep > step.id
? 'bg-emerald-600 text-white'
: 'bg-white text-zinc-400'}"
: 'border border-zinc-200 bg-white text-zinc-400'}"
>
{#if rota.currentStep > step.id}
<svg
@@ -54,7 +54,7 @@
<div class="flex flex-col items-start">
<span
class="text-[10px] font-bold tracking-widest uppercase
{rota.currentStep === step.id ? 'text-black-800' : 'text-zinc-400'}"
{rota.currentStep === step.id ? 'text-zinc-600' : 'text-zinc-400'}"
>
ΒΗΜΑ {step.id}
</span>
@@ -70,19 +70,130 @@
</div>
</nav>
<div class="border-t border-zinc-200 bg-white p-6">
<div class="rounded-xl border border-zinc-100 bg-zinc-50 p-4">
<div class="mb-2 flex items-center justify-between">
<span class="text-[10px] font-bold text-zinc-500 uppercase">ΟΛΟΚΛΗΡΩΣΗ</span>
<span class="text-[10px] font-bold text-zinc-500"
>{(((rota.currentStep - 1) / (steps.length - 1)) * 100).toFixed(0)}%</span
{#if rota.metrics.length > 0}
<div class="h-px w-full bg-zinc-200"></div>
<div class="flex flex-1 flex-col py-4">
<p class="px-6 pb-2 text-[10px] font-black tracking-widest text-zinc-400 uppercase">
Δικαιωσυνη
</p>
<div class="w-full overflow-hidden px-2 text-[10px]">
<table class="w-full">
<thead>
<tr class="border-b border-zinc-300 bg-zinc-50">
<th
class="border-r border-zinc-300 px-2 py-1 text-left font-bold text-zinc-500 uppercase last:border-r-0"
>Ειδικευομενος</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>ΣΥΝ</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>Α1</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>Α2</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>Κ</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>ΣΚ/Α</th
>
</tr>
</thead>
<tbody>
{#each rota.metrics as m}
<tr class="border-b border-zinc-200 last:border-0 hover:bg-zinc-50">
<td
class="border-r border-zinc-200 px-2 py-1 font-medium text-zinc-700 last:border-r-0"
>{m.name}</td
>
<td
class="border-r border-zinc-200 px-1 py-1 text-center font-bold text-zinc-800 last:border-r-0"
>{m.total}</td
>
<td
class="border-r border-zinc-200 px-1 py-1 text-center text-zinc-500 last:border-r-0"
>{m.open_first}</td
>
<td
class="border-r border-zinc-200 px-1 py-1 text-center text-zinc-500 last:border-r-0"
>{m.open_second}</td
>
<td
class="border-r border-zinc-200 px-1 py-1 text-center text-zinc-500 last:border-r-0"
>{m.closed}</td
>
<td
class="border-r border-zinc-200 px-1 py-1 text-center text-zinc-500 last:border-r-0"
>{m.holiday}</td
>
</tr>
{/each}
</tbody>
<tfoot>
<tr class="border-t border-zinc-300 bg-zinc-50">
<th
class="border-r border-zinc-300 px-2 py-1 text-left font-bold text-zinc-500 uppercase last:border-r-0"
>Συνολο</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>{rota.metrics.reduce((s, m) => s + m.total, 0)}</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>{rota.metrics.reduce((s, m) => s + m.open_first, 0)}</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>{rota.metrics.reduce((s, m) => s + m.open_second, 0)}</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>{rota.metrics.reduce((s, m) => s + m.closed, 0)}</th
>
<th
class="border-r border-zinc-300 px-1 py-1 text-center font-bold text-zinc-500 last:border-r-0"
>{rota.metrics.reduce((s, m) => s + m.holiday, 0)}</th
>
</tr>
</tfoot>
</table>
</div>
</div>
{/if}
<div class="h-px w-full bg-zinc-200"></div>
<div class="space-y-4 p-4">
<div
class="border-l-2 py-2 pl-3 transition-colors
{rota.engineStatus === EngineStatus.Running
? 'border-amber-400'
: rota.engineStatus === EngineStatus.Success
? 'border-emerald-500'
: rota.engineStatus === EngineStatus.Error
? 'border-red-500'
: 'border-zinc-300'}"
>
<div class="mb-2 flex items-center gap-2">
<span class="text-[10px] font-black tracking-widest text-zinc-400 uppercase"
>ΚΑΤΑΣΤΑΣΗ ΜΗΧΑΝΗΣ</span
>
</div>
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-200">
<div
class="h-full bg-emerald-600 transition-all duration-500"
style="width: {(((rota.currentStep - 1) / (steps.length - 1)) * 100).toFixed(0)}%"
></div>
<div class="flex flex-col gap-1">
<span class="text-[11px] font-bold text-zinc-800 uppercase">
{rota.engineStatus}
</span>
<p class="text-[10px] leading-tight font-medium text-zinc-500">
{rota.lastMessage}
</p>
</div>
</div>
</div>
@@ -97,8 +208,6 @@
{:else if rota.currentStep === 3}
<Advanced />
{:else if rota.currentStep === 4}
<Preview />
{:else if rota.currentStep === 5}
<Generate />
{/if}
</div>