Dateien nach "general-market-intelligence/components" hochladen
This commit is contained in:
127
general-market-intelligence/components/StepStrategy.tsx
Normal file
127
general-market-intelligence/components/StepStrategy.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { SearchStrategy, SearchSignal } from '../types';
|
||||
import { Settings, Edit2, CheckCircle2, Plus, Trash2, HelpCircle } from 'lucide-react';
|
||||
|
||||
interface StepStrategyProps {
|
||||
strategy: SearchStrategy;
|
||||
onConfirm: (strategy: SearchStrategy) => void;
|
||||
}
|
||||
|
||||
export const StepStrategy: React.FC<StepStrategyProps> = ({ strategy, onConfirm }) => {
|
||||
const [localStrategy, setLocalStrategy] = useState<SearchStrategy>(strategy);
|
||||
|
||||
const handleSignalChange = (index: number, field: keyof SearchSignal, value: any) => {
|
||||
const newSignals = [...localStrategy.signals];
|
||||
newSignals[index] = { ...newSignals[index], [field]: value };
|
||||
setLocalStrategy({ ...localStrategy, signals: newSignals });
|
||||
};
|
||||
|
||||
const handleRemoveSignal = (index: number) => {
|
||||
setLocalStrategy({
|
||||
...localStrategy,
|
||||
signals: localStrategy.signals.filter((_, i) => i !== index)
|
||||
});
|
||||
};
|
||||
|
||||
const handleAddSignal = () => {
|
||||
const newId = `sig_${Date.now()}`;
|
||||
setLocalStrategy({
|
||||
...localStrategy,
|
||||
signals: [...localStrategy.signals, {
|
||||
id: newId,
|
||||
name: "New Signal",
|
||||
description: "Describe what to look for...",
|
||||
targetPageKeywords: ["homepage"]
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto mt-12 px-4 pb-24">
|
||||
<div className="text-center mb-8">
|
||||
<h2 className="text-2xl font-bold text-slate-900">Define Search Strategy</h2>
|
||||
<p className="text-slate-600">Based on <strong>{strategy.productContext}</strong>, we identified these digital traces to look for.</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 mb-6">
|
||||
<h3 className="text-sm font-bold text-slate-500 uppercase tracking-wide mb-3">Ideal Customer Profile (AI Generated)</h3>
|
||||
<p className="text-slate-800 bg-slate-50 p-4 rounded-lg border border-slate-100 italic">
|
||||
"{localStrategy.idealCustomerProfile}"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between px-2">
|
||||
<h3 className="font-bold text-slate-900 flex items-center gap-2">
|
||||
<Settings size={20} className="text-indigo-600" />
|
||||
Digital Signals (The "Audit")
|
||||
</h3>
|
||||
<button onClick={handleAddSignal} className="text-sm text-indigo-600 font-medium flex items-center gap-1 hover:underline">
|
||||
<Plus size={16} /> Add Signal
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{localStrategy.signals.map((signal, index) => (
|
||||
<div key={signal.id} className="bg-white p-5 rounded-xl border border-slate-200 shadow-sm transition-all hover:border-indigo-300">
|
||||
<div className="flex gap-4 items-start">
|
||||
<div className="bg-indigo-50 text-indigo-600 font-bold rounded-full w-8 h-8 flex items-center justify-center shrink-0">
|
||||
{index + 1}
|
||||
</div>
|
||||
<div className="flex-1 space-y-3">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-slate-500 uppercase">Signal Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={signal.name}
|
||||
onChange={(e) => handleSignalChange(index, 'name', e.target.value)}
|
||||
className="w-full font-bold text-slate-900 border-b border-slate-200 focus:border-indigo-500 outline-none py-1"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-slate-500 uppercase">Target Pages</label>
|
||||
<input
|
||||
type="text"
|
||||
value={signal.targetPageKeywords.join(", ")}
|
||||
onChange={(e) => handleSignalChange(index, 'targetPageKeywords', e.target.value.split(',').map(s => s.trim()))}
|
||||
className="w-full text-slate-600 border-b border-slate-200 focus:border-indigo-500 outline-none py-1 text-sm"
|
||||
placeholder="e.g. about, legal, careers"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-slate-500 uppercase">Description / Instruction for AI</label>
|
||||
<textarea
|
||||
value={signal.description}
|
||||
onChange={(e) => handleSignalChange(index, 'description', e.target.value)}
|
||||
className="w-full text-slate-700 bg-slate-50 rounded-lg p-2 mt-1 border border-slate-200 focus:border-indigo-500 outline-none text-sm"
|
||||
rows={2}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleRemoveSignal(index)}
|
||||
className="text-slate-300 hover:text-red-500 transition-colors"
|
||||
title="Remove Signal"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-white/80 backdrop-blur-md border-t border-slate-200 p-4 z-40">
|
||||
<div className="max-w-4xl mx-auto flex justify-end">
|
||||
<button
|
||||
onClick={() => onConfirm(localStrategy)}
|
||||
className="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-8 rounded-xl shadow-lg shadow-indigo-600/20 transition-all transform active:scale-[0.98] flex items-center gap-2"
|
||||
>
|
||||
<CheckCircle2 size={20} /> Approve Strategy & Find Leads
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user