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>
This commit is contained in:
2026-10-08 18:29:57 +02:00
parent acd3efeac6
commit b65e85f908
26 changed files with 1397 additions and 118 deletions
+42 -3
View File
@@ -7,6 +7,10 @@
value = $bindable(),
type = 'text',
placeholder = '',
maxlength,
inputmode,
err = false,
suffix,
oninput,
icon
}: {
@@ -15,15 +19,30 @@
value: string | number;
type?: string;
placeholder?: string;
oninput?: () => void;
maxlength?: number;
inputmode?: 'text' | 'numeric' | 'decimal' | 'none' | 'tel' | 'search' | 'email' | 'url';
err?: boolean;
suffix?: string;
oninput?: (e: Event & { currentTarget: HTMLInputElement }) => void;
icon?: Snippet;
} = $props();
</script>
<div class="field">
<div class="field" class:err>
<label for={id}>{label}</label>
{#if icon}{@render icon()}{/if}
<input {id} {type} {placeholder} bind:value {oninput} autocomplete="off" spellcheck="false" />
<input
{id}
{type}
{placeholder}
{maxlength}
{inputmode}
bind:value
{oninput}
autocomplete="off"
spellcheck="false"
/>
{#if suffix}<span class="suffix">{suffix}</span>{/if}
</div>
<style>
@@ -52,6 +71,20 @@
box-shadow: 0 0 0 4px var(--ox-accent-ring);
}
.field.err,
.field.err:hover,
.field.err:focus-within {
border-color: #e5484d;
}
.field.err:focus-within {
box-shadow: 0 0 0 4px rgba(229, 72, 77, 0.18);
}
.field.err label {
color: #ff8a8f;
}
.field label {
position: absolute;
top: -9px;
@@ -93,4 +126,10 @@
-webkit-appearance: none;
margin: 0;
}
.suffix {
flex: none;
font-size: 14px;
color: var(--ox-text-subtle);
}
</style>