// Prodz — App shell. Provides language + navigation context, the 5-item // bottom nav (Home · Network · Crea · Shoutouts · Threads), global top-bar // surfaces (Inbox · Profile), detail stack, and the conversation funnel: // Shoutouts "Rispondi" + Network "Collab" -> Collab Proposal -> Inbox. const { useState: useStateA, useMemo: useMemoA, useEffect: useEffectA } = React; function AppShell() { const { L } = useL(); const { BottomNav } = window.ProdzDesignSystem_d0b87b; const [onboarded, setOnboarded] = useStateA(false); const [tab, setTab] = useStateA('home'); const [stack, setStack] = useStateA([]); // overlay routes const [conversations, setConversations] = useStateA(() => CONVERSATIONS.map((c) => ({ ...c }))); const [recs, setRecs] = useStateA(() => RECS_SEED); const [moodboards, setMoodboards] = useStateA(() => [ { id: 'mb1', name: { it: 'Riferimenti luce', en: 'Lighting refs' }, cover: IMG.fashion, items: [{ t: 'production', id: 'noir' }, { t: 'location', id: 'loft' }, { t: 'moment', id: 'm2' }, { t: 'gear', id: 'g3' }] }, { id: 'mb2', name: { it: 'Location moda', en: 'Fashion locations' }, cover: IMG.interior, items: [{ t: 'location', id: 'loft' }, { t: 'location', id: 'rooftop' }, { t: 'production', id: 'luce' }] }, { id: 'mb3', name: { it: 'Da provare', en: 'To try' }, cover: IMG.studio, items: [{ t: 'gear', id: 'g5' }, { t: 'moment', id: 'm5' }] }] ); const [toast, setToast] = useStateA(null); const [collabFor, setCollabFor] = useStateA(null); // person -> Collab chooser sheet const toastTimer = React.useRef(null); const fireToast = (msg, actionLabel, onAction) => { if (toastTimer.current) clearTimeout(toastTimer.current); setToast({ msg, actionLabel, onAction }); toastTimer.current = setTimeout(() => setToast(null), 3600); }; const newConv = (conv) => { setConversations((cs) => [conv, ...cs]); setStack((s) => [...s, { name: 'conversation', params: { id: conv.id } }]); }; const nav = useMemoA(() => ({ conversations, get inboxCount() {return conversations.reduce((n, c) => n + (c.unread || 0), 0);}, goTab: (id) => {setStack([]);setTab(id);}, pop: () => setStack((s) => s.slice(0, -1)), openInbox: () => setStack((s) => [...s, { name: 'inbox' }]), openProfile: (id) => setStack((s) => [...s, { name: 'profile', params: { id } }]), openThread: (id) => setStack((s) => [...s, { name: 'thread', params: { id } }]), openSaved: () => setStack((s) => [...s, { name: 'saved' }]), openLocations: () => setStack((s) => [...s, { name: 'locations' }]), openAllProductions: () => setStack((s) => [...s, { name: 'allProductions' }]), openProduction: (id) => setStack((s) => [...s, { name: 'production', params: { id } }]), openStories: (i = 0) => setStack((s) => [...s, { name: 'stories', params: { i } }]), moodboards, recs, recOf: (id) => recs[id] || { sum: 0, count: 0 }, recommend: (id, stars, text) => setRecs((r) => { const cur = r[id] || { sum: 0, count: 0, entries: [] }; const entry = { by: 'me', stars, time: { it: 'adesso', en: 'now' }, text: text && text.trim() ? { it: text.trim(), en: text.trim() } : null }; return { ...r, [id]: { sum: cur.sum + stars, count: cur.count + 1, entries: [entry, ...(cur.entries || [])] } }; }), openConversation: (id) => { setConversations((cs) => cs.map((c) => c.id === id ? { ...c, unread: 0 } : c)); setStack((s) => [...s, { name: 'conversation', params: { id } }]); }, toast: fireToast, // Shoutouts "Rispondi" -> creates a Collab Proposal / Job Call conversation replyShoutout: (card) => { const first = card.author.split(' ')[0]; newConv({ id: 'conv-' + Date.now(), person: card.person || null, org: card.person ? null : card.author, kind: card.kind, subject: card.title, unread: 0, time: { it: 'adesso', en: 'now' }, preview: { it: 'Conversazione avviata dai Shoutouts', en: 'Conversation started from Shoutouts' }, messages: [ { me: true, time: L('adesso', 'now'), text: { it: 'Ciao! Mi interessa: ' + card.title.it + '. Possiamo parlarne?', en: 'Hi! I’m interested in: ' + card.title.en + '. Can we talk?' } }, { me: false, time: L('adesso', 'now'), text: { it: 'Perfetto, parliamone. Che disponibilità hai?', en: 'Great, let’s talk. What’s your availability?' } }] }); fireToast(L('Risposta inviata · è nell’Inbox', 'Reply sent · it’s in your Inbox'), null); }, // Network / Profile "Collab" -> opens a chooser (Invite to job / Collab proposal) sendCollab: (person) => setCollabFor(person) }), [conversations, recs, moodboards, L]); if (!onboarded) { return (