Compare commits
3 Commits
fd6a0daf8e
...
7b5db124da
| Author | SHA1 | Date |
|---|---|---|
|
|
7b5db124da | |
|
|
f68e76c4b4 | |
|
|
228ba3b536 |
15
api/index.ts
15
api/index.ts
|
|
@ -1,12 +1,9 @@
|
|||
"use server";
|
||||
import baseUrl from "@/baseUrl";
|
||||
import routes from "@/routes";
|
||||
import { cookies } from "next/headers";
|
||||
import { revalidateTag } from "next/cache";
|
||||
|
||||
export async function authenticateLottery(
|
||||
phone: string,
|
||||
code: string,
|
||||
) {
|
||||
export async function authenticateLottery(phone: string, code: string) {
|
||||
try {
|
||||
const res = await fetch(`${baseUrl.QUIZ_SRC}${routes.lotteryActive}`, {
|
||||
method: "POST",
|
||||
|
|
@ -17,6 +14,10 @@ export async function authenticateLottery(
|
|||
phone: phone,
|
||||
key: code,
|
||||
}),
|
||||
next: {
|
||||
revalidate: 300,
|
||||
tags: ["lotteryData"],
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
|
|
@ -32,3 +33,7 @@ export async function authenticateLottery(
|
|||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const revalidateTagName = (tag: string) => {
|
||||
revalidateTag(tag);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import LotteryAuthForm from "@/components/lottery/auth/LotteryAuthForm";
|
||||
|
||||
const LotteryAuthPage = () => {
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="flex justify-center items-center min-h-[50vh] py-[200px]">
|
||||
{/* <LotteryAuthForm /> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LotteryAuthPage;
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLotteryAuth } from "@/store/useLotteryAuth";
|
||||
import ProtectedRoute from "@/components/lottery/auth/ProtectedRoute";
|
||||
import LotteryHeader from "@/components/lottery/LotteryHeader";
|
||||
|
||||
import LotteryWinnersSection from "@/components/lottery/LotteryWinnersSection";
|
||||
import LotteryRulesSection from "@/components/lottery/rules/LotteryRulesSection";
|
||||
import LotteryCountDown from "@/components/lottery/countDown/LotteryCountDown";
|
||||
import { Queries } from "@/api/queries";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Loader from "@/components/Loader";
|
||||
import { authenticateLottery } from "@/api";
|
||||
import { ILotteryResponse } from "@/models/lottery/lottery.model";
|
||||
|
||||
const LotteryPage = () => {
|
||||
const [lotteryData, setData] = useState<ILotteryResponse>();
|
||||
const [status, setStatus] = useState<"not-started" | "started" | "ended">(
|
||||
"not-started"
|
||||
);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
const checkAuth = async () => {
|
||||
const res = await authenticateLottery();
|
||||
setData(res);
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
}, []);
|
||||
|
||||
if (isLoading && !lotteryData?.data) {
|
||||
<div className="flex w-full h-[90vh] justify-center items-center">
|
||||
<Loader />
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ProtectedRoute>
|
||||
{lotteryData?.data && (
|
||||
<div className="flex flex-col md:gap-[128px] gap-[80px] font-roboto md:pt-[64px] sm:pt-[48px] pt-[40px] ms:pb-[128px] pb-[80px] text-lightOnSurface">
|
||||
{lotteryData && (
|
||||
<div className="flex flex-col sm:gap-[64px] gap-[40px]">
|
||||
<LotteryHeader
|
||||
title={lotteryData.data.title}
|
||||
description={lotteryData.data.description}
|
||||
image={lotteryData.data.image}
|
||||
smsCode={lotteryData.data.sms_code}
|
||||
startDate={lotteryData.data.start_time}
|
||||
/>
|
||||
|
||||
{status === "not-started" ? (
|
||||
<div className="container">
|
||||
<LotteryCountDown
|
||||
lotteryStatus={status}
|
||||
setLotteryStatus={setStatus}
|
||||
endDate={lotteryData.data.end_time}
|
||||
startDate={lotteryData.data.start_time}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<LotteryRulesSection />
|
||||
|
||||
<div className="flex flex-col gap-10">
|
||||
{lotteryData && (status === "ended" || status === "started") && (
|
||||
<LotteryWinnersSection lotteryStatus={status} />
|
||||
)}
|
||||
<div className="w-full">
|
||||
<div className="container">
|
||||
<Link
|
||||
href="/lottery/auth"
|
||||
className="sm:text-textLarge sm:leading-textLarge text-[16px] rounded-full leading-[24px] sm:py-[12px] py-[8px] w-full flex justify-center items-center border-2 border-lightPrimary hover:bg-lightPrimary font-medium text-lightPrimary hover:text-lightOnPrimary disabled:opacity-50 transition-all duration-300"
|
||||
>
|
||||
Çykmak
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ProtectedRoute>
|
||||
);
|
||||
};
|
||||
|
||||
export default LotteryPage;
|
||||
|
|
@ -4,13 +4,7 @@ import ReactConfetti from "react-confetti";
|
|||
import { useWindowSize } from "react-use";
|
||||
import { useMediaQuery } from "usehooks-ts";
|
||||
|
||||
const Confetti = ({
|
||||
numberOfPieces = 200,
|
||||
showConfetti,
|
||||
}: {
|
||||
numberOfPieces?: number;
|
||||
showConfetti: boolean;
|
||||
}) => {
|
||||
const Confetti = () => {
|
||||
const [recycle, setRecycle] = useState<boolean>(true);
|
||||
const { width, height } = useWindowSize();
|
||||
const colors = [
|
||||
|
|
@ -26,7 +20,7 @@ const Confetti = ({
|
|||
|
||||
useEffect(() => {
|
||||
setTimeout(() => setRecycle(false), 30000);
|
||||
}, []);
|
||||
}, [recycle]);
|
||||
|
||||
return (
|
||||
<div className="fixed top-0 left-0 z-50">
|
||||
|
|
@ -34,7 +28,7 @@ const Confetti = ({
|
|||
width={width}
|
||||
height={height}
|
||||
recycle={recycle}
|
||||
numberOfPieces={mobile ? 200 / 3 : 200}
|
||||
numberOfPieces={mobile ? 300 / 3 : 300}
|
||||
tweenDuration={500}
|
||||
colors={colors}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import AnimatedText from "@/components/common/AnimatedText";
|
|||
import { useWebsocketLottery } from "@/hooks/useWebSocketLottery";
|
||||
import Confetti from "../common/Confetti";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { revalidateTagName } from "@/api";
|
||||
|
||||
const WEBSOCKET_URL = "wss://sms.turkmentv.gov.tm/ws/lottery?dst=";
|
||||
const SLOT_COUNTER_DURATION = 30000;
|
||||
|
|
@ -112,6 +113,7 @@ const LotteryWinnersSection = ({ data }: { data: any }) => {
|
|||
setWinnerSelectingStatus("selected");
|
||||
setIsConfettiActive(true);
|
||||
|
||||
revalidateTagName("lotteryData");
|
||||
// Add the winner to the list
|
||||
setWinners((prevWinners) => [...prevWinners, winner]);
|
||||
// Wait for the animation duration
|
||||
|
|
@ -125,7 +127,7 @@ const LotteryWinnersSection = ({ data }: { data: any }) => {
|
|||
Websocket connection error.
|
||||
</div>
|
||||
)}
|
||||
<Confetti showConfetti={isConfettiActive} numberOfPieces={300} />
|
||||
{isConfettiActive && <Confetti />}
|
||||
|
||||
<div className="container">
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useLotteryAuth } from "@/store/useLotteryAuth";
|
||||
import { Queries } from "@/api/queries";
|
||||
|
||||
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
|
||||
const router = useRouter();
|
||||
const { setAuth } = useLotteryAuth();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const checkAuth = async () => {
|
||||
// ✅ Check credentials from localStorage
|
||||
const phone = localStorage.getItem("lotteryPhone");
|
||||
const code = localStorage.getItem("lotteryCode");
|
||||
|
||||
if (phone && code) {
|
||||
try {
|
||||
// ✅ Authenticate using stored credentials
|
||||
const response = await Queries.authenticateLottery(phone, code);
|
||||
|
||||
if (response.errorMessage) {
|
||||
// If authentication fails, redirect to the auth page
|
||||
console.log("redirecting form protected route");
|
||||
router.replace("/lottery/auth");
|
||||
} else {
|
||||
// ✅ Set the authenticated state
|
||||
setAuth(response, phone, code);
|
||||
setIsLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Authentication failed:", err);
|
||||
router.replace("/lottery/auth");
|
||||
}
|
||||
} else {
|
||||
// Redirect to the auth page if no credentials are found
|
||||
router.replace("/lottery/auth");
|
||||
}
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
}, [router, setAuth]);
|
||||
|
||||
// Show nothing while checking auth
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default ProtectedRoute;
|
||||
Loading…
Reference in New Issue