Supra_App/src/routes/(authed)/sheet/overview/+page.svelte

149 lines
4.4 KiB
Svelte

<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { get } from 'svelte/store';
import { addNotification } from '$lib/core/stores/noti.js';
import { departmentStore } from '$lib/core/stores/departments.js';
import { referenceFromPage } from '$lib/core/stores/recipeStore.js';
import {
sheetCatalogs,
sheetCatalogsLoading,
type Catalog
} from '$lib/core/stores/sheetStore.js';
import { waitForOpenSocket } from '$lib/core/stores/websocketStore.js';
import { requestCatalogs } from '$lib/core/services/sheetService.js';
import Button from '$lib/components/ui/button/button.svelte';
import * as Table from '$lib/components/ui/table/index.js';
import Badge from '$lib/components/ui/badge/badge.svelte';
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
import { RefreshCw } from '@lucide/svelte/icons';
// Get country from route params or department store
let selectedCountry = $state<string>($page.params.country || get(departmentStore) || '');
let catalogs = $derived($sheetCatalogs);
let loading = $derived($sheetCatalogsLoading);
let error = $state<string | null>(null);
onMount(() => {
referenceFromPage.set('sheet');
if (selectedCountry) {
void loadCatalogs();
}
});
async function loadCatalogs() {
if (!selectedCountry) return;
error = null;
sheetCatalogsLoading.set(true);
sheetCatalogs.set([]);
const socket = await waitForOpenSocket();
if (!socket) {
error = 'WebSocket is still connecting. Please try again.';
sheetCatalogsLoading.set(false);
addNotification('ERR:WebSocket not connected');
return;
}
const sent = requestCatalogs(selectedCountry);
if (!sent) {
error = 'WebSocket not connected. Please try again.';
sheetCatalogsLoading.set(false);
addNotification('ERR:WebSocket not connected');
}
}
function handleEditCatalog(catalog: Catalog) {
if (catalog.status === 'locked') {
addNotification(`WARN:Catalog is locked by ${catalog.locked_by}`);
return;
}
goto(`/sheet/edit/${selectedCountry}/${catalog.catalog}`);
}
</script>
<div class="mx-8 flex">
<div class="w-full">
<!-- Header -->
<div class="mb-4 flex items-center justify-between">
<div>
<h1 class="m-8 text-4xl font-bold">Sheet Overview</h1>
<p class="mx-8 my-0 text-muted-foreground">
Catalogs for {selectedCountry.toUpperCase()}
</p>
</div>
<div class="mr-8">
<Button variant="outline" onclick={loadCatalogs} disabled={loading}>
<RefreshCw class="mr-2 h-4 w-4" />
Refresh
</Button>
</div>
</div>
<!-- Content Area -->
<div class="mx-8">
{#if loading}
<div class="flex h-64 items-center justify-center">
<Spinner class="h-12 w-12" />
<p class="ml-4 text-muted-foreground">
Loading catalogs for {selectedCountry}...
</p>
</div>
{:else if error}
<div class="rounded-md border border-red-200 bg-red-50 p-4">
<p class="text-sm text-red-600">{error}</p>
<Button variant="outline" size="sm" class="mt-2" onclick={loadCatalogs}>
<RefreshCw class="mr-2 h-4 w-4" />
Retry
</Button>
</div>
{:else if catalogs.length === 0}
<div class="flex h-64 items-center justify-center text-muted-foreground">
<p>No catalogs found for {selectedCountry}</p>
</div>
{:else}
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>Catalog Name</Table.Head>
<Table.Head>Status</Table.Head>
<Table.Head>Locked By</Table.Head>
<Table.Head>Actions</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each catalogs as catalog}
<Table.Row>
<Table.Cell class="font-medium">{catalog.catalog}</Table.Cell>
<Table.Cell>
<Badge
variant={catalog.status === 'free' ? 'default' : 'secondary'}
>
{catalog.status.toUpperCase()}
</Badge>
</Table.Cell>
<Table.Cell class="text-muted-foreground">
{catalog.locked_by || '-'}
</Table.Cell>
<Table.Cell>
<Button
size="sm"
variant={catalog.status === 'free' ? 'default' : 'outline'}
onclick={() => handleEditCatalog(catalog)}
disabled={catalog.status === 'locked'}
>
{catalog.status === 'free' ? 'Edit' : 'Locked'}
</Button>
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
{/if}
</div>
</div>
</div>