вывод номера дня в шапке на странице отдельного упражнения

This commit is contained in:
Tatyana 2025-09-05 12:05:24 +03:00
parent 8029d6907f
commit 28c7d6d0f8
4 changed files with 412 additions and 477 deletions

View File

@ -1,23 +1,23 @@
import { Switch, Route, Redirect } from "react-router-dom" import { Switch, Route, Redirect } from "react-router-dom"
import Welcome from "./pages/Welcome"; import Welcome from "./pages/Welcome"
import Login from "./pages/Login"; import Login from "./pages/Login"
import Home from "./pages/Home"; import Home from "./pages/Home"
import ForgotPasword from "./pages/ForgotPassword"; import ForgotPasword from "./pages/ForgotPassword"
import { Courses } from "./pages/Courses"; import { Courses } from "./pages/Courses"
import { CourseExercises } from "./pages/CourseExercises"; import { CourseExercises } from "./pages/CourseExercises"
import { Exercise } from "./pages/Exercise"; import { Exercise } from "./pages/Exercise"
import Settings from "./pages/Settings"; import Settings from "./pages/Settings"
import CourseComplete from "./pages/CourseComplete"; import CourseComplete from "./pages/CourseComplete"
import { getRouteWelcome } from "./shared/consts/router"; import { getRouteWelcome } from "./shared/consts/router"
import { getRouteLogin } from "./shared/consts/router"; import { getRouteLogin } from "./shared/consts/router"
import { getRouteHome } from "./shared/consts/router"; import { getRouteHome } from "./shared/consts/router"
import { getRouteForgotPassword } from "./shared/consts/router"; import { getRouteForgotPassword } from "./shared/consts/router"
import { getRouteCourses } from "./shared/consts/router"; import { getRouteCourses } from "./shared/consts/router"
import { getRouteSettings } from "./shared/consts/router"; import { getRouteSettings } from "./shared/consts/router"
import { getRouteCourseComplete } from "./shared/consts/router"; import { getRouteCourseComplete } from "./shared/consts/router"
const AppRoutes = () => ( const AppRoutes = () => (
<Switch> <Switch>
@ -31,6 +31,7 @@ const AppRoutes = () => (
<Route path={getRouteForgotPassword()} component={ForgotPasword} /> <Route path={getRouteForgotPassword()} component={ForgotPasword} />
<Route exact path={getRouteCourses()} component={Courses} /> <Route exact path={getRouteCourses()} component={Courses} />
<Route exact path="/course/:id" component={CourseExercises} /> <Route exact path="/course/:id" component={CourseExercises} />
<Route exact path="/course/:courseId/exercise/:exerciseIndex" component={Exercise} />
<Route exact path="/course/:courseId/:exerciseId" component={Exercise} /> <Route exact path="/course/:courseId/:exerciseId" component={Exercise} />
<Route path={getRouteSettings()} component={Settings} /> <Route path={getRouteSettings()} component={Settings} />
<Route path={getRouteCourseComplete()} component={CourseComplete} /> <Route path={getRouteCourseComplete()} component={CourseComplete} />

View File

@ -1,139 +1,120 @@
"use client" "use client"
import { useState, useEffect } from "react"; import { useState, useEffect } from "react"
import { useParams, useHistory, useLocation } from "react-router-dom"; import { useParams, useHistory, useLocation } from "react-router-dom"
import HeaderNav from "../components/HeaderNav"; import HeaderNav from "../components/HeaderNav"
import BottomNavigation from "../components/BottomNavigation"; import BottomNavigation from "../components/BottomNavigation"
import { connect } from '../confconnect'; import { connect } from "../confconnect"
import { getRouteExercise } from "../shared/consts/router"; import { getRouteExerciseByIndex } from "../shared/consts/router"
import { ArrowIcon } from "../components/icons/ArrowIcon"; import { ArrowIcon } from "../components/icons/ArrowIcon"
import type { Course } from "../pages/Courses"; import type { Course } from "../pages/Courses"
// import { Exercise } from "./Exercise";
export interface CourseExercises { export interface CourseExercises {
id: number; id: number
id_course: number; id_course: number
id_exercise: number; id_exercise: number
exercise: Exercise; exercise: Exercise
day: number; day: number
position: number; position: number
repeats: number; repeats: number
time: string; time: string
DeletedAt: string | null; DeletedAt: string | null
} }
interface Exercise { interface Exercise {
id: number; id: number
title: string; title: string
} }
export const CourseExercises = () => { export const CourseExercises = () => {
const history = useHistory(); const history = useHistory()
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>()
const location = useLocation<{ course?: Course }>(); const location = useLocation<{ course?: Course }>()
const course = location.state?.course; const course = location.state?.course
const [course_exercises, setExercises] = useState<CourseExercises[]>([])
const [selectedDay, setSelectedDay] = useState<number | null>(null)
const [course_exercises, setExercises] = useState<CourseExercises[]>([]); const token = localStorage.getItem("authToken")
const [selectedDay, setSelectedDay] = useState<number | null>(null);
const token = localStorage.getItem('authToken');
useEffect(() => { useEffect(() => {
console.log(token) console.log(token)
if (!token) { if (!token) {
console.log('Токен не найден'); console.log("Токен не найден")
return; return
} }
connect.get(`/pacient/${id}`, { connect
.get(`/pacient/${id}`, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
'Content-Type': 'application/json', "Content-Type": "application/json",
}, },
}) })
.then(response => { .then((response) => {
console.log('Данные упражнения курса:', response.data.course_exercises); console.log("Данные упражнения курса:", response.data.course_exercises)
setExercises(response.data.course_exercises)
setExercises(response.data.course_exercises);
}) })
.catch(error => { .catch((error) => {
if (error.response) { if (error.response) {
console.error('Ошибка ответа сервера:', error.response.status, error.response.data); console.error("Ошибка ответа сервера:", error.response.status, error.response.data)
} else if (error.request) { } else if (error.request) {
console.error('Нет ответа от сервера:', error.request); console.error("Нет ответа от сервера:", error.request)
} else { } else {
console.error('Ошибка при настройке запроса:', error.message); console.error("Ошибка при настройке запроса:", error.message)
} }
}); })
}, []); }, [])
useEffect(() => { useEffect(() => {
if (course_exercises.length > 0 && selectedDay === null) { if (course_exercises.length > 0 && selectedDay === null) {
setSelectedDay(course_exercises[0].day); setSelectedDay(course_exercises[0].day)
} }
}, [course_exercises]); }, [course_exercises])
const uniqueDays = Array.from(new Set(course_exercises.map(ex => ex.day))).sort((a, b) => a - b); const uniqueDays = Array.from(new Set(course_exercises.map((ex) => ex.day))).sort((a, b) => a - b)
const dayMap: { [key: number]: number } = {}; const dayMap: { [key: number]: number } = {}
uniqueDays.forEach((day, index) => { uniqueDays.forEach((day, index) => {
dayMap[day] = index + 1; dayMap[day] = index + 1
}); })
const daysNav = uniqueDays.map(day => dayMap[day]); const daysNav = uniqueDays.map((day) => dayMap[day])
const days = Array.from(new Set(course_exercises.map(ex => ex.day))).sort((a, b) => a - b); const days = Array.from(new Set(course_exercises.map((ex) => ex.day))).sort((a, b) => a - b)
const filteredExercises = selectedDay !== null const filteredExercises =
? course_exercises.filter(ex => ex.day === selectedDay) selectedDay !== null ? course_exercises.filter((ex) => ex.day === selectedDay) : course_exercises
: course_exercises;
console.log('отфильтрованный список по дням',filteredExercises) console.log("отфильтрованный список по дням", filteredExercises)
return ( return (
<div className="my-36 min-h-screen max-w-4xl mx-auto"> <div className="my-36 min-h-screen max-w-4xl mx-auto">
<HeaderNav item={course?.title ?? 'Название курса'} text={'курс'} /> <HeaderNav item={course?.title ?? "Название курса"} text={"курс"} />
<div className="px-6 mb-8"> <div className="px-6 mb-8">
{/* Заголовок секции */}
<div className="flex flex-col sm:flex-row justify-between content-center mb-6"> <div className="flex flex-col sm:flex-row justify-between content-center mb-6">
<h2 className="text-xl font-black text-[#5F5C5C]">Упражнения</h2> <h2 className="text-xl font-black text-[#5F5C5C]">Упражнения</h2>
<span className="text-sm text-gray-500">Количество упражнений: {course_exercises.length}</span> <span className="text-sm text-gray-500">Количество упражнений: {course_exercises.length}</span>
</div> </div>
{/* <p>{JSON.stringify(course_exercises)}</p> */}
{/* Кнопки выбора дня */}
{days.length > 1 && ( {days.length > 1 && (
<div className="mb-6"> <div className="mb-6">
<div className="flex flex-wrap gap-2 overflow-x-auto pb-2"> <div className="flex flex-wrap gap-2 overflow-x-auto pb-2">
{days.map((day, index) => ( {days.map((day, index) => (
<button <button
key={day} key={day}
onClick={() => { onClick={() => {
setSelectedDay(day); setSelectedDay(day)
}} }}
className={`flex-shrink-0 px-4 py-2 rounded-full text-xs sm:text-sm font-semibold transition-all duration-300 inline-block ${selectedDay === day className={`flex-shrink-0 px-4 py-2 rounded-full text-xs sm:text-sm font-semibold transition-all duration-300 inline-block ${
selectedDay === day
? "bg-[#2BACBE] text-white shadow-lg" ? "bg-[#2BACBE] text-white shadow-lg"
: "bg-white text-gray-600 hover:bg-gray-100" : "bg-white text-gray-600 hover:bg-gray-100"
}`} }`}
@ -145,41 +126,34 @@ console.log('отфильтрованный список по дням',filtered
</div> </div>
)} )}
<div className="exercise-list mb-20"> <div className="exercise-list mb-20">
{ {filteredExercises.length > 0 ? (
filteredExercises.length > 0 ? (
filteredExercises.map((item, index) => ( filteredExercises.map((item, index) => (
<div <div
key={index} key={index}
onClick={() => { onClick={() => {
history.push(
// console.log(course_exercises.map(ex => ex.id_exercise)) getRouteExerciseByIndex(
item.id_course.toString(),
index, // Используем индекс из отфильтрованного массива
// Передаем id_course и индекс из полного массива selectedDay || undefined, // Передаем выбранный день для контекста
history.push(getRouteExercise(item.id_course.toString(), item.id_exercise.toString())); ),
)
}} }}
className="p-4 mb-4 cursor-pointer hover:scale-105 transition duration-300 glass-morphism rounded-3xl border border-white/50 shadow-2xl overflow-hidden backdrop-blur-2xl relative"> className="p-4 mb-4 cursor-pointer hover:scale-105 transition duration-300 glass-morphism rounded-3xl border border-white/50 shadow-2xl overflow-hidden backdrop-blur-2xl relative"
>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div> <div>
<h3 className="text-xs sm:text-base">Упражнение {++index}</h3> <h3 className="text-xs sm:text-base">Упражнение {index + 1}</h3>
<h3 className="text-base sm:text-xl font-semibold text-gray-600">{item.exercise.title}</h3> <h3 className="text-base sm:text-xl font-semibold text-gray-600">{item.exercise.title}</h3>
</div> </div>
<ArrowIcon className="text-cyan-600" /> <ArrowIcon className="text-cyan-600" />
</div> </div>
<div className="h-0.5 w-full bg-gray-200 my-3"></div> <div className="h-0.5 w-full bg-gray-200 my-3"></div>
<div className="flex gap-10 text-xs text-gray-500"> <div className="flex gap-10 text-xs text-gray-500">
<p>Повторений: {item.repeats}</p> <p>Повторений: {item.repeats}</p>
<p>Время выполнения: {item.time}</p> <p>Время выполнения: {item.time}</p>
</div> </div>
</div> </div>
@ -192,27 +166,5 @@ console.log('отфильтрованный список по дням',filtered
<BottomNavigation /> <BottomNavigation />
</div> </div>
) )
} }
// type ButtonTheme = 'primary' | 'secondary' | 'contrast';
// interface ButtonProps {
// onClick: (event: MouseEvent) =>
// theme: ButtonTheme
// }
// const Button = (props: ButtonProps) => {
// const {theme} = props;
// return <button className={theme === 'primary' ? 'bg-teal-500 text-black' : "ajksdf"}>кнопка</button>
// }
// const Page = () => {
// const t: ButtonTheme = 'contrast'
// return (
// <div>
// <Button onClick={() => {}} theme={t}/>
// </div>
// )
// }

File diff suppressed because it is too large Load Diff

View File

@ -6,5 +6,11 @@ export const getRouteCourses = () => `/courses`
export const getRouteCourseExercises = (id: number | string) => `/course/${id}` export const getRouteCourseExercises = (id: number | string) => `/course/${id}`
export const getRouteExercise = (courseId: number | string, exerciseId: number | string) => export const getRouteExercise = (courseId: number | string, exerciseId: number | string) =>
`/course/${courseId}/${exerciseId}` `/course/${courseId}/${exerciseId}`
export const getRouteExerciseByIndex = (courseId: number | string, exerciseIndex: number, day?: number) => {
const dayParam = day ? `?day=${day}` : ""
return `/course/${courseId}/exercise/${exerciseIndex}${dayParam}`
}
export const getRouteSettings = () => `/settings` export const getRouteSettings = () => `/settings`
export const getRouteCourseComplete = () => `/course-complete` export const getRouteCourseComplete = () => `/course-complete`