Skip to content

Commit 5034eee

Browse files
committed
Tutor FIX
1 parent 0a7e805 commit 5034eee

File tree

3 files changed

+204
-116
lines changed

3 files changed

+204
-116
lines changed

src/App.css

Lines changed: 120 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10271,35 +10271,134 @@ body.modal-open .collection-container-modern {
1027110271
}
1027210272

1027310273
.elemental-card-modern {
10274-
background: rgba(255, 255, 255, 0.05);
10274+
background: transparent;
10275+
border: none;
10276+
padding: 0;
10277+
width: 160px;
10278+
height: 220px;
10279+
display: flex;
10280+
flex-direction: column;
10281+
cursor: pointer;
10282+
position: relative;
10283+
pointer-events: auto;
10284+
}
10285+
10286+
.elemental-card-modern.on-cooldown {
10287+
cursor: default;
10288+
pointer-events: none;
10289+
opacity: 0.7;
10290+
}
10291+
10292+
.elemental-battle-card {
10293+
width: 100%;
10294+
height: 100%;
10295+
background: linear-gradient(145deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.4));
1027510296
border-radius: 16px;
10276-
padding: 0.75rem;
10277-
border: 2px solid var(--rarity-color, rgba(255, 255, 255, 0.1));
10278-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
10279-
backdrop-filter: blur(20px);
10280-
transition: all 0.3s ease;
10297+
border: 2px solid var(--rarity-color, rgba(255, 255, 255, 0.3));
10298+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
1028110299
position: relative;
1028210300
overflow: hidden;
10283-
width: 274px !important;
10284-
height: 274px !important;
10285-
min-width: 274px !important;
10286-
max-width: 274px !important;
10287-
min-height: 274px !important;
10288-
max-height: 274px !important;
10289-
margin-bottom: 20rem;
10290-
flex-shrink: 0;
10291-
flex-grow: 0;
10301+
display: flex;
10302+
flex-direction: column;
1029210303
}
1029310304

10294-
.elemental-card-modern::before {
10295-
content: '';
10305+
.elemental-battle-image {
10306+
width: 100%;
10307+
height: 100%;
10308+
object-fit: cover;
10309+
border-radius: 16px;
1029610310
position: absolute;
1029710311
top: 0;
1029810312
left: 0;
10299-
right: 0;
10300-
height: 3px;
10301-
background: linear-gradient(90deg, var(--rarity-color), var(--rarity-glow));
10302-
border-radius: 20px 20px 0 0;
10313+
}
10314+
10315+
.elemental-battle-placeholder {
10316+
width: 100%;
10317+
height: 100%;
10318+
display: flex;
10319+
align-items: center;
10320+
justify-content: center;
10321+
font-size: 4rem;
10322+
background: linear-gradient(145deg, rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.3));
10323+
border-radius: 16px;
10324+
position: absolute;
10325+
top: 0;
10326+
left: 0;
10327+
}
10328+
10329+
.elemental-battle-rarity {
10330+
position: absolute;
10331+
bottom: 8px;
10332+
left: 50%;
10333+
transform: translateX(-50%);
10334+
background: var(--rarity-color);
10335+
color: white;
10336+
padding: 4px 12px;
10337+
border-radius: 12px;
10338+
font-size: 0.7rem;
10339+
font-weight: 700;
10340+
text-transform: uppercase;
10341+
letter-spacing: 0.5px;
10342+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
10343+
z-index: 2;
10344+
}
10345+
10346+
.cooldown-overlay-modern {
10347+
position: absolute;
10348+
top: 8px;
10349+
left: 50%;
10350+
transform: translateX(-50%);
10351+
background: rgba(255, 255, 255, 0.5);
10352+
border: 1px solid rgba(255, 215, 0, 0.8);
10353+
border-radius: 8px;
10354+
padding: 6px 8px;
10355+
z-index: 10000;
10356+
box-shadow: 0 4px 16px rgba(255, 215, 0, 0.3);
10357+
backdrop-filter: blur(5px);
10358+
min-width: 80px;
10359+
text-align: center;
10360+
}
10361+
10362+
.cooldown-timer-modern {
10363+
display: flex;
10364+
align-items: center;
10365+
justify-content: center;
10366+
gap: 4px;
10367+
}
10368+
10369+
.cooldown-time-unit {
10370+
display: flex;
10371+
flex-direction: column;
10372+
align-items: center;
10373+
min-width: 16px;
10374+
}
10375+
10376+
.time-value {
10377+
color: #ff6b6b;
10378+
font-size: 0.8rem;
10379+
font-weight: 900;
10380+
text-shadow: 0 0 8px rgba(255, 107, 107, 0.8);
10381+
font-family: 'Courier New', monospace;
10382+
line-height: 1;
10383+
letter-spacing: 1px;
10384+
}
10385+
10386+
.time-label {
10387+
color: rgba(255, 255, 255, 0.8);
10388+
font-size: 0.7rem;
10389+
font-weight: 600;
10390+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
10391+
margin-top: 2px;
10392+
}
10393+
10394+
.cooldown-separator {
10395+
color: rgba(255, 107, 107, 0.8);
10396+
font-size: 0.8rem;
10397+
font-weight: 900;
10398+
text-shadow: 0 0 8px rgba(255, 107, 107, 0.8);
10399+
margin: 0 2px;
10400+
animation: pulse 1s ease-in-out infinite;
10401+
font-family: 'Courier New', monospace;
1030310402
}
1030410403

1030510404
.elemental-card-modern:hover {

src/App.tsx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -178,30 +178,8 @@ const App: React.FC = () => {
178178
);
179179
}, [hasSeenBattleTutorial, hasSeenCollectionTutorial]);
180180

181-
// Auto-show tutorial for new users
182-
useEffect(() => {
183-
if (
184-
activeTab === 'battle' &&
185-
!hasSeenBattleTutorial &&
186-
gameState.gamePhase === 'menu'
187-
) {
188-
const timer = setTimeout(() => {
189-
setShowBattleTutorial(true);
190-
}, 5000); // Show after 5 second delay (after loading screen)
191-
return () => clearTimeout(timer);
192-
}
193-
return undefined;
194-
}, [activeTab, hasSeenBattleTutorial, gameState.gamePhase]);
195-
196-
useEffect(() => {
197-
if (activeTab === 'collection' && !hasSeenCollectionTutorial) {
198-
const timer = setTimeout(() => {
199-
setShowCollectionTutorial(true);
200-
}, 500); // Show after 0.5 second delay
201-
return () => clearTimeout(timer);
202-
}
203-
return undefined;
204-
}, [activeTab, hasSeenCollectionTutorial]);
181+
// Tutorials are now only shown manually via settings buttons
182+
// Auto-show has been disabled to prevent repeated tutorials
205183

206184
// Manage modal-open class for rules page
207185
useEffect(() => {

src/components/BattleComponent.tsx

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,10 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
287287
player.mana,
288288
key as Location
289289
);
290-
const isSelected = player.selectedLocation === key;
291-
const isFocused = focusedIndex === index;
290+
// Don't show persistent selection, only during tutorial or on hover
291+
const isSelected = false;
292+
// Don't show focus effects during normal gameplay
293+
const isFocused = false;
292294

293295
return (
294296
<button
@@ -454,8 +456,10 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
454456

455457
<div className='element-grid' role='group' aria-label='Battle elements'>
456458
{elements.map(([key, element], index) => {
457-
const isSelected = player.selectedElement === key;
458-
const isFocused = focusedIndex === index;
459+
// Don't show persistent selection, only during tutorial or on hover
460+
const isSelected = false;
461+
// Don't show focus effects during normal gameplay
462+
const isFocused = false;
459463

460464
return (
461465
<button
@@ -645,7 +649,8 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
645649
selectedElement,
646650
elemental.rarity
647651
);
648-
const isSelected = player.selectedElemental === elemental.rarity;
652+
// Don't show persistent selection, only during tutorial or on hover
653+
const isSelected = false;
649654
// Use static cooldown snapshot during elemental selection to prevent re-renders
650655
const isOnCooldown = gamePhase === 'elementalSelection'
651656
? (staticCooldownSnapshot[elemental.id] ?? false)
@@ -657,7 +662,8 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
657662
const cooldownText = gamePhase === 'elementalSelection'
658663
? '' // Don't show dynamic cooldown text during selection
659664
: formatCooldownTime(cooldownRemaining);
660-
const isFocused = focusedIndex === index;
665+
// Don't show focus effects during normal gameplay
666+
const isFocused = false;
661667
const protection = Math.round(elementalData.protection * 100);
662668

663669
// Force re-render for real-time cooldown updates (only outside elemental selection)
@@ -668,13 +674,16 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
668674
return (
669675
<button
670676
key={elemental.id}
671-
className={`elemental-btn ${elemental.rarity} ${isSelected ? 'selected' : ''} ${isOnCooldown ? 'on-cooldown' : ''} ${isFocused ? 'focused' : ''}`}
677+
className={`elemental-card-modern ${elemental.rarity} ${isSelected ? 'selected' : ''} ${isOnCooldown ? 'on-cooldown' : ''} ${isFocused ? 'focused' : ''}`}
672678
data-elemental={elemental.rarity}
673679
onClick={() => {
674680
// Allow clicks during tutorial even if on cooldown
675681
if (!isOnCooldown || showFocusOutlines) {
676682
onSelectElemental(elemental.rarity);
677-
onStartBattle();
683+
// Auto-proceed to battle after selection
684+
setTimeout(() => {
685+
onStartBattle();
686+
}, 100);
678687
}
679688
}}
680689
onFocus={() => {
@@ -711,74 +720,76 @@ const BattleComponent: React.FC<BattleComponentProps> = ({
711720
? '2px solid var(--secondary-gold)'
712721
: 'none',
713722
outlineOffset: isFocused && showFocusOutlines ? '2px' : '0',
714-
}}
723+
'--rarity-color':
724+
elemental.rarity === 'common' ? '#6b7280' :
725+
elemental.rarity === 'rare' ? '#3b82f6' :
726+
elemental.rarity === 'epic' ? '#8b5cf6' :
727+
'#f59e0b',
728+
'--rarity-glow':
729+
elemental.rarity === 'common' ? '#9ca3af' :
730+
elemental.rarity === 'rare' ? '#60a5fa' :
731+
elemental.rarity === 'epic' ? '#a78bfa' :
732+
'#fbbf24'
733+
} as React.CSSProperties}
715734
>
716-
<span className='elemental-emoji' aria-hidden='true'>
717-
{elementalData.emoji}
718-
</span>
719-
<div className='elemental-info'>
720-
<div
721-
className='elemental-rarity-badge'
722-
aria-label={`${elementalData.rarity} rarity`}
723-
>
724-
{elementalData.rarity}
725-
</div>
726-
<div
727-
className='elemental-level'
728-
aria-label={`Level ${elemental.level}`}
729-
>
730-
Lv.{elemental.level}
731-
</div>
732-
<div
733-
className='elemental-protection'
734-
aria-label={`${protection}% protection`}
735-
>
736-
🛡️ {protection}%
735+
<div className='elemental-battle-card'>
736+
<img
737+
src={`${process.env.PUBLIC_URL}/resources/elmental/${selectedElement === 'fire' ? 'Fire' : selectedElement === 'water' ? 'Water' : 'Earth'}_${elemental.rarity === 'common' ? 'Common' : elemental.rarity === 'rare' ? 'Rare' : elemental.rarity === 'epic' ? 'Epic' : 'Immortal'}.png`}
738+
alt={elementalData.name}
739+
className='elemental-battle-image'
740+
onError={(e) => {
741+
// Fallback to emoji if image fails to load
742+
const target = e.currentTarget as HTMLImageElement;
743+
target.style.display = 'none';
744+
const placeholder = target.nextElementSibling as HTMLElement;
745+
if (placeholder) {
746+
placeholder.style.display = 'flex';
747+
}
748+
}}
749+
/>
750+
<div className='elemental-battle-placeholder' style={{display: 'none'}}>
751+
{elementalData.emoji}
737752
</div>
738-
<div
739-
className='elemental-usage'
740-
aria-label={`Used ${elemental.timesUsed} times`}
741-
>
742-
⚔️ {elemental.timesUsed}
753+
<div className='elemental-battle-rarity'>
754+
{elemental.rarity.toUpperCase()}
743755
</div>
756+
</div>
744757

745-
{isOnCooldown && (
746-
<div className='cooldown-indicator' aria-live='polite'>
747-
<span className='cooldown-icon' aria-hidden='true'>
748-
⏱️
749-
</span>
750-
<span
751-
className='cooldown-text'
752-
aria-label={`Cooldown remaining: ${cooldownText}`}
753-
>
754-
{cooldownText}
755-
</span>
756-
<div
757-
className='cooldown-progress-bar'
758-
role='progressbar'
759-
aria-valuenow={Math.round(
760-
(1 -
761-
cooldownRemaining /
762-
(getElementalCooldownHours(elemental.rarity) *
763-
60 *
764-
60 *
765-
1000)) *
766-
100
767-
)}
768-
aria-valuemin={0}
769-
aria-valuemax={100}
770-
aria-label='Cooldown progress'
771-
>
772-
<div
773-
className='cooldown-progress-fill'
774-
style={{
775-
width: `${Math.round((1 - cooldownRemaining / (getElementalCooldownHours(elemental.rarity) * 60 * 60 * 1000)) * 100)}%`,
776-
}}
777-
></div>
778-
</div>
758+
{isOnCooldown && (
759+
<div className='cooldown-overlay-modern'>
760+
<div className='cooldown-timer'>
761+
{(() => {
762+
const totalMs = cooldownRemaining;
763+
const hours = Math.floor(totalMs / (1000 * 60 * 60));
764+
const minutes = Math.floor((totalMs % (1000 * 60 * 60)) / (1000 * 60));
765+
const seconds = Math.floor((totalMs % (1000 * 60)) / 1000);
766+
767+
return (
768+
<>
769+
{hours > 0 && (
770+
<>
771+
<div className='cooldown-time-unit'>
772+
<span className='time-value'>{hours.toString().padStart(2, '0')}</span>
773+
<span className='time-label'>ч</span>
774+
</div>
775+
<span className='cooldown-separator'>:</span>
776+
</>
777+
)}
778+
<div className='cooldown-time-unit'>
779+
<span className='time-value'>{minutes.toString().padStart(2, '0')}</span>
780+
<span className='time-label'>м</span>
781+
</div>
782+
<span className='cooldown-separator'>:</span>
783+
<div className='cooldown-time-unit'>
784+
<span className='time-value'>{seconds.toString().padStart(2, '0')}</span>
785+
<span className='time-label'>с</span>
786+
</div>
787+
</>
788+
);
789+
})()}
779790
</div>
780-
)}
781-
</div>
791+
</div>
792+
)}
782793

783794
<div
784795
id={`elemental-stats-${elemental.id}`}

0 commit comments

Comments
 (0)