diff --git a/web/src/lib/components/download-season-dialog.svelte b/web/src/lib/components/download-season-dialog.svelte
index e4aa01f..8365312 100644
--- a/web/src/lib/components/download-season-dialog.svelte
+++ b/web/src/lib/components/download-season-dialog.svelte
@@ -7,9 +7,14 @@
import type {PublicIndexerQueryResult} from '$lib/types.js';
import {convertTorrentSeasonRangeToIntegerRange, getFullyQualifiedShowName} from '$lib/utils';
+ import {LoaderCircle} from "lucide-svelte";
+ import * as Dialog from '$lib/components/ui/dialog/index.js';
+ import * as Tabs from '$lib/components/ui/tabs/index.js';
+ import * as Select from '$lib/components/ui/select/index.js';
+ import * as Table from '$lib/components/ui/table/index.js';
let {show} = $props();
-
+ let dialogueState = $state(false);
let selectedSeasonNumber: number = $state(1);
let torrents: PublicIndexerQueryResult[] = $state([]);
let isLoadingTorrents: boolean = $state(false);
@@ -83,24 +88,27 @@
const errorMessage = `Failed to fetch torrents for show ${show.id} and season ${selectedSeasonNumber}: ${response.statusText}`;
console.error(errorMessage);
torrentsError = errorMessage;
- toast.error(errorMessage);
+ if (dialogueState)
+ toast.error(errorMessage);
return [];
}
const data: PublicIndexerQueryResult[] = await response.json();
console.log('Fetched torrents:', data);
- if (data.length > 0) {
- toast.success(`Found ${data.length} torrents.`);
- } else {
- toast.info('No torrents found for your query.');
+ if (dialogueState) {
+ if (data.length > 0) {
+ toast.success(`Found ${data.length} torrents.`);
+ } else {
+ toast.info('No torrents found for your query.');
+ }
}
-
return data;
} catch (err) {
const errorMessage = `Error fetching torrents: ${err instanceof Error ? err.message : 'An unknown error occurred'}`;
console.error(errorMessage);
torrentsError = errorMessage;
- toast.error(errorMessage);
+ if (dialogueState)
+ toast.error(errorMessage);
return [];
} finally {
isLoadingTorrents = false;
@@ -128,7 +136,7 @@
: ' - ' + filePathSuffix}.mkv
{/snippet}
-
+
Download Seasons
@@ -283,6 +291,7 @@
{/each}
+ {torrent.seasons}
{convertTorrentSeasonRangeToIntegerRange(torrent)}
diff --git a/web/src/lib/components/login-form.svelte b/web/src/lib/components/login-form.svelte
index 6fd9c76..a56d91c 100644
--- a/web/src/lib/components/login-form.svelte
+++ b/web/src/lib/components/login-form.svelte
@@ -6,6 +6,7 @@
import {goto} from '$app/navigation';
import {env} from '$env/dynamic/public';
import * as Tabs from "$lib/components/ui/tabs/index.js";
+ import {toast} from 'svelte-sonner';
let apiUrl = env.PUBLIC_API_URL;
@@ -37,8 +38,9 @@
if (response.ok) {
console.log('Login successful!');
console.log('Received User Data: ', response);
- goto('/dashboard');
errorMessage = 'Login successful! Redirecting...';
+ toast.success(errorMessage);
+ goto('/dashboard');
} else {
let errorText = await response.text();
try {
@@ -47,11 +49,13 @@
} catch {
errorMessage = errorText || 'Login failed. Please check your credentials.';
}
+ toast.error(errorMessage);
console.error('Login failed:', response.status, errorText);
}
} catch (error) {
console.error('Login request failed:', error);
errorMessage = 'An error occurred during the login request.';
+ toast.error(errorMessage);
} finally {
isLoading = false;
}
@@ -81,7 +85,8 @@
console.log('Registration successful!');
console.log('Received User Data: ', response);
tabValue = "login"; // Switch to login tab after successful registration
- errorMessage = 'Registration successful! Redirecting...';
+ errorMessage = 'Registration successful! Please login.';
+ toast.success(errorMessage);
} else {
let errorText = await response.text();
try {
@@ -90,11 +95,13 @@
} catch {
errorMessage = errorText || 'Registration failed. Please check your credentials.';
}
+ toast.error(errorMessage);
console.error('Registration failed:', response.status, errorText);
}
} catch (error) {
console.error('Registration request failed:', error);
errorMessage = 'An error occurred during the Registration request.';
+ toast.error(errorMessage);
} finally {
isLoading = false;
}
diff --git a/web/src/lib/components/season-requests-table.svelte b/web/src/lib/components/season-requests-table.svelte
index 51cad49..e21b58c 100644
--- a/web/src/lib/components/season-requests-table.svelte
+++ b/web/src/lib/components/season-requests-table.svelte
@@ -35,13 +35,15 @@
requests[requestIndex].authorized = !currentAuthorizedStatus;
requests[requestIndex].authorized_by = user();
}
+ toast.success(`Request ${!currentAuthorizedStatus ? 'approved' : 'unapproved'} successfully.`);
} else {
- console.error(`Failed to update request status ${response.statusText}`, await response.text());
- // Optionally, add user-facing error handling here
+ const errorText = await response.text();
+ console.error(`Failed to update request status ${response.statusText}`, errorText);
+ toast.error(`Failed to update request status: ${response.statusText}`);
}
} catch (error) {
console.error('Error updating request status:', error);
- // Optionally, add user-facing error handling here
+ toast.error('Error updating request status: ' + (error instanceof Error ? error.message : String(error)));
}
}
diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts
index 59f1fad..e7b36d9 100644
--- a/web/src/lib/utils.ts
+++ b/web/src/lib/utils.ts
@@ -41,8 +41,8 @@ export function getFullyQualifiedShowName(show: { name: string; year: number }):
}
export function convertTorrentSeasonRangeToIntegerRange(torrent: any): string {
- if (torrent.seasons.length === 1) return torrent.seasons[0]?.toString();
- if (torrent.seasons.length >= 2) return torrent.seasons[0]?.toString() + "-" + torrent.seasons.at(-1).toString();
+ if (torrent.season?.length === 1) return torrent.season[0]?.toString();
+ if (torrent.season?.length >= 2) return torrent.season[0]?.toString() + "-" + torrent.season.at(-1).toString();
else {
console.log("Error parsing season range: " + torrent.seasons);
return "Error parsing season range: " + torrent.seasons;
@@ -50,7 +50,7 @@ export function convertTorrentSeasonRangeToIntegerRange(torrent: any): string {
}
-export async function handleLogout(): null {
+export async function handleLogout() {
const response = await fetch(apiUrl + '/auth/cookie/logout', {
method: 'POST',
credentials: 'include'
@@ -63,5 +63,4 @@ export async function handleLogout(): null {
console.error('Logout failed:', response.status);
toast.error('Logout failed: ' + response.status);
}
-}
-
+}
\ No newline at end of file
diff --git a/web/src/routes/dashboard/+layout.svelte b/web/src/routes/dashboard/+layout.svelte
index d9e1ff9..aa12dc9 100644
--- a/web/src/routes/dashboard/+layout.svelte
+++ b/web/src/routes/dashboard/+layout.svelte
@@ -5,10 +5,12 @@
import {setContext} from 'svelte';
import {goto} from '$app/navigation';
import {base} from "$app/paths";
+ import {toast} from "svelte-sonner";
let {data, children}: LayoutProps = $props();
console.log('Received User Data: ', data.user);
if (!data.user.is_verified) {
+ toast.info("Your account requires verification. Redirecting...");
goto(base + '/login/verify')
}
setContext('user', () => data.user);
diff --git a/web/src/routes/dashboard/tv/[showId=uuid]/+page.svelte b/web/src/routes/dashboard/tv/[showId=uuid]/+page.svelte
index 071d9af..c218425 100644
--- a/web/src/routes/dashboard/tv/[showId=uuid]/+page.svelte
+++ b/web/src/routes/dashboard/tv/[showId=uuid]/+page.svelte
@@ -71,9 +71,9 @@
{show().overview}
-
+
{#if user().is_superuser}
-
+
{/if}
diff --git a/web/src/routes/dashboard/tv/add-show/+page.svelte b/web/src/routes/dashboard/tv/add-show/+page.svelte
index 22d7d20..7142835 100644
--- a/web/src/routes/dashboard/tv/add-show/+page.svelte
+++ b/web/src/routes/dashboard/tv/add-show/+page.svelte
@@ -14,6 +14,7 @@
import {goto} from '$app/navigation';
import {base} from '$app/paths';
import AddShowCard from '$lib/components/add-show-card.svelte';
+ import {toast} from 'svelte-sonner';
let searchTerm: string = $state('');
let metadataProvider: string = $state('tmdb');
@@ -26,12 +27,30 @@
let url = new URL(env.PUBLIC_API_URL + '/tv/search');
url.searchParams.append('query', searchTerm);
url.searchParams.append('metadata_provider', metadataProvider);
- const response = await fetch(url, {
- method: 'GET',
- credentials: 'include'
- });
- results = await response.json();
+ toast.info(`Searching for "${searchTerm}" using ${metadataProvider.toUpperCase()}...`);
+ try {
+ const response = await fetch(url, {
+ method: 'GET',
+ credentials: 'include'
+ });
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Search failed: ${response.status} ${errorText || response.statusText}`);
+ }
+ results = await response.json();
+ if (results && results.length > 0) {
+ toast.success(`Found ${results.length} result(s) for "${searchTerm}".`);
+ } else {
+ toast.info(`No results found for "${searchTerm}".`);
+ }
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred during search.';
+ console.error('Search error:', error);
+ toast.error(errorMessage);
+ results = null; // Clear previous results on error
+ }
} else {
+ toast.warning('Please enter a search term.');
results = null;
}
}