review fixes: light-mode contrast, tz robustness, deploy copy
- admin: maroon buttons use .danger class (white text); replace hardcoded #333/#ff8a8a/drop-target colors with theme vars so light mode is legible - time.ts: force hourCycle h23 (no 24:00 artifact), drop dead 24-guard - Makefile/README: rsync with excludes instead of `cp -a .` so .git and the dev DB don't ship to /opt; add rsync to deps
This commit is contained in:
parent
6a0d30c8b5
commit
cca3077b7a
4 changed files with 16 additions and 11 deletions
11
Makefile
11
Makefile
|
|
@ -26,7 +26,7 @@ build:
|
||||||
|
|
||||||
## deps: install Node.js, pnpm and native-module build tools (Fedora)
|
## deps: install Node.js, pnpm and native-module build tools (Fedora)
|
||||||
deps: require-root
|
deps: require-root
|
||||||
dnf install -y nodejs gcc-c++ make python3
|
dnf install -y nodejs gcc-c++ make python3 rsync
|
||||||
corepack enable
|
corepack enable
|
||||||
|
|
||||||
## install: full production install on a fresh checkout (Fedora)
|
## install: full production install on a fresh checkout (Fedora)
|
||||||
|
|
@ -41,9 +41,14 @@ service: require-root
|
||||||
# Dedicated system user (no login, no home).
|
# Dedicated system user (no login, no home).
|
||||||
id -u $(SERVICE_USER) >/dev/null 2>&1 || \
|
id -u $(SERVICE_USER) >/dev/null 2>&1 || \
|
||||||
useradd --system --no-create-home --shell /usr/sbin/nologin $(SERVICE_USER)
|
useradd --system --no-create-home --shell /usr/sbin/nologin $(SERVICE_USER)
|
||||||
# Copy the whole tree so pnpm's symlinked node_modules stay intact.
|
# Copy the tree (preserving pnpm's symlinked node_modules) but leave behind
|
||||||
|
# the repo metadata, local dev database, and editor/nix cruft.
|
||||||
mkdir -p $(PREFIX)
|
mkdir -p $(PREFIX)
|
||||||
cp -a . $(PREFIX)/
|
rsync -a --delete \
|
||||||
|
--exclude='.git' --exclude='.direnv' --exclude='.env' \
|
||||||
|
--exclude='*.db' --exclude='*.db-wal' --exclude='*.db-shm' \
|
||||||
|
--exclude='$(PREFIX)' \
|
||||||
|
./ $(PREFIX)/
|
||||||
# Config + secrets — never clobber an existing env file.
|
# Config + secrets — never clobber an existing env file.
|
||||||
mkdir -p $(CONFDIR)
|
mkdir -p $(CONFDIR)
|
||||||
test -f $(CONFDIR)/wutzcalc.env || \
|
test -f $(CONFDIR)/wutzcalc.env || \
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ sudo useradd --system --no-create-home --shell /usr/sbin/nologin wutzcalc
|
||||||
|
|
||||||
# 2. Install the built app (run `pnpm install && pnpm build` first)
|
# 2. Install the built app (run `pnpm install && pnpm build` first)
|
||||||
sudo mkdir -p /opt/wutzcalc
|
sudo mkdir -p /opt/wutzcalc
|
||||||
sudo cp -a . /opt/wutzcalc # or rsync/checkout into place
|
sudo rsync -a --exclude='.git' --exclude='*.db*' ./ /opt/wutzcalc/
|
||||||
sudo chown -R root:root /opt/wutzcalc # app dir stays read-only to the service
|
sudo chown -R root:root /opt/wutzcalc # app dir stays read-only to the service
|
||||||
|
|
||||||
# 3. Config + secrets (chmod 600 — holds ADMIN_PASSWORD)
|
# 3. Config + secrets (chmod 600 — holds ADMIN_PASSWORD)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ function Login({ onAuthed }: { onAuthed: () => void }) {
|
||||||
value={pw}
|
value={pw}
|
||||||
onInput={(e: any) => setPw(e.currentTarget.value)}
|
onInput={(e: any) => setPw(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
{err && <div style="color:#ff8a8a">{err}</div>}
|
{err && <div style="color:var(--danger)">{err}</div>}
|
||||||
<button type="submit">Anmelden</button>
|
<button type="submit">Anmelden</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -107,7 +107,7 @@ function Stats() {
|
||||||
<>
|
<>
|
||||||
<div class="row" style="justify-content: space-between">
|
<div class="row" style="justify-content: space-between">
|
||||||
<h2 style="margin:0">Umsatz nach Tagen</h2>
|
<h2 style="margin:0">Umsatz nach Tagen</h2>
|
||||||
<button onClick={reset} style="background:#5a2a2a; border-color:#7a3a3a">Statistik zurücksetzen</button>
|
<button class="danger" onClick={reset}>Statistik zurücksetzen</button>
|
||||||
</div>
|
</div>
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Tag</th><th>Transaktionen</th><th>Bezahlt</th><th>Crew-Transaktionen</th><th>Pfand zurück</th></tr></thead>
|
<thead><tr><th>Tag</th><th>Transaktionen</th><th>Bezahlt</th><th>Crew-Transaktionen</th><th>Pfand zurück</th></tr></thead>
|
||||||
|
|
@ -227,7 +227,7 @@ function Drinks() {
|
||||||
<button onClick={() => patch(d.id, { archived: !d.archived } as any)}>
|
<button onClick={() => patch(d.id, { archived: !d.archived } as any)}>
|
||||||
{d.archived ? 'aktivieren' : 'archivieren'}
|
{d.archived ? 'aktivieren' : 'archivieren'}
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => del(d)} style="background:#5a2a2a; border-color:#7a3a3a">löschen</button>
|
<button class="danger" onClick={() => del(d)}>löschen</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -377,7 +377,7 @@ function Bars() {
|
||||||
<>
|
<>
|
||||||
<h2>Bars</h2>
|
<h2>Bars</h2>
|
||||||
{bars.map(b => (
|
{bars.map(b => (
|
||||||
<div key={b.id} style="margin-bottom:16px; padding:8px; border:1px solid #333; border-radius:6px">
|
<div key={b.id} style="margin-bottom:16px; padding:8px; border:1px solid var(--border); border-radius:6px">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>
|
<label>
|
||||||
Name
|
Name
|
||||||
|
|
@ -397,7 +397,7 @@ function Bars() {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<button onClick={() => delBar(b)} style="background:#5a2a2a; border-color:#7a3a3a; margin-left:auto">Tresen löschen</button>
|
<button class="danger" onClick={() => delBar(b)} style="margin-left:auto">Tresen löschen</button>
|
||||||
</div>
|
</div>
|
||||||
<BarDrinkEditor
|
<BarDrinkEditor
|
||||||
bar={b}
|
bar={b}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ function localParts(d: Date, tz: string = TZ): LocalParts {
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
second: '2-digit',
|
second: '2-digit',
|
||||||
hour12: false,
|
hourCycle: 'h23', // force midnight as 00, never the 24 artifact
|
||||||
});
|
});
|
||||||
const parts: Record<string, string> = {};
|
const parts: Record<string, string> = {};
|
||||||
for (const p of fmt.formatToParts(d)) {
|
for (const p of fmt.formatToParts(d)) {
|
||||||
|
|
@ -49,7 +49,7 @@ function localParts(d: Date, tz: string = TZ): LocalParts {
|
||||||
year: Number(parts.year),
|
year: Number(parts.year),
|
||||||
month: Number(parts.month),
|
month: Number(parts.month),
|
||||||
day: Number(parts.day),
|
day: Number(parts.day),
|
||||||
hour: Number(parts.hour === '24' ? '0' : parts.hour),
|
hour: Number(parts.hour),
|
||||||
minute: Number(parts.minute),
|
minute: Number(parts.minute),
|
||||||
second: Number(parts.second),
|
second: Number(parts.second),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue