Compare commits

..

No commits in common. "28d20b23a0e471c543c100acef9240297545138e" and "b414c0e8ab65b0104dca58526687d046bb07b6df" have entirely different histories.

21 changed files with 96 additions and 2399 deletions

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Реабилитация</title>
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>

View File

@ -1,22 +1,38 @@
import type React from "react"
import { IonApp, IonRouterOutlet } from "@ionic/react"
import { IonReactRouter } from "@ionic/react-router"
import AppRoutes from "./AppRoutes"
import "./index.css"
import "@ionic/react/css/core.css"
// import Header from "./components/Header"
// import Footer from "./components/Footer"
import React from 'react';
import { IonApp, IonRouterOutlet } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import AppRoutes from './AppRoutes';
import './index.css'
import '@ionic/react/css/core.css';
import Header from './components/Header';
import Footer from './components/Footer';
const App: React.FC = () => (
<IonApp>
<IonReactRouter>
{/* Постоянный Header */}
<Header />
{/* Основной контейнер для контента */}
<div className='flex flex-col min-h-screen container mx-auto px-4 bg-fuchsia-200'>
<div className='container mt-20 flex-1'>
<IonRouterOutlet>
<AppRoutes />
</IonRouterOutlet>
</div>
{/* Постоянный Footer */}
<Footer />
</div>
</IonReactRouter>
</IonApp>
)
);
export default App
export default App;

View File

@ -1,29 +1,16 @@
import { Route } from "react-router-dom"
import Home from "./pages/Home"
import Login from "./pages/Login"
import Register from "./pages/Register"
import Welcome from "./pages/Welcome"
import ForgotPassword from "./pages/ForgotPassword"
import Courses from "./pages/Courses"
import CourseExercises from "./pages/CourseExercises"
import Exercise from "./pages/Exercise"
import Settings from "./pages/Settings"
import CourseComplete from "./pages/CourseComplete"
import React from 'react';
import { Route } from 'react-router-dom';
import Home from './pages/Home';
import Login from './pages/Login';
import Register from './pages/Register';
const AppRoutes = () => (
<>
<Route exact path="/" component={Welcome} />
<Route path="/home" component={Home} exact />
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
<Route path="/welcome" component={Welcome} />
<Route path="/courses" component={Courses} />
<Route path="/course/:id/exercises" component={CourseExercises} />
<Route path="/exercise/:id" component={Exercise} />
<Route path="/settings" component={Settings} />
<Route path="/course-complete" component={CourseComplete} />
</>
)
);
export default AppRoutes
export default AppRoutes;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -1,3 +0,0 @@
<svg width="231" height="414" viewBox="0 0 231 414" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.6304 288.512L34.3361 320.212C31.8969 324.5 28.1648 327.336 23.14 328.72C18.1152 330.105 13.4623 329.566 9.18144 327.103C4.90057 324.641 2.08324 320.892 0.729464 315.857C-0.624315 310.822 -0.0937818 306.148 2.32107 301.835L87.3896 154.363C75.8032 142.419 67.1134 128.789 61.3202 113.475C55.527 98.1616 52.6304 82.3884 52.6304 66.1557C52.6304 58.1925 53.3195 50.1558 54.6977 42.0456C56.0759 33.9354 58.4358 26.0457 61.7776 18.3766C63.607 13.7824 66.961 10.7932 71.8395 9.40881C76.7179 8.02444 81.2915 8.56349 85.5602 11.026C89.8289 13.4884 92.6523 17.1637 94.0304 22.0519C95.4086 26.9401 95.3294 31.8405 93.7926 36.7532C92.2681 41.3473 91.1278 46.0211 90.3716 50.7745C89.6154 55.5279 89.2312 60.3487 89.2191 65.2369C89.2191 81.4695 93.1828 96.7099 101.11 110.958C109.038 125.206 120.319 136.612 134.955 145.175L176.117 169.065C195.021 180.091 208.894 195.943 217.737 216.623C226.579 237.303 231 256.672 231 274.73C231 282.999 230.238 291.195 228.713 299.318C227.189 307.44 224.902 315.324 221.853 322.969C220.023 327.869 216.669 331.011 211.791 332.396C206.912 333.78 202.186 333.241 197.613 330.779C193.344 328.328 190.448 324.653 188.923 319.753C187.399 314.852 187.399 309.799 188.923 304.592C190.448 299.692 191.594 294.865 192.362 290.111C193.131 285.358 193.509 280.537 193.497 275.649C193.497 265.848 192.125 256.353 189.38 247.165C186.636 237.977 182.215 229.401 176.117 221.438L70.01 404.744C67.5708 409.032 63.8388 411.868 58.8139 413.253C53.7891 414.637 49.1362 414.098 44.8553 411.636C40.5745 409.173 37.7572 405.424 36.4034 400.389C35.0496 395.354 35.5801 390.68 37.995 386.368L83.7308 306.889L52.6304 288.512ZM185.264 147.013C175.202 147.013 166.592 143.417 159.433 136.226C152.273 129.034 148.688 120.379 148.676 110.26C148.663 100.14 152.249 91.4909 159.433 84.3118C166.616 77.1327 175.227 73.5308 185.264 73.5063C195.302 73.4818 203.918 77.0837 211.114 84.3118C218.31 91.5399 221.889 100.189 221.853 110.26C221.816 120.33 218.237 128.985 211.114 136.226C203.991 143.466 195.375 147.062 185.264 147.013ZM139.528 55.1298C131.601 55.1298 125.045 52.3733 119.862 46.8603C114.679 41.3473 112.087 34.9155 112.087 27.5649C112.087 19.6017 114.831 13.0167 120.319 7.81005C125.808 2.60335 132.211 0 139.528 0C147.456 0 154.011 2.75649 159.195 8.26946C164.378 13.7824 166.97 20.2142 166.97 27.5649C166.97 35.5281 164.226 42.113 158.737 47.3197C153.249 52.5264 146.846 55.1298 139.528 55.1298Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,114 +0,0 @@
"use client"
import type React from "react"
import { useHistory, useLocation } from "react-router-dom"
const BottomNavigation: React.FC = () => {
const history = useHistory()
const location = useLocation()
const HomeIcon = ({ active }: { active: boolean }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className={active ? "text-white" : "text-[#5F5C5C]"}>
<path
d="M3 9L12 2L21 9V20C21 20.5304 20.7893 21.0391 20.4142 21.4142C20.0391 21.7893 19.5304 22 19 22H5C4.46957 22 3.96086 21.7893 3.58579 21.4142C3.21071 21.0391 3 20.5304 3 20V9Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M9 22V12H15V22" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)
const CoursesIcon = ({ active }: { active: boolean }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className={active ? "text-white" : "text-[#5F5C5C]"}>
<path
d="M2 3H8C9.06087 3 10.0783 3.42143 10.8284 4.17157C11.5786 4.92172 12 5.93913 12 7V21C12 20.2044 11.6839 19.4413 11.1213 18.8787C10.5587 18.3161 9.79565 18 9 18H2V3Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M22 3H16C14.9391 3 13.9217 3.42143 13.1716 4.17157C12.4214 4.92172 12 5.93913 12 7V21C12 20.2044 12.3161 19.4413 12.8787 18.8787C13.4413 18.3161 14.2044 18 15 18H22V3Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
const ExerciseIcon = ({ active }: { active: boolean }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className={active ? "text-white" : "text-[#5F5C5C]"}>
<path
d="M6.2 5H12.8C13.9201 5 14.9798 5.44772 15.7549 6.22183C16.5301 6.99594 16.9778 8.05556 16.9778 9.17647V19.8235C16.9778 18.7026 16.5301 17.643 15.7549 16.8689C14.9798 16.0948 13.9201 15.6471 12.8 15.6471H6.2V5Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.2 5C5.07989 5 4.02015 5.44772 3.24505 6.22183C2.46995 6.99594 2.02222 8.05556 2.02222 9.17647V19.8235C2.02222 18.7026 2.46995 17.643 3.24505 16.8689C4.02015 16.0948 5.07989 15.6471 6.2 15.6471"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
const SettingsIcon = ({ active }: { active: boolean }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className={active ? "text-white" : "text-[#5F5C5C]"}>
<circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="2" />
<path
d="M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.2569 9.77251 19.9859C9.5799 19.7148 9.31074 19.5063 9 19.38C8.69838 19.2469 8.36381 19.2072 8.03941 19.266C7.71502 19.3248 7.41568 19.4795 7.18 19.71L7.12 19.77C6.93425 19.956 6.71368 20.1035 6.47088 20.2041C6.22808 20.3048 5.96783 20.3566 5.705 20.3566C5.44217 20.3566 5.18192 20.3048 4.93912 20.2041C4.69632 20.1035 4.47575 19.956 4.29 19.77C4.10405 19.5843 3.95653 19.3637 3.85588 19.1209C3.75523 18.8781 3.70343 18.6178 3.70343 18.355C3.70343 18.0922 3.75523 17.8319 3.85588 17.5891C3.95653 17.3463 4.10405 17.1257 4.29 16.94L4.35 16.88C4.58054 16.6443 4.73519 16.345 4.794 16.0206C4.85282 15.6962 4.81312 15.3616 4.68 15.06C4.55324 14.7642 4.34276 14.512 4.07447 14.3343C3.80618 14.1566 3.49179 14.0613 3.17 14.06H3C2.46957 14.06 1.96086 13.8493 1.58579 13.4742C1.21071 13.0991 1 12.5904 1 12.06C1 11.5296 1.21071 11.0209 1.58579 10.6458C1.96086 10.2707 2.46957 10.06 3 10.06H3.09C3.42099 10.0523 3.742 9.94512 4.01309 9.75251C4.28417 9.5599 4.49268 9.29074 4.62 8.98C4.75312 8.67838 4.79282 8.34381 4.734 8.01941C4.67519 7.69502 4.52054 7.39568 4.29 7.16L4.23 7.1C4.04405 6.91425 3.89653 6.69368 3.79588 6.45088C3.69523 6.20808 3.64343 5.94783 3.64343 5.685C3.64343 5.42217 3.69523 5.16192 3.79588 4.91912C3.89653 4.67632 4.04405 4.45575 4.23 4.27C4.41575 4.08405 4.63632 3.93653 4.87912 3.83588C5.12192 3.73523 5.38217 3.68343 5.645 3.68343C5.90783 3.68343 6.16808 3.73523 6.41088 3.83588C6.65368 3.93653 6.87425 4.08405 7.06 4.27L7.12 4.33C7.35568 4.56054 7.65502 4.71519 7.97941 4.774C8.30381 4.83282 8.63838 4.79312 8.94 4.66H9C9.29577 4.53324 9.54802 4.32276 9.72569 4.05447C9.90337 3.78618 9.99872 3.47179 10 3.15V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65 7.1C19.4195 7.33568 19.2648 7.63502 19.206 7.95941C19.1472 8.28381 19.1869 8.61838 19.32 8.92V9C19.4468 9.29577 19.6572 9.54802 19.9255 9.72569C20.1938 9.90337 20.5082 9.99872 20.83 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.5882 14.0013 20.2738 14.0966 20.0055 14.2743C19.7372 14.452 19.5268 14.7042 19.4 15Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
const navItems = [
{ path: "/home", icon: HomeIcon, label: "Домой" },
{ path: "/courses", icon: CoursesIcon, label: "Курсы" },
{ path: "/exercise/1", icon: ExerciseIcon, label: "Заниматься" },
{ path: "/settings", icon: SettingsIcon, label: "Меню" },
]
const isActive = (path: string) => {
if (path === "/exercise/1") return location.pathname.includes("/exercise")
return location.pathname === path
}
return (
<div className="fixed bottom-0 left-0 right-0 bg-white/20 backdrop-blur-xl border-t border-white/10 px-4 py-3 z-50 shadow-2xl">
<div className="flex justify-around items-center max-w-md mx-auto">
{navItems.map((item) => {
const active = isActive(item.path)
const IconComponent = item.icon
return (
<button
key={item.path}
onClick={() => history.push(item.path)}
className={`flex flex-col items-center py-2 px-4 rounded-2xl transition-all duration-300 transform ${
active
? "text-white bg-[#2BACBE]/80 backdrop-blur-lg scale-110 shadow-lg"
: "text-[#5F5C5C] hover:text-[#2BACBE] hover:bg-white/10 hover:scale-105"
}`}
>
<div className="mb-1 filter drop-shadow-sm">
<IconComponent active={active} />
</div>
<span className="text-xs font-semibold tracking-wide">{item.label}</span>
</button>
)
})}
</div>
</div>
)
}
export default BottomNavigation

12
src/components/Footer.tsx Normal file
View File

@ -0,0 +1,12 @@
function Footer() {
return (
<div className='mt-auto bg-fuchsia-400'>
<h1>Footer</h1>
</div>
);
}
export default Footer;

16
src/components/Header.tsx Normal file
View File

@ -0,0 +1,16 @@
import React from 'react';
import { IonRouterLink } from '@ionic/react';
function Header() {
return (
<div className='fixed top-0 left-0 w-full z-50 bg-fuchsia-400 shadow h-12 px-4 flex justify-between'>
<h1>Вмеда</h1>
<IonRouterLink href="/register">
<a className="text-sm">Зарегистрироваться</a>
</IonRouterLink>
</div>
);
}
export default Header;

View File

@ -0,0 +1,12 @@
function MainContent() {
return (
<div className="flex-1 mt-12 bg-green-200">
<p>main content</p>
</div>
);
}
export default MainContent;

View File

@ -1,361 +1 @@
@import "tailwindcss";
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--radius: 0.625rem;
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.145 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.145 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
@layer components {
.glass-morphism {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
}
.glass-morphism-dark {
background: rgba(0, 0, 0, 0.15);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
}
.scrollable-content {
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
scrollbar-color: rgba(43, 172, 190, 0.3) transparent;
}
}
@layer utilities {
.animate-float {
animation: float 6s ease-in-out infinite;
}
.animate-slide-up {
animation: slideUp 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.animate-fade-in {
animation: fadeIn 0.8s ease-out;
}
.animate-scale-in {
animation: scaleIn 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.animate-bounce-gentle {
animation: bounceGentle 2s ease-in-out infinite;
}
.animate-glow {
animation: glow 2s ease-in-out infinite alternate;
}
}
@keyframes float {
0%,
100% {
transform: translateY(0px) rotate(0deg);
}
33% {
transform: translateY(-10px) rotate(1deg);
}
66% {
transform: translateY(-5px) rotate(-1deg);
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes bounceGentle {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-5px);
}
}
@keyframes glow {
from {
box-shadow: 0 0 20px rgba(43, 172, 190, 0.3);
}
to {
box-shadow: 0 0 30px rgba(43, 172, 190, 0.6);
}
}
/* Enhanced scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(45deg, #2bacbe, #5f5c5c);
border-radius: 10px;
border: 2px solid transparent;
background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(45deg, #2bacbe, #2bacbe);
background-clip: content-box;
}
/* Smooth transitions for all interactive elements */
button,
input,
select,
div {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Focus styles for accessibility */
button:focus,
input:focus,
select:focus {
outline: 2px solid #2bacbe;
outline-offset: 2px;
}
/* Loading animation */
.loading-spinner {
border: 3px solid rgba(43, 172, 190, 0.1);
border-top: 3px solid #2bacbe;
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Backdrop blur support */
@supports (backdrop-filter: blur(20px)) {
.backdrop-blur-2xl {
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
}
@supports not (backdrop-filter: blur(20px)) {
.backdrop-blur-2xl {
background: rgba(255, 255, 255, 0.8);
}
}
/* Modern gradient backgrounds */
.gradient-mesh {
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
background-size: 400% 400%;
animation: gradientShift 15s ease infinite;
}
@keyframes gradientShift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
/* Enhanced card hover effects */
.card-hover {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.card-hover:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
/* Improved button styles */
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
font-weight: 700;
padding: 12px 24px;
border-radius: 16px;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.btn-primary:active {
transform: translateY(0);
}

View File

@ -1,141 +0,0 @@
"use client"
import type React from "react"
import { useEffect, useState } from "react"
import { useHistory } from "react-router-dom"
const CourseComplete: React.FC = () => {
const history = useHistory()
const [animationPhase, setAnimationPhase] = useState(0)
useEffect(() => {
const timer1 = setTimeout(() => setAnimationPhase(1), 500)
const timer2 = setTimeout(() => setAnimationPhase(2), 1500)
const timer3 = setTimeout(() => setAnimationPhase(3), 2500)
return () => {
clearTimeout(timer1)
clearTimeout(timer2)
clearTimeout(timer3)
}
}, [])
return (
<div className="min-h-screen bg-gradient-to-br from-green-400 via-blue-500 to-purple-600 flex items-center justify-center p-4 relative overflow-hidden">
{/* Background Animation */}
<div className="absolute inset-0">
<div className="absolute top-20 left-10 w-20 h-20 bg-white/10 rounded-full animate-pulse"></div>
<div className="absolute bottom-32 right-16 w-16 h-16 bg-white/10 rounded-full animate-bounce"></div>
<div className="absolute top-1/2 left-1/4 w-12 h-12 bg-white/10 rounded-full animate-ping"></div>
</div>
{/* Main Content */}
<div className="text-center z-10 max-w-md">
{/* Volleyball Animation */}
<div className="relative mb-8 h-40">
{/* Net */}
<div
className={`absolute bottom-0 left-1/2 transform -translate-x-1/2 transition-all duration-1000 ${
animationPhase >= 1 ? "opacity-100" : "opacity-0"
}`}
>
<div className="w-32 h-20 border-2 border-white/60 border-b-0">
<div className="grid grid-cols-8 h-full">
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="border-r border-white/40 last:border-r-0"></div>
))}
</div>
<div className="grid grid-rows-4 h-full absolute inset-0">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="border-b border-white/40 last:border-b-0"></div>
))}
</div>
</div>
</div>
{/* Volleyball */}
<div
className={`absolute transition-all duration-2000 ${
animationPhase >= 2
? "bottom-8 left-1/2 transform -translate-x-1/2 scale-75"
: "bottom-32 left-8 scale-100"
}`}
>
<div
className={`w-16 h-16 rounded-full bg-white flex items-center justify-center text-2xl shadow-lg ${
animationPhase >= 2 ? "animate-bounce" : ""
}`}
>
🏐
</div>
</div>
{/* Success particles */}
{animationPhase >= 3 && (
<div className="absolute inset-0">
<div className="absolute top-4 left-8 animate-ping"></div>
<div className="absolute top-8 right-12 animate-pulse"></div>
<div className="absolute bottom-16 left-16 animate-bounce">🎉</div>
<div className="absolute bottom-12 right-8 animate-ping">🏆</div>
</div>
)}
</div>
{/* Congratulations */}
<div
className={`transition-all duration-1000 delay-500 ${
animationPhase >= 2 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
}`}
>
<h1 className="text-4xl font-bold text-white mb-4">Поздравляем! 🎉</h1>
<p className="text-white/90 text-lg mb-2">Вы успешно завершили курс</p>
<p className="text-white/80 text-xl font-semibold mb-6">"Восстановление колена"</p>
</div>
{/* Stats */}
<div
className={`bg-white/10 backdrop-blur-lg rounded-2xl p-6 border border-white/20 mb-8 transition-all duration-1000 delay-1000 ${
animationPhase >= 3 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
}`}
>
<div className="grid grid-cols-3 gap-4 text-center">
<div>
<div className="text-2xl font-bold text-white">12</div>
<div className="text-white/70 text-sm">Упражнений</div>
</div>
<div>
<div className="text-2xl font-bold text-white">4</div>
<div className="text-white/70 text-sm">Недели</div>
</div>
<div>
<div className="text-2xl font-bold text-white">100%</div>
<div className="text-white/70 text-sm">Завершено</div>
</div>
</div>
</div>
{/* Action Buttons */}
<div
className={`space-y-4 transition-all duration-1000 delay-1500 ${
animationPhase >= 3 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
}`}
>
<button
onClick={() => history.push("/courses")}
className="w-full bg-white/20 backdrop-blur-lg hover:bg-white/30 text-white font-semibold py-3 px-6 rounded-xl border border-white/30 transition-all duration-200 transform hover:scale-105"
>
Выбрать новый курс
</button>
<button
onClick={() => history.push("/home")}
className="w-full bg-transparent border-2 border-white/50 hover:bg-white/10 text-white font-semibold py-3 px-6 rounded-xl transition-all duration-200"
>
На главную
</button>
</div>
</div>
</div>
)
}
export default CourseComplete

View File

@ -1,312 +0,0 @@
"use client"
import type React from "react"
import { useState } from "react"
import { useHistory, useParams } from "react-router-dom"
import BottomNavigation from "../components/BottomNavigation"
const CourseExercises: React.FC = () => {
const history = useHistory()
const { id } = useParams<{ id: string }>()
const [currentSlide, setCurrentSlide] = useState(0)
const exercises = [
{
id: 1,
name: "Подъемы ног лежа",
duration: "15 мин",
sets: 3,
reps: 12,
image: "/placeholder.svg?height=200&width=300",
difficulty: "Легкий",
description: "Укрепление мышц бедра и улучшение подвижности коленного сустава",
calories: 45,
},
{
id: 2,
name: "Приседания у стены",
duration: "10 мин",
sets: 2,
reps: 15,
image: "/placeholder.svg?height=200&width=300",
difficulty: "Средний",
description: "Безопасные приседания для восстановления силы ног",
calories: 60,
},
{
id: 3,
name: "Растяжка квадрицепса",
duration: "8 мин",
sets: 1,
reps: 30,
image: "/placeholder.svg?height=200&width=300",
difficulty: "Легкий",
description: "Улучшение гибкости и снятие напряжения",
calories: 25,
},
{
id: 4,
name: "Укрепление икр",
duration: "12 мин",
sets: 3,
reps: 20,
image: "/placeholder.svg?height=200&width=300",
difficulty: "Средний",
description: "Развитие силы и выносливости икроножных мышц",
calories: 40,
},
]
const nextSlide = () => {
setCurrentSlide((prev) => (prev + 1) % exercises.length)
}
const prevSlide = () => {
setCurrentSlide((prev) => (prev - 1 + exercises.length) % exercises.length)
}
const currentExercise = exercises[currentSlide]
const getDifficultyColor = (difficulty: string) => {
switch (difficulty) {
case "Легкий":
return "bg-gradient-to-r from-emerald-400 to-green-500"
case "Средний":
return "bg-gradient-to-r from-amber-400 to-orange-500"
case "Сложный":
return "bg-gradient-to-r from-red-400 to-pink-500"
default:
return "bg-gradient-to-r from-gray-400 to-gray-500"
}
}
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 overflow-y-auto scrollable-content">
{/* Header */}
<div className="sticky top-0 z-40 bg-gradient-to-br from-[#2BACBE] via-blue-500 to-indigo-600 backdrop-blur-xl">
<div className="absolute inset-0 bg-gradient-to-r from-black/10 to-transparent"></div>
<div className="relative px-4 sm:px-6 pt-12 pb-6">
<div className="flex items-center justify-between mb-4">
<button
onClick={() => history.goBack()}
className="w-12 h-12 bg-white/20 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 hover:bg-white/30 transition-all duration-300 shadow-lg"
>
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<div className="text-center">
<h1 className="text-xl sm:text-2xl font-black text-white">Восстановление колена</h1>
<p className="text-blue-100 text-sm font-medium">Курс упражнений</p>
</div>
<div className="w-12 h-12 bg-white/20 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
</div>
</div>
</div>
</div>
{/* Exercise Slider */}
<div className="px-4 sm:px-6 -mt-4 mb-8">
<div className="glass-morphism rounded-3xl border border-white/50 shadow-2xl overflow-hidden backdrop-blur-2xl">
{/* Exercise Image */}
<div className="relative">
<img
src={currentExercise.image || "/placeholder.svg"}
alt={currentExercise.name}
className="w-full h-56 sm:h-64 object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-black/10"></div>
{/* Difficulty Badge */}
<div className="absolute top-4 right-4">
<div
className={`px-4 py-2 rounded-full text-xs font-bold text-white shadow-lg backdrop-blur-sm ${getDifficultyColor(currentExercise.difficulty)}`}
>
{currentExercise.difficulty}
</div>
</div>
{/* Navigation arrows */}
<button
onClick={prevSlide}
className="absolute left-4 top-1/2 transform -translate-y-1/2 w-12 h-12 bg-black/20 backdrop-blur-xl rounded-full flex items-center justify-center text-white hover:bg-black/30 transition-all duration-300 shadow-lg border border-white/20"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<button
onClick={nextSlide}
className="absolute right-4 top-1/2 transform -translate-y-1/2 w-12 h-12 bg-black/20 backdrop-blur-xl rounded-full flex items-center justify-center text-white hover:bg-black/30 transition-all duration-300 shadow-lg border border-white/20"
>
<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>
</button>
{/* Play Button Overlay */}
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-20 h-20 bg-white/90 backdrop-blur-xl rounded-full flex items-center justify-center shadow-2xl hover:bg-white transition-all duration-300 transform hover:scale-110 border border-white/50">
<svg className="w-8 h-8 text-gray-800 ml-1" fill="currentColor" viewBox="0 0 24 24">
<path d="M8 5v14l11-7z" />
</svg>
</div>
</div>
</div>
{/* Exercise Info */}
<div className="p-6 sm:p-8">
<h3 className="text-2xl sm:text-3xl font-black text-gray-800 mb-3">{currentExercise.name}</h3>
<p className="text-gray-600 mb-6 leading-relaxed text-sm sm:text-base">{currentExercise.description}</p>
{/* Stats Grid */}
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6">
<div className="text-center">
<div className="w-12 h-12 bg-gradient-to-r from-blue-400 to-cyan-500 rounded-2xl flex items-center justify-center mx-auto mb-2 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div className="text-lg font-black text-gray-800">{currentExercise.duration}</div>
<div className="text-xs text-gray-600 font-medium">Время</div>
</div>
<div className="text-center">
<div className="w-12 h-12 bg-gradient-to-r from-green-400 to-emerald-500 rounded-2xl flex items-center justify-center mx-auto mb-2 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
</div>
<div className="text-lg font-black text-gray-800">{currentExercise.sets}</div>
<div className="text-xs text-gray-600 font-medium">Подходы</div>
</div>
<div className="text-center">
<div className="w-12 h-12 bg-gradient-to-r from-purple-400 to-pink-500 rounded-2xl flex items-center justify-center mx-auto mb-2 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
</div>
<div className="text-lg font-black text-gray-800">{currentExercise.reps}</div>
<div className="text-xs text-gray-600 font-medium">Повторы</div>
</div>
<div className="text-center">
<div className="w-12 h-12 bg-gradient-to-r from-orange-400 to-red-500 rounded-2xl flex items-center justify-center mx-auto mb-2 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 .5-5 2.986-7C14 5 16.09 5.777 17.656 7.343A7.975 7.975 0 0120 13a7.975 7.975 0 01-2.343 5.657z"
/>
</svg>
</div>
<div className="text-lg font-black text-gray-800">{currentExercise.calories}</div>
<div className="text-xs text-gray-600 font-medium">Калории</div>
</div>
</div>
<button
onClick={() => history.push(`/exercise/${currentExercise.id}`)}
className="w-full bg-gradient-to-r from-[#2BACBE] via-blue-500 to-indigo-600 text-white font-black py-4 px-6 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 shadow-lg backdrop-blur-sm"
>
🚀 Начать упражнение
</button>
</div>
</div>
{/* Slide indicators */}
<div className="flex justify-center mt-6 space-x-2">
{exercises.map((_, index) => (
<button
key={index}
onClick={() => setCurrentSlide(index)}
className={`h-2 rounded-full transition-all duration-300 ${
index === currentSlide
? "bg-gradient-to-r from-[#2BACBE] to-blue-600 w-8 shadow-lg"
: "bg-gray-300 w-2 hover:bg-gray-400"
}`}
/>
))}
</div>
</div>
{/* Exercise List */}
<div className="px-4 sm:px-6 pb-28">
<h2 className="text-xl sm:text-2xl font-black text-gray-800 mb-6">Все упражнения курса</h2>
<div className="space-y-4">
{exercises.map((exercise, index) => (
<div
key={exercise.id}
onClick={() => history.push(`/exercise/${exercise.id}`)}
className={`glass-morphism rounded-2xl p-4 sm:p-6 border border-white/50 shadow-lg cursor-pointer transition-all duration-300 hover:shadow-2xl transform hover:scale-[1.02] backdrop-blur-xl ${
index === currentSlide ? "ring-2 ring-[#2BACBE] bg-blue-50/20" : ""
}`}
>
<div className="flex items-center space-x-4">
<div className="relative">
<div className="w-14 h-14 sm:w-16 sm:h-16 bg-gradient-to-br from-[#2BACBE] via-blue-500 to-indigo-600 rounded-2xl flex items-center justify-center text-white font-black text-lg sm:text-xl shadow-xl">
{index + 1}
</div>
<div className="absolute -top-1 -right-1 w-6 h-6 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-200">
<span className="text-xs">{index < currentSlide ? "✅" : index === currentSlide ? "▶️" : "⏳"}</span>
</div>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-black text-gray-800 text-lg sm:text-xl truncate">{exercise.name}</h3>
<p className="text-gray-600 text-sm mb-2 line-clamp-2">{exercise.description}</p>
<div className="flex items-center space-x-4 text-xs text-gray-500">
<span className="flex items-center space-x-1">
<span>💪</span>
<span>
{exercise.sets} × {exercise.reps}
</span>
</span>
<span className="flex items-center space-x-1">
<span></span>
<span>{exercise.duration}</span>
</span>
<span className="flex items-center space-x-1">
<span>🔥</span>
<span>{exercise.calories} кал</span>
</span>
</div>
</div>
<div className="text-[#2BACBE] transform transition-transform duration-300 hover:translate-x-1">
<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>
))}
</div>
</div>
<BottomNavigation />
</div>
)
}
export default CourseExercises

View File

@ -1,130 +0,0 @@
"use client"
import type React from "react"
import BottomNavigation from "../components/BottomNavigation"
import { useHistory } from "react-router-dom"
const Home: React.FC = () => {
const history = useHistory()
const currentDate = new Date().toLocaleDateString("ru-RU", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})
const courses = [
{ id: 1, name: "Восстановление колена", progress: 75, color: "from-[#2BACBE] to-[#2BACBE]/80" },
{ id: 2, name: "Укрепление спины", progress: 45, color: "from-[#5F5C5C] to-[#5F5C5C]/80" },
{ id: 3, name: "Реабилитация плеча", progress: 90, color: "from-[#2BACBE]/80 to-[#5F5C5C]" },
]
return (
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 pb-24 overflow-y-auto">
{/* Welcome Section */}
<div className="pt-12 px-6 mb-8">
<div className="bg-white/40 backdrop-blur-2xl rounded-3xl p-6 border border-white/20 shadow-2xl">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-black text-[#5F5C5C] mb-1">Привет, Александр!</h1>
<p className="text-[#5F5C5C]/70 font-medium">{currentDate}</p>
</div>
<div className="w-16 h-16 bg-gradient-to-br from-[#2BACBE] to-[#2BACBE]/80 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 shadow-lg">
<span className="text-2xl filter drop-shadow-sm">👤</span>
</div>
</div>
</div>
</div>
{/* Analytics Cards */}
<div className="px-6 mb-8">
<div className="grid grid-cols-2 gap-4">
<div className="bg-white/30 backdrop-blur-2xl rounded-2xl p-5 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
<div className="text-center">
<div className="text-3xl font-black text-[#2BACBE] mb-1">12</div>
<div className="text-sm text-[#5F5C5C] font-semibold">Дней подряд</div>
</div>
</div>
<div className="bg-white/30 backdrop-blur-2xl rounded-2xl p-5 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
<div className="text-center">
<div className="text-3xl font-black text-[#2BACBE] mb-1">85%</div>
<div className="text-sm text-[#5F5C5C] font-semibold">Прогресс</div>
</div>
</div>
</div>
</div>
{/* Current Exercise */}
<div className="px-6 mb-8">
<h2 className="text-xl font-black text-[#5F5C5C] mb-4">Текущее упражнение</h2>
<div className="bg-white/30 backdrop-blur-2xl rounded-3xl p-6 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300">
<div className="flex items-center space-x-5">
<div className="w-20 h-20 bg-gradient-to-br from-[#2BACBE] to-[#2BACBE]/80 rounded-2xl flex items-center justify-center shadow-lg">
<span className="text-3xl filter drop-shadow-sm">🦵</span>
</div>
<div className="flex-1">
<h3 className="font-black text-[#5F5C5C] text-lg mb-1">Подъемы ног</h3>
<p className="text-sm text-[#5F5C5C]/70 font-medium mb-3">Восстановление колена 3 подхода</p>
<div className="bg-white/50 rounded-full h-3 overflow-hidden">
<div
className="bg-gradient-to-r from-[#2BACBE] to-[#2BACBE]/80 h-3 rounded-full shadow-sm transition-all duration-500"
style={{ width: "60%" }}
></div>
</div>
</div>
<button
onClick={() => history.push("/exercise/1")}
className="bg-gradient-to-r from-[#2BACBE] to-[#2BACBE]/80 text-white px-6 py-3 rounded-2xl font-bold hover:shadow-xl transition-all duration-300 transform hover:scale-105 backdrop-blur-sm"
>
Продолжить
</button>
</div>
</div>
</div>
{/* Courses */}
<div className="px-6 mb-8">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-black text-[#5F5C5C]">Мои курсы</h2>
<button onClick={() => history.push("/courses")} className="text-[#2BACBE] text-sm font-bold hover:underline">
Все курсы
</button>
</div>
<div className="space-y-4">
{courses.map((course) => (
<div
key={course.id}
onClick={() => history.push(`/course/${course.id}/exercises`)}
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 items-center space-x-5">
<div
className={`w-16 h-16 bg-gradient-to-br ${course.color} rounded-2xl flex items-center justify-center shadow-lg`}
>
<span className="text-2xl text-white filter drop-shadow-sm">💪</span>
</div>
<div className="flex-1">
<h3 className="font-black text-[#5F5C5C] text-lg mb-2">{course.name}</h3>
<div className="bg-white/50 rounded-full h-3 mb-2 overflow-hidden">
<div
className={`bg-gradient-to-r ${course.color} h-3 rounded-full transition-all duration-700 shadow-sm`}
style={{ width: `${course.progress}%` }}
></div>
</div>
<p className="text-sm text-[#5F5C5C]/70 font-semibold">{course.progress}% завершено</p>
</div>
<div className="text-[#2BACBE] transform transition-transform duration-300 hover:translate-x-1">
<span className="text-2xl font-bold"></span>
</div>
</div>
</div>
))}
</div>
</div>
<BottomNavigation />
</div>
)
}
export default Home

View File

@ -1,264 +0,0 @@
"use client"
import type React from "react"
import { useState, useEffect } from "react"
import { useHistory, useParams } from "react-router-dom"
import BottomNavigation from "../components/BottomNavigation"
const Exercise: React.FC = () => {
const history = useHistory()
const { id } = useParams<{ id: string }>()
const [isPlaying, setIsPlaying] = useState(false)
const [currentTime, setCurrentTime] = useState(0)
const [totalTime] = useState(900) // 15 minutes in seconds
const [currentSet, setCurrentSet] = useState(1)
const [totalSets] = useState(3)
useEffect(() => {
let interval: NodeJS.Timeout
if (isPlaying) {
interval = setInterval(() => {
setCurrentTime((prev) => {
if (prev >= totalTime) {
setIsPlaying(false)
// Show completion animation
history.push("/course-complete")
return totalTime
}
return prev + 1
})
}, 1000)
}
return () => clearInterval(interval)
}, [isPlaying, totalTime, history])
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 progress = (currentTime / totalTime) * 100
const exerciseSteps = [
{
title: "Исходное положение",
description:
"Лягте на спину на коврик. Руки вдоль тела, ладони прижаты к полу. Ноги выпрямлены, носки направлены вверх. Поясница плотно прижата к полу.",
icon: "1⃣",
color: "from-blue-400 to-cyan-500",
},
{
title: "Задание",
description:
"Медленно поднимите прямые ноги до угла 90 градусов. Задержитесь на 2 секунды, затем медленно опустите ноги, не касаясь пола. Повторите движение плавно и контролируемо.",
icon: "2⃣",
color: "from-emerald-400 to-green-500",
},
{
title: "Подходы",
description: "Выполните 3 подхода по 12 повторений с отдыхом 60 секунд между подходами.",
icon: "3⃣",
color: "from-purple-400 to-pink-500",
},
{
title: "Перерыв",
description: "Отдыхайте 60 секунд между подходами. Дышите спокойно и расслабьте мышцы.",
icon: "4⃣",
color: "from-orange-400 to-red-500",
},
{
title: "Динамика и статика",
description:
"Динамическая фаза: подъем и опускание ног выполняется плавно, 2 секунды вверх, 2 секунды вниз. Статическая фаза: удержание ног в верхней точке на 2 секунды.",
icon: "5⃣",
color: "from-indigo-400 to-purple-500",
},
]
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 overflow-y-auto scrollable-content">
{/* Header */}
<div className="sticky top-0 z-40 bg-gradient-to-br from-[#2BACBE] via-blue-500 to-indigo-600 backdrop-blur-xl">
<div className="absolute inset-0 bg-gradient-to-r from-black/10 to-transparent"></div>
<div className="relative px-4 sm:px-6 pt-12 pb-4">
<div className="flex items-center justify-between mb-4">
<button
onClick={() => history.goBack()}
className="w-12 h-12 bg-white/20 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 hover:bg-white/30 transition-all duration-300 shadow-lg"
>
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<div className="text-center">
<h1 className="text-lg sm:text-xl font-black text-white">Подъемы ног лежа</h1>
<p className="text-blue-100 text-sm font-medium">Упражнение 1 из 12</p>
</div>
<div className="w-12 h-12 bg-white/20 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
</div>
</div>
{/* Set Counter */}
<div className="flex justify-center space-x-2">
{Array.from({ length: totalSets }).map((_, index) => (
<div
key={index}
className={`w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm transition-all duration-300 ${
index + 1 <= currentSet
? "bg-white text-[#2BACBE] shadow-lg"
: "bg-white/20 text-white border border-white/30"
}`}
>
{index + 1}
</div>
))}
</div>
</div>
</div>
{/* Video/Image Section */}
<div className="px-4 sm:px-6 -mt-4 mb-6">
<div className="glass-morphism rounded-3xl overflow-hidden shadow-2xl border border-white/50 backdrop-blur-2xl">
<div className="relative">
<img
src="/placeholder.svg?height=250&width=400"
alt="Exercise demonstration"
className="w-full h-56 sm:h-64 object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-black/10"></div>
<div className="absolute inset-0 flex items-center justify-center">
<button
onClick={() => setIsPlaying(!isPlaying)}
className="w-20 h-20 bg-white/90 backdrop-blur-xl rounded-full flex items-center justify-center shadow-2xl hover:bg-white transition-all duration-300 transform hover:scale-110 border border-white/50"
>
<span className="text-3xl text-gray-800 ml-1">{isPlaying ? "⏸️" : "▶️"}</span>
</button>
</div>
{/* Live indicators */}
{isPlaying && (
<div className="absolute top-4 left-4 flex items-center space-x-2">
<div className="w-3 h-3 bg-red-500 rounded-full animate-pulse"></div>
<span className="text-white text-sm font-bold bg-black/30 px-3 py-1 rounded-full backdrop-blur-sm">
LIVE
</span>
</div>
)}
{/* Timer Display */}
<div className="absolute top-4 right-4 bg-black/30 backdrop-blur-sm px-3 py-1 rounded-full">
<span className="text-white text-sm font-bold">{formatTime(currentTime)}</span>
</div>
</div>
</div>
</div>
{/* Exercise Steps */}
<div className="px-4 sm:px-6 space-y-4 mb-6">
{exerciseSteps.map((step, index) => (
<div
key={index}
className="glass-morphism rounded-2xl p-5 border border-white/50 shadow-lg hover:shadow-xl transition-all duration-300 backdrop-blur-xl"
>
<div className="flex items-start space-x-4">
<div
className={`w-12 h-12 bg-gradient-to-r ${step.color} rounded-xl flex items-center justify-center shadow-lg flex-shrink-0`}
>
<span className="text-lg">{step.icon}</span>
</div>
<div>
<h3 className="text-lg font-black text-gray-800 mb-2">{step.title}</h3>
<p className="text-gray-700 leading-relaxed text-sm sm:text-base">{step.description}</p>
</div>
</div>
</div>
))}
</div>
{/* Important Notes */}
<div className="px-4 sm:px-6 mb-32">
<div className="bg-gradient-to-r from-amber-50 to-orange-50 backdrop-blur-xl rounded-2xl p-5 border border-amber-200/50 shadow-lg">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 bg-gradient-to-r from-amber-400 to-orange-500 rounded-full flex items-center justify-center flex-shrink-0">
<span className="text-white font-bold text-sm">!</span>
</div>
<div>
<h3 className="text-lg font-black text-amber-800 mb-2">Важные замечания</h3>
<ul className="space-y-1 text-amber-800 text-sm">
<li> Не отрывайте поясницу от пола</li>
<li> Дышите равномерно, не задерживайте дыхание</li>
<li> При болевых ощущениях немедленно прекратите</li>
<li> Движения должны быть плавными и контролируемыми</li>
</ul>
</div>
</div>
</div>
</div>
{/* Fixed Timer at Bottom */}
<div className="fixed bottom-20 left-0 right-0 bg-white/95 backdrop-blur-2xl border-t border-gray-200/50 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">
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
<span className="text-sm font-bold text-gray-600">
Подход {currentSet} из {totalSets}
</span>
</div>
<span className="text-sm font-black text-gray-800">
{formatTime(currentTime)} / {formatTime(totalTime)}
</span>
</div>
<div className="bg-gray-200 rounded-full h-3 mb-4 overflow-hidden">
<div
className="bg-gradient-to-r from-[#2BACBE] via-blue-500 to-indigo-600 h-3 rounded-full transition-all duration-1000 shadow-sm"
style={{ width: `${progress}%` }}
></div>
</div>
<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 ${
isPlaying
? "bg-gradient-to-r from-red-500 to-pink-500 hover:from-red-600 hover:to-pink-600 text-white shadow-lg"
: "bg-gradient-to-r from-[#2BACBE] via-blue-500 to-indigo-600 hover:shadow-xl text-white"
}`}
>
{isPlaying ? "⏸️ Пауза" : "▶️ Начать"}
</button>
<button
onClick={() => {
setCurrentTime(0)
setIsPlaying(false)
}}
className="px-6 py-3 bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold rounded-xl transition-all duration-300 hover:shadow-lg"
>
🔄
</button>
<button
onClick={() => setCurrentSet((prev) => Math.min(prev + 1, totalSets))}
className="px-6 py-3 bg-gradient-to-r from-emerald-500 to-green-600 hover:from-emerald-600 hover:to-green-700 text-white font-bold rounded-xl transition-all duration-300 hover:shadow-lg"
>
</button>
</div>
</div>
</div>
<BottomNavigation />
</div>
)
}
export default Exercise

View File

@ -1,125 +0,0 @@
"use client"
import type React from "react"
import { useState } from "react"
import { useHistory } from "react-router-dom"
const ForgotPassword: React.FC = () => {
const history = useHistory()
const [email, setEmail] = useState("")
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
setIsSubmitted(true)
// Simulate sending reset email
setTimeout(() => {
history.push("/login")
}, 3000)
}
return (
<div className="min-h-screen bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Header */}
<div className="text-center mb-8">
<button
onClick={() => history.goBack()}
className="absolute top-6 left-6 w-12 h-12 bg-white/10 backdrop-blur-lg rounded-xl flex items-center justify-center border border-white/20 text-white hover:bg-white/20 transition-all"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<div className="w-20 h-20 bg-white/10 backdrop-blur-2xl rounded-2xl flex items-center justify-center mx-auto mb-4 border border-white/20 shadow-2xl">
<svg className="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
<h1 className="text-3xl font-black text-white mb-2">Забыли пароль?</h1>
<p className="text-white/80 font-medium">
{isSubmitted ? "Проверьте вашу почту" : "Введите email для восстановления пароля"}
</p>
</div>
{/* Form */}
<div className="glass-morphism rounded-3xl p-8 border border-white/20 shadow-2xl">
{!isSubmitted ? (
<form onSubmit={handleSubmit} className="space-y-6">
{/* Email Input */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Электронная почта</label>
<div className="relative">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="example@mail.com"
required
/>
<svg
className="absolute right-3 top-3.5 w-5 h-5 text-white/60"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"
/>
</svg>
</div>
</div>
{/* Submit Button */}
<button
type="submit"
className="w-full bg-white/20 backdrop-blur-lg hover:bg-white/30 text-white font-bold py-3 px-6 rounded-2xl border border-white/30 transition-all duration-300 transform hover:scale-105 shadow-lg"
>
Отправить ссылку
</button>
</form>
) : (
<div className="text-center space-y-6">
{/* Success Icon */}
<div className="w-16 h-16 bg-green-500/20 backdrop-blur-lg rounded-full flex items-center justify-center mx-auto border border-green-400/30">
<svg className="w-8 h-8 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 className="text-xl font-bold text-white mb-2">Письмо отправлено!</h3>
<p className="text-white/80 text-sm leading-relaxed">
Мы отправили инструкции по восстановлению пароля на адрес{" "}
<span className="font-semibold">{email}</span>
</p>
</div>
<div className="text-center">
<p className="text-white/60 text-xs mb-4">Автоматический переход через 3 секунды...</p>
<button
onClick={() => history.push("/login")}
className="text-white/80 text-sm font-medium hover:text-white transition-colors"
>
Вернуться к входу
</button>
</div>
</div>
)}
</div>
</div>
</div>
)
}
export default ForgotPassword

View File

@ -1,236 +1,10 @@
"use client"
import type React from "react"
import { useEffect, useState } from "react"
import { useHistory } from "react-router-dom"
import BottomNavigation from "../components/BottomNavigation"
const Home: React.FC = () => {
const history = useHistory()
const [currentDate, setCurrentDate] = useState("")
useEffect(() => {
setCurrentDate(
new Date().toLocaleDateString("ru-RU", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
}),
)
}, [])
const stats = [
{ value: "12", label: "Дней подряд", icon: "🔥", color: "from-orange-400 to-red-500" },
{ value: "85%", label: "Прогресс", icon: "📈", color: "from-emerald-400 to-green-500" },
{ value: "3", label: "Курса", icon: "📚", color: "from-blue-400 to-cyan-500" },
{ value: "45", label: "Минут", icon: "⏱️", color: "from-purple-400 to-pink-500" },
]
const courses = [
{
id: 1,
name: "Восстановление колена",
progress: 75,
color: "from-[#2BACBE] to-blue-600",
icon: "🦵",
exercises: 12,
nextExercise: "Подъемы ног лежа",
},
{
id: 2,
name: "Укрепление спины",
progress: 45,
color: "from-emerald-500 to-green-600",
icon: "🏃‍♂️",
exercises: 8,
nextExercise: "Планка",
},
{
id: 3,
name: "Реабилитация плеча",
progress: 90,
color: "from-purple-500 to-pink-600",
icon: "💪",
exercises: 10,
nextExercise: "Вращения плечами",
},
]
function Home() {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 overflow-y-auto scrollable-content">
{/* Header */}
<div className="bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] pt-12 pb-8 px-4 sm:px-6 relative overflow-hidden">
{/* Background Pattern */}
<div className="absolute inset-0 opacity-10">
<div className="absolute top-10 left-10 w-20 h-20 bg-white rounded-full animate-pulse"></div>
<div className="absolute bottom-10 right-10 w-16 h-16 bg-white rounded-full animate-bounce"></div>
<div className="absolute top-1/2 right-1/4 w-12 h-12 bg-white rounded-full animate-ping"></div>
<div className="absolute top-1/4 left-1/3 w-8 h-8 bg-white rounded-full animate-pulse"></div>
</div>
<div className="relative z-10">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-2xl sm:text-3xl font-black text-white mb-2">Привет, Александр! 👋</h1>
<p className="text-white/80 font-medium text-sm sm:text-base">{currentDate}</p>
</div>
<div className="w-16 h-16 bg-white/20 backdrop-blur-xl rounded-2xl flex items-center justify-center border border-white/30 shadow-xl relative">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
<div className="absolute -top-1 -right-1 w-5 h-5 bg-green-400 rounded-full border-2 border-white animate-pulse"></div>
</div>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-2 gap-3 sm:gap-4">
{stats.map((stat, index) => (
<div
key={index}
className="bg-white/15 backdrop-blur-xl rounded-2xl p-4 border border-white/20 shadow-lg hover:bg-white/20 transition-all duration-300 transform hover:scale-105"
>
<div className="flex items-center space-x-3">
<div
className={`w-10 h-10 sm:w-12 sm:h-12 bg-gradient-to-r ${stat.color} rounded-xl flex items-center justify-center shadow-lg`}
>
<span className="text-lg sm:text-xl">{stat.icon}</span>
</div>
<div>
<div className="text-xl sm:text-2xl font-black text-white">{stat.value}</div>
<div className="text-white/70 text-xs sm:text-sm font-medium">{stat.label}</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
<div className="px-4 sm:px-6 space-y-8 -mt-4 pb-28">
{/* Current Exercise */}
<div className="glass-morphism rounded-3xl p-6 border border-white/50 shadow-2xl backdrop-blur-2xl">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl sm:text-2xl font-black text-gray-800">Текущее упражнение</h2>
<div className="px-3 py-1 bg-gradient-to-r from-green-400 to-emerald-500 rounded-full shadow-lg">
<span className="text-white text-sm font-bold">Активно</span>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="relative">
<div className="w-20 h-20 bg-gradient-to-br from-[#2BACBE] via-blue-500 to-indigo-600 rounded-2xl flex items-center justify-center shadow-xl">
<span className="text-3xl">🦵</span>
</div>
<div className="absolute -bottom-1 -right-1 w-6 h-6 bg-gradient-to-r from-orange-400 to-red-500 rounded-full flex items-center justify-center shadow-lg animate-pulse">
<svg className="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M8 5v14l11-7z" />
</svg>
</div>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-black text-gray-800 text-lg mb-1">Подъемы ног лежа</h3>
<p className="text-gray-600 font-medium mb-3 text-sm">Восстановление колена 3 подхода по 12</p>
<div className="relative">
<div className="bg-gray-200 rounded-full h-3 overflow-hidden">
<div
className="bg-gradient-to-r from-[#2BACBE] via-blue-500 to-indigo-600 h-3 rounded-full shadow-sm transition-all duration-700"
style={{ width: "60%" }}
></div>
</div>
<div className="absolute right-0 -top-6 text-sm font-bold text-gray-600">60%</div>
</div>
</div>
<button
onClick={() => history.push("/exercise/1")}
className="bg-gradient-to-r from-[#2BACBE] via-blue-500 to-indigo-600 text-white px-4 sm:px-6 py-3 rounded-2xl font-bold hover:shadow-xl transition-all duration-300 transform hover:scale-105 backdrop-blur-sm text-sm sm:text-base"
>
Продолжить
</button>
</div>
</div>
{/* Quick Stats */}
<div className="grid grid-cols-3 gap-4">
<div className="glass-morphism rounded-2xl p-4 text-center border border-white/50 shadow-lg backdrop-blur-xl">
<div className="text-2xl font-black text-[#2BACBE] mb-1">24</div>
<div className="text-xs text-gray-600 font-semibold">Упражнений</div>
</div>
<div className="glass-morphism rounded-2xl p-4 text-center border border-white/50 shadow-lg backdrop-blur-xl">
<div className="text-2xl font-black text-emerald-500 mb-1">180</div>
<div className="text-xs text-gray-600 font-semibold">Минут</div>
</div>
<div className="glass-morphism rounded-2xl p-4 text-center border border-white/50 shadow-lg backdrop-blur-xl">
<div className="text-2xl font-black text-purple-500 mb-1">7</div>
<div className="text-xs text-gray-600 font-semibold">Дней</div>
</div>
</div>
{/* Courses */}
<div>
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl sm:text-2xl font-black text-gray-800">Мои курсы</h2>
<button
onClick={() => history.push("/courses")}
className="text-[#2BACBE] text-sm font-bold hover:underline flex items-center space-x-1"
>
<span>Все курсы</span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
<div className="space-y-4">
{courses.map((course) => (
<div
key={course.id}
onClick={() => history.push(`/course/${course.id}/exercises`)}
className="glass-morphism rounded-3xl p-6 border border-white/50 shadow-xl cursor-pointer hover:shadow-2xl transition-all duration-300 transform hover:scale-[1.02] backdrop-blur-2xl"
>
<div className="flex items-center space-x-5">
<div
className={`w-16 h-16 bg-gradient-to-br ${course.color} rounded-2xl flex items-center justify-center shadow-xl relative`}
>
<span className="text-2xl text-white filter drop-shadow-sm">{course.icon}</span>
<div className="absolute -top-1 -right-1 w-5 h-5 bg-white rounded-full flex items-center justify-center shadow-lg">
<span className="text-xs font-bold text-gray-600">{course.exercises}</span>
</div>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-black text-gray-800 text-lg mb-1">{course.name}</h3>
<p className="text-gray-600 text-sm mb-2">Следующее: {course.nextExercise}</p>
<div className="bg-gray-200 rounded-full h-3 mb-2 overflow-hidden">
<div
className={`bg-gradient-to-r ${course.color} h-3 rounded-full transition-all duration-700 shadow-sm`}
style={{ width: `${course.progress}%` }}
></div>
</div>
<p className="text-sm text-gray-600 font-semibold">{course.progress}% завершено</p>
</div>
<div className="text-[#2BACBE] transform transition-transform duration-300 hover:translate-x-1">
<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>
))}
</div>
</div>
</div>
<BottomNavigation />
</div>
)
<>
<p className="pt-20">Домашняя страница</p>
</>
);
}
export default Home
export default Home;

View File

@ -1,151 +1,11 @@
"use client"
import type React from "react"
import { useState } from "react"
import { useHistory } from "react-router-dom"
const Login: React.FC = () => {
const history = useHistory()
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [showPassword, setShowPassword] = useState(false)
const handleLogin = (e: React.FormEvent) => {
e.preventDefault()
// Simulate login
history.push("/home")
}
function Login() {
return (
<div className="min-h-screen bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Logo */}
<div className="text-center mb-8">
<div className="w-20 h-20 bg-white/10 backdrop-blur-2xl rounded-2xl flex items-center justify-center mx-auto mb-4 border border-white/20 shadow-2xl">
<svg width="40" height="40" viewBox="0 0 100 100" fill="none" className="text-white">
<circle cx="50" cy="20" r="8" fill="currentColor" />
<path
d="M50 28 L50 60 M50 45 L35 35 M50 45 L65 35 M50 60 L35 80 M50 60 L65 80"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
/>
</svg>
</div>
<h1 className="text-3xl font-black text-white mb-2">Добро пожаловать!</h1>
<p className="text-white/80 font-medium">Войдите в свой аккаунт</p>
</div>
<div className=''>
<h1>Войти/залогиниться</h1>
{/* Login Form */}
<div className="glass-morphism rounded-3xl p-8 border border-white/20 shadow-2xl">
<form onSubmit={handleLogin} className="space-y-6">
{/* Email Input */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Электронная почта</label>
<div className="relative">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="example@mail.com"
required
/>
<svg
className="absolute right-3 top-3.5 w-5 h-5 text-white/60"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"
/>
</svg>
</div>
</div>
{/* Password Input */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Пароль</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="••••••••"
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-3.5 text-white/60 hover:text-white transition-colors"
>
{showPassword ? (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
)}
</button>
</div>
</div>
{/* Forgot Password */}
<div className="text-right">
<button
type="button"
onClick={() => history.push("/forgot-password")}
className="text-white/80 text-sm font-medium hover:text-white transition-colors"
>
Забыли пароль?
</button>
</div>
{/* Login Button */}
<button
type="submit"
className="w-full bg-white/20 backdrop-blur-lg hover:bg-white/30 text-white font-bold py-3 px-6 rounded-2xl border border-white/30 transition-all duration-300 transform hover:scale-105 shadow-lg"
>
Войти
</button>
</form>
{/* Register Link */}
<div className="text-center mt-6">
<p className="text-white/80 text-sm">
Нет аккаунта?{" "}
<button onClick={() => history.push("/register")} className="text-white font-semibold hover:underline">
Зарегистрироваться
</button>
</p>
</div>
</div>
</div>
</div>
)
);
}
export default Login
export default Login;

View File

@ -1,228 +1,13 @@
"use client"
import type React from "react"
import { useState } from "react"
import { useHistory } from "react-router-dom"
const Register: React.FC = () => {
const history = useHistory()
const [formData, setFormData] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
confirmPassword: "",
})
const [showPassword, setShowPassword] = useState(false)
const [showConfirmPassword, setShowConfirmPassword] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
if (formData.password !== formData.confirmPassword) {
alert("Пароли не совпадают")
return
}
// Simulate registration
history.push("/home")
}
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
})
}
function Auth() {
return (
<div className="min-h-screen bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Header */}
<div className="text-center mb-8">
<button
onClick={() => history.goBack()}
className="absolute top-6 left-6 w-12 h-12 bg-white/10 backdrop-blur-lg rounded-xl flex items-center justify-center border border-white/20 text-white hover:bg-white/20 transition-all"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<div className='pt-20'>
<div className="w-20 h-20 bg-white/10 backdrop-blur-2xl rounded-2xl flex items-center justify-center mx-auto mb-4 border border-white/20 shadow-2xl">
<svg width="40" height="40" viewBox="0 0 100 100" fill="none" className="text-white">
<circle cx="50" cy="20" r="8" fill="currentColor" />
<path
d="M50 28 L50 60 M50 45 L35 35 M50 45 L65 35 M50 60 L35 80 M50 60 L65 80"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
/>
</svg>
</div>
<h1 className="text-3xl font-black text-white mb-2">Регистрация</h1>
<p className="text-white/80 font-medium">Создайте новый аккаунт</p>
</div>
<h1 className='cursor-pointer'>Страница регистрации</h1>
{/* Registration Form */}
<div className="glass-morphism rounded-3xl p-8 border border-white/20 shadow-2xl">
<form onSubmit={handleSubmit} className="space-y-4">
{/* Name Fields */}
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Имя</label>
<input
type="text"
name="firstName"
value={formData.firstName}
onChange={handleInputChange}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="Иван"
required
/>
</div>
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Фамилия</label>
<input
type="text"
name="lastName"
value={formData.lastName}
onChange={handleInputChange}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="Иванов"
required
/>
</div>
</div>
{/* Email */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Электронная почта</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleInputChange}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="example@mail.com"
required
/>
</div>
{/* Password */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Пароль</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
name="password"
value={formData.password}
onChange={handleInputChange}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="••••••••"
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-3.5 text-white/60 hover:text-white transition-colors"
>
{showPassword ? (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
)}
</button>
</div>
</div>
{/* Confirm Password */}
<div>
<label className="block text-white/90 text-sm font-semibold mb-2">Подтвердите пароль</label>
<div className="relative">
<input
type={showConfirmPassword ? "text" : "password"}
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleInputChange}
className="w-full bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl px-4 py-3 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-transparent transition-all"
placeholder="••••••••"
required
/>
<button
type="button"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
className="absolute right-3 top-3.5 text-white/60 hover:text-white transition-colors"
>
{showConfirmPassword ? (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
)}
</button>
</div>
</div>
{/* Register Button */}
<button
type="submit"
className="w-full bg-white/20 backdrop-blur-lg hover:bg-white/30 text-white font-bold py-3 px-6 rounded-2xl border border-white/30 transition-all duration-300 transform hover:scale-105 shadow-lg mt-6"
>
Зарегистрироваться
</button>
</form>
{/* Login Link */}
<div className="text-center mt-6">
<p className="text-white/80 text-sm">
Уже есть аккаунт?{" "}
<button onClick={() => history.push("/login")} className="text-white font-semibold hover:underline">
Войти
</button>
</p>
</div>
</div>
</div>
</div>
)
);
}
export default Register
export default Auth;

View File

@ -1,204 +0,0 @@
"use client"
import type React from "react"
import { useHistory } from "react-router-dom"
import BottomNavigation from "../components/BottomNavigation"
const Settings: React.FC = () => {
const history = useHistory()
const handleLogout = () => {
// Simulate logout
history.push("/login")
}
return (
<div className="min-h-screen bg-gray-50 pb-20">
{/* Header */}
<div className="bg-gradient-to-r from-gray-600 to-gray-800 px-4 pt-12 pb-6">
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-2xl font-bold text-white">Настройки</h1>
<p className="text-gray-300">Профиль пациента</p>
</div>
<div className="w-16 h-16 bg-white/20 backdrop-blur-lg rounded-full flex items-center justify-center border border-white/30">
<span className="text-2xl">👤</span>
</div>
</div>
</div>
{/* Profile Information */}
<div className="px-4 -mt-4 mb-6">
<div className="bg-white/80 backdrop-blur-lg rounded-2xl p-6 border border-gray-200/50 shadow-lg">
<h2 className="text-lg font-semibold text-gray-800 mb-4">Личная информация</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Имя</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<span className="text-gray-800">Александр Петров</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Email</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<span className="text-gray-800">alexander.petrov@email.com</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Логин</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<span className="text-gray-800">alex_petrov</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Дата регистрации</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<span className="text-gray-800">15 марта 2024</span>
</div>
</div>
</div>
</div>
</div>
{/* Medical Information */}
<div className="px-4 mb-6">
<div className="bg-white/80 backdrop-blur-lg rounded-2xl p-6 border border-gray-200/50 shadow-lg">
<h2 className="text-lg font-semibold text-gray-800 mb-4">Медицинская информация</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Тип травмы</label>
<div className="bg-red-50 rounded-lg p-3 border border-red-200">
<div className="flex items-center space-x-2">
<span className="text-red-600">🦵</span>
<span className="text-red-800 font-medium">Травма колена</span>
</div>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Описание травмы</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<p className="text-gray-800 text-sm leading-relaxed">
Повреждение передней крестообразной связки левого колена. Получена во время игры в футбол 12 февраля
2024 года. Проведена артроскопическая операция 20 февраля 2024 года.
</p>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Лечащий врач</label>
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<span className="text-gray-800">Доктор Иванов И.И.</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-600 mb-1">Стадия восстановления</label>
<div className="bg-green-50 rounded-lg p-3 border border-green-200">
<div className="flex items-center justify-between">
<span className="text-green-800 font-medium">Активная реабилитация</span>
<span className="text-green-600 text-sm">75% завершено</span>
</div>
<div className="mt-2 bg-green-200 rounded-full h-2">
<div className="bg-green-500 h-2 rounded-full" style={{ width: "75%" }}></div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Statistics */}
<div className="px-4 mb-6">
<div className="bg-white/80 backdrop-blur-lg rounded-2xl p-6 border border-gray-200/50 shadow-lg">
<h2 className="text-lg font-semibold text-gray-800 mb-4">Статистика</h2>
<div className="grid grid-cols-2 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-blue-600">28</div>
<div className="text-sm text-gray-600">Дней занятий</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-green-600">156</div>
<div className="text-sm text-gray-600">Упражнений выполнено</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-purple-600">3</div>
<div className="text-sm text-gray-600">Курса завершено</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-orange-600">42</div>
<div className="text-sm text-gray-600">Часов тренировок</div>
</div>
</div>
</div>
</div>
{/* Settings Options */}
<div className="px-4 mb-6">
<div className="bg-white/80 backdrop-blur-lg rounded-2xl border border-gray-200/50 shadow-lg overflow-hidden">
<div className="divide-y divide-gray-200">
<button className="w-full px-6 py-4 text-left hover:bg-gray-50 transition-colors">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<span className="text-xl">🔔</span>
<span className="font-medium text-gray-800">Уведомления</span>
</div>
<span className="text-gray-400"></span>
</div>
</button>
<button className="w-full px-6 py-4 text-left hover:bg-gray-50 transition-colors">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<span className="text-xl">🌙</span>
<span className="font-medium text-gray-800">Темная тема</span>
</div>
<span className="text-gray-400"></span>
</div>
</button>
<button className="w-full px-6 py-4 text-left hover:bg-gray-50 transition-colors">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<span className="text-xl">🌍</span>
<span className="font-medium text-gray-800">Язык</span>
</div>
<span className="text-gray-400"></span>
</div>
</button>
<button className="w-full px-6 py-4 text-left hover:bg-gray-50 transition-colors">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<span className="text-xl">📊</span>
<span className="font-medium text-gray-800">Экспорт данных</span>
</div>
<span className="text-gray-400"></span>
</div>
</button>
</div>
</div>
</div>
{/* Logout Button */}
<div className="px-4 mb-8">
<button
onClick={handleLogout}
className="w-full bg-red-500 hover:bg-red-600 text-white font-semibold py-4 px-6 rounded-2xl transition-all duration-200 transform hover:scale-105 shadow-lg"
>
Выйти из аккаунта
</button>
</div>
<BottomNavigation />
</div>
)
}
export default Settings

View File

@ -1,98 +0,0 @@
"use client"
import type React from "react"
import { useEffect, useState } from "react"
import { useHistory } from "react-router-dom"
import manImage from '../assets/man.svg';
import emblemImage from '../assets/emblem.png';
const Welcome: React.FC = () => {
const history = useHistory()
const [animationPhase, setAnimationPhase] = useState(0)
useEffect(() => {
const timer1 = setTimeout(() => setAnimationPhase(1), 500)
const timer2 = setTimeout(() => setAnimationPhase(2), 1500)
const timer3 = setTimeout(() => setAnimationPhase(3), 2500)
// const timer4 = setTimeout(() => history.push("/login"), 4000)
return () => {
clearTimeout(timer1)
clearTimeout(timer2)
clearTimeout(timer3)
// clearTimeout(timer4)
}
}, [history])
return (
<div className="min-h-screen relative overflow-hidden">
<img
className="h-[30rem] lg:h-[50rem] w-auto z-50 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 opacity-15"
src={manImage}
alt=""
/>
{/* <img
className="h-[30rem] lg:h-[0rem] w-auto z-50 absolute right-0 bottom-0 transform opacity-10"
src={emblemImage}
alt=""
/> */}
<div className="absolute inset-0 bg-gradient-to-br from-[#3ABBC7] to-[#0D212C]">
{/* Floating particles */}
<div className="absolute inset-0">
<div className="absolute top-20 left-10 w-32 h-32 bg-white/5 rounded-full animate-pulse blur-xl"></div>
<div className="absolute bottom-32 right-16 w-24 h-24 bg-white/10 rounded-full animate-bounce blur-lg"></div>
<div className="absolute top-1/2 left-1/4 w-16 h-16 bg-white/5 rounded-full animate-ping blur-md"></div>
<div className="absolute top-1/3 right-1/3 w-20 h-20 bg-white/5 rounded-full animate-pulse blur-lg"></div>
</div>
{/* Main Content */}
<div className="flex items-center justify-center min-h-screen">
<div className="text-center z-10 px-8">
{/* App Name */}
<div
className={`transition-all duration-1000 delay-300 ${animationPhase >= 1 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
}`}
>
<h1 className="text-5xl font-black text-white mb-4 tracking-tight filter drop-shadow-lg">Реабилитация</h1>
<p className="text-white/90 text-xl font-medium tracking-wide">Восстановление через движение</p>
</div>
{/* Loading indicator */}
<div
className={`mt-16 transition-all duration-500 delay-700 ${animationPhase >= 1 ? "opacity-100" : "opacity-0"}`}
>
<div className="w-64 h-3 bg-white/10 rounded-full mx-auto overflow-hidden backdrop-blur-sm border border-white/20">
<div
className="h-full bg-gradient-to-r from-white via-white/80 to-white rounded-full shadow-lg"
style={{
width: `${Math.min((animationPhase + 1) * 25, 100)}%`,
transition: "width 0.8s cubic-bezier(0.4, 0, 0.2, 1)",
}}
></div>
</div>
<p className="text-white/70 text-lg mt-6 font-medium">Загрузка...</p>
</div>
</div>
</div>
</div>
</div>
)
}
export default Welcome

View File

@ -1,14 +0,0 @@
/** @type {import('tailwindcss').Config} */
const defaultConfig = require("shadcn/ui/tailwind.config")
module.exports = {
...defaultConfig,
content: [
...defaultConfig.content,
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"*.{js,ts,jsx,tsx,mdx}",
],
plugins: [...defaultConfig.plugins, require("tailwindcss-animate")],
}