Files
ALwrity/frontend/src/pages/ResearchDashboard/ResearchDashboard.tsx

158 lines
5.7 KiB
TypeScript

import React, { useState } from 'react';
import { ResearchWizard } from '../../components/Research';
import { BlogResearchResponse } from '../../services/blogWriterApi';
import { ResearchPersonaModal } from '../../components/Research/ResearchPersonaModal';
import { OnboardingCompetitorModal } from '../../components/Research/OnboardingCompetitorModal';
import { useProjectRestoration } from './hooks/useProjectRestoration';
import { usePersonaManagement } from './hooks/usePersonaManagement';
import { useCompetitorManagement } from './hooks/useCompetitorManagement';
import { Header } from './components/Header';
import { LeftPanel } from './components/LeftPanel';
import { FooterStats } from './components/FooterStats';
import { PersonaDetailsModal } from './components/PersonaDetailsModal';
import { ResearchPreset } from './types';
import { dashboardStyles } from './styles';
export const ResearchDashboard: React.FC = () => {
const [results, setResults] = useState<BlogResearchResponse | null>(null);
const [showDebug, setShowDebug] = useState(false);
const [showPersonaDetailsModal, setShowPersonaDetailsModal] = useState(false);
// Custom hooks for state management
const projectRestoration = useProjectRestoration();
const personaManagement = usePersonaManagement();
const competitorManagement = useCompetitorManagement();
const handleComplete = (researchResults: BlogResearchResponse) => {
setResults(researchResults);
};
const handlePresetClick = (preset: ResearchPreset) => {
projectRestoration.setPresetKeywords([preset.keywords]);
projectRestoration.setPresetIndustry(preset.industry);
projectRestoration.setPresetTargetAudience(preset.targetAudience);
projectRestoration.setPresetMode(preset.researchMode);
projectRestoration.setPresetConfig(preset.config);
setResults(null);
};
const handleOpenPersonaDetails = async () => {
setShowPersonaDetailsModal(true);
await personaManagement.handleOpenPersonaDetails();
};
return (
<div style={{
minHeight: '100vh',
background: 'linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 50%, #bae6fd 100%)',
position: 'relative',
overflow: 'hidden'
}}>
{/* Animated Background Elements */}
<div style={{
position: 'absolute',
top: '10%',
left: '5%',
width: '400px',
height: '400px',
background: 'radial-gradient(circle, rgba(14,165,233,0.08) 0%, transparent 70%)',
borderRadius: '50%',
filter: 'blur(40px)',
animation: 'float 20s ease-in-out infinite',
}} />
<div style={{
position: 'absolute',
bottom: '10%',
right: '5%',
width: '300px',
height: '300px',
background: 'radial-gradient(circle, rgba(56,189,248,0.08) 0%, transparent 70%)',
borderRadius: '50%',
filter: 'blur(40px)',
animation: 'float 15s ease-in-out infinite reverse',
}} />
<style>{dashboardStyles}</style>
{/* Header */}
<Header />
{/* Main Content */}
<div style={{
maxWidth: '1400px',
margin: '0 auto',
padding: '0 24px',
display: 'flex',
gap: '20px',
flexWrap: 'wrap',
position: 'relative',
zIndex: 10
}}>
{/* Left Panel */}
<LeftPanel
presets={personaManagement.displayPresets}
personaExists={personaManagement.personaExists}
showDebug={showDebug}
results={results}
onPresetClick={handlePresetClick}
onReset={projectRestoration.handleReset}
onToggleDebug={setShowDebug}
/>
{/* Main Content - Wizard */}
<div style={{ flex: '2 1 800px', animation: 'fadeInUp 0.4s ease-out' }}>
<ResearchWizard
initialKeywords={projectRestoration.presetKeywords}
initialIndustry={projectRestoration.presetIndustry}
initialResults={
projectRestoration.restoredProject?.intent_result ||
projectRestoration.restoredProject?.legacy_result ||
results
}
initialTargetAudience={projectRestoration.presetTargetAudience}
initialResearchMode={projectRestoration.presetMode}
initialConfig={projectRestoration.presetConfig}
onComplete={handleComplete}
headerActions={{
onOpenPersona: handleOpenPersonaDetails,
onOpenCompetitors: competitorManagement.handleOpenCompetitorModal,
personaExists: personaManagement.personaExists,
}}
/>
</div>
</div>
{/* Footer Stats */}
{results && <FooterStats results={results} />}
{/* Research Persona Generation Modal */}
<ResearchPersonaModal
open={personaManagement.showPersonaModal}
onClose={() => personaManagement.setShowPersonaModal(false)}
onGenerate={personaManagement.handleGeneratePersona}
onCancel={personaManagement.handleCancelPersona}
/>
{/* Competitor Analysis Modal */}
<OnboardingCompetitorModal
open={competitorManagement.showCompetitorModal}
onClose={() => competitorManagement.setShowCompetitorModal(false)}
data={competitorManagement.competitorData}
loading={competitorManagement.loadingCompetitors}
error={competitorManagement.competitorError}
onRefresh={competitorManagement.handleRefreshCompetitors}
/>
{/* Research Persona Details Modal */}
<PersonaDetailsModal
open={showPersonaDetailsModal}
loading={personaManagement.loadingPersonaDetails}
researchPersona={personaManagement.researchPersona}
onClose={() => setShowPersonaDetailsModal(false)}
/>
</div>
);
};
export default ResearchDashboard;