diff --git a/competitor-analysis/components/Step7_Battlecards.tsx b/competitor-analysis/components/Step7_Battlecards.tsx
new file mode 100644
index 00000000..c8132def
--- /dev/null
+++ b/competitor-analysis/components/Step7_Battlecards.tsx
@@ -0,0 +1,91 @@
+import React, { useState } from 'react';
+import type { AppState, Battlecard } from '../types';
+
+interface Step7BattlecardsProps {
+ appState: AppState | null;
+ t: any;
+}
+
+const ProfileIcon = () => ();
+const StrengthsIcon = () => ();
+const LandmineIcon = () => ();
+const BulletIcon = () => ();
+
+const BattlecardComponent: React.FC<{ battlecard: Battlecard, t: any }> = ({ battlecard, t }) => {
+
+ return (
+
+
+
+
{t.profile}
+
{battlecard.competitor_profile.focus}
+
{battlecard.competitor_profile.positioning}
+
+
+
{t.strengths}
+
+ {(battlecard.strengths_vs_weaknesses || []).map((item, i) => - {item}
)}
+
+
+
+
{t.landmines}
+
+ {(battlecard.landmine_questions || []).map((item, i) => - {item}
)}
+
+
+
+
{t.silverBullet}
+
+ "{battlecard.silver_bullet}"
+
+
+
+
+ );
+}
+
+const Step7_Battlecards: React.FC = ({ appState, t }) => {
+ const [activeTab, setActiveTab] = useState(0);
+
+ if (!appState || !appState.battlecards || appState.battlecards.length === 0) {
+ return (
+
+
{t.title}
+
{t.generating}
+
+ );
+ }
+
+ const { battlecards } = appState;
+ const activeBattlecard = battlecards[activeTab];
+
+ return (
+
+
{t.title}
+
+ {t.subtitle}
+
+
+
+ {battlecards.map((card, index) => (
+
+ ))}
+
+
+ {activeBattlecard &&
}
+
+
+ );
+};
+
+export default Step7_Battlecards;
\ No newline at end of file
diff --git a/competitor-analysis/components/Step8_References.tsx b/competitor-analysis/components/Step8_References.tsx
new file mode 100644
index 00000000..94e7264c
--- /dev/null
+++ b/competitor-analysis/components/Step8_References.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import type { ReferenceAnalysis } from '../types';
+
+interface Step8ReferencesProps {
+ analyses: ReferenceAnalysis[];
+ groundingMetadata: any[];
+ t: any;
+}
+
+const LinkIcon = () => ();
+
+
+const Step8_References: React.FC = ({ analyses, groundingMetadata, t }) => {
+ return (
+
+
{t.title}
+
+ {t.subtitle}
+
+
+
+ {(analyses || []).map((analysis, index) => {
+ // This robust check prevents crashes if `references` is null, undefined, or not an array.
+ const hasReferences = Array.isArray(analysis.references) && analysis.references.length > 0;
+
+ return (
+
+
{analysis.competitor_name}
+
+ {!hasReferences ? (
+
{t.noReferencesFound}
+ ) : (
+
+ {analysis.references.map((ref, refIndex) => (
+
+
+
+ {ref.name}
+ {ref.industry && {ref.industry}}
+
+ {ref.case_study_url && (
+
+ {t.caseStudyLink}
+
+ )}
+
+ {ref.testimonial_snippet && (
+
+ "{ref.testimonial_snippet}"
+
+ )}
+
+ ))}
+
+ )}
+
+ );
+ })}
+
+
+ {groundingMetadata && groundingMetadata.length > 0 && (
+
+ )}
+
+ );
+};
+
+export default Step8_References;
\ No newline at end of file
diff --git a/competitor-analysis/components/StepIndicator.tsx b/competitor-analysis/components/StepIndicator.tsx
new file mode 100644
index 00000000..060537bc
--- /dev/null
+++ b/competitor-analysis/components/StepIndicator.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+
+interface StepIndicatorProps {
+ currentStep: number;
+ highestStep: number;
+ onStepClick: (step: number) => void;
+ t: {
+ title: string;
+ steps: string[];
+ }
+}
+
+const StepIndicator: React.FC = ({ currentStep, highestStep, onStepClick, t }) => {
+
+ const steps = t.steps.map((name, index) => ({ id: index + 1, name }));
+
+ return (
+
+
{t.title}
+
+ {steps.map((step) => {
+ const isCompleted = step.id < currentStep;
+ const isActive = step.id === currentStep;
+ const isClickable = step.id <= highestStep;
+
+ return (
+ - isClickable && onStepClick(step.id)}
+ >
+
+ {isCompleted ? '✓' : step.id}
+
+
+ {step.name}
+
+
+ )
+ })}
+
+
+ );
+};
+
+export default StepIndicator;
\ No newline at end of file