uniqueSlug($user, Str::slug($attributes['slug'] ?? $name) ?: 'saved-cards'); return NovaCardCollection::query()->create([ 'user_id' => $user->id, 'slug' => $slug, 'name' => $name, 'description' => $attributes['description'] ?? null, 'visibility' => $attributes['visibility'] ?? NovaCardCollection::VISIBILITY_PRIVATE, 'official' => false, ]); } public function createManagedCollection(array $attributes): NovaCardCollection { $owner = User::query()->findOrFail((int) $attributes['user_id']); $name = trim((string) ($attributes['name'] ?? 'Untitled Collection')); $slug = $this->uniqueSlug($owner, Str::slug($attributes['slug'] ?? $name) ?: 'nova-collection'); return NovaCardCollection::query()->create([ 'user_id' => $owner->id, 'slug' => $slug, 'name' => $name, 'description' => $attributes['description'] ?? null, 'visibility' => $attributes['visibility'] ?? NovaCardCollection::VISIBILITY_PUBLIC, 'official' => (bool) ($attributes['official'] ?? false), 'featured' => (bool) ($attributes['featured'] ?? false), ]); } public function listCollections(User $user): array { return NovaCardCollection::query() ->withCount('items') ->where('user_id', $user->id) ->orderByDesc('updated_at') ->get() ->map(fn (NovaCardCollection $collection): array => [ 'id' => (int) $collection->id, 'slug' => (string) $collection->slug, 'name' => (string) $collection->name, 'description' => $collection->description, 'visibility' => (string) $collection->visibility, 'featured' => (bool) $collection->featured, 'cards_count' => (int) $collection->cards_count, 'items_count' => (int) $collection->items_count, ]) ->values() ->all(); } public function saveCard(User $user, NovaCard $card, ?int $collectionId = null, ?string $note = null): NovaCardCollection { $collection = $collectionId ? NovaCardCollection::query()->where('user_id', $user->id)->findOrFail($collectionId) : $this->defaultCollection($user); $this->addCardToCollection($collection, $card, $note); return $collection->refresh(); } public function addCardToCollection(NovaCardCollection $collection, NovaCard $card, ?string $note = null, ?int $sortOrder = null): NovaCardCollectionItem { $sortOrder ??= (int) NovaCardCollectionItem::query()->where('collection_id', $collection->id)->max('sort_order') + 1; $item = NovaCardCollectionItem::query()->updateOrCreate([ 'collection_id' => $collection->id, 'card_id' => $card->id, ], [ 'note' => $note, 'sort_order' => $sortOrder, ]); $this->refreshCounts($collection, $card); return $item; } public function unsaveCard(User $user, NovaCard $card, ?int $collectionId = null): void { $query = NovaCardCollectionItem::query() ->where('card_id', $card->id) ->whereHas('collection', fn ($builder) => $builder->where('user_id', $user->id)); if ($collectionId !== null) { $query->where('collection_id', $collectionId); } $collectionIds = $query->pluck('collection_id')->unique()->all(); $query->delete(); foreach ($collectionIds as $id) { $collection = NovaCardCollection::query()->find($id); if ($collection) { $this->refreshCounts($collection, $card); } } } public function removeCardFromCollection(NovaCardCollection $collection, NovaCard $card): void { NovaCardCollectionItem::query() ->where('collection_id', $collection->id) ->where('card_id', $card->id) ->delete(); $this->refreshCounts($collection, $card); } public function defaultCollection(User $user): NovaCardCollection { return NovaCardCollection::query()->firstOrCreate([ 'user_id' => $user->id, 'slug' => 'saved-cards', ], [ 'name' => 'Saved Cards', 'description' => 'Private library of Nova Cards saved for remixing, referencing, and future collections.', 'visibility' => NovaCardCollection::VISIBILITY_PRIVATE, 'official' => false, ]); } private function refreshCounts(NovaCardCollection $collection, NovaCard $card): void { $collection->forceFill([ 'cards_count' => NovaCardCollectionItem::query()->where('collection_id', $collection->id)->count(), ])->save(); UpdateNovaCardStatsJob::dispatch($card->id); } private function uniqueSlug(User $user, string $base): string { $slug = $base; $suffix = 2; while (NovaCardCollection::query()->where('user_id', $user->id)->where('slug', $slug)->exists()) { $slug = $base . '-' . $suffix; $suffix++; } return $slug; } }