Task 2: SpireTab Overhaul - add Climb the Spire button, implement Spire Mode with exit condition
This commit is contained in:
@@ -1,86 +1,149 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Sparkles, Swords, BookOpen, Target, FlaskConical } from 'lucide-react';
|
||||
import { Sparkles, Swords, BookOpen, Target, FlaskConical, Cog, Hammer } from 'lucide-react';
|
||||
import type { GameAction } from '@/lib/game/types';
|
||||
|
||||
interface ActionButtonsProps {
|
||||
currentAction: GameAction;
|
||||
currentStudyTarget: { type: 'skill' | 'spell'; id: string; progress: number; required: number } | null;
|
||||
designProgress: { progress: number; required: number } | null;
|
||||
designProgress2: { progress: number; required: number } | null;
|
||||
preparationProgress: { progress: number; required: number } | null;
|
||||
applicationProgress: { progress: number; required: number } | null;
|
||||
setAction: (action: GameAction) => void;
|
||||
equipmentCraftingProgress: { progress: number; required: number } | null;
|
||||
}
|
||||
|
||||
// Map action IDs to labels and icons
|
||||
const ACTION_CONFIG: Record<string, { label: string; icon: typeof Sparkles; color: string }> = {
|
||||
meditate: { label: 'Meditating', icon: Sparkles, color: 'text-blue-400' },
|
||||
climb: { label: 'Climbing', icon: Swords, color: 'text-green-400' },
|
||||
study: { label: 'Studying', icon: BookOpen, color: 'text-yellow-400' },
|
||||
design: { label: 'Designing Enchantment', icon: Target, color: 'text-purple-400' },
|
||||
prepare: { label: 'Preparing Equipment', icon: FlaskConical, color: 'text-purple-400' },
|
||||
enchant: { label: 'Enchanting', icon: Sparkles, color: 'text-purple-400' },
|
||||
craft: { label: 'Crafting Equipment', icon: Hammer, color: 'text-orange-400' },
|
||||
convert: { label: 'Converting Mana', icon: Cog, color: 'text-cyan-400' },
|
||||
};
|
||||
|
||||
function ProgressBar({ progress, required, label }: { progress: number; required: number; label?: string }) {
|
||||
const percentage = Math.min(100, (progress / required) * 100);
|
||||
return (
|
||||
<div className="mt-1">
|
||||
{label && <div className="text-xs text-gray-400 mb-0.5">{label}</div>}
|
||||
<div className="w-full bg-gray-700 rounded-full h-1.5">
|
||||
<div
|
||||
className="bg-blue-500 h-1.5 rounded-full transition-all duration-300"
|
||||
style={{ width: `${percentage}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ActionButtons({
|
||||
currentAction,
|
||||
currentStudyTarget,
|
||||
designProgress,
|
||||
designProgress2,
|
||||
preparationProgress,
|
||||
applicationProgress,
|
||||
setAction,
|
||||
equipmentCraftingProgress,
|
||||
}: ActionButtonsProps) {
|
||||
const actions: { id: GameAction; label: string; icon: typeof Swords }[] = [
|
||||
{ id: 'meditate', label: 'Meditate', icon: Sparkles },
|
||||
{ id: 'climb', label: 'Climb', icon: Swords },
|
||||
{ id: 'study', label: 'Study', icon: BookOpen },
|
||||
];
|
||||
const config = ACTION_CONFIG[currentAction] || { label: currentAction, icon: Sparkles, color: 'text-gray-400' };
|
||||
const Icon = config.icon;
|
||||
|
||||
const hasDesignProgress = designProgress !== null;
|
||||
const hasPrepProgress = preparationProgress !== null;
|
||||
const hasAppProgress = applicationProgress !== null;
|
||||
// Calculate additional info for specific actions
|
||||
const getActionDetails = () => {
|
||||
switch (currentAction) {
|
||||
case 'study':
|
||||
if (currentStudyTarget) {
|
||||
const progress = currentStudyTarget.progress;
|
||||
const required = currentStudyTarget.required;
|
||||
const percentage = Math.min(100, (progress / required) * 100);
|
||||
return (
|
||||
<ProgressBar
|
||||
progress={progress}
|
||||
required={required}
|
||||
label={`${currentStudyTarget.type === 'skill' ? 'Skill' : 'Spell'}: ${percentage.toFixed(0)}%`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'design':
|
||||
if (designProgress) {
|
||||
return (
|
||||
<ProgressBar
|
||||
progress={designProgress.progress}
|
||||
required={designProgress.required}
|
||||
label="Design progress"
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'prepare':
|
||||
if (preparationProgress) {
|
||||
return (
|
||||
<ProgressBar
|
||||
progress={preparationProgress.progress}
|
||||
required={preparationProgress.required}
|
||||
label="Preparation progress"
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'enchant':
|
||||
if (applicationProgress) {
|
||||
return (
|
||||
<ProgressBar
|
||||
progress={applicationProgress.progress}
|
||||
required={applicationProgress.required}
|
||||
label="Enchantment progress"
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'craft':
|
||||
if (equipmentCraftingProgress) {
|
||||
return (
|
||||
<ProgressBar
|
||||
progress={equipmentCraftingProgress.progress}
|
||||
required={equipmentCraftingProgress.required}
|
||||
label="Crafting progress"
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{actions.map(({ id, label, icon: Icon }) => (
|
||||
<Button
|
||||
key={id}
|
||||
variant={currentAction === id ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className={`h-9 ${currentAction === id ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-800/50 hover:bg-gray-700/50 border-gray-600'}`}
|
||||
onClick={() => setAction(id)}
|
||||
>
|
||||
<Icon className="w-4 h-4 mr-1" />
|
||||
{label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Crafting actions row - shown when there's active crafting progress */}
|
||||
{(hasDesignProgress || hasPrepProgress || hasAppProgress) && (
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<Button
|
||||
variant={currentAction === 'design' ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
disabled={!hasDesignProgress}
|
||||
className={`h-9 ${currentAction === 'design' ? 'bg-purple-600 hover:bg-purple-700' : 'bg-gray-800/50 hover:bg-gray-700/50 border-gray-600'}`}
|
||||
onClick={() => hasDesignProgress && setAction('design')}
|
||||
>
|
||||
<Target className="w-4 h-4 mr-1" />
|
||||
Design
|
||||
</Button>
|
||||
<Button
|
||||
variant={currentAction === 'prepare' ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
disabled={!hasPrepProgress}
|
||||
className={`h-9 ${currentAction === 'prepare' ? 'bg-purple-600 hover:bg-purple-700' : 'bg-gray-800/50 hover:bg-gray-700/50 border-gray-600'}`}
|
||||
onClick={() => hasPrepProgress && setAction('prepare')}
|
||||
>
|
||||
<FlaskConical className="w-4 h-4 mr-1" />
|
||||
Prepare
|
||||
</Button>
|
||||
<Button
|
||||
variant={currentAction === 'enchant' ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
disabled={!hasAppProgress}
|
||||
className={`h-9 ${currentAction === 'enchant' ? 'bg-purple-600 hover:bg-purple-700' : 'bg-gray-800/50 hover:bg-gray-700/50 border-gray-600'}`}
|
||||
onClick={() => hasAppProgress && setAction('enchant')}
|
||||
>
|
||||
<Sparkles className="w-4 h-4 mr-1" />
|
||||
Enchant
|
||||
</Button>
|
||||
<div className="bg-gray-800/50 rounded-lg p-3 border border-gray-700">
|
||||
<div className="flex items-center gap-2">
|
||||
<Icon className={`w-4 h-4 ${config.color}`} />
|
||||
<span className="text-sm font-medium text-gray-200">Current Activity</span>
|
||||
</div>
|
||||
)}
|
||||
<div className={`text-lg font-semibold mt-1 ${config.color}`}>
|
||||
{config.label}
|
||||
</div>
|
||||
{getActionDetails()}
|
||||
|
||||
{/* Show second design slot if active */}
|
||||
{designProgress2 && (
|
||||
<div className="mt-2 pt-2 border-t border-gray-700">
|
||||
<div className="flex items-center gap-2">
|
||||
<Target className="w-3 h-3 text-purple-400" />
|
||||
<span className="text-xs text-gray-400">Second Design Slot</span>
|
||||
</div>
|
||||
<ProgressBar
|
||||
progress={designProgress2.progress}
|
||||
required={designProgress2.required}
|
||||
label="Design progress"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user