refactor: streamline character selection and improve rendering logic in +page.svelte

This commit is contained in:
2026-03-14 17:29:57 +01:00
parent fd83ac911a
commit 8b08950719

View File

@@ -15,13 +15,11 @@
let filterGender = $state('all'); let filterGender = $state('all');
let filterArc = $state('all'); let filterArc = $state('all');
let filterHaki = $state<'all' | 'observation' | 'armament' | 'conqueror' | 'none'>('all'); let filterHaki = $state<'all' | 'observation' | 'armament' | 'conqueror' | 'none'>('all');
let selectedCharacterId = $state<string | null>(null);
let isEditModalOpen = $state(false); let isEditModalOpen = $state(false);
let isSaving = $state(false); let isSaving = $state(false);
let saveMessage = $state<{ type: 'success' | 'error'; text: string } | null>(null); let saveMessage = $state<{ type: 'success' | 'error'; text: string } | null>(null);
let dailyModeToast = $state<{ type: 'success' | 'error'; text: string } | null>(null); let dailyModeToast = $state<{ type: 'success' | 'error'; text: string } | null>(null);
let selectedChar = $state<any>(null); let selectedChar = $state<any>(null);
let showOriginalValue = $state<Record<string, boolean>>({});
const showDailyModeToast = (type: 'success' | 'error', text: string) => { const showDailyModeToast = (type: 'success' | 'error', text: string) => {
dailyModeToast = { type, text }; dailyModeToast = { type, text };
@@ -38,12 +36,6 @@
} }
}; };
const getFandomUrl = (url: string | null | undefined) => {
if (!url) return null;
if (url.startsWith('http://') || url.startsWith('https://')) return url;
return `https://onepiece.fandom.com/fr/wiki/${url}`;
};
let editForm = $state<any>({ let editForm = $state<any>({
id: '', id: '',
name: '', name: '',
@@ -98,7 +90,6 @@
}; };
const openEditModal = (char: any) => { const openEditModal = (char: any) => {
selectedCharacterId = char.id;
selectedChar = char; selectedChar = char;
const override = char.override || {}; const override = char.override || {};
@@ -123,13 +114,11 @@
arcId: override.arcId !== null && override.arcId !== undefined ? override.arcId : (char.arcId || ''), arcId: override.arcId !== null && override.arcId !== undefined ? override.arcId : (char.arcId || ''),
status: override.status ?? '' status: override.status ?? ''
}; };
showOriginalValue = {};
isEditModalOpen = true; isEditModalOpen = true;
}; };
const closeModal = () => { const closeModal = () => {
isEditModalOpen = false; isEditModalOpen = false;
selectedCharacterId = null;
selectedChar = null; selectedChar = null;
editForm = { editForm = {
id: '', id: '',
@@ -179,6 +168,7 @@
}, 3000); }, 3000);
} }
} catch (error) { } catch (error) {
console.error('Error deleting character:', error);
saveMessage = { saveMessage = {
type: 'error', type: 'error',
text: 'Error deleting character' text: 'Error deleting character'
@@ -221,7 +211,7 @@
class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600" class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600"
> >
<option value="all">All Statuses</option> <option value="all">All Statuses</option>
{#each data.availableStatuses as status} {#each data.availableStatuses as status (status)}
<option value={status}>{status}</option> <option value={status}>{status}</option>
{/each} {/each}
</select> </select>
@@ -230,7 +220,7 @@
class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600" class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600"
> >
<option value="all">All Genders</option> <option value="all">All Genders</option>
{#each data.availableGenders as gender} {#each data.availableGenders as gender (gender)}
<option value={gender}>{gender}</option> <option value={gender}>{gender}</option>
{/each} {/each}
</select> </select>
@@ -239,8 +229,8 @@
class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600" class="rounded-lg bg-slate-700 px-4 py-2 text-sm text-white outline-none transition focus:ring-2 focus:ring-amber-600"
> >
<option value="all">All Arcs</option> <option value="all">All Arcs</option>
{#each data.arcs as arc} {#each data.arcs as arc (arc.id)}
<option value={String(arc.id)}>{arc.name}</option> <option value={arc.id}>{arc.name}</option>
{/each} {/each}
</select> </select>
<select <select
@@ -284,17 +274,17 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each filteredCharacters as char} {#each filteredCharacters as char (char.id)}
<tr class="border-b border-white/5 hover:bg-slate-800/50"> <tr class="border-b border-white/5 hover:bg-slate-800/50">
<!-- Character --> <!-- Character -->
<td class="px-4 py-4 text-sm text-white w-64 max-w-64 {isFieldOverridden(char, 'name') || isFieldOverridden(char, 'pictureUrl') ? 'bg-amber-500/10' : ''}"> <td class="px-4 py-4 text-sm text-white w-64 max-w-64 {isFieldOverridden(char, 'name') || isFieldOverridden(char, 'pictureUrl') ? 'bg-amber-500/10' : ''}">
<div class="flex items-center gap-3 min-w-0"> <div class="flex items-center gap-3 min-w-0">
{#if getFandomUrl(char.displayValues.url)} {#if char.displayValues.url}
<a <a
href={getFandomUrl(char.displayValues.url)} href={"https://onepiece.fandom.com/fr/wiki/" + char.displayValues.url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex-shrink-0 transition-opacity hover:opacity-80" class="shrink-0 transition-opacity hover:opacity-80"
> >
{#if char.displayValues.pictureUrl} {#if char.displayValues.pictureUrl}
<img <img
@@ -315,18 +305,18 @@
src={char.displayValues.pictureUrl} src={char.displayValues.pictureUrl}
alt={char.displayValues.name} alt={char.displayValues.name}
loading="lazy" loading="lazy"
class="h-10 w-10 flex-shrink-0 rounded-full object-cover" class="h-10 w-10 shrink-0 rounded-full object-cover"
/> />
{:else} {:else}
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-slate-700 text-gray-400"> <div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-slate-700 text-gray-400">
{char.displayValues.name?.charAt(0).toUpperCase() || '?'} {char.displayValues.name?.charAt(0).toUpperCase() || '?'}
</div> </div>
{/if} {/if}
{/if} {/if}
<div class="flex flex-col min-w-0"> <div class="flex flex-col min-w-0">
{#if getFandomUrl(char.displayValues.url)} {#if char.displayValues.url}
<a <a
href={getFandomUrl(char.displayValues.url)} href="https://onepiece.fandom.com/fr/wiki/${char.displayValues.url}"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="font-medium truncate text-white hover:text-amber-200 hover:underline" class="font-medium truncate text-white hover:text-amber-200 hover:underline"
@@ -461,7 +451,7 @@
{/if} {/if}
{#if dailyModeToast} {#if dailyModeToast}
<div class="fixed right-6 top-6 z-[60]"> <div class="fixed right-6 top-6 z-60">
<div <div
class={`rounded-lg border px-4 py-3 text-sm font-medium shadow-lg backdrop-blur ${ class={`rounded-lg border px-4 py-3 text-sm font-medium shadow-lg backdrop-blur ${
dailyModeToast.type === 'success' dailyModeToast.type === 'success'
@@ -628,7 +618,7 @@
class="w-full rounded-lg border border-gray-500 bg-slate-800 px-3 py-2 text-white" class="w-full rounded-lg border border-gray-500 bg-slate-800 px-3 py-2 text-white"
> >
<option value="">None</option> <option value="">None</option>
{#each data.arcs as arc} {#each data.arcs as arc (arc.id)}
<option value={arc.id}>{arc.name}</option> <option value={arc.id}>{arc.name}</option>
{/each} {/each}
</select> </select>
@@ -651,7 +641,7 @@
class="w-full rounded-lg border border-gray-500 bg-slate-800 px-3 py-2 text-white" class="w-full rounded-lg border border-gray-500 bg-slate-800 px-3 py-2 text-white"
> >
<option value="">None</option> <option value="">None</option>
{#each data.devilFruits as fruit} {#each data.devilFruits as fruit (fruit.id)}
<option value={fruit.id}>{fruit.name}</option> <option value={fruit.id}>{fruit.name}</option>
{/each} {/each}
</select> </select>