feat: add svelte web workspace shell
This commit is contained in:
28
apps/web/src/features/auth/ServerLogin.svelte
Normal file
28
apps/web/src/features/auth/ServerLogin.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let apiBase: string;
|
||||
|
||||
const dispatch = createEventDispatcher<{ serverChange: { apiBase: string } }>();
|
||||
let server = apiBase;
|
||||
|
||||
function saveServer() {
|
||||
const normalized = normalizeServer(server);
|
||||
server = normalized;
|
||||
dispatch('serverChange', { apiBase: normalized });
|
||||
}
|
||||
|
||||
function normalizeServer(value: string) {
|
||||
const trimmed = value.trim();
|
||||
if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
||||
return trimmed;
|
||||
}
|
||||
return `http://${trimmed}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<form aria-label="服务器登录" class="server-login" on:submit|preventDefault={saveServer}>
|
||||
<label for="server-address">服务器 IP 或域名</label>
|
||||
<input id="server-address" name="server" bind:value={server} placeholder="http://localhost:8080" />
|
||||
<button type="submit">保存服务器</button>
|
||||
</form>
|
||||
21
apps/web/src/features/projects/ProjectDashboard.svelte
Normal file
21
apps/web/src/features/projects/ProjectDashboard.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type { ProjectDashboardSummary } from '../../lib/api';
|
||||
|
||||
export let summary: ProjectDashboardSummary;
|
||||
|
||||
$: metrics = [
|
||||
['待处理 Inbox', summary.pending_inbox_count],
|
||||
['当前任务', summary.open_task_count],
|
||||
['笔记资料', summary.recent_note_count],
|
||||
['AI 会话', summary.recent_session_count],
|
||||
] as const;
|
||||
</script>
|
||||
|
||||
<section aria-label="项目总览" class="dashboard-grid">
|
||||
{#each metrics as [label, value]}
|
||||
<article class="dashboard-metric">
|
||||
<span>{label}</span>
|
||||
<strong>{value}</strong>
|
||||
</article>
|
||||
{/each}
|
||||
</section>
|
||||
25
apps/web/src/features/projects/ProjectDashboard.test.ts
Normal file
25
apps/web/src/features/projects/ProjectDashboard.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import ProjectDashboard from './ProjectDashboard.svelte';
|
||||
|
||||
describe('ProjectDashboard', () => {
|
||||
it('shows project counters', () => {
|
||||
render(ProjectDashboard, {
|
||||
props: {
|
||||
summary: {
|
||||
project_id: 1,
|
||||
pending_inbox_count: 2,
|
||||
open_task_count: 5,
|
||||
recent_note_count: 3,
|
||||
recent_session_count: 4,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.getByText('待处理 Inbox')).toBeInTheDocument();
|
||||
expect(screen.getByText('2')).toBeInTheDocument();
|
||||
expect(screen.getByText('当前任务')).toBeInTheDocument();
|
||||
expect(screen.getByText('5')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user