Files
watch-stock-list/src/lib/components/AddReviewCardForm.svelte

119 lines
4.3 KiB
Svelte

<script lang="ts">
import { REVIEW_TAGS, PRICE_LABELS, type ReviewTag, type PriceLabel, type ReviewCard } from '$lib/types/review';
let { open = false, onClose, onAdd } = $props<{ open?: boolean; onClose: () => void; onAdd: (card: Omit<ReviewCard, 'id' | 'createdAt' | 'updatedAt' | 'starred'>) => void }>();
let form = $state({
title: '',
content: '',
tags: [] as ReviewTag[],
stock: {
name: '',
code: '',
amount: 0,
priceGroups: [
{ price: 0, label: PRICE_LABELS[0] as PriceLabel }
]
}
});
function addPriceGroup() {
form.stock.priceGroups.push({ price: 0, label: PRICE_LABELS[0] });
}
function removePriceGroup(idx: number) {
if (form.stock.priceGroups.length > 1) {
form.stock.priceGroups.splice(idx, 1);
}
}
function resetForm() {
form.title = '';
form.content = '';
form.tags = [];
form.stock = {
name: '',
code: '',
amount: 0,
priceGroups: [
{ price: 0, label: PRICE_LABELS[0] }
]
};
}
function handleSubmit() {
if (!form.title.trim() || !form.content.trim()) return;
onAdd({
title: form.title,
content: form.content,
tags: [...form.tags],
stock: {
name: form.stock.name,
code: form.stock.code,
amount: form.stock.amount,
priceGroups: form.stock.priceGroups.map(pg => ({ ...pg }))
}
});
resetForm();
onClose();
}
function handleCancel() {
resetForm();
onClose();
}
</script>
{#if open}
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm">
<div class="bg-white dark:bg-zinc-900 rounded-xl shadow-xl p-6 w-full max-w-md relative animate-in fade-in-0 zoom-in-95">
<h2 class="text-lg font-bold mb-4">添加复盘卡片</h2>
<form on:submit|preventDefault={handleSubmit}>
<div class="mb-3">
<label class="block text-sm font-medium mb-1">标题</label>
<input class="input input-bordered w-full" bind:value={form.title} required />
</div>
<div class="mb-3">
<label class="block text-sm font-medium mb-1">内容</label>
<textarea class="input input-bordered w-full min-h-[80px]" bind:value={form.content} required />
</div>
<div class="mb-3">
<label class="block text-sm font-medium mb-1">标签</label>
<div class="flex flex-wrap gap-2">
{#each REVIEW_TAGS as tag}
<label class="flex items-center gap-1 cursor-pointer">
<input type="checkbox" bind:group={form.tags} value={tag} />
<span class="text-xs">{tag}</span>
</label>
{/each}
</div>
</div>
<div class="mb-3">
<label class="block text-sm font-medium mb-1">股票信息</label>
<div class="flex gap-2 mb-2">
<input class="input input-bordered flex-1" placeholder="名称" bind:value={form.stock.name} />
<input class="input input-bordered flex-1" placeholder="代码" bind:value={form.stock.code} />
<input class="input input-bordered w-20" type="number" min="0" placeholder="数量" bind:value={form.stock.amount} />
</div>
<div>
<label class="block text-xs font-medium mb-1">价格组</label>
{#each form.stock.priceGroups as pg, i}
<div class="flex items-center gap-2 mb-1">
<select class="input input-bordered w-24" bind:value={pg.label}>
{#each PRICE_LABELS as label}
<option value={label}>{label}</option>
{/each}
</select>
<input class="input input-bordered w-24" type="number" min="0" placeholder="价格" bind:value={pg.price} />
{#if form.stock.priceGroups.length > 1}
<button type="button" class="btn btn-xs btn-error" on:click={() => removePriceGroup(i)}>移除</button>
{/if}
</div>
{/each}
<button type="button" class="btn btn-xs btn-primary mt-1" on:click={addPriceGroup}>添加价格组</button>
</div>
</div>
<div class="flex justify-end gap-2 mt-6">
<button type="button" class="btn btn-ghost" on:click={handleCancel}>取消</button>
<button type="submit" class="btn btn-primary">添加</button>
</div>
</form>
</div>
</div>
{/if}