route changes

This commit is contained in:
Ilgeldi 2025-03-28 17:50:41 +05:00
parent ce90ebeb50
commit 5fe9491f86
5 changed files with 230 additions and 201 deletions

View File

@ -1,197 +1,12 @@
"use client";
import QuizMainPage from "@/components/quiz/QuizMainPage";
import React, { Suspense } from "react";
import { Queries } from "@/api/queries";
import Loader from "@/components/Loader";
import QuizQuestionList from "@/components/quiz/QuizQuestionList";
import QuizSearch from "@/components/quiz/QuizSearch";
import QuizTable from "@/components/quiz/QuizTable";
import QuizWinnerTable from "@/components/quiz/QuizWinnerTable";
import GradientTitle from "@/components/vote/GradientTitle";
import { IQuizQuestions } from "@/models/quizQuestions.model";
import QuizProvider from "@/providers/QuizProvider";
import { useQuizSearchActive, useSteps } from "@/store/store";
import { Validator } from "@/utils/validator";
import Image from "next/image";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";
import { useMediaQuery } from "usehooks-ts";
const page = () => {
const searchParams = useSearchParams();
const router = useRouter();
const [quizFinished, setQuizFinished] = useState<boolean>(false);
const [data, setData] = useState<IQuizQuestions>();
const { active } = useQuizSearchActive();
const { step, setStep } = useSteps();
const id = searchParams.get("d");
useEffect(() => {
if (id) {
Queries.getQuizByUUID(id).then((res) => {
setData(res);
if (res.data.questions) {
res.data.questions.map((question) =>
question.status === "active" || question.status === "new"
? setQuizFinished(false)
: setQuizFinished(true)
);
} else if (res.data.steps && res.data.steps?.length > 0) {
setStep(res.data.steps[0].tapgyr);
for (let i = 0; i < res.data.steps.length; i++) {
res.data.steps[i].questions.map((question) =>
question.status === "active" || question.status === "new"
? setQuizFinished(false)
: setQuizFinished(true)
);
}
}
});
} else {
router.push("/quiz/active");
}
}, []);
const mobile = useMediaQuery("(max-width: 768px)");
if (data) {
if (!data.data) {
function page() {
return (
<main className="h-full py-[200px]">
<div className="container">
<GradientTitle title={data?.message} size="big" />
</div>
</main>
<Suspense>
<QuizMainPage />
</Suspense>
);
}
return (
<main className="pt-[60px] pb-[200px]">
{typeof data !== "string" ? (
<div className="container flex flex-col md:gap-[200px] gap-[80px]">
<QuizProvider>
<div className="flex flex-col gap-[100px]">
<div className="flex flex-col gap-[45px]">
<div className="flex flex-col gap-[10px] md:gap-[5px]">
<h3 className="text-base md:text-[14px] text-textLight font-semibold md:font-normal">
{data ? Validator.reveseDate(data?.data.date) : null}
</h3>
<h1 className="text-textBlack text-[32px] md:text-[60px] leading-[100%] font-semibold">
{data?.data.title}
</h1>
<h3 className="text-base font-medium leading-[125%] md:text-[14px] text-textDarkt mt-[5px] max-w-[600px]">
{data?.data.description}
</h3>
</div>
{data?.data.banner ? (
<div className="relative w-full md:min-h-[150px] md:h-auto h-[100px]">
{mobile ? (
<Image
src={
data.data.banner_mobile !== null
? data.data.banner_mobile
: data.data.banner
}
alt={"banner"}
unoptimized
unselectable="off"
fill
className="rounded-[8px]"
/>
) : (
<Image
src={data?.data.banner}
alt={"banner"}
unoptimized
unselectable="off"
fill
className="rounded-[8px]"
/>
)}
</div>
) : null}
</div>
{data?.data.rules && data.data.notes ? (
<QuizTable
rules={data?.data.rules}
notes={data?.data.notes}
/>
) : null}
</div>
<div className="flex flex-col md:gap-[160px] gap-[80px]">
{data.data.has_steps !== 0 &&
data.data.steps &&
data.data.steps?.length > 0 && (
<div className="flex flex-col gap-4 items-center w-full">
<h1 className="text-textBlack md:text-[60px] leading-[100%] font-semibold">
Tapgyr
</h1>
<div className="flex w-full md:w-1/2 gap-[10px]">
{data.data.steps.map((item) => (
<button
onClick={() => {
setStep(item.tapgyr);
}}
key={item.tapgyr}
className={`flex-1 py-[5px] rounded-lg transition-all duration-300 ${
step === item.tapgyr
? "bg-lightPrimary text-white"
: "bg-lightPrimaryContainer text-textLight"
}`}
>
{item.tapgyr}
</button>
))}
<Link
href={`/quiz/${data.data.id}/results`}
className={`flex-1 py-[5px] rounded-lg transition-all duration-300 bg-lightPrimaryContainer text-center text-textLight`}
>
Netije
</Link>
</div>
</div>
)}
{data?.data && !active ? (
<QuizQuestionList
paramsId={String(data.data.id)}
initialQuestionsData={data}
setQuizFinished={setQuizFinished}
quizFinished={quizFinished}
/>
) : null}
{data?.data.id && quizFinished && data.data.has_steps === 0 ? (
<QuizSearch quizId={data?.data.id} />
) : null}
{data?.data.id && data.data.has_steps === 0 && (
<QuizWinnerTable
quizId={data?.data.id}
questionsData={data.data.questions}
/>
)}
</div>
</QuizProvider>
</div>
) : (
<div className="container text-[40px] flex items-center justify-center font-bold text-textLight min-h-[30vh]">
Непредвиденная ошибка. Нет активной викторины.
</div>
)}
</main>
);
} else {
return (
<main className="h-full py-[200px]">
<div className="container">
<Loader />
</div>
</main>
);
}
};
}
export default page;

View File

@ -1,5 +1,6 @@
import ParticipantsList from '@/components/vote/ParticipantsList';
import VoteProvider from '@/providers/VoteProvider';
import ParticipantsList from "@/components/vote/ParticipantsList";
import VoteProvider from "@/providers/VoteProvider";
import { Suspense } from "react";
const page = () => {
return (
@ -7,7 +8,9 @@ const page = () => {
<div className="container">
<VoteProvider>
<div className="flex flex-col items-center w-full">
<ParticipantsList />
<Suspense>
<ParticipantsList all />
</Suspense>
</div>
</VoteProvider>
</div>

View File

@ -1,5 +1,7 @@
"use client";
import ParticipantsList from "@/components/vote/ParticipantsList";
import VoteProvider from "@/providers/VoteProvider";
import { Suspense } from "react";
const page = () => {
return (
@ -7,7 +9,9 @@ const page = () => {
<div className="container">
<VoteProvider>
<div className="flex flex-col items-center w-full">
<Suspense>
<ParticipantsList />
</Suspense>
</div>
</VoteProvider>
</div>

View File

@ -0,0 +1,197 @@
"use client";
import { Queries } from "@/api/queries";
import Loader from "@/components/Loader";
import QuizQuestionList from "@/components/quiz/QuizQuestionList";
import QuizSearch from "@/components/quiz/QuizSearch";
import QuizTable from "@/components/quiz/QuizTable";
import QuizWinnerTable from "@/components/quiz/QuizWinnerTable";
import GradientTitle from "@/components/vote/GradientTitle";
import { IQuizQuestions } from "@/models/quizQuestions.model";
import QuizProvider from "@/providers/QuizProvider";
import { useQuizSearchActive, useSteps } from "@/store/store";
import { Validator } from "@/utils/validator";
import Image from "next/image";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";
import { useMediaQuery } from "usehooks-ts";
const QuizMainPage = () => {
const searchParams = useSearchParams();
const router = useRouter();
const [quizFinished, setQuizFinished] = useState<boolean>(false);
const [data, setData] = useState<IQuizQuestions>();
const { active } = useQuizSearchActive();
const { step, setStep } = useSteps();
const id = searchParams.get("d");
useEffect(() => {
if (id) {
Queries.getQuizByUUID(id).then((res) => {
setData(res);
if (res.data.questions) {
res.data.questions.map((question) =>
question.status === "active" || question.status === "new"
? setQuizFinished(false)
: setQuizFinished(true)
);
} else if (res.data.steps && res.data.steps?.length > 0) {
setStep(res.data.steps[0].tapgyr);
for (let i = 0; i < res.data.steps.length; i++) {
res.data.steps[i].questions.map((question) =>
question.status === "active" || question.status === "new"
? setQuizFinished(false)
: setQuizFinished(true)
);
}
}
});
} else {
router.push("/quiz/active");
}
}, []);
const mobile = useMediaQuery("(max-width: 768px)");
if (data) {
if (!data.data) {
return (
<main className="h-full py-[200px]">
<div className="container">
<GradientTitle title={data?.message} size="big" />
</div>
</main>
);
}
return (
<main className="pt-[60px] pb-[200px]">
{typeof data !== "string" ? (
<div className="container flex flex-col md:gap-[200px] gap-[80px]">
<QuizProvider>
<div className="flex flex-col gap-[100px]">
<div className="flex flex-col gap-[45px]">
<div className="flex flex-col gap-[10px] md:gap-[5px]">
<h3 className="text-base md:text-[14px] text-textLight font-semibold md:font-normal">
{data ? Validator.reveseDate(data?.data.date) : null}
</h3>
<h1 className="text-textBlack text-[32px] md:text-[60px] leading-[100%] font-semibold">
{data?.data.title}
</h1>
<h3 className="text-base font-medium leading-[125%] md:text-[14px] text-textDarkt mt-[5px] max-w-[600px]">
{data?.data.description}
</h3>
</div>
{data?.data.banner ? (
<div className="relative w-full md:min-h-[150px] md:h-auto h-[100px]">
{mobile ? (
<Image
src={
data.data.banner_mobile !== null
? data.data.banner_mobile
: data.data.banner
}
alt={"banner"}
unoptimized
unselectable="off"
fill
className="rounded-[8px]"
/>
) : (
<Image
src={data?.data.banner}
alt={"banner"}
unoptimized
unselectable="off"
fill
className="rounded-[8px]"
/>
)}
</div>
) : null}
</div>
{data?.data.rules && data.data.notes ? (
<QuizTable
rules={data?.data.rules}
notes={data?.data.notes}
/>
) : null}
</div>
<div className="flex flex-col md:gap-[160px] gap-[80px]">
{data.data.has_steps !== 0 &&
data.data.steps &&
data.data.steps?.length > 0 && (
<div className="flex flex-col gap-4 items-center w-full">
<h1 className="text-textBlack md:text-[60px] leading-[100%] font-semibold">
Tapgyr
</h1>
<div className="flex w-full md:w-1/2 gap-[10px]">
{data.data.steps.map((item) => (
<button
onClick={() => {
setStep(item.tapgyr);
}}
key={item.tapgyr}
className={`flex-1 py-[5px] rounded-lg transition-all duration-300 ${
step === item.tapgyr
? "bg-lightPrimary text-white"
: "bg-lightPrimaryContainer text-textLight"
}`}
>
{item.tapgyr}
</button>
))}
<Link
href={`/quiz/${data.data.id}/results`}
className={`flex-1 py-[5px] rounded-lg transition-all duration-300 bg-lightPrimaryContainer text-center text-textLight`}
>
Netije
</Link>
</div>
</div>
)}
{data?.data && !active ? (
<QuizQuestionList
paramsId={String(data.data.id)}
initialQuestionsData={data}
setQuizFinished={setQuizFinished}
quizFinished={quizFinished}
/>
) : null}
{data?.data.id && quizFinished && data.data.has_steps === 0 ? (
<QuizSearch quizId={data?.data.id} />
) : null}
{data?.data.id && data.data.has_steps === 0 && (
<QuizWinnerTable
quizId={data?.data.id}
questionsData={data.data.questions}
/>
)}
</div>
</QuizProvider>
</div>
) : (
<div className="container text-[40px] flex items-center justify-center font-bold text-textLight min-h-[30vh]">
Непредвиденная ошибка. Нет активной викторины.
</div>
)}
</main>
);
} else {
return (
<main className="h-full py-[200px]">
<div className="container">
<Loader />
</div>
</main>
);
}
};
export default QuizMainPage;

View File

@ -17,6 +17,7 @@ import { useRouter, useSearchParams } from "next/navigation";
interface IParams {
vote_id?: string;
all?: boolean;
}
interface ISocketMessage {
@ -27,7 +28,7 @@ interface ISocketMessage {
date: string;
}
const ParticipantsList = ({ vote_id }: IParams) => {
const ParticipantsList = ({ vote_id, all }: IParams) => {
const searchParams = useSearchParams();
const router = useRouter();
const [data, setData] = useState<IAllVotes>();
@ -65,7 +66,16 @@ const ParticipantsList = ({ vote_id }: IParams) => {
setVoteStatus(res.data.status);
setSmsNumber(res.data.sms_number);
});
} else {
} else if (all) {
Queries.getAllVotes().then((res) => {
setData(res);
setParticipantsData([...res.data.voting_items]);
setVoteDescription(res.data.description);
setVoteStatus(res.data.status);
setSmsNumber(res.data.sms_number);
});
}
{
router.push("/vote/active");
}