визуальный таймер

This commit is contained in:
Nastya 2025-09-21 12:55:46 +03:00
parent 13de6c7f1c
commit 2ea14d81f8
3 changed files with 133 additions and 21 deletions

@ -24,7 +24,7 @@ export const ApologyPage = ({ error }: Props) => {
color: "text.primary", color: "text.primary",
}} }}
> >
{t(message.toLowerCase())} {/* {t(message.toLowerCase())} */}
</Typography> </Typography>
</Box> </Box>
); );

@ -24,6 +24,7 @@ import { DESIGN_LIST } from "@/utils/designList";
import { type ReactNode } from "react"; import { type ReactNode } from "react";
import { isProduction } from "@/utils/defineDomain"; import { isProduction } from "@/utils/defineDomain";
import { useQuizStore } from "@/stores/useQuizStore"; import { useQuizStore } from "@/stores/useQuizStore";
import { CustomCircularTimer } from "@/ui_kit/timer/CircularTimer";
type Props = { type Props = {
currentQuestion: RealTypedQuizQuestion; currentQuestion: RealTypedQuizQuestion;
@ -94,13 +95,25 @@ export const Question = ({
stepNumber={currentQuestionStepNumber} stepNumber={currentQuestionStepNumber}
/> />
{show_badge && ( {show_badge && (
<Link <Box
target="_blank"
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
sx={{ sx={{
mt: "20px", mt: "20px",
alignSelf: "end", alignSelf: "end",
display: "flex",
flexDirection: "column",
alignItems: "end",
gap: "13px",
}} }}
>
{
<CustomCircularTimer
duration={60}
remaining={30}
/>
}
<Link
target="_blank"
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
> >
{quizThemes[settings.cfg.theme].isLight ? ( {quizThemes[settings.cfg.theme].isLight ? (
<NameplateLogoFQ <NameplateLogoFQ
@ -120,6 +133,7 @@ export const Question = ({
/> />
)} )}
</Link> </Link>
</Box>
)} )}
</Box> </Box>
</Box> </Box>

@ -0,0 +1,98 @@
import { CircularProgress, Box, Typography, useTheme, styled } from "@mui/material";
const StyledCircularProgress = styled(CircularProgress)(({ theme }) => ({
"& .MuiCircularProgress-circle": {
strokeLinecap: "round",
transition: "stroke-dashoffset 0.3s ease",
},
}));
export const CustomCircularTimer: React.FC<CircularTimerProps> = ({ duration, remaining }) => {
const theme = useTheme();
const progress = (remaining / duration) * 100;
return (
<Box sx={{ position: "relative", display: "inline-flex", width: 76, height: 76 }}>
{/* Серый фон */}
<Box
sx={{
border: "#9A9AAF solid 1px",
position: "absolute",
height: "72px",
width: "72px",
borderRadius: "100%",
top: "2px",
left: "2px",
}}
/>
{/* Основной прогресс */}
<StyledCircularProgress
variant="determinate"
value={progress}
size={76}
thickness={4}
sx={{
color: "linear-gradient(135deg, #FC712F 0%, #7E2AEA 100%)",
position: "absolute",
"& .MuiCircularProgress-circle": {
strokeLinecap: "round",
stroke: "url(#timer-gradient)", // ← правильное использование
},
}}
/>
<svg
width={0}
height={0}
>
<defs>
<linearGradient
id="timer-gradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop
offset="9.9%"
stopColor="#FC712F"
/>
<stop
offset="73.88%"
stopColor="#7E2AEA"
/>
</linearGradient>
</defs>
</svg>
{/* Центральный контент */}
<Box
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 56,
height: 56,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Typography
variant="body1"
fontWeight="bold"
sx={{
fontSize: "16px",
fontWeight: 400,
color: theme.palette.text.primary,
}}
>
{remaining}
</Typography>
</Box>
</Box>
);
};