feat(sammler): mehrere sammler mit eigener sammlung und wunschliste

Der Katalog bleibt gemeinsam - ein Set existiert einmal, unabhaengig
davon, wer es hat. Besitz und Wunschlisten gehoeren dagegen je einem
Sammler. Damit beantwortet "hat er das schon?" jetzt die Frage "hat *er*
das schon?": ein Set, das nur die Schwester besitzt, faellt fuer den
Bruder wieder unter "fehlt noch" und darf auf seine Wunschliste.

Wichtig fuer den Alltag: Solange es nur einen Sammler gibt, taucht die
Unterscheidung nirgends in der Oberflaeche auf. Kein Umschalter, keine
Abfrage beim Hinzufuegen, keine Badges - die App bleibt exakt so
einfach wie vorher. Erst der zweite Sammler schaltet all das frei.

Die Besitzlogik liegt weiterhin an genau einer Stelle
(src/lib/ownership.ts) und hat nur eine Dimension dazubekommen. Das
automatische "erfuellt" auf Wunschlisten fragt jetzt ebenfalls je Liste:
ein Wunsch auf Max' Liste ist erfuellt, wenn Max das Set bekommt - nicht
wenn Mia es hat. Listen ohne Sammler verhalten sich wie bisher.

Die Migration legt einen Sammler "Sammlung" an und ordnet ihm alles
Vorhandene zu; umbenennen laesst er sich unter Verwaltung -> Sammler.
Der Seed uebernimmt ihn statt einen dritten anzulegen.

Refs Phase 3

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
unknown
2026-09-07 09:00:35 +02:00
co-authored by Claude Opus 5
parent 7265c03548
commit c23b754515
35 changed files with 3104 additions and 66 deletions
+10 -1
View File
@@ -11,6 +11,7 @@ import {
parseForm,
type ActionResult,
} from '@/lib/action-result';
import { defaultCollectorId } from '@/lib/queries/collectors';
import { reconcileFulfilledWishlistItems } from '@/lib/queries/wishlists';
import { requireUser } from '@/lib/session';
import { collectionItemSchema, missingPartSchema } from '@/lib/validation';
@@ -32,17 +33,24 @@ function revalidateCollection(setId?: string) {
* Quick add from the set detail page: one tap, sensible defaults, details can
* be filled in later.
*/
export async function addSetToCollection(setId: string): Promise<ActionResult<{ id: string }>> {
export async function addSetToCollection(
setId: string,
collectorId?: string,
): Promise<ActionResult<{ id: string }>> {
await requireUser();
const exists = db.select({ id: set.id }).from(set).where(eq(set.id, setId)).get();
if (!exists) return actionError('Das Set gibt es nicht mehr.');
// With a single collector nobody is asked - the copy simply belongs to them.
const owner = collectorId ?? defaultCollectorId();
const id = crypto.randomUUID();
db.insert(collectionItem)
.values({
id,
setId,
collectorId: owner,
status: 'owned',
completeness: 'unknown',
createdAt: now(),
@@ -68,6 +76,7 @@ export async function updateCollectionItem(id: string, input: unknown): Promise<
db.update(collectionItem)
.set({
collectorId: parsed.data.collectorId ?? existing.collectorId,
status: parsed.data.status,
completeness: parsed.data.completeness,
condition: parsed.data.condition as Condition | null,