feat: enhance user feedback with toast notifications for various actions and errors

This commit is contained in:
maxDorninger
2025-05-24 20:58:54 +02:00
parent 6513065ba8
commit 0ea500bacd
7 changed files with 64 additions and 26 deletions

View File

@@ -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}
<Dialog.Root>
<Dialog.Root bind:open={dialogueState}>
<Dialog.Trigger class={buttonVariants({ variant: 'default' })}
>Download Seasons
</Dialog.Trigger>
@@ -283,6 +291,7 @@
{/each}
</Table.Cell>
<Table.Cell>
{torrent.seasons}
{convertTorrentSeasonRangeToIntegerRange(torrent)}
</Table.Cell>
<Table.Cell class="text-right">

View File

@@ -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;
}

View File

@@ -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)));
}
}

View File

@@ -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);
}
}
}