2025-07-31 12:25:44 +03:00

264 lines
9.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type React from "react"
import { useState, useEffect } from "react"
import {
IonContent,
IonPage,
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonButton,
IonIcon,
IonProgressBar,
IonBadge,
} from "@ionic/react"
import { playOutline, pauseOutline, stopOutline, timerOutline, fitnessOutline, trophyOutline } from "ionicons/icons"
interface Exercise {
id: number
name: string
duration: number // в секундах
description: string
difficulty: "easy" | "medium" | "hard"
completed: boolean
}
const Home: React.FC = () => {
const [currentExercise, setCurrentExercise] = useState<Exercise | null>(null)
const [timeLeft, setTimeLeft] = useState(0)
const [isRunning, setIsRunning] = useState(false)
const [isPaused, setIsPaused] = useState(false)
const exercises: Exercise[] = [
{
id: 1,
name: "Разминка плечевого сустава",
duration: 300, // 5 минут
description: "Медленные круговые движения плечами для восстановления подвижности",
difficulty: "easy",
completed: true,
},
{
id: 2,
name: "Упражнения для кисти",
duration: 600, // 10 минут
description: "Сжимание и разжимание кулака, вращения кистью",
difficulty: "medium",
completed: false,
},
{
id: 3,
name: "Растяжка мышц руки",
duration: 450, // 7.5 минут
description: "Статические упражнения на растяжку поврежденных мышц",
difficulty: "hard",
completed: false,
},
]
const [exerciseList, setExerciseList] = useState(exercises)
useEffect(() => {
let interval: NodeJS.Timeout
if (isRunning && !isPaused && timeLeft > 0) {
interval = setInterval(() => {
setTimeLeft(timeLeft - 1)
}, 1000)
} else if (timeLeft === 0 && currentExercise) {
// Упражнение завершено
setIsRunning(false)
setCurrentExercise(null)
// Отмечаем упражнение как выполненное
setExerciseList((prev) => prev.map((ex) => (ex.id === currentExercise.id ? { ...ex, completed: true } : ex)))
}
return () => clearInterval(interval)
}, [isRunning, isPaused, timeLeft, currentExercise])
const startExercise = (exercise: Exercise) => {
setCurrentExercise(exercise)
setTimeLeft(exercise.duration)
setIsRunning(true)
setIsPaused(false)
}
const pauseExercise = () => {
setIsPaused(!isPaused)
}
const stopExercise = () => {
setIsRunning(false)
setIsPaused(false)
setCurrentExercise(null)
setTimeLeft(0)
}
const formatTime = (seconds: number) => {
const mins = Math.floor(seconds / 60)
const secs = seconds % 60
return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`
}
const getDifficultyColor = (difficulty: string) => {
switch (difficulty) {
case "easy":
return "text-emerald-400"
case "medium":
return "text-yellow-400"
case "hard":
return "text-red-400"
default:
return "text-slate-400"
}
}
const getDifficultyBg = (difficulty: string) => {
switch (difficulty) {
case "easy":
return "bg-emerald-500/20 border-emerald-500/30"
case "medium":
return "bg-yellow-500/20 border-yellow-500/30"
case "hard":
return "bg-red-500/20 border-red-500/30"
default:
return "bg-slate-500/20 border-slate-500/30"
}
}
const completedCount = exerciseList.filter((ex) => ex.completed).length
const totalCount = exerciseList.length
const progressPercentage = (completedCount / totalCount) * 100
return (
<IonPage>
<IonContent className="bg-gradient-to-br from-slate-100 via-teal-50 to-cyan-50">
<div className="p-4 space-y-6">
{/* Приветствие и статистика */}
<div className="text-center mb-6">
<h1 className="text-2xl font-bold text-slate-800 mb-2">Добро пожаловать, Иван!</h1>
<p className="text-slate-600">Продолжайте восстановление. Вы на правильном пути!</p>
</div>
{/* Общий прогресс */}
<IonCard className="bg-white/80 backdrop-blur-sm border border-teal-200/50 shadow-lg">
<IonCardHeader>
<IonCardTitle className="text-slate-800 flex items-center gap-2">
<IonIcon icon={trophyOutline} className="text-teal-600" />
Общий прогресс
</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<div className="space-y-4">
<div className="flex justify-between items-center">
<span className="text-slate-600">Выполнено упражнений</span>
<span className="font-bold text-teal-600">
{completedCount}/{totalCount}
</span>
</div>
<IonProgressBar value={progressPercentage / 100} className="h-2 rounded-full" color="success" />
<div className="text-center text-sm text-slate-500">{progressPercentage.toFixed(0)}% завершено</div>
</div>
</IonCardContent>
</IonCard>
{/* Текущее упражнение (если активно) */}
{currentExercise && (
<IonCard className="bg-gradient-to-r from-teal-500 to-cyan-500 text-white shadow-xl">
<IonCardHeader>
<IonCardTitle className="flex items-center gap-2">
<IonIcon icon={timerOutline} />
Текущее упражнение
</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<div className="space-y-4">
<h3 className="text-lg font-semibold">{currentExercise.name}</h3>
<div className="text-center">
<div className="text-4xl font-bold mb-2">{formatTime(timeLeft)}</div>
<IonProgressBar
value={(currentExercise.duration - timeLeft) / currentExercise.duration}
className="h-2 rounded-full mb-4"
/>
</div>
<div className="flex gap-2 justify-center">
<IonButton fill="outline" color="light" onClick={pauseExercise}>
<IonIcon icon={isPaused ? playOutline : pauseOutline} slot="start" />
{isPaused ? "Продолжить" : "Пауза"}
</IonButton>
<IonButton fill="outline" color="light" onClick={stopExercise}>
<IonIcon icon={stopOutline} slot="start" />
Остановить
</IonButton>
</div>
</div>
</IonCardContent>
</IonCard>
)}
{/* Список упражнений */}
<div className="space-y-4">
<h2 className="text-xl font-bold text-slate-800 flex items-center gap-2">
<IonIcon icon={fitnessOutline} className="text-teal-600" />
Сегодняшние упражнения
</h2>
{exerciseList.map((exercise) => (
<IonCard
key={exercise.id}
className={`${exercise.completed ? "bg-emerald-50/80" : "bg-white/80"} backdrop-blur-sm border border-teal-200/50 shadow-md`}
>
<IonCardContent>
<div className="flex justify-between items-start mb-3">
<div className="flex-1">
<h3 className={`font-semibold ${exercise.completed ? "text-emerald-700" : "text-slate-800"}`}>
{exercise.name}
</h3>
<p className="text-sm text-slate-600 mt-1">{exercise.description}</p>
</div>
{exercise.completed && (
<IonBadge color="success" className="ml-2">
Выполнено
</IonBadge>
)}
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<span className="text-sm text-slate-500">{formatTime(exercise.duration)}</span>
<IonBadge
className={`${getDifficultyBg(exercise.difficulty)} ${getDifficultyColor(exercise.difficulty)} border`}
>
{exercise.difficulty === "easy"
? "Легко"
: exercise.difficulty === "medium"
? "Средне"
: "Сложно"}
</IonBadge>
</div>
{!exercise.completed && !currentExercise && (
<IonButton
size="small"
onClick={() => startExercise(exercise)}
className="bg-gradient-to-r from-teal-500 to-cyan-500"
>
<IonIcon icon={playOutline} slot="start" />
Начать
</IonButton>
)}
</div>
</IonCardContent>
</IonCard>
))}
</div>
</div>
</IonContent>
</IonPage>
)
}
export default Home