// thread-view.jsx — Thread view with newest-first sort. // Each reply is its own card with the parent attached below as a quoted card. // Thread starter (oldest) sits at the bottom of the feed. function ThreadView({ dark }) { const t = useTheme(dark); // Thread starter — original prediction post const starter = { id: 'p1', name: 'PapaSmurf', acc: '78%', when: '2h ago', badge: 'TOP 1%', prediction: { dir: 'Buy', tp: 268, conf: 9 }, body: 'AWS revenue growth re-accelerating + ad business compounding. Q2 setup looks like a blowout vs sandbagged guidance. Holding through earnings, adding on any pullback under €220.', likes: 47, replies: 12, isStarter: true, }; // Replies, newest first const replies = [ { id: 'st', name: 'Stefan', acc: '52%', when: '2m', replyTo: 'PapaSmurf', body: 'You might be underweighting FX on AWS — but if the dollar keeps weakening, that\'s actually a tailwind for next quarter. Bullish in disguise?', likes: 0, isYou: true, }, { id: 'in', name: 'Investorin_DE', acc: '49%', when: '8m', replyTo: 'PapaSmurf', body: 'Macht hier jemand covered calls vor den Earnings? IV ist gerade richtig hoch.', likes: 2, }, { id: 'b', name: 'Bankster', acc: '64%', when: '24m', replyTo: 'fenjal', prediction: { dir: 'Sell', tp: 195, conf: 6 }, body: 'Disagree on the margin story. Ad business is decelerating QoQ, multiple is still stretched vs historical average.', likes: 4, }, { id: 'f', name: 'fenjal', acc: '71%', when: '34m', replyTo: 'PapaSmurf', prediction: { dir: 'Buy', tp: 255, conf: 7 }, body: 'Adding my view: cost discipline + ad business is the real story here. Stop watching FTC, watch NA retail margins.', likes: 9, }, { id: 'p2', name: 'PapaSmurf', acc: '78%', when: '40m', replyTo: 'Lisa_K', isOP: true, body: 'Fair question. My view: even if they lose, structural separation would take 5+ years to litigate. We hold through Q2 first, then re-assess.', likes: 12, }, { id: 'm', name: 'Mike_T', acc: '61%', when: '52m', replyTo: 'Lisa_K', body: 'The ruling is more nuanced than headlines suggest. Even a worst-case outcome is fines + behavioral remedies, not a structural breakup.', likes: 3, }, { id: 'l', name: 'Lisa_K', acc: '54%', when: '1h 12m', replyTo: 'PapaSmurf', body: 'How are you thinking about the FTC overhang? Feels like a real risk before the EOY ruling — could compress the multiple even if fundamentals deliver.', likes: 8, }, ]; // Lookup parent by name for the attached-quote rendering const allPosts = [starter, ...replies]; const byName = {}; allPosts.forEach(p => { if (!byName[p.name]) byName[p.name] = p; }); return (
{/* Header */}
{Icon.back(t.text, 22)}
Thread
12 replies · started by @PapaSmurf
{ActIcon.more(t.text, 20)}
{/* AMZN context strip */}
Amazon.com AMZN · NASDAQ
€227.35 −1.50%
{/* Sort header */}
Activity Sort: Newest first
{/* Newest-first feed: replies, then thread starter at the bottom */}
{replies.map(r => ( ))} {/* Thread starter, anchored at the end (oldest) */}
{/* Sticky composer at bottom */}
Reply to the thread…
{Icon.plus(t.bg, 11)}Predict
); } // ───────────────────────── Reply card with attached parent quote ───────────────────────── function ReplyCard({ t, reply, parent }) { const r = reply; const hasPred = !!r.prediction; const up = hasPred && r.prediction.dir === 'Buy'; const dn = hasPred && r.prediction.dir === 'Sell'; const predColor = up ? t.up : dn ? t.down : t.text; const delta = hasPred ? ((r.prediction.tp - 227.35) / 227.35 * 100).toFixed(1) : null; return (
{/* Author row */}
{r.isYou ? 'You' : r.name} {r.isOP && ( OP )} {r.when}
{r.acc} accuracy
{/* "Replying to @X" indicator */} {r.replyTo && (
{ActIcon.reply(t.textDim, 11)} Replying to @{r.replyTo}
)} {/* Optional prediction pill */} {hasPred && (
{up ? Icon.arrowUp(predColor, 10) : Icon.arrowDown(predColor, 10)} {r.prediction.dir.toUpperCase()} €{r.prediction.tp} {delta > 0 ? '+' : ''}{delta}%
)} {/* Reply body */}
{r.body}
{/* Attached parent quote */} {parent && } {/* Actions */}
{Icon.heart(t.textDim, 14)} {r.likes} Reply {ActIcon.share2(t.textDim, 13)}
); } // ───────────────────────── Attached parent quote — compact ───────────────────────── function QuotedParent({ t, parent }) { const p = parent; const hasPred = !!p.prediction; const up = hasPred && p.prediction.dir === 'Buy'; const predColor = up ? t.up : t.down; const delta = hasPred ? ((p.prediction.tp - 227.35) / 227.35 * 100).toFixed(1) : null; return (
{p.name} {p.badge && ( {p.badge} )} {p.when}
{hasPred && (
{p.prediction.dir.toUpperCase()} €{p.prediction.tp} {delta > 0 ? '+' : ''}{delta}%
)} {/* Truncated body */}
{p.body}
); } // ───────────────────────── Thread starter card (oldest, at the bottom) ───────────────────────── function ThreadStarterCard({ t, post: p }) { const hasPred = !!p.prediction; const up = hasPred && p.prediction.dir === 'Buy'; const predColor = up ? t.up : t.down; const delta = hasPred ? ((p.prediction.tp - 227.35) / 227.35 * 100).toFixed(1) : null; return (
{/* "Thread starter" badge at top */}
Thread starter
{p.name} {p.badge && ( {p.badge} )}
{p.acc} accuracy · {p.when}
+ Follow
{hasPred && (
{up ? Icon.arrowUp(predColor, 11) : Icon.arrowDown(predColor, 11)} {p.prediction.dir.toUpperCase()} €{p.prediction.tp} {delta > 0 ? '+' : ''}{delta}% · conf {p.prediction.conf}/10
)}
{p.body}
{Icon.heart(t.textDim, 14)} {p.likes} {ActIcon.reply(t.text, 14)} {p.replies} {ActIcon.share2(t.textDim, 14)}
); } Object.assign(window, { ThreadView });