228 lines
8.4 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 { useState, useEffect } from 'react';
import { useHistory } from "react-router-dom";
import BottomNavigation from "../components/BottomNavigation";
import HeaderNav from "../components/HeaderNav";
import { connect } from '../confconnect';
import { getRouteCourseExercises } from '../shared/consts/router';
import type { CourseExercises } from './CourseExercises';
export interface Course {
ID: number;
title: string;
desc: string;
url_file_img: string;
course_exercises: CourseExercises;
}
const ProgressLine = () => {
return (
<div
className="h-full bg-gradient-to-r from-orange-300 to-orange-500 transition-all duration-500 absolute left-0 top-0 rounded-l-xl"
style={{ width: '85%' }}
/>
);
}
const AnalitcsCards = () => {
return (
<div className="px-6 mb-8" >
<div className="text-center relative ">
<div className="w-full h-10 bg-gray-500 rounded-xl relative flex items-center justify-center mb-4 shadow-xl">
{/* Прогрессная часть */}
<ProgressLine />
{/* Текст поверх линии */}
<div className="absolute text-white font-semibold text-sm sm:text-base">Вы прошли реабилитацию на {85}%</div>
</div>
</div>
</div>
)
}
// НАЧАЛО КОМПОНЕНТА
export const Courses = () => {
const history = useHistory();
const [courses, setCourses] = useState<Course[]>([]);
const [error, setError] = useState<string>('');
const token = localStorage.getItem('authToken');
const [course_exercises, setExercises] = useState<CourseExercises[]>([]);
useEffect(() => {
console.log(token)
if (!token) {
setError('Токен не найден');
return;
}
connect.get('/pacient/courses', {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then(response => {
console.log('Response status:', response.data);
setExercises(response.data.courses.course_exercises);
// Предполагаемая структура:
// response.data.courses — массив пользователей
const users = response.data.courses || [];
// Собираем все курсы из всех пользователей
const allCourses: Course[] = [];
users.forEach(user => {
if (user.Courses && Array.isArray(user.Courses)) {
user.Courses.forEach(course => {
// Можно добавить проверку или преобразование
allCourses.push({
ID: course.id, // или course.ID, зависит от структуры
title: course.title,
desc: course.desc,
url_file_img: course.url_file_img,
});
});
}
});
setCourses(allCourses);
})
.catch(error => {
if (error.response) {
console.error('Ошибка ответа сервера:', error.response.status, error.response.data);
setError(`Ошибка сервера: ${error.response.status}`);
} else if (error.request) {
console.error('Нет ответа от сервера:', error.request);
setError('Нет ответа от сервера');
} else {
console.error('Ошибка при настройке запроса:', error.message);
setError(`Ошибка: ${error.message}`);
}
});
}, [token]);
// Генерируем случайный прогресс для каждого курса
const getRandomProgress = () => Math.floor(Math.random() * 100);
// Цвета для прогресс-баров в оттенках cyan
const progressColors = [
"from-gray-400 to-cyan-800",
];
//item.exercise.title
return (
<div className="my-36 min-h-screen max-w-4xl mx-auto">
<HeaderNav item='Курсы' text='все назначенные' />
<AnalitcsCards />
<div className="px-6 mb-8">
{error && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
<p className="text-red-600 font-medium">{error}</p>
</div>
)}
{/* Заголовок секции */}
<div className="flex flex-col sm:flex-row content-center justify-between mb-6">
<h2 className="text-xl font-black text-[#5F5C5C]">Мои курсы</h2>
<span className="text-sm text-gray-500"> Назначенных: {courses.length}</span>
</div>
{/* Выводим список курсов */}
<div className='space-y-4'>
{courses.length > 0 ? (
courses.map((course, index) => {
const progress = getRandomProgress();
const colorClass = progressColors[index % progressColors.length];
return (
<div
key={course.ID}
onClick={() => history.push(getRouteCourseExercises(course.ID.toString()), { course })}
className="bg-white/30 backdrop-blur-2xl rounded-3xl p-6 border border-white/20 shadow-xl cursor-pointer hover:shadow-2xl transition-all duration-300 transform hover:scale-[1.02]"
>
<div className="flex flex-col sm:flex-row sm:content-center space-x-5">
{/* Изображение курса */}
{course.url_file_img && (
<div className="h-10 w-10 md:h-20 md:w-20 rounded-2xl overflow-hidden flex-shrink-0">
<img
src={course.url_file_img || "/placeholder.svg"}
alt={course.title}
className="w-full h-full object-cover"
onError={(e) => {
e.currentTarget.src = "/placeholder.svg?height=64&width=64&text=Course"
}}
/>
</div>
)}
<div className="flex-1">
<h3 className="font-semibold text-[#5F5C5C] text-lg mb-2">{course.title}</h3>
{/* Описание курса */}
{course.desc && (
<p className="text-sm text-[#5F5C5C]/60 mb-3 line-clamp-2">{course.desc}</p>
)}
{/* Индикатор прогресса */}
<div className="bg-white/50 rounded-full h-3 mb-2 overflow-hidden">
<div
className={`bg-gradient-to-r ${colorClass} h-3 rounded-full transition-all duration-700 shadow-sm`}
style={{ width: `${progress}%` }}
/>
</div>
{/* Информация о прогрессе */}
<div className="flex flex-col md:flex-row md:justify-between content-center">
<p className="text-sm text-[#5F5C5C]/70 font-semibold">{progress}% завершено</p>
<p className="text-xs text-[#5F5C5C]/50">{course_exercises} упражнений</p>
</div>
</div>
{/* Иконка стрелки */}
<div className="hidden sm:block text-[#2BACBE] transform transition-transform duration-300 hover:translate-x-1 my-auto">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</div>
)
})
) : (
!error && (
<div className="bg-gray-50 border border-gray-200 rounded-lg p-8 text-center">
<p className="text-gray-600 mb-4">У вас пока нет назначенных курсов</p>
<button
onClick={() => history.push("/courses")}
className="bg-[#2BACBE] text-white px-4 py-2 rounded-lg hover:bg-[#2A9FB8] transition-colors"
>
Просмотреть доступные курсы
</button>
</div>
)
)}
</div>
</div>
<BottomNavigation />
</div>
);
};