vkashti / app / admin / quiz / components / LatestAnswers.tsx
LatestAnswers.tsx
Raw
'use client';
import { QuizAnswer } from '@/types/types';
import { useState, useEffect } from 'react';
import { FaRegClock, FaArrowRight, FaArrowLeft, FaCheck } from 'react-icons/fa';
import { motion } from 'framer-motion';
import { useSearchParams } from 'next/navigation';

type LatestAnswersProps = {
  answers: QuizAnswer[];
  onQuestionChange?: (slideNumber: number) => void;
  currentQuestionNumber?: number | null;
};

export function LatestAnswers({ answers, onQuestionChange, currentQuestionNumber = null }: LatestAnswersProps) {
  const [latestAnswers, setLatestAnswers] = useState<QuizAnswer[]>([]);
  const searchParams = useSearchParams();
  
  // For checking if we're on a special slide like instruction or answer
  const isSpecialSlide = currentQuestionNumber === null;
  
  // Sort answers by creation time (newest first) and take the latest 20
  useEffect(() => {
    // Filter answers for the current question number only
    if (currentQuestionNumber !== null) {
      // Get all answers for this question
      const answersForQuestion = answers.filter(answer => 
        answer.question_number === currentQuestionNumber
      );
      
      // Find the first submitted answer
      const sortedByOldest = [...answersForQuestion].sort((a, b) => 
        new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
      );
      
      const firstAnswer = sortedByOldest.length > 0 ? sortedByOldest[0] : null;
      
      // Get other answers (excluding the first one)
      const otherAnswers = firstAnswer 
        ? answersForQuestion.filter(a => a.id !== firstAnswer.id)
                            .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
                            .slice(0, 19) // One less to make room for the first answer
        : answersForQuestion.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
                            .slice(0, 20);
      
      // Combine first answer with others, putting first answer at the beginning
      const orderedAnswers = firstAnswer 
        ? [firstAnswer, ...otherAnswers]
        : otherAnswers;
      
      setLatestAnswers(orderedAnswers);
    } else {
      setLatestAnswers([]);
    }
  }, [answers, currentQuestionNumber]);

  // New function to check if an answer is the first submitted for its question
  const isFirstSubmittedAnswer = (answer: QuizAnswer) => {
    const answersForQuestion = answers.filter(a => a.question_number === answer.question_number);
    if (answersForQuestion.length === 0) return false;
    
    // Sort by creation time (oldest first)
    const sortedAnswers = [...answersForQuestion].sort((a, b) => 
      new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
    );
    
    // Check if this is the first answer
    return answer.id === sortedAnswers[0].id;
  };

  const handleNextQuestion = () => {
    // Get the current slide from URL
    const currentSlide = parseInt(searchParams?.get('slide') || '1');
    
    // Find the next question number in the dataset
    if (answers.length > 0) {
      const questionNumbers = Array.from(new Set(answers.map(a => a.question_number))).sort((a, b) => a - b);
      const currentIndex = currentQuestionNumber !== null ? 
        questionNumbers.indexOf(currentQuestionNumber) : -1;
      
      let nextQuestionNumber: number;
      
      if (currentIndex < questionNumbers.length - 1) {
        // Move to next question
        nextQuestionNumber = questionNumbers[currentIndex + 1];
      } else if (currentQuestionNumber !== null) {
        // If we're at the last question, move to a hypothetical next one
        nextQuestionNumber = currentQuestionNumber + 1;
      } else {
        // If no current question, start with 1
        nextQuestionNumber = 1;
      }
      
      // Update the URL with the new slide number without triggering a navigation
      // Simply increment the slide number
      const nextSlide = currentSlide + 1;
      const url = new URL(window.location.href);
      url.searchParams.set('slide', nextSlide.toString());
      window.history.pushState({}, '', url.toString());
      
      // Call onQuestionChange with the new slide number
      if (onQuestionChange) {
        onQuestionChange(nextSlide);
      }
    } else {
      // If no answers yet, simply increment the slide
      const nextSlide = currentSlide + 1;
      const url = new URL(window.location.href);
      url.searchParams.set('slide', nextSlide.toString());
      window.history.pushState({}, '', url.toString());
      
      // Call onQuestionChange with the new slide number
      if (onQuestionChange) {
        onQuestionChange(nextSlide);
      }
    }
  };

  const handlePreviousQuestion = () => {
    // Get the current slide from URL
    const currentSlide = parseInt(searchParams?.get('slide') || '1');
    
    // For special slides (instruction or answer slides)
    if (isSpecialSlide) {
      if (currentSlide > 1) {
        // Simply decrement the slide number for special slides
        const prevSlide = currentSlide - 1;
        const url = new URL(window.location.href);
        url.searchParams.set('slide', prevSlide.toString());
        window.history.pushState({}, '', url.toString());
        
        // Call onQuestionChange with the new slide number
        if (onQuestionChange) {
          onQuestionChange(prevSlide);
        }
      }
    }
    // For question slides (existing logic)
    else if (currentQuestionNumber !== null && currentQuestionNumber > 1) {
      // Find the previous question number in the dataset
      const questionNumbers = Array.from(new Set(answers.map(a => a.question_number))).sort((a, b) => a - b);
      const currentIndex = questionNumbers.indexOf(currentQuestionNumber);
      
      let prevQuestionNumber: number;
      
      if (currentIndex > 0) {
        // Move to previous question
        prevQuestionNumber = questionNumbers[currentIndex - 1];
      } else {
        // If not found in the set or at the beginning, just decrement
        prevQuestionNumber = currentQuestionNumber - 1;
      }
      
      // Update the URL with the new slide number without triggering a navigation
      // Simply decrement the slide number
      const prevSlide = Math.max(1, currentSlide - 1); // Ensure we don't go below slide 1
      const url = new URL(window.location.href);
      url.searchParams.set('slide', prevSlide.toString());
      window.history.pushState({}, '', url.toString());
      
      // Call onQuestionChange with the new slide number
      if (onQuestionChange) {
        onQuestionChange(prevSlide);
      }
    }
  };

  if (isSpecialSlide) {
    return (
      <div className="mb-8 p-6 bg-amber-50 rounded-lg border border-amber-100 text-center">
        <div className="text-lg font-semibold text-amber-800 mb-1">
          Специален слайд (инструкции или отговори)
        </div>
        <p className="text-amber-600 mb-4">
          Този слайд показва инструкции за кръг или отговори.
        </p>
      </div>
    );
  }

  // If we have a question number but no answers for this question
  if (currentQuestionNumber !== null && latestAnswers.length === 0) {
    return (
      <div className="mb-8">
        <div className="mb-4">
          <div className="text-xl font-bold text-amber-900 flex items-center gap-2">
            <FaRegClock className="text-amber-500" />
            0 отговора
          </div>
        </div>
        
        <div className="p-6 bg-amber-50 rounded-lg border border-amber-100 text-center">
          <p className="text-amber-700">
            Все още няма отговори за този въпрос.
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="mb-8">
      <div className="mb-4">
        <div className="text-xl font-bold text-amber-900 flex items-center gap-2">
          <FaRegClock className="text-amber-500" />
          {latestAnswers.length} {latestAnswers.length === 1 ? 'отговор' : 'отговора'}
        </div>
      </div>
      
      <div className="grid grid-cols-1 gap-3">
        {latestAnswers.length > 0 ? (
          // Render just the team names with their status
          <>
            {latestAnswers.map((answer, index) => {
              const isCorrect = answer.correct === true;
              
              return (
                <motion.div
                  key={answer.id}
                  initial={{ opacity: 0, y: 10 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{ duration: 0.2, delay: index * 0.03 }}
                  className={`relative rounded-lg overflow-hidden shadow-sm ${
                    isCorrect
                      ? 'border border-green-500 bg-green-50' 
                      : isFirstSubmittedAnswer(answer)
                        ? 'border-2 border-amber-500 bg-amber-50'
                        : 'border border-gray-200 bg-white'
                  }`}
                >
                  {isFirstSubmittedAnswer(answer) && !isCorrect && (
                    <div className="absolute top-0 right-0 bg-amber-500 text-white text-xs px-2 py-0.5 rounded-bl-lg">
                      Първи
                    </div>
                  )}
                  
                  {isCorrect && (
                    <div className="absolute top-0 right-0 bg-green-500 text-white text-xs px-2 py-0.5 rounded-bl-lg flex items-center gap-1">
                      <FaCheck size={10} />
                    </div>
                  )}
                  
                  <div className="p-2 flex justify-between items-center">
                    <div className="font-medium text-lg text-gray-700 truncate">
                      {answer.team_name}
                    </div>
                    <div className="text-xs text-gray-500 flex-shrink-0">
                      {new Date(answer.created_at).toLocaleTimeString('bg-BG', {hour: '2-digit', minute:'2-digit', second: '2-digit'})}
                    </div>
                  </div>
                </motion.div>
              );
            })}
          </>
        ) : (
          <div className="col-span-full p-6 bg-gray-50 rounded-lg text-center">
            <p className="text-gray-500">
              Няма отговори за показване.
            </p>
          </div>
        )}
      </div>
    </div>
  );
}