From 16f0f16cdfc4b00848b97c3af636ffcc761ef9f5 Mon Sep 17 00:00:00 2001 From: Floke Date: Fri, 9 Jan 2026 17:41:40 +0000 Subject: [PATCH] Dateien nach "competitor-analysis/components" hochladen --- .../components/Step7_Battlecards.tsx | 91 +++++++++++++++++++ .../components/Step8_References.tsx | 81 +++++++++++++++++ .../components/StepIndicator.tsx | 50 ++++++++++ 3 files changed, 222 insertions(+) create mode 100644 competitor-analysis/components/Step7_Battlecards.tsx create mode 100644 competitor-analysis/components/Step8_References.tsx create mode 100644 competitor-analysis/components/StepIndicator.tsx 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 && ( +
+

{t.sourcesTitle}

+ +
+ )} +
+ ); +}; + +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 ( +
  1. isClickable && onStepClick(step.id)} + > + + {isCompleted ? '✓' : step.id} + + + {step.name} + +
  2. + ) + })} +
+
+ ); +}; + +export default StepIndicator; \ No newline at end of file