import { GenerativePage, useThemeName } from '@my/ui' import { getServerAddress } from 'app/utils/getServerAddress' import { EventSourcePolyfill as EventSource } from 'event-source-polyfill' import React, { useEffect, useState, useCallback } from 'react' import { useRouter } from 'solito/router' import { useParams } from 'solito/navigation' export const PostPage = () => { const params = useParams() const router = useRouter() const [title, setTitle] = useState('Title') const [loading, setLoading] = useState(true) const [streamId, setStreamId] = useState(null) const [code, setCode] = useState('') const [shouldFetch, setShouldFetch] = useState(true) const themeName = useThemeName() const isDarkMode = themeName.includes('dark') const fetchPostData = useCallback( async (guideline: string) => { const serverAddress = getServerAddress() const url = `${serverAddress}/post/${params.title}` try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ generationGuideline: `${guideline}\n${isDarkMode ? 'Use dark mode colors.' : ''}`, }), }) if (!response.headers.get('content-type')?.includes('application/json')) { throw new Error('Unexpected Content Type') } const data = await response.json() if (data.action === 'render_post_data') { const { title: postTitle, generated_code } = data.post_data setTitle(postTitle || 'Title') setCode(generated_code || '') setLoading(false) } else if (data.action === 'generating_post_page') { setStreamId(data.stream_id) setTitle(data.post_title) } else { console.warn('Unexpected Server Response:', data.action) setLoading(false) } } catch (error) { console.error('Error:', error) setLoading(false) } }, [params?.title, isDarkMode] ) const initializeFetch = useCallback(async () => { if (!params?.title || !shouldFetch) return setShouldFetch(false) setTitle('Loading') setLoading(true) const guideline = `Post Title: ${params.title}` await fetchPostData(guideline) }, [params?.title, shouldFetch, fetchPostData]) const handleGuidelineSubmit = useCallback( async (guideline: string) => { if (!params?.title) return setLoading(true) await fetchPostData(guideline) }, [params?.title, fetchPostData] ) useEffect(() => { initializeFetch() }, [initializeFetch]) useEffect(() => { if (streamId) { const serverAddress = getServerAddress() const eventSource = new EventSource(`${serverAddress}/stream/${streamId}`) eventSource.onmessage = (event) => { const eventData = event.data try { const data = JSON.parse(eventData) if (data.action === 'render_post_page') { setCode(data.page_code || '') setTitle(data.page_title || '') if (data.page_link && data.page_link !== params?.title) { router.push(`/post/${data.page_link}`, undefined, { shallow: true }) } setLoading(false) 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, params?.title, router]) return ( ) }