From 114ed1cb95a9ea02b031cb71e1b19b5b4fa73e88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 Aug 2025 17:07:29 +0000 Subject: [PATCH 1/4] Initial plan From 46c14344835fcd7c5dbfcc37eeb12201d232663b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 Aug 2025 17:21:52 +0000 Subject: [PATCH 2/4] feat: implement start page with Create/Join room forms - Replace test implementation with proper start page - Add Create Room button with API integration - Add Join Room form with UUID validation - Implement responsive layout and error handling - Add loading states for better UX Co-authored-by: underscorekadji <3449713+underscorekadji@users.noreply.github.com> --- src/app/page.tsx | 270 ++++++++++++++++++++++++++--------------------- 1 file changed, 149 insertions(+), 121 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index fe5e929..f230ad6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,85 +1,61 @@ 'use client' -import { useState, useEffect, useRef } from 'react' - -export default function HomePage() { - const [text, setText] = useState('') - const [receivedText, setReceivedText] = useState('') - const [connectionStatus, setConnectionStatus] = useState< - 'connecting' | 'connected' | 'disconnected' - >('connecting') - const [testRoomId, setTestRoomId] = useState('') - const [clientId, setClientId] = useState('') - const eventSourceRef = useRef(null) - - useEffect(() => { - // Use fixed room for testing - all tabs will share the same room - const roomId = 'test-room' - const generatedClientId = Math.random().toString(36).substring(2, 15) - - setTestRoomId(roomId) - setClientId(generatedClientId) - - // Use Server-Sent Events for real-time updates - const eventSource = new EventSource(`/api/live-text?room=${roomId}&client=${generatedClientId}`) - eventSourceRef.current = eventSource - - eventSource.onopen = () => { - console.info('Connected to live text stream') - setConnectionStatus('connected') - } - - eventSource.onmessage = event => { - const data = JSON.parse(event.data) - - if (data.clientId !== generatedClientId) { - setReceivedText(data.text) +import { useState } from 'react' + +export default function StartPage() { + const [joinRoomId, setJoinRoomId] = useState('') + const [isCreating, setIsCreating] = useState(false) + const [isJoining, setIsJoining] = useState(false) + const [errorMessage, setErrorMessage] = useState('') + + const handleCreateRoom = async () => { + setIsCreating(true) + setErrorMessage('') + + try { + const response = await fetch('/api/room', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + throw new Error('Failed to create room') } - } - eventSource.onerror = () => { - setConnectionStatus('disconnected') + const result = (await response.json()) as { roomId: string } + window.location.href = `/room/${result.roomId}` + } catch (error) { + console.error('Error creating room:', error) + setErrorMessage('Failed to create room. Please try again.') + } finally { + setIsCreating(false) } + } - return () => { - eventSource.close() - } - }, []) + const handleJoinRoom = (e: React.FormEvent) => { + e.preventDefault() + setIsJoining(true) + setErrorMessage('') - const handleTextChange = async (newText: string) => { - setText(newText) + const trimmedRoomId = joinRoomId.trim() - // Send text update via POST request - if (connectionStatus === 'connected') { - try { - await fetch('/api/live-text', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - room: testRoomId, - text: newText, - clientId: clientId, - }), - }) - } catch (error) { - console.error('Failed to send text update:', error) - } + if (!trimmedRoomId) { + setErrorMessage('Please enter a room ID') + setIsJoining(false) + return } - } - const getStatusColor = () => { - switch (connectionStatus) { - case 'connected': - return 'text-green-600' - case 'connecting': - return 'text-yellow-600' - case 'disconnected': - return 'text-red-600' - default: - return 'text-gray-600' + // Basic UUID format validation + const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i + if (!uuidPattern.test(trimmedRoomId)) { + setErrorMessage('Please enter a valid room ID (UUID format)') + setIsJoining(false) + return } + + window.location.href = `/room/${trimmedRoomId}` } return ( @@ -89,71 +65,123 @@ export default function HomePage() {

Welcome to Wheel

-

+

Real-time spinning wheel app for presenter selection

-
- Socket Status: - {connectionStatus} -
-
+
+ {/* Create New Room Section */} +
+

+ Create New Room +

+

+ Start a new session and invite others to join +

+ +
+ + {/* Join Room Section */}
-

- Live Text Test +

+ Join Existing Room

-
+

+ Enter the room ID to join an existing session +

+
-