import { InfoCardProps } from '@junwon/centum' import { Page } from '@my/ui' import usePageOpener from 'app/utils/catalog/usePageOpener' import { getServerAddress } from 'app/utils/getServerAddress' import { EventSourcePolyfill as EventSource } from 'event-source-polyfill' import React, { useEffect, useState, useCallback } from 'react' import { useParams } from 'solito/navigation' export const TopicPage = () => { const params = useParams() const { openTopicPage } = usePageOpener() const [title, setTitle] = useState('Title') const [headline, setHeadline] = useState('This is a cool headline') const [cards, setCards] = useState([]) const [loading, setLoading] = useState(true) const [streamId, setStreamId] = useState(null) const fetchTopicData = useCallback(async () => { if (params?.title) { setTitle('Loading') setHeadline('I am checking the catalog to see if we have info on this topic.') setLoading(true) const serverAddress = getServerAddress() try { const url = `${serverAddress}/topic/${params.title}` const response = await fetch(url, { method: 'POST' }) const contentType = response.headers.get('content-type') if (contentType && contentType.includes('application/json')) { const data = await response.json() if (data.action === 'render_post_data') { const post_data = data.post_data setTitle(post_data.title || 'Title') setHeadline(post_data.headline || 'Headline') setCards(post_data.cards || []) } else if (data.action === 'inform_missing_topic') { setStreamId(data.stream_id) setTitle(data.topic_top_candidate) setHeadline( 'You have reached a topic which no one has reached yet in the history of this site. (Congratulations!). I am sorry that we do not have info ready yet. Please give me one more chance to satisfy you by checking again tomorrow. If you have any other asks, you can text me using the link in the control page (click the menu button on the home page)!' ) setCards(data.cards || []) } else { console.warn('Unexpected Server Response:', data.action) } } else { console.error('Unexpected content type:', contentType) } } catch (error) { console.error('Error fetching topic data:', error) } finally { setLoading(false) } } }, [params]) useEffect(() => { fetchTopicData() }, [params, fetchTopicData]) useEffect(() => { if (streamId) { const serverAddress = getServerAddress() const eventSource = new EventSource(`${serverAddress}/stream/${streamId}`, { withCredentials: true, }) eventSource.onmessage = (event) => { const eventData = event.data try { const data = JSON.parse(eventData) if (data.action === 'content_generated') { const post_data = data.post setTitle(post_data.title || 'Title') setHeadline(post_data.headline || 'Headline') setCards(post_data.cards || []) eventSource.close() } } catch (error) { console.error('Error processing stream message:', error) } } eventSource.onerror = (error) => { console.error('EventSource error:', error) eventSource.close() } return () => { if (eventSource.readyState !== EventSource.CLOSED) { eventSource.close() } } } }, [streamId]) const handleLinkPress = (destination_topic: string) => { openTopicPage(destination_topic) } return ( ({ ...card, onLinkPress: handleLinkPress }))} showBackButton showLoading={loading} /> ) }