Commit Graph
31 Commits
Author SHA1 Message Date
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
nicolabelluti 268a917a69 [skip ci] Updated the root README.md 2026-10-06 20:31:24 +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
nicolabellutiandClaude Sonnet 5 cc8181ebdc Turned the repo into a Cargo workspace, with r701 as a member
Check, format and test / build (push) Successful in 44s
Moving the library into its own r701/ directory makes room for the
Tauri GUI client (Oxibadge) to be added as a sibling workspace member
in a following commit. edition/license/repository are now inherited
from the new workspace root instead of being duplicated per member.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-06 12:49:54 +02:00
nicolabellutiandClaude Sonnet 5 c2471ed548 Bumped version to 0.2.0
Check, format and test / build (push) Successful in 48s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-04 15:27:43 +02:00
nicolabellutiandClaude Sonnet 5 9a637190b5 Expanded the e2e test suite and fake device data
Check, format and test / build (push) Successful in 46s
- fake_records now generates a full year (2026) of classic workday
  punches (09:00-13:00, 14:00-18:00) for the employees in fake_users;
  this spans many 1024-byte blocks, exercising the multi-block
  streaming path
- fake_users/fake_records are now public so tests can assert against
  them instead of hardcoded expectations
- scoped #[allow(clippy::unwrap_used)] to only the functions that
  actually use unwrap, instead of a blanket file-level allow
- added gets_total_record_count, streams_records, and
  gets_none_for_unknown_employee tests

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-04 15:25:18 +02:00
nicolabellutiandClaude Sonnet 5 9977db0e46 Added an e2e test harness with a fake R701 device
Check, format and test / build (push) Successful in 47s
tests/mock/mod.rs emulates the device's TCP protocol (ping, get_name,
get_total_record_count, get_record_bytes), grounded in the reverse
engineering notes at
https://nicolabelluti.me/posts/2024/05/studying-a-communication-protocol/,
so tests/e2e.rs can exercise the real R701 client against it instead of
needing a physical reader. Starts with one test (connect + ping);
more scenarios (get_name, record streaming, error cases) to follow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-04 14:47:29 +02:00
nicolabellutiandClaude Sonnet 5 f697660ff4 Documented the public API and removed the missing_errors_doc allows
Check, format and test / build (push) Successful in 42s
Added rustdoc comments to every public item (R701, Record, Clock,
RecordIterator and their methods/fields/variants), each with an
# Errors section where applicable, so the clippy::missing_errors_doc
allows are no longer needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 15:07:40 +02:00
nicolabelluti d8c6440a59 Re-added npm to the CI/CD pipeline
Check, format and test / build (push) Successful in 33s
2026-10-01 14:49:02 +02:00
nicolabellutiandClaude Sonnet 5 e0e453c9c5 Cleaned up the protocol layer and metadata
Check, format and test / build (push) Failing after 5s
- request() now reads exactly the expected response length with
  read_exact instead of a single non-guaranteed fill_buf, fixing a
  latent bug where a response split across multiple TCP packets could
  be mistaken for malformed data; the per-method length checks are now
  redundant and were removed
- sequence_number wraps explicitly via wrapping_add instead of
  relying on implicit (and debug-vs-release inconsistent) overflow
  behavior after 65536 requests
- get_name validates UTF-8 strictly instead of silently lossy-decoding
  invalid bytes; on invalid data it now returns the FromUtf8Error
  itself (byte-level \0 trimming moved after the UTF-8 check), letting
  the caller choose to fail or fall back to a lossy rendering
- removed the unused Default derive from Clock and Record
- removed npm from the CI image (no JS/Node in this repo), fixed a
  typo in a CI step name
- fixed the Cargo.toml license field to the actual SPDX identifier
  (AGPL-3.0-or-later, per the notice at the end of LICENSE) instead of
  the free-text "GNU AGPLv3.0"

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 14:43:50 +02:00
nicolabellutiandClaude Sonnet 5 9af4a82e39 Made R701 shareable via an internal Mutex, allowing get_name to be called while streaming records
Check, format and test / build (push) Successful in 34s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 14:02:47 +02:00
nicolabellutiandClaude Sonnet 5 1745ecc05e Made the library async using tokio and the iterator return a Result
Check, format and test / build (push) Successful in 33s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 13:28:32 +02:00
nicolabellutiandClaude Sonnet 5 93f9e9d3af Updated the Rust version used by the CI/CD and silenced clippy's missing_errors_doc lint
Check, format and test / build (push) Successful in 1m13s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 12:44:07 +02:00
nicolabelluti 07ef2a96bc Updated the README.md and the tests
Check, format and test / build (push) Failing after 20s
2024-07-31 13:13:07 +02:00
nicolabelluti b2b5f0c66c Removed Nix and the sample-main, added a CI/CD pipeline and updated the README.md
Check, format and test / build (push) Failing after 49s
2024-07-31 12:00:34 +02:00
nicolabelluti 987af19ec8 Added a sample main function to get the data 2024-06-16 17:57:32 +02:00
nicolabelluti 35e75745db Put the lib into a workspace 2024-06-16 17:48:15 +02:00
nicolabelluti 0dd05c0d91 Avoided two overflows 2024-06-16 14:06:13 +02:00
nicolabelluti 78248eb2a5 Renamed a variable 2024-05-13 13:25:17 +02:00
nicolabelluti 4d9361e383 Return a None if the name is an empty String 2024-05-13 13:05:27 +02:00
nicolabelluti 85e07886e9 Added Nix Flake 2024-05-06 12:27:05 +02:00
nicolabelluti ba20f457f8 Reversed the direction of the iterator 2024-05-06 11:31:41 +02:00
nicolabelluti f0ac5fe766 Added the RecordIterator struct 2024-05-05 22:16:48 +02:00
nicolabelluti e2d1f141d6 Added serde as an optional dependency 2024-05-05 21:55:52 +02:00
nicolabelluti 6f0d2587b4 Added the Record struct 2024-05-05 21:49:00 +02:00
nicolabelluti 31117fb479 Updated the README.md 2024-05-05 19:10:06 +02:00
nicolabelluti bc75ec6ebe Added the R701 struct 2024-05-05 19:06:12 +02:00
nicolabelluti b13051d408 Added the Rust base 2024-05-05 16:45:55 +02:00