refactor: consolidate loading/error states and extract instance actions hook

Frontend:
- Create reusable DataStates components (LoadingState, ErrorState, EmptyState)
- Refactor 12 pages to use shared state components instead of inline JSX
- Extract useInstanceActions hook to eliminate session action duplication
- Update dashboard and sessions pages to use shared hook

OpenSpec:
- Archive completed mobile-app-usability change (44/44 tasks)
- Archive completed add-config-profiles change (15/15 tasks)

Quality: TypeScript check passes, production build succeeds
This commit is contained in:
Alex Blank
2026-05-25 22:50:18 +02:00
parent 4c216dd1ca
commit ab79080f0b
31 changed files with 258 additions and 266 deletions
+4 -11
View File
@@ -1,6 +1,7 @@
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { createSSHKey, deleteSSHKey, listSSHKeys, signPayload, verifySignature, type SSHKey } from "../api/ssh_keys";
import { EmptyState, ErrorState, LoadingState } from "../components/data-states";
import { Icon } from "../components/icon";
import { useAsyncData } from "../hooks/use-async-data";
@@ -87,7 +88,7 @@ export const SSHKeysPage = () => {
}
}
if (status === "loading") return <div>Loading...</div>;
if (status === "loading") return <LoadingState message="Loading SSH keys..." />;
return (
<section className="stack">
@@ -130,19 +131,11 @@ export const SSHKeysPage = () => {
</button>
</form>
{status === "error" && (
<div className="card stack">
<p>Failed to load SSH keys</p>
<button className="secondary-button" onClick={() => loadKeys()} type="button">
<Icon name="refresh" size="sm" />
Retry
</button>
</div>
)}
{status === "error" && <ErrorState message="Failed to load SSH keys" onRetry={loadKeys} />}
<div className="keys-list">
{safeKeys.length === 0 ? (
<p className="muted">No SSH keys yet. Generate one above.</p>
<EmptyState message="No SSH keys yet. Generate one above." />
) : (
safeKeys.map((key) => (
<div key={key.id} className="key-card">