First working prototype
This commit is contained in:
148
src/routes/Resume.svelte
Normal file
148
src/routes/Resume.svelte
Normal file
@@ -0,0 +1,148 @@
|
||||
<script>
|
||||
import { dayState, reopenToday } from '../lib/day.svelte.js';
|
||||
import { buildResume, resumeToText } from '../lib/resume.js';
|
||||
import { go } from '../lib/router.svelte.js';
|
||||
import { settings } from '../lib/settings.svelte.js';
|
||||
import { fmtDuration, weekday } from '../lib/time.js';
|
||||
|
||||
let copied = $state(false);
|
||||
|
||||
const resume = $derived(
|
||||
buildResume(
|
||||
dayState.lastClosed,
|
||||
dayState.lastClosedEntries,
|
||||
settings.roundingMinutes,
|
||||
),
|
||||
);
|
||||
|
||||
const text = $derived(resumeToText(resume));
|
||||
|
||||
/** Shown when today is a work day whose start time has not arrived yet. */
|
||||
const startsAt = $derived(
|
||||
settings.workdays.includes(weekday(dayState.today)) ? settings.dayStart : null,
|
||||
);
|
||||
|
||||
const closedToday = $derived(dayState.lastClosed?.date === dayState.today);
|
||||
|
||||
async function copy() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch {
|
||||
// Clipboard API needs a secure context; fall back to a selectable dialog.
|
||||
window.prompt('Copier le récapitulatif :', text);
|
||||
}
|
||||
copied = true;
|
||||
setTimeout(() => (copied = false), 2500);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="screen">
|
||||
{#if !resume}
|
||||
<div class="card center stack">
|
||||
<h2>Aucune journée enregistrée</h2>
|
||||
<p class="dim">
|
||||
Le récapitulatif de la dernière journée s'affichera ici, prêt à recopier.
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="row-between">
|
||||
<h1>{resume.label}</h1>
|
||||
</div>
|
||||
|
||||
<div class="card stack">
|
||||
{#each resume.clients as client (client.name)}
|
||||
<div class="client">
|
||||
<div class="row-between head">
|
||||
<h2>{client.name}</h2>
|
||||
<span class="tnum">{fmtDuration(client.totalMs)}</span>
|
||||
</div>
|
||||
<ul>
|
||||
{#each client.tasks as task (task.name)}
|
||||
<li class="row-between">
|
||||
<span>{task.name}</span>
|
||||
<span class="tnum">{fmtDuration(task.ms)}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
{#if resume.lunch}
|
||||
<hr />
|
||||
<div class="row-between">
|
||||
<span
|
||||
>Déjeuner : {resume.lunch.type === 'restaurant'
|
||||
? `restaurant (${resume.lunch.restaurant || 'non précisé'})`
|
||||
: 'panier'}</span
|
||||
>
|
||||
<span class="tnum">{fmtDuration(resume.lunch.ms)}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<hr />
|
||||
<div class="row-between total">
|
||||
<strong>Total travaillé</strong>
|
||||
<strong class="tnum">{fmtDuration(resume.workedMs)}</strong>
|
||||
</div>
|
||||
|
||||
{#if resume.omitted}
|
||||
<p class="dim small">
|
||||
{resume.omitted} poste{resume.omitted > 1 ? 's' : ''} de moins de {settings.roundingMinutes}
|
||||
min non affiché{resume.omitted > 1 ? 's' : ''}.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn-primary" onclick={copy}>
|
||||
{copied ? '✓ Copié' : 'Copier le récapitulatif'}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if closedToday}
|
||||
<button
|
||||
type="button"
|
||||
onclick={async () => {
|
||||
await reopenToday();
|
||||
go('today');
|
||||
}}>Reprendre la journée</button
|
||||
>
|
||||
{:else if startsAt}
|
||||
<p class="dim center small">
|
||||
La journée démarrera automatiquement à {startsAt}.
|
||||
</p>
|
||||
{:else}
|
||||
<p class="dim center small">Aujourd'hui n'est pas un jour travaillé.</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.client + .client {
|
||||
border-top: 2px solid var(--line);
|
||||
padding-top: var(--gap);
|
||||
}
|
||||
|
||||
.head {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 var(--pad);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
li {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.total {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user