refactor: streamline character selection and improve rendering logic in +page.svelte
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user