diff --git a/src/routes/[type]/[id]/+page.svelte b/src/routes/[type]/[id]/+page.svelte
index 172c9c3..89108b1 100644
--- a/src/routes/[type]/[id]/+page.svelte
+++ b/src/routes/[type]/[id]/+page.svelte
@@ -37,7 +37,7 @@
let productionCompanies = 4;
let magnetLink = '';
let magnetLoading = false;
- let isShow = data.riven ? isRivenShow(data.riven) : false;
+ let isShow = data.details.media_type === 'tv';
let selectedMagnetItem: Selected<{ id: string; file?: string; folder?: string }>;
$: buttonEnabled = magnetLink && !magnetLoading && (isShow ? selectedMagnetItem : true);
@@ -710,6 +710,7 @@
{/if}
diff --git a/src/routes/browse/+page.svelte b/src/routes/browse/+page.svelte
index 11607cb..b197f7c 100644
--- a/src/routes/browse/+page.svelte
+++ b/src/routes/browse/+page.svelte
@@ -1,60 +1,231 @@
+
-
-
-
-
- {#if loading}
-
- {:else if query.length > 0}
-
Search results for {query}
+
+
+
+
+
+ {#each items as item (item.id)}
+
+
+
+ {/each}
+
+
+
+
{
+ pageNumber = page;
+ fetchItems();
+ }}
+ >
+
+
+
+
+ {#each pages as page (page.key)}
+ {#if page.type === 'ellipsis'}
+
+
+
+ {:else}
+
+
+ {page.value}
+
+
+ {/if}
+ {/each}
+
+
+
+
+
+
+
diff --git a/src/routes/browse/+page.ts b/src/routes/browse/+page.ts
index d2a5256..76c8536 100644
--- a/src/routes/browse/+page.ts
+++ b/src/routes/browse/+page.ts
@@ -1,23 +1,44 @@
-import type { PageLoad } from './$types';
-import { getMovieSearch, getTVSearch, getCollectionSearch } from '$lib/tmdb';
+import { superValidate } from 'sveltekit-superforms/client';
+import { schema } from './schema';
+import { ItemsService } from '$lib/client';
+import { zod } from 'sveltekit-superforms/adapters';
+import type { PageLoad } from '../$types';
+import type { RivenGetItemsResponse } from '$lib/types';
-export const load = (async ({ fetch, url }) => {
- const query = url.searchParams.get('query');
+export const load = (async () => {
+ const form = await superValidate({}, zod(schema));
+ const page = 1;
+ const limit = 12;
- if (query && query.length > 0) {
- const moviesRes = await getMovieSearch(fetch, query, false, 'en-US', null, 1, null, null);
- const tvRes = await getTVSearch(fetch, query, null, false, 'en-US', 1, null);
- const collectionRes = await getCollectionSearch(fetch, query, false, 'en-US', 1, null);
+ async function getItems(): Promise
{
+ try {
+ const { data, error } = await ItemsService.getItems({
+ query: {
+ page,
+ sort: form.data.sort,
+ limit,
+ type: form.data.type,
+ states: form.data.state
+ }
+ });
- return {
- movies: moviesRes.results,
- shows: tvRes.results,
- collections: collectionRes.results
- };
- } else {
- return {
- movies: [],
- shows: []
- };
+ if (error) {
+ console.error('Error fetching items:', error);
+ return { success: true, items: [], page: 0, limit: 0, total_items: 0, total_pages: 0 };
+ }
+
+ return data as unknown as RivenGetItemsResponse;
+ } catch (err) {
+ console.error('Error in getItems:', err);
+ return { success: true, items: [], page: 0, limit: 0, total_items: 0, total_pages: 0 };
+ }
}
+
+ const itemsData = await getItems();
+
+ return {
+ form,
+ page,
+ itemsData
+ };
}) satisfies PageLoad;
diff --git a/src/routes/browse/schema.ts b/src/routes/browse/schema.ts
new file mode 100644
index 0000000..ceaa450
--- /dev/null
+++ b/src/routes/browse/schema.ts
@@ -0,0 +1,52 @@
+import { z } from 'zod';
+
+export const schema = z.object({
+ state: z
+ .enum([
+ '',
+ 'Unknown',
+ 'Unreleased',
+ 'Ongoing',
+ 'Requested',
+ 'Indexed',
+ 'Scraped',
+ 'Downloaded',
+ 'Symlinked',
+ 'Completed',
+ 'PartiallyCompleted',
+ 'Failed'
+ ])
+ .default(''),
+ type: z.enum(['movie', 'show', 'movie,show']).default('movie,show'),
+ sort: z.enum(['date_desc', 'date_asc', 'title_asc', 'title_desc']).default('date_desc')
+});
+
+export const states = {
+ '': 'Any State',
+ Unknown: 'Unknown',
+ Unreleased: 'Unreleased',
+ Ongoing: 'Ongoing',
+ Requested: 'Requested',
+ Indexed: 'Indexed',
+ Scraped: 'Scraped',
+ Downloaded: 'Downloaded',
+ Symlinked: 'Symlinked',
+ Completed: 'Completed',
+ PartiallyCompleted: 'Partially Completed',
+ Failed: 'Failed'
+};
+
+export const types = {
+ movie: 'Movies',
+ show: 'Shows',
+ 'movie,show': 'Movies & Shows'
+};
+
+export const sortOptions = {
+ date_desc: 'Date (Newest)',
+ date_asc: 'Date (Oldest)',
+ title_asc: 'Title (A-Z)',
+ title_desc: 'Title (Z-A)'
+};
+
+export type FormSchema = typeof schema;
diff --git a/src/routes/collection/[id]/+page.svelte b/src/routes/collection/[id]/+page.svelte
index b5b0b74..a1c7138 100644
--- a/src/routes/collection/[id]/+page.svelte
+++ b/src/routes/collection/[id]/+page.svelte
@@ -28,7 +28,7 @@
{#each data.details.parts as item}
- import type { PageData } from './$types';
- import { writable, type Writable } from 'svelte/store';
- import { page } from '$app/stores';
- import Header from '$lib/components/header.svelte';
- import MediaItem from '$lib/components/media-item.svelte';
- import * as Pagination from '$lib/components/ui/pagination';
- import { goto } from '$app/navigation';
- import { Input } from '$lib/components/ui/input';
- import * as Select from '$lib/components/ui/select/index.js';
- import { statesName } from '$lib/constants';
- import { Button } from '$lib/components/ui/button';
- import { onMount } from 'svelte';
-
- export let data: PageData;
-
- $: pageSize = writable(Number($page.url.searchParams.get('limit') || 24));
- $: totalDataItems = writable(Number($page.data.total));
- $: library = writable(data.library);
-
- $: limit = writable(Number($page.url.searchParams.get('limit')) || 24) as Writable
;
- $: query = writable($page.url.searchParams.get('query') || undefined) as Writable<
- string | undefined
- >;
- $: types = writable($page.url.searchParams.get('types') || undefined) as Writable<
- string | undefined
- >;
- $: states = writable($page.url.searchParams.get('states') || undefined) as Writable<
- string | undefined
- >;
-
- function submitQueries() {
- const queries = new URLSearchParams();
-
- if ($query) queries.set('query', $query);
- if ($limit) queries.set('limit', $limit.toString());
-
- if ($types) {
- queries.set('types', $types);
- }
-
- if ($states) {
- queries.set('states', $states);
- }
-
- goto(`?${queries.toString()}`, { replaceState: true });
- }
-
- function resetQueries() {
- $limit = 24;
- $query = undefined;
- $types = undefined;
- $states = undefined;
-
- goto(`?`, { replaceState: true });
- }
-
- onMount(() => {
- function handleKeydown(e: KeyboardEvent) {
- if (e.key === 'Enter') {
- e.preventDefault();
- submitQueries();
- }
- }
-
- document.addEventListener('keydown', handleKeydown);
- return () => {
- document.removeEventListener('keydown', handleKeydown);
- };
- });
-
-
-
- Library | Riven
-
-
-
-
-
-
-
- {
- $limit = Number(selected?.value);
- }}
- selected={{
- value: $limit,
- label: $limit?.toString() || 'Select limit'
- }}
- >
-
-
-
-
-
- {#each [12, 24, 48, 96] as limit}
- {limit}
- {/each}
-
-
-
- {
- $types = selected?.map((type) => type.value).join(',') || undefined;
- }}
- selected={($types || '')
- .split(',')
- .filter((type) => type.trim() !== '')
- .map((type) => ({
- value: type,
- label: type
- }))}
- multiple={true}
- >
-
-
-
-
-
- Movie
- Show
- Anime
-
-
-
- {
- $states = selected?.map((state) => state.value).join(',') || undefined;
- }}
- selected={($states || '')
- .split(',')
- .filter((state) => state.trim() !== '')
- .map((state) => ({
- value: state,
- label: statesName[state]
- }))}
- multiple={true}
- >
-
-
-
-
-
- {#each Object.keys(statesName) as state}
- {statesName[state]}
- {/each}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {#each $library as item (item.id)}
-
- {/each}
-
-
- {#if $totalDataItems > 0}
-
{
- const params = new URLSearchParams(window.location.search);
- params.set('page', page.toString());
- goto(`?${params.toString()}`, { replaceState: true });
- }}
- >
-
-
-
-
- {#each pages as page (page.key)}
- {#if page.type === 'ellipsis'}
-
-
-
- {:else}
-
-
- {page.value}
-
-
- {/if}
- {/each}
-
-
-
-
-
- {/if}
-
diff --git a/src/routes/library/+page.ts b/src/routes/library/+page.ts
deleted file mode 100644
index a357a2f..0000000
--- a/src/routes/library/+page.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { PageLoad } from './$types';
-import { ItemsService, type ItemsResponse } from '$lib/client';
-import { error } from '@sveltejs/kit';
-
-export const load: PageLoad = async ({ url }) => {
- async function getLibraryApi(): Promise {
- const limit = Number(url.searchParams.get('limit')) || 24;
- const page = Number(url.searchParams.get('page')) || 1;
- const types = url.searchParams.get('types');
- const query = url.searchParams.get('query');
- const states = url.searchParams.get('states');
-
- const { data, error: itemsError } = await ItemsService.getItems({
- query: {
- limit,
- page,
- states,
- type: types ?? 'movie,show',
- search: query,
- sort: 'date_desc'
- }
- });
-
- if (data) {
- return data;
- } else {
- console.log(itemsError);
- throw error(500, "Couldn't reach backend to get library items");
- }
- }
-
- const { items, total_items } = await getLibraryApi();
-
- return {
- library: items,
- total: total_items
- };
-};
diff --git a/src/routes/people/[id]/+page.svelte b/src/routes/people/[id]/+page.svelte
index ab3f747..21729b6 100644
--- a/src/routes/people/[id]/+page.svelte
+++ b/src/routes/people/[id]/+page.svelte
@@ -84,7 +84,7 @@