lotteryWinnersSection update

This commit is contained in:
Kakabay 2025-01-02 17:47:39 +05:00
parent 6c03d191b6
commit fb6090d9fd
9 changed files with 202 additions and 191 deletions

View File

@ -1,24 +1,8 @@
"use client"; 'use client';
import LotteryAuthForm from "@/components/lottery/auth/LotteryAuthForm"; import LotteryAuthForm from '@/components/lottery/auth/LotteryAuthForm';
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useLotteryAuth } from "@/store/useLotteryAuth";
const LotteryAuthPage = () => { const LotteryAuthPage = () => {
const router = useRouter();
const { isAuthenticated, logout } = useLotteryAuth();
useEffect(() => {
if (isAuthenticated) {
router.push("/lottery");
}
}, [isAuthenticated, router]);
useEffect(() => {
logout();
}, [logout]);
return ( return (
<div className="container"> <div className="container">
<div className="flex justify-center items-center min-h-[50vh] py-[200px]"> <div className="flex justify-center items-center min-h-[50vh] py-[200px]">

View File

@ -9,6 +9,7 @@ import LotteryWinnersSection from '@/components/lottery/LotteryWinnersSection';
import LotteryRulesSection from '@/components/lottery/rules/LotteryRulesSection'; import LotteryRulesSection from '@/components/lottery/rules/LotteryRulesSection';
import LotteryCountDown from '@/components/lottery/countDown/LotteryCountDown'; import LotteryCountDown from '@/components/lottery/countDown/LotteryCountDown';
import LotteryCountDownAllert from '@/components/lottery/countDown/countDownAllert/LotteryCountDownAllert'; import LotteryCountDownAllert from '@/components/lottery/countDown/countDownAllert/LotteryCountDownAllert';
import { LotteryWinnerDataSimplified } from '@/typings/lottery/lottery.types';
const LotteryPage = () => { const LotteryPage = () => {
const { lotteryData } = useLotteryAuth(); const { lotteryData } = useLotteryAuth();
@ -42,15 +43,7 @@ const LotteryPage = () => {
<LotteryRulesSection /> <LotteryRulesSection />
{lotteryData && (status === 'ended' || status === 'started') && ( {lotteryData && (status === 'ended' || status === 'started') && (
<div className="flex flex-col gap-[0px]"> <LotteryWinnersSection lotteryStatus={status} />
<LotteryCountDownAllert
lotteryStatus={status}
setLotteryStatus={setStatus}
endDate={lotteryData.data.end_time}
startDate={lotteryData.data.start_time}
/>
<LotteryWinnersSection lotteryStatus={status} />
</div>
)} )}
</div> </div>
</ProtectedRoute> </ProtectedRoute>

View File

@ -0,0 +1,49 @@
import { motion } from 'framer-motion';
interface AnimatedTextProps {
text: string;
className?: string;
wordClassName?: string;
initialY?: number;
duration?: number;
wordDelay?: number;
}
const AnimatedText = ({
text,
className = '',
wordClassName = '',
initialY = -100,
duration = 0.5,
wordDelay = 0.2,
}: AnimatedTextProps) => {
const words = text.split(' ');
return (
<div className="overflow-hidden">
<motion.p
className={className}
initial={{ y: initialY, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: initialY, opacity: 0 }}>
{words.map((word, i) => (
<motion.span
key={i}
initial={{ y: initialY, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: initialY, opacity: 0 }}
transition={{
duration,
delay: i * wordDelay,
ease: 'easeOut',
}}
className={`inline-block mx-2 ${wordClassName}`}>
{word}
</motion.span>
))}
</motion.p>
</div>
);
};
export default AnimatedText;

View File

@ -16,25 +16,6 @@ const LotteryHeader = ({ title, description, image, smsCode }: LotteryHeaderProp
{title} {title}
</h1> </h1>
<p className="text-center text-textLarge leading-textLarge">{description}</p> <p className="text-center text-textLarge leading-textLarge">{description}</p>
<div className="flex items-center gap-[8px] px-4 py-3 bg-lightInfoAllertContainer">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4.92893 4.92893C6.8043 3.05357 9.34784 2 12 2C14.6522 2 17.1957 3.05357 19.0711 4.92893C20.9464 6.8043 22 9.34784 22 12C22 13.3132 21.7413 14.6136 21.2388 15.8268C20.7362 17.0401 19.9997 18.1425 19.0711 19.0711C18.1425 19.9997 17.0401 20.7362 15.8268 21.2388C14.6136 21.7413 13.3132 22 12 22C10.6868 22 9.38642 21.7413 8.17317 21.2388C6.95991 20.7362 5.85752 19.9997 4.92893 19.0711C4.00035 18.1425 3.26375 17.0401 2.7612 15.8268C2.25866 14.6136 2 13.3132 2 12C2 9.34784 3.05357 6.8043 4.92893 4.92893ZM12 4C9.87827 4 7.84344 4.84285 6.34315 6.34315C4.84285 7.84344 4 9.87827 4 12C4 13.0506 4.20693 14.0909 4.60896 15.0615C5.011 16.0321 5.60028 16.914 6.34315 17.6569C7.08601 18.3997 7.96793 18.989 8.93853 19.391C9.90914 19.7931 10.9494 20 12 20C13.0506 20 14.0909 19.7931 15.0615 19.391C16.0321 18.989 16.914 18.3997 17.6569 17.6569C18.3997 16.914 18.989 16.0321 19.391 15.0615C19.7931 14.0909 20 13.0506 20 12C20 9.87827 19.1571 7.84344 17.6569 6.34315C16.1566 4.84285 14.1217 4 12 4ZM11 9C11 8.44772 11.4477 8 12 8H12.01C12.5623 8 13.01 8.44772 13.01 9C13.01 9.55228 12.5623 10 12.01 10H12C11.4477 10 11 9.55228 11 9ZM10 12C10 11.4477 10.4477 11 11 11H12C12.5523 11 13 11.4477 13 12V15C13.5523 15 14 15.4477 14 16C14 16.5523 13.5523 17 13 17H12C11.4477 17 11 16.5523 11 16V13C10.4477 13 10 12.5523 10 12Z"
fill="#1E3A5F"
/>
</svg>
<span className="font-base-medium text-lightOnInfoAllertContainer">
SMS-kod: {smsCode}
</span>
</div>
</div> </div>
{image && ( {image && (
<div className="md:mb-8 sm:mb-[40px] mb-[16px]"> <div className="md:mb-8 sm:mb-[40px] mb-[16px]">

View File

@ -1,42 +1,40 @@
"use client"; 'use client';
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from 'react';
import { useLotteryAuth } from "@/store/useLotteryAuth"; import { useLotteryAuth } from '@/store/useLotteryAuth';
import { LotteryWinnerDataSimplified } from "@/typings/lottery/lottery.types"; import { LotteryWinnerDataSimplified } from '@/typings/lottery/lottery.types';
import LotteryWinnersList from "./winners/LotteryWinnersList"; import LotteryWinnersList from './winners/LotteryWinnersList';
import LotterySlotCounter from "./slotCounter/LotterySlotCounter"; import LotterySlotCounter from './slotCounter/LotterySlotCounter';
import ReactConfetti from "react-confetti"; import ReactConfetti from 'react-confetti';
import { useWindowSize } from "react-use"; import { useWindowSize } from 'react-use';
import LotteryCountDownAllert from "./countDown/countDownAllert/LotteryCountDownAllert"; import LotteryCountDownAllert from './countDown/countDownAllert/LotteryCountDownAllert';
import { motion } from 'framer-motion';
import AnimatedText from '@/components/common/AnimatedText';
const WEBSOCKET_URL = "wss://sms.turkmentv.gov.tm/ws/lottery?dst=0506"; const WEBSOCKET_URL = 'wss://sms.turkmentv.gov.tm/ws/lottery?dst=0506';
const PING_INTERVAL = 25000; const PING_INTERVAL = 25000;
const SLOT_COUNTER_DURATION = 20000; const SLOT_COUNTER_DURATION = 20000;
const LotteryWinnersSection = ({ const LotteryWinnersSection = ({ lotteryStatus }: { lotteryStatus: string }) => {
lotteryStatus,
}: {
lotteryStatus: string;
}) => {
// UI States // UI States
const [winners, setWinners] = useState<LotteryWinnerDataSimplified[]>([]); const [winners, setWinners] = useState<LotteryWinnerDataSimplified[]>([]);
const [currentNumber, setCurrentNumber] = useState<string>("00-00-00-00-00"); const [currentNumber, setCurrentNumber] = useState<string>('00-00-00-00-00');
const [isConfettiActive, setIsConfettiActive] = useState(false); const [isConfettiActive, setIsConfettiActive] = useState(false);
const [wsStatus, setWsStatus] = useState< const [wsStatus, setWsStatus] = useState<'connecting' | 'connected' | 'error'>('connecting');
"connecting" | "connected" | "error"
>("connecting");
const { width, height } = useWindowSize(); const { width, height } = useWindowSize();
const { lotteryData } = useLotteryAuth(); const { lotteryData } = useLotteryAuth();
const [isSlotCounterAnimating, setIsSlotCounterAnimating] = useState(false); const [isSlotCounterAnimating, setIsSlotCounterAnimating] = useState(false);
const [pendingWinner, setPendingWinner] = const [pendingWinner, setPendingWinner] = useState<LotteryWinnerDataSimplified | null>(null);
useState<LotteryWinnerDataSimplified | null>(null);
// Refs // Refs
const wsRef = useRef<WebSocket | null>(null); const wsRef = useRef<WebSocket | null>(null);
const pingIntervalRef = useRef<NodeJS.Timeout>(); const pingIntervalRef = useRef<NodeJS.Timeout>();
const mountedRef = useRef(false); const mountedRef = useRef(false);
// Add new state for display text
const [displayText, setDisplayText] = useState<string>('...');
// Initialize winners from lottery data // Initialize winners from lottery data
useEffect(() => { useEffect(() => {
if (lotteryData?.data.winners) { if (lotteryData?.data.winners) {
@ -46,9 +44,7 @@ const LotteryWinnersSection = ({
ticket: winner.ticket, ticket: winner.ticket,
})); }));
setWinners(simplifiedWinners); setWinners(simplifiedWinners);
setCurrentNumber( setCurrentNumber(lotteryData.data.winners.at(-1)?.ticket || '00-00-00-00-00');
lotteryData.data.winners.at(-1)?.ticket || "00-00-00-00-00"
);
} }
}, [lotteryData]); }, [lotteryData]);
@ -61,21 +57,21 @@ const LotteryWinnersSection = ({
const socket = new WebSocket(WEBSOCKET_URL); const socket = new WebSocket(WEBSOCKET_URL);
wsRef.current = socket; wsRef.current = socket;
socket.addEventListener("open", () => { socket.addEventListener('open', () => {
if (!mountedRef.current) return; if (!mountedRef.current) return;
console.log("WebSocket Connected"); console.log('WebSocket Connected');
setWsStatus("connected"); setWsStatus('connected');
pingIntervalRef.current = setInterval(() => { pingIntervalRef.current = setInterval(() => {
if (socket.readyState === WebSocket.OPEN) { if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "ping" })); socket.send(JSON.stringify({ type: 'ping' }));
} }
}, PING_INTERVAL); }, PING_INTERVAL);
}); });
socket.addEventListener("message", async (event) => { socket.addEventListener('message', async (event) => {
if (!mountedRef.current) return; if (!mountedRef.current) return;
console.log("Message received:", event.data); console.log('Message received:', event.data);
try { try {
const newWinner = JSON.parse(event.data); const newWinner = JSON.parse(event.data);
@ -85,67 +81,58 @@ const LotteryWinnersSection = ({
ticket: newWinner.ticket, ticket: newWinner.ticket,
}; };
// Set initial animation text
setDisplayText(`${winnerData.winner_no}-nji ýeňiji saýlanýar`);
// Start the sequence // Start the sequence
setIsSlotCounterAnimating(true); setIsSlotCounterAnimating(true);
setPendingWinner(winnerData); setPendingWinner(winnerData);
setCurrentNumber(winnerData.ticket); setCurrentNumber(winnerData.ticket);
// Wait for slot counter animation // Wait for slot counter animation
await new Promise((resolve) => await new Promise((resolve) => setTimeout(resolve, SLOT_COUNTER_DURATION));
setTimeout(resolve, SLOT_COUNTER_DURATION)
); // Update text to show winner's phone
setDisplayText(winnerData.client);
setIsConfettiActive(true); setIsConfettiActive(true);
setWinners((prev) => [...prev, winnerData]); setWinners((prev) => [...prev, winnerData]);
// Hide confetti after 5 seconds // Reset everything after 5 seconds
// setTimeout(() => { setTimeout(() => {
// if (mountedRef.current) { if (mountedRef.current) {
// setIsConfettiActive(false); setIsConfettiActive(false);
// setIsSlotCounterAnimating(false); setIsSlotCounterAnimating(false);
// setPendingWinner(null); setPendingWinner(null);
// } setDisplayText('...'); // Reset text
// }, 5000); }
}, 5000);
// Show confetti and add winner simultaneously
if (mountedRef.current) {
setIsConfettiActive(true);
setWinners((prev) => [...prev, winnerData]);
// Hide confetti after 5 seconds
setTimeout(() => {
if (mountedRef.current) {
setIsConfettiActive(false);
setIsSlotCounterAnimating(false);
setPendingWinner(null);
}
}, 5000);
}
} catch (error) { } catch (error) {
console.error("Error processing message:", error); console.error('Error processing message:', error);
setIsSlotCounterAnimating(false); setIsSlotCounterAnimating(false);
setPendingWinner(null); setPendingWinner(null);
setDisplayText('...'); // Reset text on error
} }
}); });
socket.addEventListener("error", (error) => { socket.addEventListener('error', (error) => {
if (!mountedRef.current) return; if (!mountedRef.current) return;
console.error("WebSocket Error:", error); console.error('WebSocket Error:', error);
setWsStatus("error"); setWsStatus('error');
}); });
socket.addEventListener("close", () => { socket.addEventListener('close', () => {
if (!mountedRef.current) return; if (!mountedRef.current) return;
console.log("WebSocket Closed"); console.log('WebSocket Closed');
setWsStatus("error"); setWsStatus('error');
if (pingIntervalRef.current) { if (pingIntervalRef.current) {
clearInterval(pingIntervalRef.current); clearInterval(pingIntervalRef.current);
} }
}); });
} catch (error) { } catch (error) {
console.error("Error creating WebSocket:", error); console.error('Error creating WebSocket:', error);
setWsStatus("error"); setWsStatus('error');
} }
}; };
@ -165,7 +152,7 @@ const LotteryWinnersSection = ({
return ( return (
<section> <section>
{wsStatus === "error" && ( {wsStatus === 'error' && (
<div className="text-red-500 text-center mb-2"> <div className="text-red-500 text-center mb-2">
Connection error. Please refresh the page. Connection error. Please refresh the page.
</div> </div>
@ -181,26 +168,29 @@ const LotteryWinnersSection = ({
tweenDuration={10000} tweenDuration={10000}
run={true} run={true}
colors={[ colors={[
"linear-gradient(45deg, #5D5D72, #8589DE)", 'linear-gradient(45deg, #5D5D72, #8589DE)',
"linear-gradient(45deg, #E1E0FF, #575992)", 'linear-gradient(45deg, #E1E0FF, #575992)',
"#8589DE", '#8589DE',
"#575992", '#575992',
"#E1E0FF", '#E1E0FF',
"#BA1A1A", '#BA1A1A',
]} ]}
/> />
</div> </div>
)} )}
<div className="container"> <div className="container">
<div className="flex flex-col items-center"> <div
className="flex flex-col items-center rounded-[32px] pt-[40px]"
style={{ background: 'linear-gradient(180deg, #F0ECF4 0%, #E1E0FF 43.5%)' }}>
<AnimatedText
text={displayText}
className="text-center text-[100px] leading-[108px] text-[#E65E19]"
/>
<div className="translate-y-1/2 z-10"> <div className="translate-y-1/2 z-10">
<LotterySlotCounter <LotterySlotCounter numberString={currentNumber} isAnimating={isSlotCounterAnimating} />
numberString={currentNumber}
isAnimating={isSlotCounterAnimating}
/>
</div> </div>
<div className="flex gap-6 bg-lightPrimaryContainer rounded-[12px] flex-1 w-full items-center justify-center md:pt-[122px] sm:pt-[90px] pt-[40px] sm:pb-[62px] pb-[32px] px-4"> <div className="flex gap-6 rounded-[12px] flex-1 w-full items-center justify-center md:pt-[122px] sm:pt-[90px] pt-[40px] sm:pb-[62px] pb-[32px] px-4">
<LotteryWinnersList winners={winners} /> <LotteryWinnersList winners={winners} />
</div> </div>
</div> </div>

View File

@ -1,24 +1,41 @@
'use client'; 'use client';
import { useEffect } from 'react'; import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useLotteryAuth } from '@/store/useLotteryAuth'; import { useLotteryAuth } from '@/store/useLotteryAuth';
import { Queries } from '@/api/queries';
interface ProtectedRouteProps { const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
children: React.ReactNode;
}
const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
const router = useRouter(); const router = useRouter();
const { isAuthenticated } = useLotteryAuth(); const { isAuthenticated, phone, code, setAuth } = useLotteryAuth();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => { useEffect(() => {
if (!isAuthenticated) { const checkAuth = async () => {
router.replace('/lottery/auth'); // First, check if we have credentials in localStorage
} if (phone && code) {
}, [isAuthenticated, router]); try {
// Try to authenticate with stored credentials
const response = await Queries.authenticateLottery(phone, code);
setAuth(response, phone, code);
setIsLoading(false);
return; // Exit early if authentication successful
} catch (err) {
console.error('Authentication failed:', err);
// Only redirect if API request fails
router.replace('/lottery/auth');
}
} else {
// Only redirect if no credentials found
router.replace('/lottery/auth');
}
};
if (!isAuthenticated) { checkAuth();
}, []);
// Show nothing while checking auth
if (isLoading) {
return null; return null;
} }

View File

@ -1,27 +1,24 @@
"use client"; 'use client';
import Image from "next/image"; import Image from 'next/image';
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
import SlotCounter from "react-slot-counter"; import SlotCounter from 'react-slot-counter';
import { useMediaQuery } from "usehooks-ts"; import { useMediaQuery } from 'usehooks-ts';
interface LotterySlotCounterProps { interface LotterySlotCounterProps {
numberString: string; numberString: string;
isAnimating: boolean; isAnimating: boolean;
} }
const LotterySlotCounter = ({ const LotterySlotCounter = ({ numberString, isAnimating }: LotterySlotCounterProps) => {
numberString,
isAnimating,
}: LotterySlotCounterProps) => {
const [formattedNumber, setFormattedNumber] = useState(numberString); const [formattedNumber, setFormattedNumber] = useState(numberString);
useEffect(() => { useEffect(() => {
const formatted = numberString.replace(/-/g, ","); const formatted = numberString.replace(/-/g, ',');
setFormattedNumber(formatted); setFormattedNumber(formatted);
}, [numberString]); }, [numberString]);
const tablet = useMediaQuery("(max-width: 769px)"); const tablet = useMediaQuery('(max-width: 769px)');
const mobile = useMediaQuery("(max-width: 426px)"); const mobile = useMediaQuery('(max-width: 426px)');
return ( return (
<div className="relative w-fit"> <div className="relative w-fit">
@ -65,31 +62,29 @@ const LotterySlotCounter = ({
className="flex items-center h-fit md:max-w-[1132px] sm:max-w-[640px] max-w-[324px] w-full justify-center text-white md:py-4 md:px-6 rounded-full overflow-y-hidden overflow-x-visible relative border-4 border-lightPrimary" className="flex items-center h-fit md:max-w-[1132px] sm:max-w-[640px] max-w-[324px] w-full justify-center text-white md:py-4 md:px-6 rounded-full overflow-y-hidden overflow-x-visible relative border-4 border-lightPrimary"
style={{ style={{
background: background:
"linear-gradient(180deg, #454673 0%, #575992 10.5%, #575992 90%, #454673 100%)", 'linear-gradient(180deg, #454673 0%, #575992 10.5%, #575992 90%, #454673 100%)',
boxShadow: "0px 4px 4px 0px #00000040", boxShadow: '0px 4px 4px 0px #00000040',
}} }}>
>
{/* Highlight */} {/* Highlight */}
<div <div
className="absolute top-[50%] -translate-y-1/2 left-0 w-full h-full" className="absolute top-[50%] -translate-y-1/2 left-0 w-full h-full"
style={{ style={{
background: background:
"linear-gradient(180deg, rgba(87, 89, 146, 0) 0%, #7274AB 50%, rgba(87, 89, 146, 0) 100%)", 'linear-gradient(180deg, rgba(87, 89, 146, 0) 0%, #7274AB 50%, rgba(87, 89, 146, 0) 100%)',
}} }}></div>
></div>
<div className="z-10"> <div className="z-10">
<SlotCounter <SlotCounter
value={formattedNumber} value={formattedNumber}
// startValue={'00,00,00,00,00'} startValue={formattedNumber}
charClassName="rolling-number" charClassName="rolling-number"
separatorClassName="slot-seperator" separatorClassName="slot-seperator"
duration={2} duration={2}
speed={2} speed={2}
startFromLastDigit startFromLastDigit
delay={2} delay={2}
animateUnchanged={true} animateUnchanged={false}
// autoAnimationStart={false} autoAnimationStart={false}
/> />
</div> </div>
</div> </div>

View File

@ -1,16 +1,9 @@
import { import { LotteryWinnerData, LotteryWinnerDataSimplified } from '@/typings/lottery/lottery.types';
LotteryWinnerData, import LotteryWinner from './LotteryWinner';
LotteryWinnerDataSimplified, import { motion, AnimatePresence } from 'framer-motion';
} from "@/typings/lottery/lottery.types"; import { v4 } from 'uuid';
import LotteryWinner from "./LotteryWinner";
import { motion, AnimatePresence } from "framer-motion";
import { v4 } from "uuid";
const LotteryWinnersList = ({ const LotteryWinnersList = ({ winners }: { winners: LotteryWinnerDataSimplified[] }) => {
winners,
}: {
winners: LotteryWinnerDataSimplified[];
}) => {
return ( return (
<div className="flex flex-col gap-4 w-full max-w-[1028px]"> <div className="flex flex-col gap-4 w-full max-w-[1028px]">
<div className="flex flex-col gap-2 w-full pb-4 border-b border-[#CECCFF]"> <div className="flex flex-col gap-2 w-full pb-4 border-b border-[#CECCFF]">
@ -21,9 +14,8 @@ const LotteryWinnersList = ({
</div> </div>
<motion.div <motion.div
layout layout
className="grid md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-x-2 gap-y-4 w-full h-[244px] overflow-y-auto lottery-scrollbar" className="grid md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-x-2 gap-y-4 w-full ">
> <AnimatePresence mode="wait">
<AnimatePresence mode="popLayout">
{winners.map((item, index) => ( {winners.map((item, index) => (
<LotteryWinner <LotteryWinner
key={v4()} key={v4()}

View File

@ -1,5 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { ILotteryResponse } from '@/models/lottery/lottery.model'; import { ILotteryResponse } from '@/models/lottery/lottery.model';
import { persist } from 'zustand/middleware';
interface LotteryAuthState { interface LotteryAuthState {
isAuthenticated: boolean; isAuthenticated: boolean;
@ -10,21 +11,30 @@ interface LotteryAuthState {
logout: () => void; logout: () => void;
} }
export const useLotteryAuth = create<LotteryAuthState>((set) => ({ export const useLotteryAuth = create<LotteryAuthState>()(
isAuthenticated: false, persist(
lotteryData: null, (set) => ({
phone: null, isAuthenticated: false,
code: null, lotteryData: null,
setAuth: (data, phone, code) => set({ phone: null,
isAuthenticated: true, code: null,
lotteryData: data, setAuth: (data, phone, code) =>
phone, set({
code isAuthenticated: true,
}), lotteryData: data,
logout: () => set({ phone,
isAuthenticated: false, code,
lotteryData: null, }),
phone: null, logout: () =>
code: null set({
}), isAuthenticated: false,
})); lotteryData: null,
phone: null,
code: null,
}),
}),
{
name: 'lottery-auth-storage',
},
),
);