Commit Graph
10 Commits
Author SHA1 Message Date
nicolabelluti 5dbb3f51f1 feat(oxibadge): consolidate review toolbar and add a "shift times" action
Check, format and test / build (push) Successful in 11m56s
The per-employee correction buttons (Fix shifts, Add lunch break,
Round) and the day filter used to be scattered across the employee
header. They're now grouped into a single toolbar attached to the top
of the timesheet table: a "Corrections" dropdown (with per-item counts
and an "Apply all corrections" entry) and a "Shift times" panel, plus
the existing day filter and "Undo all changes" button.

"Shift times" adds a fixed offset (in steps of the configured rounding
granularity, ±12h) to every punch in a chosen day range, for either
the current employee or everyone — for when the time clock didn't
follow a daylight-saving change. EmployeeHeader is now just the name
editor and stats; TimesheetTable no longer owns the table's outer
border/background, which moved to the new shared card wrapper.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 15:21:47 +02:00
nicolabelluti da5daf5bca fix(oxibadge): accept hostnames and FQDNs for the time clock address
Check, format and test / build (push) Successful in 11m10s
The "Edit address" field in Settings only accepted an IPv4 address
(IPV4.test), rejecting a bare hostname (e.g. "timbratore") or FQDN
(e.g. "timbratore.lan") even though the underlying connection (Rust's
ToSocketAddrs) already resolves those fine. Onboarding had no such
restriction. Replaced the IPv4-only check with isValidHost (IPv4 OR a
standard DNS hostname), dropped the numeric-only keyboard hint on that
field, and reworded the labels/placeholder error to not imply IP-only.

Also makes "Edit address" test the connection before accepting it,
instead of saving unconditionally: ActionButton gained a `disabled`
prop so the confirm/cancel buttons can be locked (with a spinner on
confirm) while the test is in flight, and the edit form now only
closes on a successful test, staying open with the raw error shown
otherwise.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 14:05:12 +02:00
nicolabelluti 0c320c39b0 feat(oxibadge): warn before losing unexported review edits, add undo
Check, format and test / build (push) Successful in 10m25s
The review screen now tracks whether there are edits not yet exported
and asks for confirmation before discarding them: clicking back, or
closing the app window entirely (intercepted via onCloseRequested,
which needed a core:window:allow-destroy capability that wasn't
granted by core:default). The confirmation dialog (ConfirmDialog.svelte)
is generic, built on a shared ModalFrame extracted from ExportModal so
the two don't duplicate the backdrop/box styling.

Also adds undo: a per-row button (icon-only, left of the note, shown
when that day has edits) reverts just that day instantly, and a
per-employee "undo all" (icon in a red box, last among the header's
tools) reverts every day for the current employee after a confirmation
dialog, since that one can't be undone itself.

ActionButton moves out of review/ next to IconButton/PillButton, since
ConfirmDialog (outside the review feature) now uses it too.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 13:46:31 +02:00
nicolabelluti 25127bee96 feat(oxibadge): cache employee names locally and let readers be a list
Check, format and test / build (push) Successful in 10m27s
Employee names are now cached locally (employees.toml, keyed by reader
index then employee id) instead of being re-fetched from the time
clock on every month: load_employees only asks the device for ids not
already in the cache. When a month has employees the cache doesn't
know yet, a new screen (NewEmployees.svelte) lets the user name them
before continuing to the review screen; the chosen names are local to
Oxibadge only, never written back to the device. The same cache can be
managed afterwards from a drawer reachable from the time clock card in
Settings ("Gestisci dipendenti"), reusing the rename-in-row pattern
from the original mockup.

Settings.readers is a list again (was flattened to a single `reader`
object) so multiple time clocks can be supported later; only the first
one is used today.

Also:
- buildEmployees() now derives the employee list from the month's
  records instead of from every cached name ever seen, so the review
  screen no longer shows employees unrelated to the selected month.
- Renaming an employee from the review screen's pencil button now
  actually persists to the cache (the callback existed but was never
  wired up).
- Translated to English a number of Rust/TS/Svelte comments that had
  been written in Italian; only the i18n locale files should contain
  Italian.
- Minor dedup: extracted PillButton.svelte (was duplicated inline in
  ReaderCard), promoted the repeated .mono CSS rule to app.css, moved
  initials() out of the review feature into $lib/text.ts.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 20:04:37 +02:00
nicolabelluti b65e85f908 feat(oxibadge): add settings screen for shifts, rounding and language
Check, format and test / build (push) Successful in 10m22s
Add a settings screen (gear button on the month-confirmation screen)
to configure the expected shift times, the rounding step, the
interface language, and the time clock address — replacing the old
onboarding-only connection flow. Settings persist to the same
preferences.toml as the reader address, under a single load_settings/
save_settings command pair.

The review screen's "fix shifts" action now redistributes stacked
punches by nearest configured shift time instead of blind position,
and a stacked cell manually cleared down to one entry no longer
leaves a dangling empty input.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 18:29:57 +02:00
nicolabelluti acd3efeac6 feat(oxibadge): add timesheet review and export screen
Check, format and test / build (push) Successful in 10m16s
Add the month-review screen shown after records/employees load: an
editable per-employee timesheet table with issue/rounding detection,
bulk fixes (reorder stacked punches, add lunch break, round to step),
and an export flow (single employee or all) wired to a new Rust
export_timesheet command. Split into focused components under
review/ instead of one large file, with shared i18n keys and a new
export_timesheet IPC command.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-07 15:56:25 +02:00
nicolabelluti b4cd8e1796 fix(oxibadge): show connection errors instead of failing silently
Check, format and test / build (push) Successful in 10m4s
load_records/load_employees failures were only logged to the console
and silently reset the UI to the month picker. Errors now flow through
a shared store (src/lib/error.ts) into an ErrorBanner, reused by both
Onboarding and ConfirmMonth, with the raw message passed straight
through from Rust (no stable-code classification layer — these are
mostly plain I/O errors, not worth categorizing).

i18n stays grouped per screen as before, with error-related strings
split into their own top-level "errors" group.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-07 13:26:01 +02:00
nicolabelluti 28186c7745 feat(oxibadge): add month-confirmation flow and fetch records/employees
Check, format and test / build (push) Successful in 10m0s
Adds the screen after onboarding: pick a month/year (ConfirmMonth), show
loading screens while the device is queried, then download that month's
records and resolve each distinct employee's name, printing both to
stdout (debug pretty-print) before landing on the placeholder "done"
screen.

- r701: RecordIterator's boxed stream is now Send, required for it to
  cross into a Tauri command's future.
- oxibadge: load_records/load_employees commands, sharing the existing
  3-retry connect_with_retries helper. load_records uses skip_while/
  take_while on the device's newest-first stream to grab only the
  target month without walking its whole history, then a single
  collect + in-place Vec::reverse() back to chronological order.
- Shared LoadingScreen/Intro components extracted so future screens
  reuse the same look without duplicating markup/CSS.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-07 12:47:36 +02:00
nicolabelluti 99772b9e4a feat(oxibadge): add onboarding flow with i18n and reader preferences
Check, format and test / build (push) Successful in 9m59s
Adds the first real screen: a setup form for the device's host/port,
tested against the real device (3 retries) and persisted to
preferences.toml before showing a placeholder "done" screen.

- Rust: test_connection/save_preferences/load_preferences commands;
  preferences stored as [[reader]] in TOML so more readers can be
  added later without a format change.
- Svelte: split the monolithic page into reusable components
  (Screen, Column, Field, Button, ErrorBanner, Hint) under
  src/lib/components, sharing design tokens from app.css.
- Automatic it/en i18n via svelte-i18n, locale detected from
  navigator.language.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-07 11:08:02 +02:00
nicolabellutiandClaude Sonnet 5 a96561d5f0 Added Oxibadge, a minimal Tauri + Svelte desktop client
Check, format and test / build (push) Successful in 14m6s
Scaffolds the oxibadge crate/frontend as a new workspace member, stripped
down to a bare hello-world, and
extends the CI pipeline

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-06 20:26:24 +02:00