frontAnswerer/lib/ui_kit/timer/CircularTimer.tsx

129 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-09-21 09:55:46 +00:00
import { CircularProgress, Box, Typography, useTheme, styled } from "@mui/material";
// Типизация для пропсов таймера
export interface CircularTimerProps {
duration: number; // Общая длительность в секундах
remaining: number; // Оставшееся время в секундах
showTime?: boolean; // Показывать ли время в формате mm:ss
size?: number; // Размер таймера
thickness?: number; // Толщина линии прогресса
color?: string; // Цвет прогресса
}
2025-09-21 09:55:46 +00:00
const StyledCircularProgress = styled(CircularProgress)(({ theme }) => ({
"& .MuiCircularProgress-circle": {
strokeLinecap: "round",
transition: "stroke-dashoffset 0.3s ease",
},
}));
// Функция для форматирования времени в mm:ss
const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.floor(seconds % 60);
return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
};
export const CustomCircularTimer: React.FC<CircularTimerProps> = ({
duration,
remaining,
showTime = true,
size = 76,
thickness = 4,
color,
}) => {
2025-09-21 09:55:46 +00:00
const theme = useTheme();
const progress = (remaining / duration) * 100;
return (
2025-10-02 00:07:05 +00:00
<Box
id="test-timer"
sx={{ position: "relative", display: "inline-flex", width: size, height: size }}
>
2025-09-21 09:55:46 +00:00
{/* Серый фон */}
<Box
sx={{
border: "#9A9AAF solid 1px",
position: "absolute",
height: `${size - 4}px`,
width: `${size - 4}px`,
2025-09-21 09:55:46 +00:00
borderRadius: "100%",
top: "2px",
left: "2px",
}}
/>
{/* Основной прогресс */}
<StyledCircularProgress
variant="determinate"
value={progress}
size={size}
thickness={thickness}
2025-09-21 09:55:46 +00:00
sx={{
color: color || "linear-gradient(135deg, #FC712F 0%, #7E2AEA 100%)",
2025-09-21 09:55:46 +00:00
position: "absolute",
"& .MuiCircularProgress-circle": {
strokeLinecap: "round",
stroke: color ? undefined : "url(#timer-gradient)",
strokeDasharray: color ? undefined : undefined,
2025-09-21 09:55:46 +00:00
},
}}
/>
<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: `${size - 20}px`,
height: `${size - 20}px`,
2025-09-21 09:55:46 +00:00
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Typography
variant="body1"
fontWeight="bold"
sx={{
fontSize: size > 60 ? "16px" : "12px",
fontWeight: 600,
2025-09-21 09:55:46 +00:00
color: theme.palette.text.primary,
textAlign: "center",
lineHeight: 1,
2025-09-21 09:55:46 +00:00
}}
>
{showTime ? formatTime(remaining) : remaining}
2025-09-21 09:55:46 +00:00
</Typography>
</Box>
</Box>
);
};