feat: extract built-in view presets and add filter chips
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { BOOK_PRESETS } from '$lib/presets';
|
||||
import { getBookCollectionState } from '$lib/state/bookCollection.svelte';
|
||||
|
||||
const bookCollection = getBookCollectionState();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Built-in views, not shelves: a fixed set every library has, so nothing here is
|
||||
named, owned or persisted. The same definitions drive the home page's shelves,
|
||||
so "Recently added" means the same thing in both places.
|
||||
-->
|
||||
<div class="flex items-center gap-1.5 overflow-x-auto" aria-label="Preset views">
|
||||
{#each BOOK_PRESETS as preset (preset.id)}
|
||||
{@const active = bookCollection.isPresetActive(preset)}
|
||||
<button
|
||||
type="button"
|
||||
aria-pressed={active}
|
||||
onclick={() => (active ? bookCollection.clearView() : bookCollection.applyPreset(preset))}
|
||||
class="shrink-0 rounded-full border px-3 py-1 text-xs whitespace-nowrap transition-colors {active
|
||||
? 'border-primary bg-primary text-primary-foreground font-medium'
|
||||
: 'border-border text-muted-foreground hover:border-muted-foreground hover:text-foreground'}"
|
||||
>
|
||||
{preset.label}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Built-in views over a library.
|
||||
*
|
||||
* These are navigation, not content — a fixed set of lenses every library has,
|
||||
* as distinct from shelves, which are named collections a user owns. Nothing
|
||||
* here is persisted or user-editable.
|
||||
*
|
||||
* Defined once and consumed twice: the home route renders them as shelves, and
|
||||
* the library view renders them as chips. Previously each home shelf was a
|
||||
* hand-written query string in the loader, which is how `create_at` (missing a
|
||||
* `d`) went unnoticed — that sort silently did nothing.
|
||||
*/
|
||||
|
||||
export interface BookPreset {
|
||||
id: string;
|
||||
label: string;
|
||||
/** Shown as the shelf heading on the home page. */
|
||||
heading: string;
|
||||
/** Filter values, keyed the way the books endpoint expects them. */
|
||||
filters: Record<string, string[]>;
|
||||
/** Backend sort field; omitted means "leave the current ordering alone". */
|
||||
orderBy?: string;
|
||||
/** asc, desc, or random — the API's CustomOrderBy accepts all three. */
|
||||
sortOrder?: string;
|
||||
}
|
||||
|
||||
export const BOOK_PRESETS: BookPreset[] = [
|
||||
{
|
||||
id: 'continue-reading',
|
||||
label: 'Reading',
|
||||
heading: 'Continue Reading',
|
||||
filters: { progress: ['in_progress'] },
|
||||
orderBy: 'last_accessed',
|
||||
sortOrder: 'desc'
|
||||
},
|
||||
{
|
||||
id: 'recently-added',
|
||||
label: 'Recently added',
|
||||
heading: 'Recently Added',
|
||||
filters: { progress: ['unread'] },
|
||||
orderBy: 'created_at',
|
||||
sortOrder: 'desc'
|
||||
},
|
||||
{
|
||||
id: 'discover',
|
||||
label: 'Discover',
|
||||
heading: 'Discover',
|
||||
filters: { progress: ['unread'] },
|
||||
sortOrder: 'random'
|
||||
},
|
||||
{
|
||||
id: 'read-again',
|
||||
label: 'Read again',
|
||||
heading: 'Read Again',
|
||||
filters: { progress: ['read'] },
|
||||
sortOrder: 'random'
|
||||
}
|
||||
];
|
||||
|
||||
export function getPreset(id: string) {
|
||||
return BOOK_PRESETS.find((preset) => preset.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query string for the books endpoint, used by the home route's loader.
|
||||
*/
|
||||
export function presetQuery(preset: BookPreset, libraryId: string | number) {
|
||||
const params = new URLSearchParams();
|
||||
params.set('libraries', String(libraryId));
|
||||
|
||||
for (const [key, values] of Object.entries(preset.filters)) {
|
||||
for (const value of values) params.append(key, value);
|
||||
}
|
||||
|
||||
if (preset.orderBy) params.set('orderBy', preset.orderBy);
|
||||
if (preset.sortOrder) params.set('sortOrder', preset.sortOrder);
|
||||
|
||||
return params.toString();
|
||||
}
|
||||
Reference in New Issue
Block a user