mirror of
https://github.com/arthur-pbty/pomodoro.git
synced 2026-06-03 15:07:32 +02:00
b933c6040c
feat: add useAmbientSound hook for ambient sound management feat: create useLocalStorage hook for persistent state management feat: develop useTheme hook for theme switching functionality feat: implement useTimer hook for Pomodoro timer logic feat: create useTodos hook for managing todo list functionality style: add global styles and custom scrollbar for better UI experience chore: set up main entry point for the application feat: define types for Timer, Todo, and Statistics feat: create utility function for class name merging chore: configure Tailwind CSS for styling chore: set up TypeScript configuration for the project chore: configure Vite for development and build process
76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
import React from 'react';
|
|
import { TimerMode } from '../types';
|
|
|
|
interface CircularProgressProps {
|
|
progress: number;
|
|
size?: number;
|
|
strokeWidth?: number;
|
|
mode: TimerMode;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function CircularProgress({
|
|
progress,
|
|
size = 280,
|
|
strokeWidth = 8,
|
|
mode,
|
|
children
|
|
}: CircularProgressProps) {
|
|
const radius = (size - strokeWidth) / 2;
|
|
const circumference = radius * 2 * Math.PI;
|
|
const offset = circumference - (progress / 100) * circumference;
|
|
|
|
const getColor = () => {
|
|
switch (mode) {
|
|
case 'focus': return 'stroke-rose-500 dark:stroke-rose-400';
|
|
case 'shortBreak': return 'stroke-emerald-500 dark:stroke-emerald-400';
|
|
case 'longBreak': return 'stroke-indigo-500 dark:stroke-indigo-400';
|
|
}
|
|
};
|
|
|
|
const getBgColor = () => {
|
|
switch (mode) {
|
|
case 'focus': return 'stroke-rose-100 dark:stroke-rose-900/30';
|
|
case 'shortBreak': return 'stroke-emerald-100 dark:stroke-emerald-900/30';
|
|
case 'longBreak': return 'stroke-indigo-100 dark:stroke-indigo-900/30';
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="relative inline-flex items-center justify-center">
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
className="transform -rotate-90"
|
|
>
|
|
{/* Background circle */}
|
|
<circle
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
fill="none"
|
|
strokeWidth={strokeWidth}
|
|
className={getBgColor()}
|
|
/>
|
|
{/* Progress circle */}
|
|
<circle
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
fill="none"
|
|
strokeWidth={strokeWidth}
|
|
strokeLinecap="round"
|
|
className={`${getColor()} transition-all duration-300 ease-out`}
|
|
style={{
|
|
strokeDasharray: circumference,
|
|
strokeDashoffset: offset,
|
|
}}
|
|
/>
|
|
</svg>
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|