Files
Brancheneinstufung2/competitor-analysis-app/components/InputForm.tsx
Floke 249b06463b feat(competitor-analysis): Fix 404, SDK compatibility, and update docs
Resolved multiple issues preventing the 'competitor-analysis' app from running and serving its frontend:

1.  **Fixed Python SyntaxError in Prompts:** Corrected unterminated string literals and ensure proper multi-line string formatting (using .format() instead of f-strings for complex prompts) in .
2.  **Addressed Python SDK Compatibility (google-generativeai==0.3.0):**
    *   Removed  for  and  by adapting the orchestrator to pass JSON schemas as direct Python dictionaries, as required by the older SDK version.
    *   Updated  with detailed guidance on handling / imports and dictionary-based schema definitions for older SDKs.
3.  **Corrected Frontend Build Dependencies:** Moved critical build dependencies (like , , ) from  to  in .
    *   Updated  to include this  pitfall, ensuring frontend build tools are installed in Docker.
4.  **Updated Documentation:**
    *   : Added comprehensive lessons learned regarding  dependencies, Python SDK versioning (specifically  and  imports for ), and robust multi-line prompt handling.
    *   : Integrated specific details of the encountered errors and their solutions, making the migration report a more complete historical record and guide.

These changes collectively fix the 404 error by ensuring the Python backend starts correctly and serves the frontend assets after a successful build.
2026-01-10 09:10:00 +00:00

97 lines
5.1 KiB
TypeScript

import React, { useState } from 'react';
import { translations } from '../translations';
interface InputFormProps {
onStart: (startUrl: string, maxCompetitors: number, marketScope: string, language: 'de' | 'en') => void;
}
const InputForm: React.FC<InputFormProps> = ({ onStart }) => {
const [startUrl, setStartUrl] = useState('https://www.mobilexag.de');
const [maxCompetitors, setMaxCompetitors] = useState(12);
const [marketScope, setMarketScope] = useState('DACH');
const [language, setLanguage] = useState<'de' | 'en'>('de');
const t = translations[language];
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onStart(startUrl, maxCompetitors, marketScope, language);
};
const inputClasses = "w-full bg-light-primary dark:bg-brand-primary text-light-text dark:text-brand-text border border-light-accent dark:border-brand-accent rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-brand-highlight placeholder-light-subtle dark:placeholder-brand-light";
return (
<div className="bg-light-secondary dark:bg-brand-secondary p-8 rounded-lg shadow-2xl max-w-2xl mx-auto">
<h2 className="text-3xl font-bold mb-6 text-center">{t.inputForm.title}</h2>
<p className="text-light-subtle dark:text-brand-light mb-8 text-center">{t.inputForm.subtitle}</p>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="start_url" className="block text-sm font-medium text-light-subtle dark:text-brand-light mb-2">{t.inputForm.startUrlLabel}</label>
<input
type="url"
id="start_url"
value={startUrl}
onChange={(e) => setStartUrl(e.target.value)}
className={inputClasses}
placeholder="https://www.example-company.com"
required
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="max_competitors" className="block text-sm font-medium text-light-subtle dark:text-brand-light mb-2">{t.inputForm.maxCompetitorsLabel}</label>
<input
type="number"
id="max_competitors"
value={maxCompetitors}
onChange={(e) => setMaxCompetitors(parseInt(e.target.value, 10))}
className={inputClasses}
min="1"
max="50"
/>
</div>
<div>
<label htmlFor="market_scope" className="block text-sm font-medium text-light-subtle dark:text-brand-light mb-2">{t.inputForm.marketScopeLabel}</label>
<input
type="text"
id="market_scope"
value={marketScope}
onChange={(e) => setMarketScope(e.target.value)}
className={inputClasses}
placeholder={t.inputForm.marketScopePlaceholder}
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-light-subtle dark:text-brand-light mb-2">{t.inputForm.languageLabel}</label>
<div className="flex rounded-lg shadow-sm" role="group">
<button
type="button"
onClick={() => setLanguage('de')}
className={`px-4 py-2 text-sm font-medium rounded-l-lg w-full transition-colors ${language === 'de' ? 'bg-brand-highlight text-white' : 'bg-light-primary dark:bg-brand-primary text-light-text dark:text-brand-text hover:bg-light-accent dark:hover:bg-brand-accent'}`}
>
Deutsch
</button>
<button
type="button"
onClick={() => setLanguage('en')}
className={`px-4 py-2 text-sm font-medium rounded-r-lg w-full transition-colors ${language === 'en' ? 'bg-brand-highlight text-white' : 'bg-light-primary dark:bg-brand-primary text-light-text dark:text-brand-text hover:bg-light-accent dark:hover:bg-brand-accent'}`}
>
English
</button>
</div>
</div>
<div className="pt-4">
<button
type="submit"
className="w-full bg-brand-highlight hover:bg-blue-600 text-white font-bold py-3 px-4 rounded-lg shadow-lg transition duration-300 transform hover:scale-105"
>
{t.inputForm.submitButton}
</button>
</div>
</form>
</div>
);
};
export default InputForm;