Initials
This commit is contained in:
@@ -0,0 +1,164 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<%- include('partials/head') %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main class="container">
|
||||||
|
<section class="balance-card <%= totalBalanceMinutes < 0 ? 'is-negative' : 'is-positive' %>">
|
||||||
|
<span class="balance-card__label">Aktueller Saldo</span>
|
||||||
|
<div class="balance-card__rule" aria-hidden="true"></div>
|
||||||
|
<span class="balance-card__figure"><%= formatBalance(totalBalanceMinutes) %></span>
|
||||||
|
<span class="balance-card__hint">Stunden, inkl. Startguthaben aus den Einstellungen</span>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<% if (error) { %>
|
||||||
|
<p class="notice notice--error"><%= error %></p>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<div class="layout">
|
||||||
|
<section class="card entry-card">
|
||||||
|
<h2 class="card__title"><%= editEntry ? 'Buchung bearbeiten' : 'Buchung erfassen' %></h2>
|
||||||
|
<form action="/entries" method="POST" class="form">
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Datum</span>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
name="date"
|
||||||
|
value="<%= editEntry ? editEntry.date : '' %>"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<div class="field-row">
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Start</span>
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
name="startTime"
|
||||||
|
value="<%= editEntry ? editEntry.startTime : '' %>"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Ende</span>
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
name="endTime"
|
||||||
|
value="<%= editEntry ? editEntry.endTime : '' %>"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Pause (Minuten)</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="breakMinutes"
|
||||||
|
min="0"
|
||||||
|
step="5"
|
||||||
|
value="<%= editEntry ? editEntry.breakMinutes : 30 %>"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Notiz (optional)</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="note"
|
||||||
|
maxlength="200"
|
||||||
|
value="<%= editEntry ? editEntry.note : '' %>"
|
||||||
|
placeholder="z. B. Außendienst, Homeoffice …"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button type="submit" class="button button--primary button--block">
|
||||||
|
<%= editEntry ? 'Änderung speichern' : 'Buchung speichern' %>
|
||||||
|
</button>
|
||||||
|
<% if (editEntry) { %>
|
||||||
|
<a href="/" class="button button--ghost button--block">Abbrechen</a>
|
||||||
|
<% } %>
|
||||||
|
</form>
|
||||||
|
<p class="card__footnote">
|
||||||
|
Ein Tag = ein Eintrag. Eine bereits vorhandene Buchung für ein Datum wird beim erneuten
|
||||||
|
Speichern aktualisiert.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="card ledger-card">
|
||||||
|
<h2 class="card__title">Letzte Buchungen</h2>
|
||||||
|
<% if (entries.length === 0) { %>
|
||||||
|
<p class="empty-state">Noch keine Buchungen erfasst. Trag deinen ersten Arbeitstag links ein.</p>
|
||||||
|
<% } else { %>
|
||||||
|
<div class="table-scroll">
|
||||||
|
<table class="ledger-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Datum</th>
|
||||||
|
<th>Start</th>
|
||||||
|
<th>Ende</th>
|
||||||
|
<th>Pause</th>
|
||||||
|
<th>Gearbeitet</th>
|
||||||
|
<th>Saldo</th>
|
||||||
|
<th>Notiz</th>
|
||||||
|
<th class="ledger-table__actions-col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% entries.forEach((entry) => { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= formatDateDisplay(entry.date) %></td>
|
||||||
|
<td class="num"><%= entry.startTime %></td>
|
||||||
|
<td class="num"><%= entry.endTime %></td>
|
||||||
|
<td class="num"><%= entry.breakMinutes %> min</td>
|
||||||
|
<td class="num"><%= minutesToHM(entry.workedMinutes) %></td>
|
||||||
|
<td class="num <%= entry.balanceMinutes < 0 ? 'is-negative' : 'is-positive' %>">
|
||||||
|
<%= formatBalance(entry.balanceMinutes) %>
|
||||||
|
</td>
|
||||||
|
<td class="ledger-table__note"><%= entry.note %></td>
|
||||||
|
<td class="ledger-table__actions">
|
||||||
|
<a href="/?edit=<%= entry.date %>" class="link-button">Bearbeiten</a>
|
||||||
|
<form action="/entries/<%= entry._id %>/delete" method="POST">
|
||||||
|
<button type="submit" class="link-button link-button--danger">Löschen</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if (monthlyAgg.length > 0) { %>
|
||||||
|
<section class="card">
|
||||||
|
<h2 class="card__title">Monatsabschluss</h2>
|
||||||
|
<div class="table-scroll">
|
||||||
|
<table class="ledger-table ledger-table--compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Monat</th>
|
||||||
|
<th>Buchungstage</th>
|
||||||
|
<th>Gearbeitet</th>
|
||||||
|
<th>Saldo</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% monthlyAgg.forEach((month) => { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= formatMonthDisplay(month._id) %></td>
|
||||||
|
<td class="num"><%= month.days %></td>
|
||||||
|
<td class="num"><%= minutesToHM(month.worked) %> h</td>
|
||||||
|
<td class="num <%= month.balance < 0 ? 'is-negative' : 'is-positive' %>">
|
||||||
|
<%= formatBalance(month.balance) %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<% } %>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<%- include('partials/head') %>
|
||||||
|
</head>
|
||||||
|
<body class="auth-body">
|
||||||
|
<main class="auth-card">
|
||||||
|
<div class="auth-card__mark" aria-hidden="true"></div>
|
||||||
|
<h1 class="auth-card__title"><%= title %></h1>
|
||||||
|
<p class="auth-card__subtitle"><%= message %></p>
|
||||||
|
<a href="/" class="button button--primary button--block">Zur Übersicht</a>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<%- include('partials/head') %>
|
||||||
|
</head>
|
||||||
|
<body class="auth-body">
|
||||||
|
<main class="auth-card">
|
||||||
|
<div class="auth-card__mark" aria-hidden="true"></div>
|
||||||
|
<h1 class="auth-card__title">Zeitkonto</h1>
|
||||||
|
<p class="auth-card__subtitle">Anmelden, um Buchungen zu erfassen.</p>
|
||||||
|
|
||||||
|
<% if (error) { %>
|
||||||
|
<p class="notice notice--error"><%= error %></p>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<form action="/login" method="POST" class="form">
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Benutzername</span>
|
||||||
|
<input type="text" name="username" autocomplete="username" required autofocus />
|
||||||
|
</label>
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Passwort</span>
|
||||||
|
<input type="password" name="password" autocomplete="current-password" required />
|
||||||
|
</label>
|
||||||
|
<button type="submit" class="button button--primary button--block">Anmelden</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<%- include('partials/head') %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main class="container container--narrow">
|
||||||
|
<section class="card">
|
||||||
|
<h2 class="card__title">Einstellungen</h2>
|
||||||
|
<p class="card__footnote">
|
||||||
|
Diese Werte bestimmen, wie neue Buchungen berechnet werden. Bereits gespeicherte
|
||||||
|
Buchungen behalten ihren ursprünglich berechneten Saldo.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<% if (saved) { %>
|
||||||
|
<p class="notice notice--success">Einstellungen wurden gespeichert.</p>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<form action="/settings" method="POST" class="form">
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Soll-Arbeitszeit pro Arbeitstag (Stunden)</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="targetHoursPerDay"
|
||||||
|
min="0"
|
||||||
|
max="24"
|
||||||
|
step="0.25"
|
||||||
|
value="<%= settings.targetHoursPerDay %>"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<fieldset class="field">
|
||||||
|
<legend class="field__label">Arbeitstage</legend>
|
||||||
|
<div class="checkbox-row">
|
||||||
|
<% weekdayNames.forEach((name, index) => { %>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="workDays"
|
||||||
|
value="<%= index %>"
|
||||||
|
<%= settings.workDays.includes(index) ? 'checked' : '' %>
|
||||||
|
/>
|
||||||
|
<span><%= name %></span>
|
||||||
|
</label>
|
||||||
|
<% }) %>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<label class="field">
|
||||||
|
<span class="field__label">Start-Guthaben vor Nutzung dieser App (Stunden)</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="startingBalanceHours"
|
||||||
|
step="0.25"
|
||||||
|
value="<%= (settings.startingBalanceMinutes / 60).toFixed(2) %>"
|
||||||
|
/>
|
||||||
|
<span class="field__hint">
|
||||||
|
Positiv für bereits bestehende Überstunden, negativ für ein Minus-Saldo. 0, wenn du
|
||||||
|
ganz neu startest.
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="submit" class="button button--primary button--block">Speichern</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user