fix(oxibadge): show connection errors instead of failing silently
Check, format and test / build (push) Successful in 10m4s
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:
@@ -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')} />
|
||||
|
||||
Reference in New Issue
Block a user