Restructure CraftingTab: remove stepper, add Fabricate/Enchant top sub-tabs

This commit is contained in:
Refactoring Agent
2026-04-29 12:03:45 +02:00
parent c8a01acda3
commit 1e5eae9b9d
+70 -73
View File
@@ -1,12 +1,10 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { GameCard } from '@/components/ui/game-card'; import { GameCard } from '@/components/ui/game-card';
import { SectionHeader } from '@/components/ui/section-header'; import { SectionHeader } from '@/components/ui/section-header';
import { ActionButton } from '@/components/ui/action-button'; import { ActionButton } from '@/components/ui/action-button';
import { Stepper } from '@/components/ui/stepper';
import { Scroll, Hammer, Sparkles, Anvil } from 'lucide-react'; import { Scroll, Hammer, Sparkles, Anvil } from 'lucide-react';
import type { EquipmentInstance, EnchantmentDesign, DesignEffect, AppliedEnchantment, LootInventory, EquipmentCraftingProgress } from '@/lib/game/types'; import type { EquipmentInstance, EnchantmentDesign, DesignEffect, AppliedEnchantment, LootInventory, EquipmentCraftingProgress } from '@/lib/game/types';
import { fmt, type GameStore } from '@/lib/game/store'; import { fmt, type GameStore } from '@/lib/game/store';
@@ -22,9 +20,6 @@ export interface CraftingTabProps {
store: GameStore; store: GameStore;
} }
// Crafting phases for the stepper
const CRAFTING_PHASES = ['Design', 'Prepare', 'Apply', 'Craft'];
export function CraftingTab({ store }: CraftingTabProps) { export function CraftingTab({ store }: CraftingTabProps) {
const showToast = useGameToast(); const showToast = useGameToast();
const currentAction = store.currentAction; const currentAction = store.currentAction;
@@ -35,18 +30,8 @@ export function CraftingTab({ store }: CraftingTabProps) {
const pauseApplication = store.pauseApplication; const pauseApplication = store.pauseApplication;
const resumeApplication = store.resumeApplication; const resumeApplication = store.resumeApplication;
const [craftingStage, setCraftingStage] = useState<'design' | 'prepare' | 'apply' | 'craft'>('craft'); const [activeTab, setActiveTab] = useState<'fabricate' | 'enchant'>('fabricate');
const [enchantStage, setEnchantStage] = useState<'design' | 'prepare' | 'apply'>('design');
// Map crafting stage to stepper index
const getStepperIndex = (stage: string): number => {
switch (stage) {
case 'design': return 0;
case 'prepare': return 1;
case 'apply': return 2;
case 'craft': return 3;
default: return 0;
}
};
// Safe toFixed helper // Safe toFixed helper
const safeToFixed = (value: number | undefined, decimals: number = 0): string => { const safeToFixed = (value: number | undefined, decimals: number = 0): string => {
@@ -72,21 +57,71 @@ export function CraftingTab({ store }: CraftingTabProps) {
return ( return (
<div className="space-y-4 max-w-full overflow-x-hidden"> <div className="space-y-4 max-w-full overflow-x-hidden">
{/* Visual Stepper - Requirement: show Design, Prepare, Apply phases as visual stepper */} {/* Top Sub-Tabs: Fabricate / Enchant */}
<GameCard variant="default" className="p-4"> <GameCard variant="default" className="p-4">
<Stepper <div className="flex justify-center gap-2">
steps={CRAFTING_PHASES} <ActionButton
currentStep={getStepperIndex(craftingStage)} variant={activeTab === 'fabricate' ? 'primary' : 'secondary'}
className="px-4" onClick={() => setActiveTab('fabricate')}
/> className={activeTab === 'fabricate' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Anvil size={14} className="mr-1" />
Fabricate
</ActionButton>
<ActionButton
variant={activeTab === 'enchant' ? 'primary' : 'secondary'}
onClick={() => setActiveTab('enchant')}
className={activeTab === 'enchant' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Sparkles size={14} className="mr-1" />
Enchant
</ActionButton>
</div>
</GameCard> </GameCard>
{/* Stage Content - Without unlabeled Tabs, using conditional rendering instead */} {/* Fabricate Content: EquipmentCrafter */}
<div className="mt-4"> {activeTab === 'fabricate' && (
{craftingStage === 'craft' && (
<EquipmentCrafter store={store} /> <EquipmentCrafter store={store} />
)} )}
{craftingStage === 'design' && (
{/* Enchant Content: Design → Prepare → Apply workflow */}
{activeTab === 'enchant' && (
<div className="space-y-4">
{/* Enchant Sub-Navigation (no numbered stepper) */}
<GameCard variant="default" className="p-4">
<div className="flex justify-center gap-2 flex-wrap">
<ActionButton
variant={enchantStage === 'design' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setEnchantStage('design')}
className={enchantStage === 'design' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Scroll size={14} className="mr-1" />
Design
</ActionButton>
<ActionButton
variant={enchantStage === 'prepare' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setEnchantStage('prepare')}
className={enchantStage === 'prepare' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Hammer size={14} className="mr-1" />
Prepare
</ActionButton>
<ActionButton
variant={enchantStage === 'apply' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setEnchantStage('apply')}
className={enchantStage === 'apply' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Sparkles size={14} className="mr-1" />
Apply
</ActionButton>
</div>
</GameCard>
{/* Enchant Stage Content */}
{enchantStage === 'design' && (
<EnchantmentDesigner <EnchantmentDesigner
store={store} store={store}
selectedEquipmentType={null} selectedEquipmentType={null}
@@ -99,14 +134,14 @@ export function CraftingTab({ store }: CraftingTabProps) {
setSelectedDesign={() => {}} setSelectedDesign={() => {}}
/> />
)} )}
{craftingStage === 'prepare' && ( {enchantStage === 'prepare' && (
<EnchantmentPreparer <EnchantmentPreparer
store={store} store={store}
selectedEquipmentInstance={null} selectedEquipmentInstance={null}
setSelectedEquipmentInstance={() => {}} setSelectedEquipmentInstance={() => {}}
/> />
)} )}
{craftingStage === 'apply' && ( {enchantStage === 'apply' && (
<EnchantmentApplier <EnchantmentApplier
store={store} store={store}
selectedEquipmentInstance={null} selectedEquipmentInstance={null}
@@ -118,50 +153,9 @@ export function CraftingTab({ store }: CraftingTabProps) {
/> />
)} )}
</div> </div>
)}
{/* Stage Navigation Buttons */} {/* Current Activity Indicator: Crafting */}
<GameCard variant="default" className="p-4">
<div className="flex justify-center gap-2 flex-wrap">
<ActionButton
variant={craftingStage === 'craft' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setCraftingStage('craft')}
className={craftingStage === 'craft' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Anvil size={14} className="mr-1" />
Craft
</ActionButton>
<ActionButton
variant={craftingStage === 'design' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setCraftingStage('design')}
className={craftingStage === 'design' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Scroll size={14} className="mr-1" />
Design
</ActionButton>
<ActionButton
variant={craftingStage === 'prepare' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setCraftingStage('prepare')}
className={craftingStage === 'prepare' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Hammer size={14} className="mr-1" />
Prepare
</ActionButton>
<ActionButton
variant={craftingStage === 'apply' ? 'primary' : 'secondary'}
size="sm"
onClick={() => setCraftingStage('apply')}
className={craftingStage === 'apply' ? 'ring-2 ring-[var(--interactive-primary)]' : ''}
>
<Sparkles size={14} className="mr-1" />
Apply
</ActionButton>
</div>
</GameCard>
{/* Current Activity Indicator */}
{currentAction === 'craft' && equipmentCraftingProgress && ( {currentAction === 'craft' && equipmentCraftingProgress && (
<GameCard variant="default" className="border-[var(--mana-water)]/60 bg-[var(--mana-water)]/10"> <GameCard variant="default" className="border-[var(--mana-water)]/60 bg-[var(--mana-water)]/10">
<SectionHeader <SectionHeader
@@ -183,6 +177,7 @@ export function CraftingTab({ store }: CraftingTabProps) {
</GameCard> </GameCard>
)} )}
{/* Current Activity Indicator: Designing */}
{currentAction === 'design' && designProgress && ( {currentAction === 'design' && designProgress && (
<GameCard variant="default" className="border-[var(--mana-stellar)]/60 bg-[var(--mana-stellar)]/10"> <GameCard variant="default" className="border-[var(--mana-stellar)]/60 bg-[var(--mana-stellar)]/10">
<SectionHeader <SectionHeader
@@ -204,6 +199,7 @@ export function CraftingTab({ store }: CraftingTabProps) {
</GameCard> </GameCard>
)} )}
{/* Current Activity Indicator: Preparing */}
{currentAction === 'prepare' && preparationProgress && ( {currentAction === 'prepare' && preparationProgress && (
<GameCard variant="default" className="border-[var(--color-warning)]/60 bg-[var(--color-warning)]/10"> <GameCard variant="default" className="border-[var(--color-warning)]/60 bg-[var(--color-warning)]/10">
<SectionHeader <SectionHeader
@@ -228,6 +224,7 @@ export function CraftingTab({ store }: CraftingTabProps) {
</GameCard> </GameCard>
)} )}
{/* Current Activity Indicator: Enchanting */}
{currentAction === 'enchant' && applicationProgress && ( {currentAction === 'enchant' && applicationProgress && (
<GameCard variant="default" className="border-[var(--mana-light)]/60 bg-[var(--mana-light)]/10"> <GameCard variant="default" className="border-[var(--mana-light)]/60 bg-[var(--mana-light)]/10">
<SectionHeader <SectionHeader
@@ -238,7 +235,7 @@ export function CraftingTab({ store }: CraftingTabProps) {
<ActionButton size="sm" onClick={resumeApplication}>Resume</ActionButton> <ActionButton size="sm" onClick={resumeApplication}>Resume</ActionButton>
) : ( ) : (
<> <>
<ActionButton variant="outline" size="sm" onClick={pauseApplication}>Pause</ActionButton> <ActionButton variant="secondary" size="sm" onClick={pauseApplication}>Pause</ActionButton>
<ActionButton variant="ghost" size="sm" onClick={() => { <ActionButton variant="ghost" size="sm" onClick={() => {
store.cancelApplication(); store.cancelApplication();
showToast('warning', 'Enchantment Cancelled', 'The enchantment application was cancelled.'); showToast('warning', 'Enchantment Cancelled', 'The enchantment application was cancelled.');