Untitled

mail@pastecode.io avatar
unknown
plain_text
23 days ago
8.2 kB
2
Indexable
Never
'use client'

import { socket } from '@/app/(frontend)/app/quiz/live/socket'
import PageHeader from '@/app/shared/page-header'
import { Response } from '@/types'
import updateData from '@/utils/fetch/updateData'
import { useSession } from 'next-auth/react'
import { useParams } from 'next/navigation'
import { MouseEventHandler, useEffect, useState } from 'react'
import toast from 'react-hot-toast'
import { Button } from 'rizzui'
import Links from './Links'
import Players from './Players'
import Question from './Question'
import Statistics from './Statistics'

let popup = false

export default function LiveQuizArea({ data, liveQuiz }: any) {
  const { id }: { id: string } = useParams()
  let date = new Date(liveQuiz?.createdAt)

  const { data: session }: any = useSession() || ''
  const [players, setPlayers] = useState<any>([
    {
      name: 'Subroto 1',
      image: 'nai',
      _id: '1',
    },
    {
      name: 'Subroto 2',
      image: 'nai',
      _id: '2',
    },
  ])
  const [quizStatus, setQuizStatus] = useState(data.status)
  const [countdown, setCountdown] = useState(4)
  const [connected, setConnected] = useState(false)

  // console.log('new questions', questions)

  useEffect(() => console.log(connected), [connected])

  useEffect(() => {
    const onConnect = () => setConnected(true)
    const onDisconnect = () => setConnected(false)
    const handleJoined = (users: any) => setPlayers(users)
    const handleStatus = (status: any) => console.log(status)
    const handleError = (error: any) => console.error(error)
    const handleLeaderboard = (data: any) => console.log(data)

    socket.on('connect', onConnect)
    socket.on('disconnect', onDisconnect)
    socket.on('joined', handleJoined)
    socket.on('status', handleStatus)
    socket.on('leaderboard', handleLeaderboard)
    socket.on('error', handleError)

    return () => {
      socket.off('connect', onConnect)
      socket.off('disconnect', onDisconnect)
      socket.off('joined', handleJoined)
      socket.off('status', handleStatus)
      socket.off('leaderboard', handleLeaderboard)
      socket.off('error', handleError)
    }
  }, [])

  const handleCountdown = () => {
    if (countdown === 4) {
      setCountdown(3)
    }
    const countdownInterval = setInterval(() => {
      setCountdown((prevCountdown) => prevCountdown - 1)
    }, 1000)

    setTimeout(() => {
      clearInterval(countdownInterval)
    }, 4000)

    return () => clearInterval(countdownInterval)
  }

  const handleQuizStatus = async () => {
    const response = () => updateData(`live-quiz/status`, session?.accessToken, {}, data.quizId)

    if (popup === true) return

    toast((t) => {
      popup = t.visible

      const action = () => {
        toast.dismiss(t.id)
        toast.promise(response(), {
          loading: 'Processing...',

          success: (response: Response) => {
            console.log(response)
            if (response?.status) {
              const { status } = response.data.codeDetails
              setQuizStatus(status)
              if (status === 'running') {
                socket.emit('adminLeaderBoard', {
                  codeId: data._id,
                })

                handleCountdown()
              }
              const toggleQuiz = {
                codeId: data._id,
                status: status === 'running',
              }

              socket.emit('toggleQuiz', toggleQuiz)

              return response?.message
            }

            throw new Error(response?.message)
          },

          error: (error) => {
            if (error?.message) return error?.message
            return 'Something went wrong!'
          },
        })
      }
      return AskConfirmation(t, action, `Do you want to ${quizStatus === 'published' ? 'start' : 'end'} the quiz?`)
    })
  }

  useEffect(() => {
    const joinData = {
      codeId: data._id,
      userId: session?.id,
      name: session?.name,
      attemptId: 'admin',
      role: 'admin',
      image: session?.image,
    }
    socket.emit('joinQuiz', joinData)
  }, [data._id, id, session.id, session?.image, session?.name])

  // console.log('all data', liveQuiz)

  // console.log(date)

  return (
    <>
      <PageHeader paths={[{ name: 'Live Quizzes', href: '/admin/live-quizzes' }]} title={liveQuiz.title} />

      <div className="mb-8 grid grid-cols-1 gap-5 lg:grid-cols-2">
        {/* <button className="btn btn-primary">Hello</button> */}
        <div className="flex gap-5">
          <div className="w-full">
            <div className="flex h-full min-h-28 gap-3 overflow-hidden rounded-lg border shadow-md hover:shadow-xl">
              <img src={liveQuiz?.image} alt="live quiz image" className="w-40 rounded-md lg:w-36" />
              <div className="flex w-full flex-col gap-1 p-1">
                <p className="mb-1 text-xl font-bold opacity-90">
                  {liveQuiz?.title.length > 25 ? `${liveQuiz?.title.substring(0, 25)}...` : liveQuiz?.title}
                </p>
                <p className="text-sm">
                  <strong>Quiz Code : </strong>
                  {id}
                </p>
                {/* <p>
                  <strong>Created Time : </strong>
                  {date.toLocaleString()}
                </p> */}
                <p>
                  <strong>Questions : </strong>
                  {liveQuiz?.questionDetails.length}
                </p>
                <p>
                  <strong>Participants : </strong>
                  {players.length}
                </p>
              </div>
            </div>
          </div>
          <Statistics participants={players.length} />
        </div>

        <div className="flex w-full">
          <div className="flex w-full flex-col gap-3">
            <Links id={`${id}`} />
            <div className="flex rounded border ">
              <span className="select-none bg-gray-100 px-5 py-2 font-bold">Created Time</span>
              <span className="flex  cursor-pointer items-center gap-3 px-5 py-1">{date.toLocaleString()}</span>
            </div>
          </div>
        </div>
      </div>
      <div className="mb-4 flex items-center justify-center">
        {countdown <= 3 && countdown > 0 ? (
          <p className="my-5 text-base  font-semibold">
            The quiz will be started in {countdown} second<span className={`${countdown === 1 ? 'opacity-0' : ''}`}>s</span>
          </p>
        ) : (
          <Button
            size="lg"
            className={`my-3 ${quizStatus === 'running' ? 'bg-red-500 text-white hover:bg-red-400' : ''} disabled:bg-gray-100`}
            onClick={handleQuizStatus}
            disabled={quizStatus !== 'running' && quizStatus !== 'published'}
          >
            {quizStatus === 'published' ? 'Start Quiz' : quizStatus === 'running' ? 'End Quiz' : quizStatus === 'ended' ? 'Quiz Ended' : ''}
          </Button>
        )}
      </div>

      <div className="w-full">
        <div className="mb-3 flex bg-primary py-4 text-center text-white">
          <h1 className="w-full text-center capitalize">all Participants</h1>
          <h1 className="w-full text-center capitalize">All Quiz Questions</h1>
        </div>
        <div className="flex w-full gap-5">
          <Players participants={players} codeId={data._id} quizId={data.quizId} />
          <Question questions={liveQuiz.questionDetails} />
        </div>
      </div>
    </>
  )
}

function AskConfirmation(t: any, action: MouseEventHandler<HTMLButtonElement>, msg: string) {
  return (
    <span>
      <b className="text-xl">{msg}</b>
      <div className="mt-3 flex justify-around">
        <button className="my-1 rounded bg-primary px-3 text-lg text-white" onClick={action}>
          Confirm
        </button>

        <button className="my-1 rounded border-2 bg-gray-300 px-3 text-lg" onClick={() => toast.dismiss(t.id)}>
          Dismiss
        </button>
      </div>
    </span>
  )
}
Leave a Comment