/* ============================================================ screen_stories.jsx — Home: weekly pulse + swipeable Stories ============================================================ */ /* ---------- mini sparkline (animated draw) ---------- */ function Spark({ color = 'var(--amber)', w = 120, h = 40 }) { const pts = [6, 9, 7, 12, 10, 16, 14, 20, 24]; const max = Math.max(...pts), min = Math.min(...pts); const d = pts.map((p, i) => { const x = (i / (pts.length - 1)) * w; const y = h - ((p - min) / (max - min)) * (h - 6) - 3; return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)} ${y.toFixed(1)}`; }).join(' '); return ( ); } /* ---------- story card content by type ---------- */ function StoryContent({ s, lang, t, go, onClose }) { const valueNum = useCountUp(s.value || s.delta || (s.big ? +s.big : 0), 1100, true); return (
{tr(s.kicker, lang)}
{s.type === 'value' && (
{tr(s.title, lang)}
{fmtSum(valueNum)} {t.perMonth}
+{s.trend}% {t.thisWeek}
)} {s.type === 'watchers' && (
{valueNum}
{tr(s.title, lang)}
{[0,1,2,3,4].map(i => ( ))}
)} {s.type === 'demand' && (
{tr(s.title, lang)}
{[40, 52, 48, 66, 72, 88, 100].map((h, i) => (
= 5 ? 'linear-gradient(var(--amber-soft),var(--amber))' : 'rgba(255,255,255,.18)', animation: `barGrow .6s var(--ease-out) ${0.3 + i*0.07}s both` }} /> ))}
+{s.delta}%
)} {s.type === 'role' && (
{s.match}
{tr(s.title, lang)}
{brandName(s.company)}
)} {s.type === 'gap' && (
{tr(s.title, lang)}
)} {s.type === 'progress' && (
{tr(s.title, lang)}
{[0,1,2,3,4].map(i => ( ))}
)}
{tr(s.sub, lang)}
{(s.type === 'role' || s.type === 'watchers' || s.type === 'gap') && ( )}
); } /* ---------- fullscreen story viewer ---------- */ function StoryViewer({ start, onClose, lang, t, go }) { const [i, setI] = useState(start || 0); const [paused, setPaused] = useState(false); const [prog, setProg] = useState(0); const raf = useRef(null); const last = useRef(0); const DUR = 5200; useEffect(() => { setProg(0); last.current = 0; }, [i]); useEffect(() => { const tick = (ts) => { if (!last.current) last.current = ts; const dt = ts - last.current; last.current = ts; if (!paused) { setProg(p => { const n = p + dt / DUR; if (n >= 1) { if (i < STORIES.length - 1) { setI(i + 1); return 0; } else { setTimeout(onClose, 0); return 1; } } return n; }); } raf.current = requestAnimationFrame(tick); }; raf.current = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf.current); }, [i, paused]); const s = STORIES[i]; const next = () => { if (i < STORIES.length - 1) setI(i + 1); else onClose(); }; const prev = () => { if (i > 0) setI(i - 1); else setProg(0); }; return (
{/* decorative glow */}
{/* progress bars */}
{STORIES.map((_, k) => (
))}
{/* header */}
{t.weeklyPulse}
{/* tap zones */}
setPaused(true)} onPointerUp={() => setPaused(false)} onPointerLeave={() => setPaused(false)}>
); } /* ---------- story rail bubble ---------- */ function StoryBubble({ s, lang, onOpen, seen }) { const label = { value: { ru: 'Неделя', uz: 'Hafta' }, watchers: { ru: 'Тебя ищут', uz: 'Qidirishyapti' }, demand: { ru: 'Спрос', uz: 'Talab' }, role: { ru: 'Роль', uz: 'Rol' }, gap: { ru: 'Шаг', uz: 'Qadam' }, progress: { ru: 'Рост', uz: 'Rivoj' } }[s.type]; const icon = { value: 'trend', watchers: 'eye', demand: 'spark', role: 'briefcase', gap: 'fire', progress: 'trend' }[s.type]; return ( ); } /* ---------- home screen ---------- */ function StoriesScreen({ lang, theme, setLang, setTheme, t, go, status }) { const [viewer, setViewer] = useState(null); // start index or null const [seen, setSeen] = useState([]); const hero = STORIES[0]; const heroVal = useCountUp(hero.value, 1100, true); const open = (k) => { setViewer(k); setSeen(p => [...new Set([...p, k])]); }; return (
{viewer !== null && setViewer(null)} lang={lang} t={t} go={go} />}
} t={t} />
{/* story rail */}
{STORIES.map((s, k) => open(k)} seen={seen.includes(k)} />)}
{/* pulse hero */} {/* feed cards */} open(1)} icon="eye" color="var(--indigo-500)" delay={.08} big="14" title={t.seen} sub={tr(STORIES[1].sub, lang)} lang={lang} /> open(2)} icon="trend" color="var(--good)" delay={.14} big="+12%" title={t.demand} sub={tr(STORIES[2].sub, lang)} lang={lang} /> { setViewer(null); go('jobs'); }} icon="briefcase" color="var(--amber-deep)" delay={.2} big="92%" title={tr({ ru: 'Новая роль · SMM-менеджер', uz: 'Yangi rol · SMM menejer' }, lang)} sub={tr(STORIES[3].sub, lang)} lang={lang} /> {/* who viewed you */} {/* companies hiring rail */}
{t.companiesHiring}
{VIEWERS.map(b => ( ))}
); } function FeedCard({ icon, color, big, title, sub, onClick, delay = 0 }) { return ( ); } Object.assign(window, { StoriesScreen, StoryViewer });