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>
This commit is contained in:
2026-10-07 13:26:01 +02:00
parent 28186c7745
commit b4cd8e1796
7 changed files with 47 additions and 56 deletions
+14 -24
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { invoke } from '@tauri-apps/api/core';
import { _ } from 'svelte-i18n';
import { error, setError, clearError } from '$lib/error';
import Column from './Column.svelte';
import Intro from './Intro.svelte';
import Field from './Field.svelte';
@@ -10,40 +11,29 @@
let { onconnected }: { onconnected: (cfg: { host: string; port: number }) => void } = $props();
type Phase = 'idle' | 'testing' | 'err';
let host = $state('');
let port = $state(5005);
let phase = $state<Phase>('idle');
let errorCode = $state('');
let testing = $state(false);
const trimmedHost = $derived(host.trim());
const empty = $derived(trimmedHost === '');
const disabled = $derived(empty || phase === 'testing');
const disabled = $derived(empty || testing);
const btnLabel = $derived(
phase === 'testing'
? $_('onboarding.button.testing')
: phase === 'err'
? $_('onboarding.button.retry')
: $_('onboarding.button.idle')
testing ? $_('onboarding.button.testing') : $error ? $_('onboarding.button.retry') : $_('onboarding.button.idle')
);
function resetPhase() {
phase = 'idle';
errorCode = '';
}
async function testAndSave() {
if (disabled) return;
phase = 'testing';
errorCode = '';
testing = true;
clearError();
try {
await invoke('test_connection', { host: trimmedHost, port });
await invoke('save_preferences', { host: trimmedHost, port });
onconnected({ host: trimmedHost, port });
} catch (err) {
errorCode = String(err);
phase = 'err';
setError(err);
} finally {
testing = false;
}
}
</script>
@@ -64,7 +54,7 @@
label={$_('onboarding.host_label')}
bind:value={host}
placeholder="192.168.1.100"
oninput={resetPhase}
oninput={clearError}
>
{#snippet icon()}
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true">
@@ -79,14 +69,14 @@
bind:value={port}
type="number"
placeholder="5005"
oninput={resetPhase}
oninput={clearError}
/>
</div>
<Button type="submit" label={btnLabel} faded={empty} busy={phase === 'testing'} {disabled} />
<Button type="submit" label={btnLabel} faded={empty} busy={testing} {disabled} />
{#if phase === 'err'}
<ErrorBanner title={$_('onboarding.error_title')} message={$_(`onboarding.errors.${errorCode}`)} />
{#if $error}
<ErrorBanner title={$_('errors.title')} message={$error} />
{/if}
<Hint text={$_('onboarding.hint')} />