Spaces:
Running
Running
File size: 4,462 Bytes
afd56bc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | import React, { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { Sparkles, ArrowRight, X } from 'lucide-react';
interface OnboardingWelcomeModalProps {
onComplete: () => void;
}
export const OnboardingWelcomeModal: React.FC<OnboardingWelcomeModalProps> = ({ onComplete }) => {
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
const hasSeenWelcome = localStorage.getItem('has_seen_welcome');
if (!hasSeenWelcome) {
setIsOpen(true);
}
}, []);
const handleClose = () => {
localStorage.setItem('has_seen_welcome', 'true');
setIsOpen(false);
onComplete();
};
if (!isOpen) return null;
return createPortal(
<AnimatePresence>
{isOpen && (
<div style={{
position: 'fixed',
top: 0, left: 0, right: 0, bottom: 0,
background: 'rgba(0,0,0,0.8)',
backdropFilter: 'blur(10px)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 99999
}}>
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
className="glass-card"
style={{ position: 'relative', width: '100%', maxWidth: '600px', margin: '1rem', padding: '3rem', textAlign: 'center' }}
>
<button
onClick={handleClose}
style={{ position: 'absolute', top: '1.5rem', right: '1.5rem', background: 'transparent', border: 'none', color: 'var(--text-muted)', cursor: 'pointer' }}
className="hover-lift"
>
<X size={24} />
</button>
<div style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '64px', height: '64px', borderRadius: '50%', background: 'linear-gradient(135deg, var(--accent-blue), var(--accent-purple))', marginBottom: '2rem' }}>
<Sparkles size={32} color="#fff" />
</div>
<h2 style={{ fontSize: '2.5rem', fontWeight: 800, marginBottom: '1rem', color: 'var(--text-primary)' }}>Witaj w GrantForge Enterprise 2.0</h2>
<p style={{ fontSize: '1.1rem', color: 'var(--text-secondary)', lineHeight: '1.6', marginBottom: '2.5rem' }}>
Jesteś zaledwie o krok od automatyzacji procesu pisania wniosków unijnych. Nasz system potrafi przygotować kompletną strukturę pod programy takie jak <strong>Ścieżka SMART</strong> w kilka minut.
</p>
<div style={{ display: 'flex', gap: '1rem', justifyContent: 'center' }}>
<button
onClick={() => {
localStorage.setItem('has_seen_tour_dashboard', 'true');
localStorage.setItem('has_seen_tour_workspace', 'true');
handleClose();
}}
className="btn hover-lift"
style={{
padding: '1rem 2rem',
fontSize: '1rem',
fontWeight: 600,
borderRadius: '12px',
background: 'transparent',
color: 'var(--text-secondary)',
border: '1px solid var(--border)',
cursor: 'pointer'
}}
>
Pomiń onboarding
</button>
<button
onClick={handleClose}
className="btn hover-lift"
style={{
padding: '1rem 3rem',
fontSize: '1.1rem',
fontWeight: 800,
borderRadius: '12px',
background: 'var(--accent-green)',
color: '#000',
border: 'none',
display: 'inline-flex',
alignItems: 'center',
gap: '0.6rem',
cursor: 'pointer'
}}
>
Zaczynajmy <ArrowRight size={20} />
</button>
</div>
</motion.div>
</div>
)}
</AnimatePresence>,
document.body
);
};
|