responsive design done
This commit is contained in:
parent
007902bb6d
commit
bb9db81d69
|
|
@ -22,9 +22,11 @@ const LotteryAuthPage = () => {
|
||||||
}, [logout]);
|
}, [logout]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<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]">
|
||||||
<LotteryAuthForm />
|
<LotteryAuthForm />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,61 @@
|
||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import { useLotteryAuth } from '@/store/useLotteryAuth';
|
import { useLotteryAuth } from "@/store/useLotteryAuth";
|
||||||
import ProtectedRoute from '@/components/lottery/auth/ProtectedRoute';
|
import ProtectedRoute from "@/components/lottery/auth/ProtectedRoute";
|
||||||
import LotteryHeader from '@/components/lottery/LotteryHeader';
|
import LotteryHeader from "@/components/lottery/LotteryHeader";
|
||||||
|
|
||||||
import LotteryWinnersSection from '@/components/lottery/LotteryWinnersSection';
|
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";
|
||||||
|
|
||||||
const LotteryPage = () => {
|
const LotteryPage = () => {
|
||||||
const { lotteryData } = useLotteryAuth();
|
const { lotteryData } = useLotteryAuth();
|
||||||
const [status, setStatus] = useState<'not-started' | 'started' | 'ended'>('not-started');
|
const [status, setStatus] = useState<"not-started" | "started" | "ended">(
|
||||||
|
"not-started"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(status);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<div className="flex flex-col md:gap-[128px] gap-[80px] font-roboto md:pt-[64px] sm:pt-[48px] pt-[40px] pb-[128px] text-lightOnSurface">
|
<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 && (
|
{lotteryData && (
|
||||||
|
<div className="flex flex-col sm:gap-[64px] gap-[40px]">
|
||||||
<LotteryHeader
|
<LotteryHeader
|
||||||
title={lotteryData.data.title}
|
title={lotteryData.data.title}
|
||||||
description={lotteryData.data.description}
|
description={lotteryData.data.description}
|
||||||
image={lotteryData.data.image}
|
image={lotteryData.data.image}
|
||||||
smsCode={lotteryData.data.sms_code}
|
smsCode={lotteryData.data.sms_code}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{lotteryData ? (
|
{status === "not-started" ? (
|
||||||
status === 'not-started' ? (
|
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<LotteryCountDown
|
<LotteryCountDown
|
||||||
lotteryStatus={status}
|
lotteryStatus={status}
|
||||||
setLotteryStatus={setStatus}
|
setLotteryStatus={setStatus}
|
||||||
endDate={lotteryData?.data.end_time}
|
endDate={lotteryData.data.end_time}
|
||||||
startDate={lotteryData?.data.start_time}
|
startDate={lotteryData.data.start_time}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<div className="container">
|
|
||||||
<LotteryCountDownAllert
|
|
||||||
lotteryStatus={status}
|
|
||||||
setLotteryStatus={setStatus}
|
|
||||||
endDate={lotteryData?.data.end_time}
|
|
||||||
startDate={lotteryData?.data.start_time}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
) : null}
|
) : null}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<LotteryRulesSection />
|
<LotteryRulesSection />
|
||||||
|
|
||||||
{(status === 'ended' || status === 'started') && <LotteryWinnersSection />}
|
{lotteryData && (status === "ended" || status === "started") && (
|
||||||
|
<div className="flex flex-col sm:gap-[100px] gap-[40px]">
|
||||||
|
<LotteryCountDownAllert
|
||||||
|
lotteryStatus={status}
|
||||||
|
setLotteryStatus={setStatus}
|
||||||
|
endDate={lotteryData.data.end_time}
|
||||||
|
startDate={lotteryData.data.start_time}
|
||||||
|
/>
|
||||||
|
<LotteryWinnersSection lotteryStatus={status} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,8 @@ html {
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-stroke {
|
.text-stroke {
|
||||||
text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
|
text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white,
|
||||||
|
1px 1px 0 white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.big-swiper .swiper-pagination-bullet {
|
.big-swiper .swiper-pagination-bullet {
|
||||||
|
|
@ -121,20 +122,20 @@ html {
|
||||||
|
|
||||||
.small-swiper .swiper-button-next:after {
|
.small-swiper .swiper-button-next:after {
|
||||||
color: white;
|
color: white;
|
||||||
content: url('/arrow-right-small.svg');
|
content: url("/arrow-right-small.svg");
|
||||||
}
|
}
|
||||||
.small-swiper .swiper-button-prev:after {
|
.small-swiper .swiper-button-prev:after {
|
||||||
color: white;
|
color: white;
|
||||||
content: url('/arrow-left-small.svg');
|
content: url("/arrow-left-small.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.big-swiper .swiper-button-next:after {
|
.big-swiper .swiper-button-next:after {
|
||||||
color: white;
|
color: white;
|
||||||
content: url('/arrow-right-big.svg');
|
content: url("/arrow-right-big.svg");
|
||||||
}
|
}
|
||||||
.big-swiper .swiper-button-prev:after {
|
.big-swiper .swiper-button-prev:after {
|
||||||
color: white;
|
color: white;
|
||||||
content: url('/arrow-left-big.svg');
|
content: url("/arrow-left-big.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
video {
|
video {
|
||||||
|
|
@ -187,15 +188,15 @@ big {
|
||||||
@apply bg-[#E6E6FA] rounded-xl py-3 px-4 placeholder:text-[#BCBCD6] outline-none;
|
@apply bg-[#E6E6FA] rounded-xl py-3 px-4 placeholder:text-[#BCBCD6] outline-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar [aria-label='Go to next month'] {
|
.calendar [aria-label="Go to next month"] {
|
||||||
@apply shadow-sm transition-all;
|
@apply shadow-sm transition-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar [aria-label='Go to previous month'] {
|
.calendar [aria-label="Go to previous month"] {
|
||||||
@apply shadow-sm transition-all;
|
@apply shadow-sm transition-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.day-styles [name='day'] {
|
.day-styles [name="day"] {
|
||||||
@apply p-4 text-textDarkt leading-[140%] bg-purple-600 rounded-full;
|
@apply p-4 text-textDarkt leading-[140%] bg-purple-600 rounded-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,20 +262,12 @@ big {
|
||||||
}
|
}
|
||||||
|
|
||||||
.wheel-circle {
|
.wheel-circle {
|
||||||
background: url('/wheel-circle.svg');
|
background: url("/wheel-circle.svg");
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rolling-number {
|
|
||||||
font-size: 80px;
|
|
||||||
letter-spacing: -1%;
|
|
||||||
padding: 0px 16px;
|
|
||||||
|
|
||||||
@apply text-lightOnPrimary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.index-module_slot__DpPgW {
|
.index-module_slot__DpPgW {
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
/* height: auto !important; */
|
/* height: auto !important; */
|
||||||
|
|
@ -303,11 +296,53 @@ big {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
.slot-seperator {
|
.slot-seperator {
|
||||||
content: url('/dash.svg');
|
content: url("/dash.svg");
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
margin: 0 20px;
|
@apply md:mx-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rolling-number {
|
||||||
|
@apply text-lightOnPrimary md:text-[80px] md:leading-[88px] -tracking-[1%] md:px-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1025px) {
|
||||||
|
.rolling-number {
|
||||||
|
@apply text-[48px] px-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.slot-seperator {
|
||||||
|
content: url("/dash-md.svg");
|
||||||
|
@apply mx-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1025px) {
|
||||||
|
.rolling-number {
|
||||||
|
@apply text-[48px] px-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 426px) {
|
||||||
|
.rolling-number {
|
||||||
|
@apply text-[24px] px-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 320px) {
|
||||||
|
.rolling-number {
|
||||||
|
@apply text-[16px] px-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 426px) {
|
||||||
|
.slot-seperator {
|
||||||
|
content: url("/dash-sm.svg");
|
||||||
|
@apply mx-2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.confetti-piece {
|
.confetti-piece {
|
||||||
|
|
@ -324,7 +359,8 @@ big {
|
||||||
transform: translateX(0) translateY(0) rotate(0deg);
|
transform: translateX(0) translateY(0) rotate(0deg);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: translateX(calc(var(--end-x) / 2)) translateY(-30vh) rotate(180deg);
|
transform: translateX(calc(var(--end-x) / 2)) translateY(-30vh)
|
||||||
|
rotate(180deg);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,43 @@
|
||||||
'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";
|
||||||
|
|
||||||
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;
|
||||||
|
}) => {
|
||||||
// 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<'connecting' | 'connected' | 'error'>('connecting');
|
|
||||||
|
const [wsStatus, setWsStatus] = useState<
|
||||||
|
"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] = useState<LotteryWinnerDataSimplified | null>(null);
|
const [pendingWinner, setPendingWinner] =
|
||||||
|
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);
|
||||||
|
|
||||||
console.log(isConfettiActive, 'isConfettiActive');
|
console.log(isConfettiActive, "isConfettiActive");
|
||||||
|
|
||||||
// Initialize winners from lottery data
|
// Initialize winners from lottery data
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -39,7 +48,9 @@ const LotteryWinnersSection = () => {
|
||||||
ticket: winner.ticket,
|
ticket: winner.ticket,
|
||||||
}));
|
}));
|
||||||
setWinners(simplifiedWinners);
|
setWinners(simplifiedWinners);
|
||||||
setCurrentNumber(lotteryData.data.winners.at(-1)?.ticket || '00-00-00-00-00');
|
setCurrentNumber(
|
||||||
|
lotteryData.data.winners.at(-1)?.ticket || "00-00-00-00-00"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [lotteryData]);
|
}, [lotteryData]);
|
||||||
|
|
||||||
|
|
@ -52,21 +63,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);
|
||||||
|
|
@ -82,7 +93,9 @@ const LotteryWinnersSection = () => {
|
||||||
setCurrentNumber(winnerData.ticket);
|
setCurrentNumber(winnerData.ticket);
|
||||||
|
|
||||||
// Wait for slot counter animation
|
// Wait for slot counter animation
|
||||||
await new Promise((resolve) => setTimeout(resolve, SLOT_COUNTER_DURATION));
|
await new Promise((resolve) =>
|
||||||
|
setTimeout(resolve, SLOT_COUNTER_DURATION)
|
||||||
|
);
|
||||||
|
|
||||||
setIsConfettiActive(true);
|
setIsConfettiActive(true);
|
||||||
setWinners((prev) => [...prev, winnerData]);
|
setWinners((prev) => [...prev, winnerData]);
|
||||||
|
|
@ -111,30 +124,30 @@ const LotteryWinnersSection = () => {
|
||||||
}, 5000);
|
}, 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -154,7 +167,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>
|
||||||
|
|
@ -170,12 +183,12 @@ 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>
|
||||||
|
|
@ -183,10 +196,13 @@ const LotteryWinnersSection = () => {
|
||||||
|
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<div className="-mb-[90px] z-10">
|
<div className="md:-mb-[90px] sm:-mb-[40px] -mb-[20px] z-10">
|
||||||
<LotterySlotCounter numberString={currentNumber} isAnimating={isSlotCounterAnimating} />
|
<LotterySlotCounter
|
||||||
|
numberString={currentNumber}
|
||||||
|
isAnimating={isSlotCounterAnimating}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-6 bg-lightPrimaryContainer rounded-[12px] flex-1 w-full items-center justify-center pt-[122px] pb-[62px]">
|
<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] md:px-0 px-4">
|
||||||
<LotteryWinnersList winners={winners} />
|
<LotteryWinnersList winners={winners} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { Queries } from '@/api/queries';
|
import { Queries } from "@/api/queries";
|
||||||
import { useState, FormEvent } from 'react';
|
import { useState, FormEvent } from "react";
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from "next/navigation";
|
||||||
import { useLotteryAuth } from '@/store/useLotteryAuth';
|
import { useLotteryAuth } from "@/store/useLotteryAuth";
|
||||||
|
|
||||||
const LotteryAuthForm = () => {
|
const LotteryAuthForm = () => {
|
||||||
const [phone, setPhone] = useState('');
|
const [phone, setPhone] = useState("");
|
||||||
const [code, setCode] = useState('');
|
const [code, setCode] = useState("");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -28,12 +28,12 @@ const LotteryAuthForm = () => {
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
if (!validatePhone(phone)) {
|
if (!validatePhone(phone)) {
|
||||||
setError('Telefon belgisi nädogry formatda');
|
setError("Telefon belgisi nädogry formatda");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validateCode(code)) {
|
if (!validateCode(code)) {
|
||||||
setError('Kod nädogry formatda');
|
setError("Kod nädogry formatda");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,17 +42,17 @@ const LotteryAuthForm = () => {
|
||||||
try {
|
try {
|
||||||
const response = await Queries.authenticateLottery(phone, code);
|
const response = await Queries.authenticateLottery(phone, code);
|
||||||
setAuth(response, phone, code);
|
setAuth(response, phone, code);
|
||||||
router.replace('/lottery');
|
router.replace("/lottery");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Authentication error:', err);
|
console.error("Authentication error:", err);
|
||||||
setError('Telefon belgisi ýa-da kod nädogry');
|
setError("Telefon belgisi ýa-da kod nädogry");
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePhoneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handlePhoneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = e.target.value.replace(/\D/g, ''); // Remove non-digits
|
const value = e.target.value.replace(/\D/g, ""); // Remove non-digits
|
||||||
if (value.length <= 11) {
|
if (value.length <= 11) {
|
||||||
// Limit to 11 digits (99363 + 6 digits)
|
// Limit to 11 digits (99363 + 6 digits)
|
||||||
setPhone(value);
|
setPhone(value);
|
||||||
|
|
@ -70,8 +70,11 @@ const LotteryAuthForm = () => {
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="bg-lightSurfaceContainer rounded-[24px] p-[40px] w-[530px] flex flex-col gap-[24px]">
|
className="bg-lightSurfaceContainer rounded-[24px] md:p-[40px] sm:p-[24px] p-[16px] w-[530px] flex flex-col gap-[24px]"
|
||||||
<h1 className="text-display3 font-[500] leading-display3">Lotereýa giriş</h1>
|
>
|
||||||
|
<h1 className="md:text-display3 sm:text-[32px] text-[24px] font-[500] md:leading-display3">
|
||||||
|
Lotereýa giriş
|
||||||
|
</h1>
|
||||||
<div className="flex flex-col gap-[16px]">
|
<div className="flex flex-col gap-[16px]">
|
||||||
<div className="flex flex-col gap-[8px]">
|
<div className="flex flex-col gap-[8px]">
|
||||||
<input
|
<input
|
||||||
|
|
@ -89,17 +92,22 @@ const LotteryAuthForm = () => {
|
||||||
value={code}
|
value={code}
|
||||||
onChange={handleCodeChange}
|
onChange={handleCodeChange}
|
||||||
className="px-[16px] py-[12px] bg-lightPrimaryContainer rounded-[12px] outline-none text-lightOnSurfaceVariant text-textSmall leading-textSmall"
|
className="px-[16px] py-[12px] bg-lightPrimaryContainer rounded-[12px] outline-none text-lightOnSurfaceVariant text-textSmall leading-textSmall"
|
||||||
placeholder="5-0102030408"
|
placeholder="5-0105639808"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{error && <p className="text-lightError text-textSmall leading-textSmall">{error}</p>}
|
{error && (
|
||||||
|
<p className="text-lightError text-textSmall leading-textSmall">
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || !phone || !code}
|
disabled={isLoading || !phone || !code}
|
||||||
className="text-textLarge leading-textLarge py-[12px] w-full flex justify-center items-center rounded-[12px] bg-lightPrimary font-medium text-lightOnPrimary disabled:opacity-50">
|
className="sm:text-textLarge sm:leading-textLarge text-[16px] leading-[24px] sm:py-[12px] py-[8px] w-full flex justify-center items-center rounded-[12px] bg-lightPrimary font-medium text-lightOnPrimary disabled:opacity-50"
|
||||||
{isLoading ? 'Ýüklenilýär...' : 'Giriş'}
|
>
|
||||||
|
{isLoading ? "Ýüklenilýär..." : "Giriş"}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ const LotteryCountDown: React.FC<LotteryCountDownProps> = ({
|
||||||
seconds: 0,
|
seconds: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(lotteryStatus);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
if (lotteryStatus === "not-started") {
|
if (lotteryStatus === "not-started") {
|
||||||
|
|
@ -57,8 +59,8 @@ const LotteryCountDown: React.FC<LotteryCountDownProps> = ({
|
||||||
console.log(lotteryStatus);
|
console.log(lotteryStatus);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-lightPrimaryContainer sm:p-6 p-2 flex flex-col w-full md:gap-2 rounded-[12px] text-lightOnPrimaryContainer">
|
<div className="bg-lightPrimaryContainer sm:p-6 py-3 flex flex-col w-full md:gap-2 rounded-[12px] sm:gap-3 gap-0 text-lightOnPrimaryContainer">
|
||||||
<h3 className="text-center md:font-heading-1-regular text-[32px] leading-[40px] text-lightOnSurface">
|
<h3 className="text-center md:font-heading-1-regular sm:text-[32px] sm:leading-[40px] text-[20px] leading-[28px] text-lightOnSurface">
|
||||||
{lotteryStatus === "started"
|
{lotteryStatus === "started"
|
||||||
? "Bije dowam edýär"
|
? "Bije dowam edýär"
|
||||||
: lotteryStatus === "ended"
|
: lotteryStatus === "ended"
|
||||||
|
|
@ -68,7 +70,7 @@ const LotteryCountDown: React.FC<LotteryCountDownProps> = ({
|
||||||
{/* LotteryCountDown */}
|
{/* LotteryCountDown */}
|
||||||
{lotteryStatus === "not-started" && (
|
{lotteryStatus === "not-started" && (
|
||||||
<div className="flex items-center sm:gap-6 gap-2 justify-between">
|
<div className="flex items-center sm:gap-6 gap-2 justify-between">
|
||||||
<div className="flex flex-col items-center justify-center flex-1 p-6">
|
<div className="flex flex-col items-center justify-center flex-1 sm:p-6 p-4 sm:pb-3">
|
||||||
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
||||||
{timeLeft.hours}
|
{timeLeft.hours}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -77,12 +79,13 @@ const LotteryCountDown: React.FC<LotteryCountDownProps> = ({
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-3">
|
{/* Dots */}
|
||||||
<div className="w-3 h-3 rounded-full bg-lightOnSurfaceVariant"></div>
|
<div className="flex flex-col sm:gap-3 gap-2">
|
||||||
<div className="w-3 h-3 rounded-full bg-lightOnSurfaceVariant"></div>
|
<div className="sm:w-3 sm:h-3 w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
||||||
|
<div className="sm:w-3 sm:h-3 w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center justify-center flex-1 sm:p-6 p-4 pb-3">
|
<div className="flex flex-col items-center justify-center flex-1 sm:p-6 p-4 sm:pb-3">
|
||||||
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
||||||
{timeLeft.minutes}
|
{timeLeft.minutes}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -91,12 +94,13 @@ const LotteryCountDown: React.FC<LotteryCountDownProps> = ({
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-3">
|
{/* Dots */}
|
||||||
<div className="w-3 h-3 rounded-full bg-lightOnSurfaceVariant"></div>
|
<div className="flex flex-col sm:gap-3 gap-2">
|
||||||
<div className="w-3 h-3 rounded-full bg-lightOnSurfaceVariant"></div>
|
<div className="sm:w-3 sm:h-3 w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
||||||
|
<div className="sm:w-3 sm:h-3 w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center justify-center flex-1 p-6">
|
<div className="flex flex-col items-center justify-center flex-1 sm:p-6 p-4 sm:pb-3">
|
||||||
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
<h3 className="md:text-[80px] sm:text-[56px] text-[28px] md:leading-[88px] sm:leading-[64px] leading-[36px] -tracking-[1%]">
|
||||||
{timeLeft.seconds}
|
{timeLeft.seconds}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useLotteryAuth } from '@/store/useLotteryAuth';
|
import { useLotteryAuth } from "@/store/useLotteryAuth";
|
||||||
|
|
||||||
const LotteryRulesSection = () => {
|
const LotteryRulesSection = () => {
|
||||||
const { lotteryData } = useLotteryAuth();
|
const { lotteryData } = useLotteryAuth();
|
||||||
|
|
@ -7,17 +7,18 @@ const LotteryRulesSection = () => {
|
||||||
<section>
|
<section>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="flex flex-col md:gap-8 gap-6">
|
<div className="flex flex-col md:gap-8 gap-6">
|
||||||
<h2 className="md:font-heading-1-regular text-[32px] leading-[40px]">
|
<h2 className="md:font-heading-1-regular sm:text-[32px] text-[26px] sm:leading-[40px] leading-[34px]">
|
||||||
Lotereýanyň duzgunleri:
|
Lotereýanyň duzgunleri:
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex gap-6">
|
|
||||||
<div className="flex flex-col md:gap-4 gap-2 bg-lightSurfaceContainer py-4 md:px-8 px-6 rounded-[12px] w-full">
|
<div className="flex sm:flex-row flex-col gap-6">
|
||||||
<h3 className="md:font-heading-5-regular text-[20px] leading-[24px]">
|
<div className="flex flex-col md:gap-4 sm:gap-2 gap-4 bg-lightSurfaceContainer sm:py-4 md:px-8 sm:px-6 py-3 px-4 rounded-[12px] w-full">
|
||||||
|
<h3 className="md:font-heading-5-regular sm:text-[20px] text-[18px] sm:leading-[24px] leading-[28px]">
|
||||||
Umumy düzgünler:
|
Umumy düzgünler:
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="list-disc flex flex-col md:gap-4 gap-2 pl-[16px]">
|
<ul className="list-disc flex flex-col md:gap-4 gap-2 pl-[16px]">
|
||||||
{Array(5)
|
{Array(5)
|
||||||
.fill(' ')
|
.fill(" ")
|
||||||
.map((item, i) => (
|
.map((item, i) => (
|
||||||
<li className="font-small-regular" key={i}>
|
<li className="font-small-regular" key={i}>
|
||||||
Ilkinji we dogry jogap beren sanawda ilkinji ýeri eýelýär
|
Ilkinji we dogry jogap beren sanawda ilkinji ýeri eýelýär
|
||||||
|
|
@ -26,8 +27,10 @@ const LotteryRulesSection = () => {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col md:gap-4 gap-2 bg-lightSurfaceContainer py-4 md:px-8 px-6 rounded-[12px] w-full">
|
<div className="flex flex-col md:gap-4 sm:gap-2 gap-4 bg-lightSurfaceContainer sm:py-4 md:px-8 sm:px-6 py-3 px-4 rounded-[12px] w-full">
|
||||||
<h3 className="md:font-heading-5-regular text-[20px] leading-[24px]">Üns beriň:</h3>
|
<h3 className="md:font-heading-5-regular sm:text-[20px] text-[18px] sm:leading-[24px] leading-[28px]">
|
||||||
|
Üns beriň:
|
||||||
|
</h3>
|
||||||
<ul className="list-disc flex flex-col md:gap-4 gap-2 pl-[16px]">
|
<ul className="list-disc flex flex-col md:gap-4 gap-2 pl-[16px]">
|
||||||
{lotteryData?.user_lottery_numbers.map((item, i) => (
|
{lotteryData?.user_lottery_numbers.map((item, i) => (
|
||||||
<li className="font-small-regular" key={i}>
|
<li className="font-small-regular" key={i}>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,39 @@
|
||||||
'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";
|
||||||
|
|
||||||
interface LotterySlotCounterProps {
|
interface LotterySlotCounterProps {
|
||||||
numberString: string;
|
numberString: string;
|
||||||
isAnimating: boolean;
|
isAnimating: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LotterySlotCounter = ({ numberString, isAnimating }: LotterySlotCounterProps) => {
|
const LotterySlotCounter = ({
|
||||||
|
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 mobile = useMediaQuery("(max-width: 426px)");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-fit">
|
<div className="relative w-fit">
|
||||||
|
{mobile ? (
|
||||||
|
<Image
|
||||||
|
src="/roller-triangle-sm.svg"
|
||||||
|
alt="roller-triangle"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-1/2 z-20"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<Image
|
<Image
|
||||||
src="/roller-triangle.svg"
|
src="/roller-triangle.svg"
|
||||||
alt="roller-triangle"
|
alt="roller-triangle"
|
||||||
|
|
@ -25,6 +41,17 @@ const LotterySlotCounter = ({ numberString, isAnimating }: LotterySlotCounterPro
|
||||||
height={48}
|
height={48}
|
||||||
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-1/2 z-20"
|
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-1/2 z-20"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{mobile ? (
|
||||||
|
<Image
|
||||||
|
src="/roller-triangle-sm.svg"
|
||||||
|
alt="roller-triangle"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 z-20 rotate-180"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<Image
|
<Image
|
||||||
src="/roller-triangle.svg"
|
src="/roller-triangle.svg"
|
||||||
alt="roller-triangle"
|
alt="roller-triangle"
|
||||||
|
|
@ -32,20 +59,24 @@ const LotterySlotCounter = ({ numberString, isAnimating }: LotterySlotCounterPro
|
||||||
height={48}
|
height={48}
|
||||||
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 z-20 rotate-180"
|
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 z-20 rotate-180"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="flex w-full items-center h-[180px] max-w-[1132px] justify-center text-white py-4 px-6 rounded-full overflow-y-hidden overflow-x-visible relative border-4 border-lightPrimary"
|
className="flex items-center md:h-[180px] sm:h-[100px] h-[50px] 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
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
phone: string;
|
phone: string;
|
||||||
|
|
@ -17,14 +17,15 @@ const LotteryWinner = ({ phone, ticket, isNew, winnerNumber }: IProps) => {
|
||||||
animate={{ opacity: 1, translateY: 0 }}
|
animate={{ opacity: 1, translateY: 0 }}
|
||||||
exit={{ opacity: 0, translateY: -20 }}
|
exit={{ opacity: 0, translateY: -20 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className="flex flex-col gap-2 md:pb-4 pb-3 border-b w-full border-[#CECCFF]">
|
className="flex flex-col gap-2 md:pb-4 pb-3 border-b w-full border-[#CECCFF]"
|
||||||
|
>
|
||||||
<h4 className="md:font-heading-6-regular text-[20px] leading-[28px]">
|
<h4 className="md:font-heading-6-regular text-[20px] leading-[28px]">
|
||||||
The winner of the {winnerNumber} stage:
|
The winner of the {winnerNumber} stage:
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<p className="font-base-medium">{phone}</p>
|
<p className="md:font-base-medium font-base-regular">{phone}</p>
|
||||||
<div className="w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
<div className="w-1 h-1 rounded-full bg-lightOnSurfaceVariant"></div>
|
||||||
<p className="font-base-medium">{ticket}</p>
|
<p className="md:font-base-medium font-base-regular">{ticket}</p>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,28 @@
|
||||||
import { LotteryWinnerData, LotteryWinnerDataSimplified } from '@/typings/lottery/lottery.types';
|
import {
|
||||||
import LotteryWinner from './LotteryWinner';
|
LotteryWinnerData,
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
LotteryWinnerDataSimplified,
|
||||||
import { v4 } from 'uuid';
|
} from "@/typings/lottery/lottery.types";
|
||||||
|
import LotteryWinner from "./LotteryWinner";
|
||||||
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
const LotteryWinnersList = ({ winners }: { winners: LotteryWinnerDataSimplified[] }) => {
|
const LotteryWinnersList = ({
|
||||||
|
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 md:pb-4 pb-3 border-b border-[#CECCFF]">
|
<div className="flex flex-col gap-2 w-full pb-4 border-b border-[#CECCFF]">
|
||||||
<h4 className="font-heading-3-regular">Results</h4>
|
<h4 className="md:font-heading-3-regular text-[28px]">Results</h4>
|
||||||
<p className="font-base-medium">The results after each stage will be shown here.</p>
|
<p className="md:font-base-medium text-[16px]">
|
||||||
|
The results after each stage will be shown here.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
<motion.div
|
||||||
layout
|
layout
|
||||||
className="grid grid-cols-3 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 h-[244px] overflow-y-auto lottery-scrollbar"
|
||||||
|
>
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
{winners.map((item, index) => (
|
{winners.map((item, index) => (
|
||||||
<LotteryWinner
|
<LotteryWinner
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="25" height="4" viewBox="0 0 25 4" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="24" height="4" transform="translate(0.25)" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 172 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="12" height="2" viewBox="0 0 12 2" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="12" height="2" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 144 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 2.33975L16 11L1 19.6603L1 2.33975Z" fill="#575992" stroke="#D8D6FF" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 202 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 2.33975L16 11L1 19.6603L1 2.33975Z" fill="#575992" stroke="#D8D6FF" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 202 B |
Loading…
Reference in New Issue