diff --git a/src/components/game/ExpertMemo.tsx b/src/components/game/ExpertMemo.tsx index 7492568..f7245d4 100644 --- a/src/components/game/ExpertMemo.tsx +++ b/src/components/game/ExpertMemo.tsx @@ -13,7 +13,14 @@ interface ExpertMemoProps { audioRef?: React.RefObject; } -export const ExpertMemo: React.FC = ({ from, subject, children, isAlert = false, stage, audioRef }) => { +export const ExpertMemo: React.FC = ({ + from, + subject, + children, + isAlert = false, + stage, + audioRef +}) => { const { t } = useTranslation(); const highlightColor = isAlert ? 'text-red-500' : 'text-yellow-500'; const memoClass = isAlert ? 'expert-memo alert' : 'expert-memo'; diff --git a/src/components/game/ProgressionIndicator.tsx b/src/components/game/ProgressionIndicator.tsx new file mode 100644 index 0000000..6a5c288 --- /dev/null +++ b/src/components/game/ProgressionIndicator.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import { cn } from '@/lib/utils'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; +import { useTranslation } from 'react-i18next'; +import { ChoiceID } from './constants/metrics'; +import { MONTHS_CONFIG, getMonthConfig } from "@/utils/months"; + +interface ProgressionIndicatorProps { + currentStage: number; + totalStages: number; + previousChoices?: ChoiceID[]; + className?: string; +} + +export const ProgressionIndicator: React.FC = ({ + currentStage, + totalStages, + previousChoices = [], + className +}) => { + const { t } = useTranslation(); + + // Get month name for the stage + const getMonthName = (stageIndex: number) => { + const monthConfig = getMonthConfig(stageIndex + 1); + if (monthConfig && monthConfig.key) { + return t(`months.${monthConfig.key}`); + } + return ""; + }; + + // Get choice names for tooltips + const getChoiceName = (choiceId: ChoiceID, index: number) => { + // Try to get the choice name from the translation + try { + // Find which choice number it was (1 or 2) + const choiceNumber = choiceId.toString().includes('_1') || + choiceId.toString().endsWith('_BOTS') || + choiceId.toString().endsWith('_NEWS') || + choiceId.toString().endsWith('_COLLABORATION') || + choiceId.toString().endsWith('_COURSE') || + choiceId.toString().endsWith('_PANEL') || + choiceId.toString().endsWith('_PAPER') || + choiceId.toString().endsWith('_PLATFORMS') || + choiceId.toString().endsWith('_STRATEGY') || + choiceId.toString().endsWith('_DEFENSE') ? 1 : 2; + + return t(`stages.${index + 1}.choices.${choiceNumber}.text`); + } catch (e) { + // Fallback to the ID if translation fails + return choiceId.toString().replace(/_/g, ' '); + } + }; + + return ( +
+
+ {Array.from({ length: totalStages }).map((_, index) => { + const isActive = index <= currentStage; + const isPast = index < currentStage; + const hasChoice = index < previousChoices.length; + + // Only render tooltips for past and current stages + const DotComponent = isActive ? ( + + + +
+ {hasChoice && ( +
+ )} +
+ + + {hasChoice ? ( +
+
{getMonthName(index)}
+
{getChoiceName(previousChoices[index], index)}
+
+ ) : ( +
+
{getMonthName(index)}
+
+ )} +
+ + + ) : ( + // For future stages, just render the dot without a tooltip +
+ ); + + return ( + + {index > 0 && ( +
+ )} + + {DotComponent} + + ); + })} +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/game/constants/gameStages.tsx b/src/components/game/constants/gameStages.tsx index d8a48f6..5d2ae8f 100644 --- a/src/components/game/constants/gameStages.tsx +++ b/src/components/game/constants/gameStages.tsx @@ -18,6 +18,9 @@ export const useGameStages = (audioRef: React.RefObject): Game return t(`choices.option${number}`); }; + // Total number of stages + const totalStages = 9; + return [ { id: 1, @@ -651,7 +654,6 @@ export const useGameStages = (audioRef: React.RefObject): Game description:

{t('stages.9.expertMemo.content.greeting')}

diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 16bcb60..077bfe1 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -39,6 +39,7 @@ import { DevPanel } from "@/components/game/DevPanel"; import { motion } from "framer-motion"; import { MONTHS_CONFIG, getMonthConfig } from "@/utils/months"; import { toast } from "sonner"; +import { ProgressionIndicator } from '@/components/game/ProgressionIndicator'; // Get valid month keys (skipping index 0) const monthKeys = MONTHS_CONFIG.slice(1).map(config => config?.key).filter(Boolean) as string[]; @@ -58,6 +59,7 @@ const STAGE_CHOICES = [ const Index = () => { const { t } = useTranslation(); const audioRef = useRef(null); + const [previousChoices, setPreviousChoices] = useState([]); const stages = useGameStages(audioRef); const operationNameKey = OPERATION_NAMES[Math.floor(Math.random() * OPERATION_NAMES.length)]; const operationName = t(`operations.${operationNameKey}`); @@ -78,7 +80,6 @@ const Index = () => { const [showIntroDialog, setShowIntroDialog] = useState(true); const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [selectedChoice, setSelectedChoice] = useState(null); - const [previousChoices, setPreviousChoices] = useState([]); const [gameComplete, setGameComplete] = useState(false); const [playerChoices, setPlayerChoices] = useState([]); const [gameKey, setGameKey] = useState(0); @@ -434,59 +435,61 @@ const Index = () => { return (
-
- -
-

{t('analysis.metricsUpdate')}

- -
- -
- - {t('analysis.intelligenceGathered.description')} - -
- {currentResult.title} +
+
+ +
+

{t('analysis.metricsUpdate')}

+ +
+ +
+ + {t('analysis.intelligenceGathered.description')} + +
+ {currentResult.title} +
+ + {currentResult.description} + +
+
+ +
+

{t('analysis.keyInsights')}

+
    + {currentResult.insights.map((insight, index) => ( +
  • + + {insight} +
  • + ))} +
+
+ +
+

+ {t('analysis.strategicInsight')} + {currentResult.nextStepHint} +

- - {currentResult.description} - -
- - -
-

{t('analysis.keyInsights')}

-
    - {currentResult.insights.map((insight, index) => ( -
  • - - {insight} -
  • - ))} -
-
- -
-

- {t('analysis.strategicInsight')} - {currentResult.nextStepHint} -

-
-
- -
-
- +
+ +
+ + +
); @@ -511,6 +514,14 @@ const Index = () => {
+
+ +
+