4.7.2: Упрощение отображения прогресса
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 51s

This commit is contained in:
poignatov
2026-02-02 19:24:50 +03:00
parent 89e66d6093
commit 5ac3c931b9
3 changed files with 9 additions and 58 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "4.7.1",
"version": "4.7.2",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -6,21 +6,15 @@ import { CircularProgressbar, buildStyles } from 'react-circular-progressbar'
import 'react-circular-progressbar/dist/styles.css'
// Компонент круглого прогрессбара с использованием react-circular-progressbar
function CircularProgressBar({ progress, size = 120, strokeWidth = 8, showCheckmark = true, extraProgress = null, maxProgress = 100, textSize = 'large', displayProgress = null, textPosition = 'default', projectColor = null }) {
function CircularProgressBar({ progress, size = 120, strokeWidth = 8, showCheckmark = true, textSize = 'large', displayProgress = null, textPosition = 'default', projectColor = null }) {
// Нормализуем прогресс для визуализации (0-100%)
const normalizedProgress = Math.min(Math.max(progress || 0, 0), 100)
// Если есть extra progress, вычисляем визуальный прогресс для overlay
const extraVisual = extraProgress !== null && extraProgress > 0
? Math.min((extraProgress / maxProgress) * 100, 100)
: 0
// Определяем, достигнут ли 100% или выше
const isComplete = (displayProgress !== null ? displayProgress : progress) >= 100
// Определяем градиент ID: зелёный если >= 100%, иначе по наличию extra progress
const gradientId = isComplete ? 'success-gradient' : (extraVisual > 0 ? 'project-gradient' : 'overall-gradient')
const extraGradientId = 'project-extra-gradient'
// Определяем градиент ID: зелёный если >= 100%, иначе обычный градиент
const gradientId = isComplete ? 'success-gradient' : 'overall-gradient'
// Определяем класс размера текста
const textSizeClass = textSize === 'large' ? 'text-4xl' : textSize === 'small' ? 'text-base' : 'text-lg'
@@ -48,24 +42,6 @@ function CircularProgressBar({ progress, size = 120, strokeWidth = 8, showCheckm
// Создаем неполный круг (270 градусов)
circleRatio={0.75}
/>
{/* Extra progress overlay (если есть) */}
{extraVisual > 0 && (
<CircularProgressbar
value={extraVisual}
strokeWidth={strokeWidth / size * 100}
styles={buildStyles({
rotation: 0.625,
strokeLinecap: 'round',
textSize: '0px',
pathColor: `url(#${extraGradientId})`,
trailColor: 'transparent',
pathTransitionDuration: 1,
})}
circleRatio={0.75}
className="absolute inset-0"
/>
)}
{/* Иконка статистики в центре */}
<div className="absolute inset-0 flex items-center justify-center">
@@ -104,14 +80,6 @@ function CircularProgressBar({ progress, size = 120, strokeWidth = 8, showCheckm
<stop offset="0%" stopColor="#4f46e5" />
<stop offset="100%" stopColor="#9333ea" />
</linearGradient>
<linearGradient id="project-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#4f46e5" />
<stop offset="100%" stopColor="#9333ea" />
</linearGradient>
<linearGradient id="project-extra-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#f59e0b" />
<stop offset="100%" stopColor="#d97706" />
</linearGradient>
<linearGradient id="success-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#10b981" />
<stop offset="100%" stopColor="#059669" />
@@ -170,26 +138,9 @@ function ProjectCard({ project, projectColor, onProjectClick }) {
}
const goalProgress = getGoalProgress()
const maxProgressForPriority = 100 + (() => {
const normalizedPriority = (() => {
if (priority === null || priority === undefined) return null
const numeric = Number(priority)
return Number.isFinite(numeric) ? numeric : null
})()
if (normalizedPriority === 1) return 50
if (normalizedPriority === 2) return 35
return 20
})()
// Для визуального отображения: 100% прогрессбара = максимум для данного приоритета
// visualProgress показывает процент заполнения прогрессбара (0-100%), где 100% = maxProgressForPriority
const visualProgress = Math.min((goalProgress / maxProgressForPriority) * 100, 100)
// Для extra overlay: если goalProgress > 100%, показываем extra часть
// Но визуально это уже учтено в visualProgress, так что extra overlay не нужен
// Однако если нужно показать, что достигнут максимум, можно использовать другой подход
const baseVisualProgress = visualProgress
const extraVisualProgress = 0 // Не используем extra overlay, так как visualProgress уже показывает весь прогресс
// Для визуального отображения: круг показывает максимум 100%
const visualProgress = Math.min(goalProgress, 100)
// Вычисляем целевую зону
const getTargetZone = () => {
@@ -233,7 +184,7 @@ function ProjectCard({ project, projectColor, onProjectClick }) {
{/* Правая часть - круглый прогрессбар */}
<div className="flex-shrink-0 ml-3">
<CircularProgressBar
progress={baseVisualProgress}
progress={visualProgress}
size={80}
strokeWidth={8}
textSize="small"
@@ -399,7 +350,7 @@ function CurrentWeek({ onProjectClick, data, loading, error, onRetry, allProject
<div className="flex flex-col items-center mb-6">
<div className="relative mb-6 cursor-pointer" onClick={() => onNavigate && onNavigate('full')}>
<CircularProgressBar
progress={displayOverallProgress}
progress={displayOverallProgress !== null ? Math.min(displayOverallProgress, 100) : 0}
size={180}
strokeWidth={12}
showCheckmark={true}