GrantForge Bot
Deploy to Hugging Face
3b7f713
import React, { useState, useEffect } from 'react';
import ProgressStepper from '../components/dashboard/ProgressStepper';
import DashboardHome from '../components/dashboard/DashboardHome';
import EmptyProjectsState from '../components/dashboard/EmptyProjectsState';
import WizardModal from '../components/dashboard/WizardModal';
import { useQuery } from '@tanstack/react-query';
import { getSubscriptionStatus, createWelcomeSeed } from '../api/client';
import { useProjectStore } from '../store/useProjectStore';
import { WifiOff } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { OnboardingTour } from '../components/onboarding/OnboardingTour';
const Dashboard: React.FC = () => {
const [runTour, setRunTour] = useState(false);
const [showWizard, setShowWizard] = useState(false);
const { projects, fetchProjects } = useProjectStore();
useEffect(() => {
let timeoutId: ReturnType<typeof setTimeout>;
const initDashboard = async () => {
await fetchProjects();
const hasSeenTour = localStorage.getItem('has_seen_tour_dashboard');
if (!hasSeenTour) {
// Gdy brak projektów (Empty State) i start, tworzymy seed onboardingowy
try {
const seedData = await createWelcomeSeed();
if (seedData) {
await fetchProjects(); // Odśwież listę, aby pokazać powitalny projekt
}
} catch (e) {
console.error("Błąd podczas ładowania seeda", e);
}
timeoutId = setTimeout(() => setRunTour(true), 1500);
}
};
initDashboard();
return () => {
if (timeoutId) clearTimeout(timeoutId);
};
}, []);
// Używamy domyślnych, globalnych kroków zdefiniowanych w OnboardingTour
const { isError } = useQuery({
queryKey: ['subscription'],
queryFn: getSubscriptionStatus,
retry: false
});
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', position: 'relative' }}>
<AnimatePresence>
{isError && (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
style={{
position: 'absolute',
top: '1rem',
right: '1rem',
background: 'rgba(245, 158, 11, 0.1)',
border: '1px solid var(--accent-orange)',
color: 'var(--accent-orange)',
padding: '0.4rem 0.8rem',
borderRadius: '20px',
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
fontSize: '0.75rem',
fontWeight: 'bold',
zIndex: 100,
backdropFilter: 'blur(10px)'
}}
>
<WifiOff size={14} /> Tryb Offline (Mock)
</motion.div>
)}
</AnimatePresence>
<div style={{ flex: 1, overflowY: 'auto' }}>
{projects.length === 0 ? (
<div style={{ padding: '3rem', maxWidth: '1200px', margin: '0 auto', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<EmptyProjectsState onCreateClick={() => setShowWizard(true)} />
</div>
) : (
<>
<header className="main-header" style={{ alignItems: 'flex-start' }}>
<div>
<div style={{ fontSize: '0.75rem', color: 'var(--accent-blue)', letterSpacing: '1px', textTransform: 'uppercase', marginBottom: '0.4rem', fontWeight: 600 }}>Projekt Dotacyjny • {projects[0].status === 'completed' ? 'Zakończony' : 'W Trakcie'}</div>
<h1 className="main-title" style={{ fontSize: '1.4rem', margin: 0, fontWeight: 700 }}>Przegląd Dotacji</h1>
</div>
<ProgressStepper activeStep={
projects[0].status === 'completed' ? 5 :
(projects[0].sections && projects[0].sections.length > 0) ? (projects[0].sections.every(s => s.is_approved) ? 5 : 4) :
projects[0].program_name ? 3 :
projects[0].description ? 2 : 1
} />
</header>
<div className="main-content-scroll" style={{ paddingTop: '1rem' }}>
<DashboardHome />
</div>
</>
)}
</div>
{runTour && (
<OnboardingTour
run={runTour}
onFinish={() => {
setRunTour(false);
localStorage.setItem('has_seen_tour_dashboard', 'true');
}}
/>
)}
{showWizard && <WizardModal onClose={() => setShowWizard(false)} />}
</div>
);
};
export default Dashboard;