Update: GTM Architect v2.6.2 (Edit Specs, Report Fix) & Company Explorer v0.4 (Export, Timestamps)
This commit is contained in:
@@ -208,8 +208,8 @@ const App: React.FC = () => {
|
||||
|
||||
// Session Management
|
||||
const [sessions, setSessions] = useState<ProjectHistoryItem[]>([]);
|
||||
const [viewingSessions, setViewingSessions] = useState(true); // Start in session view
|
||||
|
||||
const [viewingSessions, setViewingSessions] = useState(false); // Start in input view
|
||||
|
||||
// Local state for adding new items (Human in the Loop inputs)
|
||||
// Phase 1
|
||||
const [newFeatureInput, setNewFeatureInput] = useState("");
|
||||
@@ -237,6 +237,10 @@ const App: React.FC = () => {
|
||||
const [brushColor, setBrushColor] = useState('#ef4444'); // Red for annotations
|
||||
const [brushSize, setBrushSize] = useState(4);
|
||||
|
||||
// Specs Editing
|
||||
const [isEditingSpecs, setIsEditingSpecs] = useState(false);
|
||||
const [specsJsonInput, setSpecsJsonInput] = useState("");
|
||||
|
||||
const labels = TRANSLATIONS[language];
|
||||
|
||||
// Apply theme to body
|
||||
@@ -918,6 +922,31 @@ const App: React.FC = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSaveSpecs = async () => {
|
||||
if (!state.projectId) return;
|
||||
try {
|
||||
const parsedSpecs = JSON.parse(specsJsonInput);
|
||||
setState(s => ({ ...s, isLoading: true }));
|
||||
|
||||
await Gemini.updateSpecs(state.projectId, parsedSpecs);
|
||||
|
||||
setState(s => ({
|
||||
...s,
|
||||
isLoading: false,
|
||||
phase1Result: s.phase1Result ? {
|
||||
...s.phase1Result,
|
||||
specs: parsedSpecs
|
||||
} : undefined
|
||||
}));
|
||||
setIsEditingSpecs(false);
|
||||
setError(null);
|
||||
} catch (e: any) {
|
||||
console.error("Failed to save specs", e);
|
||||
setError("Invalid JSON or Save Failed: " + e.message);
|
||||
setState(s => ({ ...s, isLoading: false }));
|
||||
}
|
||||
};
|
||||
|
||||
// --- Render Helpers ---
|
||||
|
||||
const renderInputPhase = () => (
|
||||
@@ -1074,7 +1103,7 @@ const App: React.FC = () => {
|
||||
<div>
|
||||
<h3 className="text-sm font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-2">{labels.features}</h3>
|
||||
<ul className="space-y-2">
|
||||
{state.phase1Result?.features.map((f, i) => (
|
||||
{(state.phase1Result?.features || []).map((f, i) => (
|
||||
<li key={i} className="flex justify-between items-center group text-sm p-2 rounded border transition-colors
|
||||
bg-slate-50 border-slate-200 text-slate-700
|
||||
dark:bg-robo-900 dark:border-robo-700 dark:text-slate-200
|
||||
@@ -1113,7 +1142,7 @@ const App: React.FC = () => {
|
||||
<div>
|
||||
<h3 className="text-sm font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-2">{labels.constraints}</h3>
|
||||
<ul className="space-y-2">
|
||||
{state.phase1Result?.constraints.map((c, i) => (
|
||||
{(state.phase1Result?.constraints || []).map((c, i) => (
|
||||
<li key={i} className="flex justify-between items-center group text-sm p-2 rounded border transition-colors
|
||||
bg-red-50 border-red-200 text-red-700
|
||||
dark:bg-robo-900 dark:border-red-900/30 dark:text-red-200
|
||||
@@ -1153,10 +1182,51 @@ const App: React.FC = () => {
|
||||
{/* NEW: Hard Facts Specs Display */}
|
||||
{state.phase1Result?.specs && 'metadata' in state.phase1Result.specs && (
|
||||
<div className="p-6 rounded-xl border transition-colors bg-white border-slate-200 dark:bg-robo-800 dark:border-robo-700">
|
||||
<h2 className="text-xl font-bold mb-4 flex items-center gap-2 text-slate-900 dark:text-white">
|
||||
<Database className="text-blue-500" /> Technical Specifications (Hard Facts)
|
||||
</h2>
|
||||
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-xl font-bold flex items-center gap-2 text-slate-900 dark:text-white">
|
||||
<Database className="text-blue-500" /> Technical Specifications (Hard Facts)
|
||||
</h2>
|
||||
{!isEditingSpecs ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
setSpecsJsonInput(JSON.stringify(state.phase1Result?.specs, null, 2));
|
||||
setIsEditingSpecs(true);
|
||||
}}
|
||||
className="text-xs font-bold px-3 py-1.5 rounded bg-slate-100 dark:bg-robo-700 hover:bg-slate-200 dark:hover:bg-robo-600 text-slate-600 dark:text-slate-300 transition-colors flex items-center gap-1"
|
||||
>
|
||||
<Pencil size={12}/> Edit Raw Data
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => setIsEditingSpecs(false)}
|
||||
className="text-xs font-bold px-3 py-1.5 rounded bg-slate-100 dark:bg-robo-700 hover:bg-slate-200 dark:hover:bg-robo-600 text-slate-600 dark:text-slate-300 transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSaveSpecs}
|
||||
className="text-xs font-bold px-3 py-1.5 rounded bg-blue-600 hover:bg-blue-700 text-white transition-colors flex items-center gap-1"
|
||||
>
|
||||
<Save size={12}/> Save Changes
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isEditingSpecs ? (
|
||||
<div className="animate-in fade-in">
|
||||
<p className="text-xs text-slate-500 mb-2">
|
||||
Edit the raw JSON data below. Be careful with the syntax. This data is used for the Strategy Report.
|
||||
</p>
|
||||
<textarea
|
||||
value={specsJsonInput}
|
||||
onChange={(e) => setSpecsJsonInput(e.target.value)}
|
||||
className="w-full h-96 font-mono text-xs p-4 rounded bg-slate-50 border border-slate-300 text-slate-800 focus:ring-2 focus:ring-blue-500 outline-none
|
||||
dark:bg-robo-900 dark:border-robo-600 dark:text-slate-300"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
{/* Core Data */}
|
||||
<div className="p-4 bg-slate-50 dark:bg-robo-900 rounded-lg border border-slate-200 dark:border-robo-700">
|
||||
@@ -1222,9 +1292,9 @@ const App: React.FC = () => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Extended Features */}
|
||||
{state.phase1Result.specs.extended_features.length > 0 && (
|
||||
{!isEditingSpecs && state.phase1Result.specs.extended_features.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-xs font-bold uppercase tracking-wider text-slate-500 mb-2">Extended Features</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
@@ -1239,7 +1309,7 @@ const App: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{state.phase1Result?.conflictCheck.hasConflict ? (
|
||||
{state.phase1Result?.conflictCheck?.hasConflict ? (
|
||||
<div className="border p-6 rounded-xl flex gap-4 transition-colors
|
||||
bg-red-50 border-red-200
|
||||
dark:bg-red-950/50 dark:border-red-500/50
|
||||
@@ -1299,7 +1369,7 @@ const App: React.FC = () => {
|
||||
<h2 className="text-2xl font-bold flex items-center gap-2 text-slate-900 dark:text-white">
|
||||
<Target className="text-blue-600 dark:text-robo-accent"/> {labels.targetId}
|
||||
</h2>
|
||||
{state.phase2Result?.icps.map((icp, i) => (
|
||||
{(state.phase2Result?.icps || []).map((icp, i) => (
|
||||
<div key={i} className="relative p-6 rounded-xl border transition-colors cursor-default group
|
||||
bg-white border-slate-200 hover:border-blue-400
|
||||
dark:bg-robo-800 dark:border-robo-700 dark:hover:border-robo-500
|
||||
@@ -1361,7 +1431,7 @@ const App: React.FC = () => {
|
||||
<Database size={16}/> {labels.dataProxies}
|
||||
</h3>
|
||||
<div className="space-y-3">
|
||||
{state.phase2Result?.dataProxies.map((proxy, i) => (
|
||||
{(state.phase2Result?.dataProxies || []).map((proxy, i) => (
|
||||
<div key={i} className="flex gap-4 items-center p-3 rounded-lg group relative
|
||||
bg-white border border-slate-200
|
||||
dark:bg-black/20 dark:border-transparent
|
||||
@@ -1452,7 +1522,7 @@ const App: React.FC = () => {
|
||||
</h3>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{state.phase3Result?.whales.map((whaleGroup, groupIdx) => (
|
||||
{(state.phase3Result?.whales || []).map((whaleGroup, groupIdx) => (
|
||||
<div key={groupIdx} className="p-6 rounded-xl border transition-colors flex flex-col
|
||||
bg-white border-slate-200
|
||||
dark:bg-robo-800 dark:border-robo-700
|
||||
@@ -1518,7 +1588,7 @@ const App: React.FC = () => {
|
||||
<UserCircle className="text-blue-500 dark:text-blue-400"/> {labels.roles}
|
||||
</h3>
|
||||
<ul className="space-y-3">
|
||||
{state.phase3Result?.roles.map((role: any, i) => (
|
||||
{(state.phase3Result?.roles || []).map((role: any, i) => (
|
||||
<li key={i} className="flex items-center justify-between group p-3 rounded-lg border transition-colors
|
||||
bg-slate-50 border-slate-200
|
||||
dark:bg-robo-900 dark:border-robo-800
|
||||
@@ -1613,7 +1683,7 @@ const App: React.FC = () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-slate-200 dark:divide-robo-700 bg-white dark:bg-robo-800">
|
||||
{state.phase4Result?.strategyMatrix.map((row, i) => (
|
||||
{(state.phase4Result?.strategyMatrix || []).map((row, i) => (
|
||||
<tr key={i} className="hover:bg-slate-50 dark:hover:bg-robo-700/50 transition-colors">
|
||||
<td className="p-4 font-bold text-slate-800 dark:text-white">{row.segment}</td>
|
||||
<td className="p-4 text-sm text-red-600 dark:text-red-300">{row.painPoint}</td>
|
||||
@@ -1657,6 +1727,14 @@ const App: React.FC = () => {
|
||||
<Terminal className="text-pink-600 dark:text-pink-400"/> {labels.genAssets}
|
||||
</h2>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={handlePhase5Submit}
|
||||
disabled={state.isLoading}
|
||||
className="text-xs flex items-center gap-1 bg-blue-100 dark:bg-robo-700 text-blue-700 dark:text-blue-300 px-3 py-1.5 rounded hover:bg-blue-200 dark:hover:bg-robo-600 transition-colors font-bold"
|
||||
title="Regenerate Report with latest data"
|
||||
>
|
||||
<RefreshCw size={14}/> Refresh
|
||||
</button>
|
||||
<div className="text-xs font-mono text-slate-500">format: markdown</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user