ui кнопок на странице упражнения

This commit is contained in:
Tatyana 2025-08-27 12:44:57 +03:00
parent ef64080882
commit c756041321
7 changed files with 116 additions and 36 deletions

View File

@ -31,7 +31,7 @@ const AppRoutes = () => (
<Route path={getRouteForgotPassword()} component={ForgotPasword} />
<Route exact path={getRouteCourses()} component={Courses} />
<Route exact path="/course/:id" component={CourseExercises} />
<Route exact path="/course/:courseId/exercise/:exerciseId" component={Exercise} />
<Route exact path="/course/:courseId/:exerciseId" component={Exercise} />
<Route path={getRouteSettings()} component={Settings} />
<Route path={getRouteCourseComplete()} component={CourseComplete} />
</Switch>

View File

@ -0,0 +1,27 @@
import React from "react";
interface IconProps {
className?: string;
}
export const CheckIcon: React.FC<IconProps> = ({ className }) => {
return (
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
className={className}
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
</svg>
)
}

View File

@ -0,0 +1,27 @@
import React from "react";
interface IconProps {
className?: string;
}
export const RefreshIcon: React.FC<IconProps> = ({ className }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#6F6F6F"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
className={className} // Передача пропса сюда
>
<path d="M2.5 2v6h6" />
<path d="M21.5 22v-6h-6" />
<path d="M22 11.5A10 10 0 0 0 3.2 7.2" />
<path d="M2 12.5a10 10 0 0 0 18.8 4.2" />
</svg>
);
};

View File

@ -63,3 +63,8 @@
transform: translateX(100%);
}
}
.rotate-360 {
transform: rotate(160deg);
}

View File

@ -110,7 +110,7 @@ const history = useHistory();
{/* Кнопки выбора дня */}
{days.length > 1 && (
<div className="px-4 sm:px-6 mb-6">
<div className="mb-6">
<div className="flex space-x-2 overflow-x-auto pb-2">
{days.map((day) => (
<button

View File

@ -3,6 +3,8 @@
import { useState, useEffect } from "react"
import { useHistory, useParams } from "react-router-dom"
import { CheckIcon } from "../components/icons/CheckIcon"
import { RefreshIcon } from "../components/icons/RefreshIcon"
import BottomNavigation from "../components/BottomNavigation"
import { getRouteCourseComplete } from "../shared/consts/router"
import HeaderNav from "../components/HeaderNav"
@ -38,7 +40,9 @@ export const Exercise = () => {
const [currentTime, setCurrentTime] = useState(0)
const [totalTime, setTotalTime] = useState(900) // Default 15 minutes
const [currentSet, setCurrentSet] = useState(1)
const [isActive, setIsActive] = useState(false)
const [totalSets, setTotalSets] = useState(3)
const [isRotating, setIsRotating] = useState(false)
useEffect(() => {
console.log("Course ID:", courseId)
@ -123,6 +127,15 @@ export const Exercise = () => {
}
}, [isPlaying, totalTime, history])
const handleClick = () => {
setIsRotating(true);
}
const handleTransitionEnd = () => {
setIsRotating(false);
};
// Функция для отправки прогресса на сервер
const submitProgress = async () => {
if (!courseId || !exerciseId) return
@ -160,28 +173,7 @@ export const Exercise = () => {
</svg>
)
const RefreshIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#6F6F6F"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M2.5 2v6h6M21.5 22v-6h-6" />
<path d="M22 11.5A10 10 0 0 0 3.2 7.2M2 12.5a10 10 0 0 0 18.8 4.2" />
</svg>
)
const CheckIcon = () => (
<svg className="w-6 h-6 text-cyan-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
</svg>
)
// Генерируем инструкции на основе реальных данных упражнения
const exerciseSteps = [
@ -318,7 +310,7 @@ export const Exercise = () => {
</div>
{/* Fixed Timer at Bottom */}
<div className="fixed bottom-36 left-0 right-0 bg-white opacity-95 border-t border-white/20 px-4 sm:px-6 py-4 shadow-2xl z-30">
<div className="fixed bottom-36 left-0 right-0 bg-white opacity-85 border-t border-white/20 px-4 sm:px-6 py-4 shadow-2xl z-30">
<div className="max-w-md mx-auto">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center space-x-2">
@ -340,11 +332,10 @@ export const Exercise = () => {
<div className="flex space-x-3">
<button
onClick={() => setIsPlaying(!isPlaying)}
className={`flex-1 font-bold py-3 px-4 rounded-xl transition-all duration-300 transform hover:scale-105 flex items-center justify-center space-x-2 ${
isPlaying
? "bg-gray-400 text-white shadow-lg"
: "bg-[#2BACBE] hover:bg-[#2099A8] text-white shadow-lg"
}`}
className={`flex-1 font-bold py-3 px-4 rounded-xl transition-all duration-300 transform hover:scale-105 flex items-center justify-center space-x-2 cursor-pointer ${isPlaying
? "bg-gray-400 text-white shadow-lg"
: "bg-[#2BACBE] hover:bg-[#2099A8] text-white shadow-lg"
}`}
>
{isPlaying ? (
<>
@ -360,20 +351,50 @@ export const Exercise = () => {
onClick={() => {
setCurrentTime(0)
setIsPlaying(false)
handleClick()
}}
className="px-6 py-3 bg-white text-gray-800 font-bold rounded-xl transition-all duration-300 hover:shadow-lg border border-gray-200 flex items-center justify-center"
className="cursor-pointer px-6 py-3 bg-white text-gray-800 font-bold rounded-xl transition-all duration-300 hover:scale-105 hover:shadow-lg border border-gray-200 flex items-center justify-center"
>
<RefreshIcon />
<div
onTransitionEnd={handleTransitionEnd}
className="inline-block">
<RefreshIcon
className={`transition-transform duration-400 ease-in-out ${isRotating ? 'rotate-360' : ''}`}
/>
</div>
</button>
<button
onClick={() => {
setCurrentSet((prev) => Math.min(prev + 1, totalSets))
submitProgress()
const newSet = Math.min(currentSet + 1, totalSets);
setCurrentSet(newSet);
}}
className="px-6 py-3 bg-white text-gray-800 font-bold rounded-xl transition-all duration-300 hover:shadow-lg border border-gray-200 flex items-center justify-center"
onMouseDown={() => setIsActive(true)}
onMouseUp={() => setIsActive(false)}
onMouseLeave={() => setIsActive(false)}
onTouchStart={() => setIsActive(true)}
onTouchEnd={() => setIsActive(false)}
className={`cursor-pointer px-6 py-3 font-bold rounded-xl transition-all duration-500 hover:scale-105 hover:shadow-lg border border-gray-200 flex items-center justify-center ${!isActive ? "bg-white text-cyan-500" : "bg-orange-400 text-white"}`}
>
<CheckIcon />
<CheckIcon
className="w-6 h-6"
/>
</button>
</div>
</div>
</div>

View File

@ -5,6 +5,6 @@ export const getRouteForgotPassword = () => `/forgot-password`
export const getRouteCourses = () => `/courses`
export const getRouteCourseExercises = (id: number | string) => `/course/${id}`
export const getRouteExercise = (courseId: number | string, exerciseId: number | string) =>
`/course/${courseId}/exercise/${exerciseId}`
`/course/${courseId}/${exerciseId}`
export const getRouteSettings = () => `/settings`
export const getRouteCourseComplete = () => `/course-complete`