You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
9.6 KiB
TypeScript

import { sendJSON } from '@/client/utils'
import type { Room, RoomData } from '@/db/model'
import { type Action, type ActionAnswer, type ActionJolly } from '@/ggwp'
import { formatDate, parse } from 'date-fns'
import { useState } from 'preact/hooks'
import { Clock } from './time'
type Outcome = 'correct' | 'partial' | 'wrong'
export const SubmitActionAnswer = ({
room,
sendAction,
onTeamQuestionIndex,
}: {
room: RoomData
sendAction: (action: Action) => void
onTeamQuestionIndex?: Receiver<{ team: string; question: string }>
}) => {
const [answer, setAnswer] = useState<Omit<ActionAnswer, 'timestamp'>>({
question: '',
team: '',
outcome: 'correct',
})
onTeamQuestionIndex?.('SubmitActionAnswer', ({ team, question }) => {
console.log('onTeamQuestionIndex', team, question)
setAnswer(answer => ({ ...answer, team, question }))
})
return (
<div class="card tint-green stack-v center">
<h3>
Invia Risposta Immediata (<Clock />)
</h3>
<select
class="fill-w"
placeholder="Domanda..."
value={answer.question}
onInput={e => setAnswer({ ...answer, question: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona domanda...
</option>
{room.questions.map((question, i) => (
<option value={question.id} key={i}>
{question.id}
</option>
))}
</select>
<select
class="fill-w"
placeholder="Squadra..."
value={answer.team}
onInput={e => setAnswer({ ...answer, team: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona squadra...
</option>
{room.teams.map((team, i) => (
<option value={team} key={i}>
{team}
</option>
))}
</select>
<select
class="fill-w"
value={answer.outcome}
onInput={e => setAnswer({ ...answer, outcome: e.currentTarget.value as Outcome })}
>
<option value="correct">Corretta</option>
<option value="partial">Parziale</option>
<option value="wrong">Sbagliata</option>
</select>
<div class="stack-h">
<button
onClick={() =>
sendAction({
...answer,
type: 'answer',
timestamp: new Date().toISOString(),
})
}
>
Invia risposta
</button>
</div>
</div>
)
}
export const SubmitActionAnswerAtTime = ({
room,
sendAction,
onTeamQuestionIndex,
}: {
room: RoomData
sendAction: (action: Action) => void
onTeamQuestionIndex?: Receiver<{ team: string; question: string }>
}) => {
type ActionTimeAnswer = Omit<ActionAnswer, 'timestamp'> & { timestampRaw: string }
const [answer, setAnswer] = useState<ActionTimeAnswer>({
timestampRaw: '',
question: '',
team: '',
outcome: 'correct',
})
onTeamQuestionIndex?.('SubmitActionAnswerAtTime', ({ team, question }) => {
console.log('onTeamQuestionIndex', team, question)
setAnswer(answer => ({ ...answer, team, question }))
})
return (
<div class="card tint-green stack-v center">
<h3>Invia Risposta al Tempo</h3>
<div class="stack-h fill-w">
<input
type="text"
class="fill"
placeholder={'Tempo in formato HH:mm:ss...'}
value={answer.timestampRaw}
onInput={e => setAnswer({ ...answer, timestampRaw: e.currentTarget.value })}
/>
<button onClick={() => setAnswer({ ...answer, timestampRaw: formatDate(new Date(), 'HH:mm:ss') })}>
Aggiorna Tempo
</button>
</div>
<select
class="fill-w"
placeholder="Domanda..."
value={answer.question}
onInput={e => setAnswer({ ...answer, question: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona domanda...
</option>
{room.questions.map((question, i) => (
<option value={question.id} key={i}>
{question.id}
</option>
))}
</select>
<select
class="fill-w"
placeholder="Squadra..."
value={answer.team}
onInput={e => setAnswer({ ...answer, team: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona squadra...
</option>
{room.teams.map((team, i) => (
<option value={team} key={i}>
{team}
</option>
))}
</select>
<select
class="fill-w"
value={answer.outcome}
onInput={e => setAnswer({ ...answer, outcome: e.currentTarget.value as Outcome })}
>
<option value="correct">Corretta</option>
<option value="partial">Parziale</option>
<option value="wrong">Sbagliata</option>
</select>
<div class="stack-h">
<button
onClick={() => {
if (answer.timestampRaw.trim() === '') {
alert('Inserisci un tempo valido')
return
}
sendAction({
...answer,
type: 'answer',
timestamp: parse(answer.timestampRaw, 'HH:mm:ss', new Date()).toISOString(),
})
}}
>
Invia risposta
</button>
</div>
</div>
)
}
type Receiver<T> = (key: string, cb: (data: T) => void) => void
export const SubmitActionJolly = ({
room,
sendAction,
onTeamQuestionIndex,
}: {
room: RoomData
sendAction: (action: Action) => void
onTeamQuestionIndex?: Receiver<{ team: string; question: string }>
}) => {
const groupsMap: Record<string, boolean> = {}
room.questions.forEach(question => {
groupsMap[question.group] = true
})
const groups = Object.keys(groupsMap)
const questionToGroup: Record<string, string> = {}
room.questions.forEach(question => {
questionToGroup[question.id] = question.group
})
const [answer, setAnswer] = useState<Omit<ActionJolly, 'timestamp'>>({
team: '',
group: '',
})
onTeamQuestionIndex?.('SubmitActionJolly', ({ team, question }) => {
console.log('onTeamQuestionIndex', team, question)
setAnswer(answer => ({ ...answer, team, group: questionToGroup[question] }))
})
return (
<div class="card tint-gold stack-v center">
<h3>Invia Jolly</h3>
<select
class="fill-w"
placeholder="Squadra..."
value={answer.team}
onInput={e => setAnswer({ ...answer, team: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona squadra...
</option>
{room.teams.map((team, i) => (
<option value={team} key={i}>
{team}
</option>
))}
</select>
<select
class="fill-w"
placeholder="Gruppo..."
value={answer.group}
onInput={e => setAnswer({ ...answer, group: e.currentTarget.value })}
>
<option value="" disabled>
Seleziona gruppo...
</option>
{groups.map(group => (
<option value={group}>{group}</option>
))}
</select>
<button
onClick={() =>
sendAction({
...answer,
type: 'jolly',
timestamp: new Date().toISOString(),
})
}
>
Imposta jolly
</button>
</div>
)
}
export const SubmitAction = ({
room,
refreshRoom,
onTeamQuestionIndex,
}: {
room: Room
refreshRoom: () => void
onTeamQuestionIndex?: Receiver<{ team: string; question: string }>
}) => {
const sendAction = async (action: Action) => {
await sendJSON(`/api/room/${room.id}/action`, action)
refreshRoom()
}
if (!room) {
return <div>Loading...</div>
}
return (
<>
<SubmitActionAnswer room={room} sendAction={sendAction} onTeamQuestionIndex={onTeamQuestionIndex} />
<SubmitActionAnswerAtTime room={room} sendAction={sendAction} onTeamQuestionIndex={onTeamQuestionIndex} />
<SubmitActionJolly room={room} sendAction={sendAction} onTeamQuestionIndex={onTeamQuestionIndex} />
</>
)
}