feat: refactor WinPanel to use selectedCharacter prop for improved clarity and consistency
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
export let dailyCharacter: any;
|
||||
export let selectedCharacter: any;
|
||||
export let selectedCharacters: any[];
|
||||
export let isGeckoMoriaWin: boolean = false;
|
||||
|
||||
@@ -49,21 +49,21 @@
|
||||
<p class="text-sm text-slate-400">Vous avez succombé à l'ombre en {selectedCharacters.length} {selectedCharacters.length > 1 ? 'tentatives' : 'tentative'} !</p>
|
||||
<p class="text-xs text-slate-300 mt-1">{attemptMessage}</p>
|
||||
<div class="mt-3">
|
||||
{#if dailyCharacter.pictureUrl}
|
||||
{#if selectedCharacter.pictureUrl}
|
||||
<a
|
||||
href={"https://onepiece.fandom.com/fr/wiki/" + dailyCharacter.url}
|
||||
href={"https://onepiece.fandom.com/fr/wiki/" + selectedCharacter.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-block"
|
||||
>
|
||||
<img
|
||||
src={dailyCharacter.pictureUrl}
|
||||
alt={dailyCharacter.name}
|
||||
src={selectedCharacter.pictureUrl}
|
||||
alt={selectedCharacter.name}
|
||||
class="w-20 h-20 mx-auto rounded-full border-2 border-slate-600 shadow-lg object-cover hover:border-slate-500 transition-colors cursor-pointer opacity-80"
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
<p class="mt-2 text-lg font-bold text-slate-200">{dailyCharacter.name}</p>
|
||||
<p class="mt-2 text-lg font-bold text-slate-200">{selectedCharacter.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,21 +75,21 @@
|
||||
<p class="text-sm text-emerald-300">Vous avez trouvé le personnage en {selectedCharacters.length} {selectedCharacters.length > 1 ? 'tentatives' : 'tentative'} !</p>
|
||||
<p class="text-xs text-emerald-200 mt-1">{attemptMessage}</p>
|
||||
<div class="mt-3">
|
||||
{#if dailyCharacter.pictureUrl}
|
||||
{#if selectedCharacter.pictureUrl}
|
||||
<a
|
||||
href={"https://onepiece.fandom.com/fr/wiki/" + dailyCharacter.url}
|
||||
href={"https://onepiece.fandom.com/fr/wiki/" + selectedCharacter.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-block"
|
||||
>
|
||||
<img
|
||||
src={dailyCharacter.pictureUrl}
|
||||
alt={dailyCharacter.name}
|
||||
src={selectedCharacter.pictureUrl}
|
||||
alt={selectedCharacter.name}
|
||||
class="w-20 h-20 mx-auto rounded-full border-2 border-emerald-400 shadow-lg object-cover hover:border-emerald-300 transition-colors cursor-pointer"
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
<p class="mt-2 text-lg font-bold text-white">{dailyCharacter.name}</p>
|
||||
<p class="mt-2 text-lg font-bold text-white">{selectedCharacter.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
|
||||
{#if hasWon}
|
||||
<WinPanel
|
||||
{dailyCharacter}
|
||||
selectedCharacter={dailyCharacter}
|
||||
{selectedCharacters}
|
||||
{isGeckoMoriaWin}
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { formatBounty } from '$lib';
|
||||
import CharacterSearchInput from '$lib/components/CharacterSearchInput.svelte';
|
||||
import GuessHistoryTable from '$lib/components/GuessHistoryTable.svelte';
|
||||
import WinPanel from '$lib/components/WinPanel.svelte';
|
||||
import HintsPanel from '$lib/components/HintsPanel.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -29,6 +30,7 @@
|
||||
let showOriginUnlock = false;
|
||||
let showFruitUnlock = false;
|
||||
let showAffiliationUnlock = false;
|
||||
let isGeckoMoriaWin = false;
|
||||
|
||||
// Load from localStorage on mount
|
||||
onMount(() => {
|
||||
@@ -104,6 +106,11 @@
|
||||
|
||||
$: characters = data.characters || [];
|
||||
$: hasWon = currentCharacter && selectedCharacters.some(char => char.id === currentCharacter.id);
|
||||
$: if (hasWon && currentCharacter?.id === 'gecko_moria_gecko_moria') {
|
||||
isGeckoMoriaWin = true;
|
||||
} else if (!hasWon) {
|
||||
isGeckoMoriaWin = false;
|
||||
}
|
||||
|
||||
// Hint availability tracking for unlock animations
|
||||
$: isOriginAvailable = selectedCharacters.length >= 5;
|
||||
@@ -193,11 +200,56 @@
|
||||
.gecko-moria-effect {
|
||||
animation: shadow-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
@keyframes moria-chaos {
|
||||
0% {
|
||||
transform: rotate(0deg) scale(1);
|
||||
filter: invert(0%) hue-rotate(0deg) blur(0px);
|
||||
}
|
||||
10% {
|
||||
transform: rotate(15deg) scale(1.02);
|
||||
filter: invert(30%) hue-rotate(45deg) blur(2px);
|
||||
}
|
||||
20% {
|
||||
transform: rotate(-10deg) scale(0.98);
|
||||
filter: invert(60%) hue-rotate(90deg) blur(1px);
|
||||
}
|
||||
30% {
|
||||
transform: rotate(25deg) scale(1.05);
|
||||
filter: invert(100%) hue-rotate(180deg) blur(3px);
|
||||
}
|
||||
40% {
|
||||
transform: rotate(-20deg) scale(0.95);
|
||||
filter: invert(80%) hue-rotate(270deg) blur(2px);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(30deg) scale(1.08);
|
||||
filter: invert(100%) hue-rotate(0deg) blur(4px);
|
||||
}
|
||||
60% {
|
||||
transform: rotate(-25deg) scale(0.92);
|
||||
filter: invert(70%) hue-rotate(90deg) blur(2px);
|
||||
}
|
||||
70% {
|
||||
transform: rotate(20deg) scale(1.03);
|
||||
filter: invert(50%) hue-rotate(180deg) blur(3px);
|
||||
}
|
||||
80% {
|
||||
transform: rotate(-15deg) scale(1.01);
|
||||
filter: invert(80%) hue-rotate(270deg) blur(1px);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg) scale(1);
|
||||
filter: invert(0%) hue-rotate(360deg) blur(0px);
|
||||
}
|
||||
}
|
||||
.moria-screen-chaos {
|
||||
animation: moria-chaos 4s ease-in-out;
|
||||
}
|
||||
</style>
|
||||
</svelte:head>
|
||||
|
||||
<main
|
||||
class="relative min-h-screen overflow-hidden bg-slate-950 text-slate-100"
|
||||
class="relative min-h-screen overflow-hidden bg-slate-950 text-slate-100 {isGeckoMoriaWin ? 'moria-screen-chaos' : ''}"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-slate-950/85 via-slate-900/60 to-slate-950/80"></div>
|
||||
<div
|
||||
@@ -231,125 +283,30 @@
|
||||
<section class="mt-10 grid gap-6">
|
||||
{#if currentCharacter}
|
||||
{#if hasWon}
|
||||
<div
|
||||
class="rounded-3xl border border-emerald-500/50 bg-emerald-500/10 p-4 shadow-[0_24px_60px_rgba(16,185,129,0.3)] backdrop-blur"
|
||||
>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl mb-2">🎉</div>
|
||||
<h2 class="text-xl font-bold text-emerald-400 mb-1">Bien joué !</h2>
|
||||
<p class="text-sm text-emerald-300">
|
||||
Vous avez trouvé le personnage en {selectedCharacters.length}
|
||||
{selectedCharacters.length > 1 ? 'tentatives' : 'tentative'} !
|
||||
</p>
|
||||
<div class="mt-3">
|
||||
{#if currentCharacter.pictureUrl}
|
||||
<a
|
||||
href={'https://onepiece.fandom.com/fr/wiki/' + currentCharacter.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-block"
|
||||
>
|
||||
<img
|
||||
src={currentCharacter.pictureUrl}
|
||||
alt={currentCharacter.name}
|
||||
class="w-20 h-20 mx-auto rounded-full border-2 border-emerald-400 shadow-lg object-cover hover:border-emerald-300 transition-colors cursor-pointer"
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
<p class="mt-2 text-lg font-bold text-white">{currentCharacter.name}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={nextCharacter}
|
||||
class="mt-4 rounded-full bg-emerald-500 px-6 py-2 text-sm font-semibold text-white transition hover:bg-emerald-600"
|
||||
>
|
||||
Recommencer
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<WinPanel
|
||||
selectedCharacter={currentCharacter}
|
||||
{selectedCharacters}
|
||||
{isGeckoMoriaWin}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onclick={nextCharacter}
|
||||
class="mt-4 w-full rounded-full bg-emerald-500 px-6 py-2 text-sm font-semibold text-white transition hover:bg-emerald-600"
|
||||
>
|
||||
Recommencer
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="rounded-3xl border border-white/10 bg-white/5 p-6 shadow-[0_24px_60px_rgba(0,0,0,0.45)] backdrop-blur"
|
||||
>
|
||||
<div class="grid gap-3 sm:grid-cols-3">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-2xl border border-white/10 px-3 py-3 flex flex-col items-center justify-center cursor-pointer hover:bg-slate-900/80 transition-colors {isOriginAvailable
|
||||
? 'bg-slate-950/60'
|
||||
: 'bg-slate-950/30 opacity-50 cursor-not-allowed hover:bg-slate-950/30'} {showOriginUnlock
|
||||
? 'hint-unlocking'
|
||||
: ''}"
|
||||
disabled={!isOriginAvailable}
|
||||
onclick={() => (showOriginUnlock = !showOriginUnlock)}
|
||||
>
|
||||
<p class="text-sm font-medium text-amber-100">Origine</p>
|
||||
{#if showOriginUnlock}
|
||||
<p class="mt-2 text-xs text-white font-semibold">
|
||||
{currentCharacter.origin || 'Inconnue'}
|
||||
</p>
|
||||
{:else if Math.max(0, 5 - selectedCharacters.length) > 0}
|
||||
<p class="mt-2 text-xs text-slate-400">
|
||||
{Math.max(0, 5 - selectedCharacters.length)} essais avant déblocage
|
||||
</p>
|
||||
{:else}
|
||||
<p class="mt-2 text-xs text-slate-400">Indice disponible !</p>
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-2xl border border-white/10 px-3 py-3 flex flex-col items-center justify-center cursor-pointer hover:bg-slate-900/80 transition-colors {isFruitAvailable
|
||||
? 'bg-slate-950/60'
|
||||
: 'bg-slate-950/30 opacity-50 cursor-not-allowed hover:bg-slate-950/30'} {showFruitUnlock
|
||||
? 'hint-unlocking'
|
||||
: ''}"
|
||||
disabled={!isFruitAvailable}
|
||||
onclick={() => (showFruitUnlock = !showFruitUnlock)}
|
||||
>
|
||||
<p class="text-sm font-medium text-amber-100">Fruit du démon</p>
|
||||
{#if showFruitUnlock}
|
||||
<p class="mt-2 text-xs text-white font-semibold">
|
||||
{currentCharacter.devilFruitName || 'Aucun'}
|
||||
</p>
|
||||
{:else if Math.max(0, 10 - selectedCharacters.length) > 0}
|
||||
<p class="mt-2 text-xs text-slate-400">
|
||||
{Math.max(0, 10 - selectedCharacters.length)} essais avant déblocage
|
||||
</p>
|
||||
{:else}
|
||||
<p class="mt-2 text-xs text-slate-400">Indice disponible !</p>
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-2xl border border-white/10 px-3 py-3 flex flex-col items-center justify-center cursor-pointer hover:bg-slate-900/80 transition-colors {isAffiliationAvailable
|
||||
? 'bg-slate-950/60'
|
||||
: 'bg-slate-950/30 opacity-50 cursor-not-allowed hover:bg-slate-950/30'} {showAffiliationUnlock
|
||||
? 'hint-unlocking'
|
||||
: ''}"
|
||||
disabled={!isAffiliationAvailable}
|
||||
onclick={() => (showAffiliationUnlock = !showAffiliationUnlock)}
|
||||
>
|
||||
<p class="text-sm font-medium text-amber-100">Affiliation</p>
|
||||
{#if showAffiliationUnlock}
|
||||
{@const affiliations = typeof currentCharacter.affiliations === 'string'
|
||||
? currentCharacter.affiliations.includes('[')
|
||||
? JSON.parse(currentCharacter.affiliations)
|
||||
: currentCharacter.affiliations
|
||||
.split(',')
|
||||
.map((a: string) => a.trim())
|
||||
: currentCharacter.affiliations}
|
||||
<p class="mt-2 text-xs text-white font-semibold">
|
||||
{Array.isArray(affiliations) ? affiliations[0] : affiliations || 'Inconnue'}
|
||||
</p>
|
||||
{:else if Math.max(0, 15 - selectedCharacters.length) > 0}
|
||||
<p class="mt-2 text-xs text-slate-400">
|
||||
{Math.max(0, 15 - selectedCharacters.length)} essais avant déblocage
|
||||
</p>
|
||||
{:else}
|
||||
<p class="mt-2 text-xs text-slate-400">Indice disponible !</p>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{#if selectedCharacters.length > 0}
|
||||
<HintsPanel
|
||||
dailyCharacter={currentCharacter}
|
||||
{selectedCharacters}
|
||||
{showOriginUnlock}
|
||||
{showFruitUnlock}
|
||||
{showAffiliationUnlock}
|
||||
/>
|
||||
{/if}
|
||||
<CharacterSearchInput
|
||||
{characters}
|
||||
{selectedCharacters}
|
||||
|
||||
Reference in New Issue
Block a user