From c87ff7213e15c7b878cede8dccd5af24c6ae7041 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sat, 31 May 2025 15:35:08 +0600 Subject: [PATCH 001/138] =?UTF-8?q?=D0=9F=D0=BE=D0=BA=D0=B0=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B8=D0=BB=D0=BE=D1=81=D1=8C?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=B5=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D1=81=D1=82=D1=83=D0=B4=D0=B5=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/{ => teacher}/page.tsx | 4 +- app/(student)/components/BaseLayout.tsx | 18 ++ app/(student)/components/CounterBanner.tsx | 61 ++++++ app/(student)/components/HomeClient.tsx | 164 ++++++++++++++ app/(student)/components/MyFontAwesome.tsx | 17 ++ app/(student)/components/VideoPlay.tsx | 49 +++++ .../components/buttons/FancyLinkBtn.tsx | 29 +++ app/(student)/components/popUp/Tiered.tsx | 57 +++++ app/(student)/layout.tsx | 13 ++ app/(student)/new/page.tsx | 11 + app/(student)/page.tsx | 8 + app/layout.tsx | 3 + package-lock.json | 94 ++++++++ package.json | 8 +- public/layout/images/home-banner-phone.png | Bin 0 -> 45155 bytes public/layout/images/logo-kg.svg | 205 ++++++++++++++++++ public/layout/images/logo-remove-white.png | Bin 0 -> 60288 bytes public/layout/images/logo-remove.png | Bin 0 -> 75195 bytes public/layout/images/man.png | Bin 0 -> 17471 bytes public/layout/images/shape.png | Bin 0 -> 2305 bytes public/layout/images/shape1.png | Bin 0 -> 382 bytes public/layout/images/shape2.png | Bin 0 -> 645 bytes public/layout/svg/red-logo.svg | 46 ++++ public/layout/svg/white-logo.svg | 47 ++++ styles/layout/_button.scss | 51 +++++ styles/layout/_topbar.scss | 17 +- styles/layout/_typography.scss | 2 +- styles/layout/layout.scss | 79 ++++++- 28 files changed, 977 insertions(+), 6 deletions(-) rename app/(main)/{ => teacher}/page.tsx (99%) create mode 100644 app/(student)/components/BaseLayout.tsx create mode 100644 app/(student)/components/CounterBanner.tsx create mode 100644 app/(student)/components/HomeClient.tsx create mode 100644 app/(student)/components/MyFontAwesome.tsx create mode 100644 app/(student)/components/VideoPlay.tsx create mode 100644 app/(student)/components/buttons/FancyLinkBtn.tsx create mode 100644 app/(student)/components/popUp/Tiered.tsx create mode 100644 app/(student)/layout.tsx create mode 100644 app/(student)/new/page.tsx create mode 100644 app/(student)/page.tsx create mode 100644 public/layout/images/home-banner-phone.png create mode 100644 public/layout/images/logo-kg.svg create mode 100644 public/layout/images/logo-remove-white.png create mode 100644 public/layout/images/logo-remove.png create mode 100644 public/layout/images/man.png create mode 100644 public/layout/images/shape.png create mode 100644 public/layout/images/shape1.png create mode 100644 public/layout/images/shape2.png create mode 100644 public/layout/svg/red-logo.svg create mode 100644 public/layout/svg/white-logo.svg create mode 100644 styles/layout/_button.scss diff --git a/app/(main)/page.tsx b/app/(main)/teacher/page.tsx similarity index 99% rename from app/(main)/page.tsx rename to app/(main)/teacher/page.tsx index afe44527..a06710d5 100644 --- a/app/(main)/page.tsx +++ b/app/(main)/teacher/page.tsx @@ -6,8 +6,8 @@ import { Column } from 'primereact/column'; import { DataTable } from 'primereact/datatable'; import { Menu } from 'primereact/menu'; import React, { useContext, useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../demo/service/ProductService'; -import { LayoutContext } from '../../layout/context/layoutcontext'; +import { ProductService } from '../../../demo/service/ProductService'; +import { LayoutContext } from '../../../layout/context/layoutcontext'; import Link from 'next/link'; import { Demo } from '@/types'; import { ChartData, ChartOptions } from 'chart.js'; diff --git a/app/(student)/components/BaseLayout.tsx b/app/(student)/components/BaseLayout.tsx new file mode 100644 index 00000000..d7027d43 --- /dev/null +++ b/app/(student)/components/BaseLayout.tsx @@ -0,0 +1,18 @@ +"use client"; + +// import Footer from "./Footer"; +// import Header from "./Header"; + +export default function BaseLayout({ children }: { children: React.ReactNode }) { + return ( + <> +
+ {/*
*/} +
+ {children} +
+ {/*
*/} +
+ + ); +} \ No newline at end of file diff --git a/app/(student)/components/CounterBanner.tsx b/app/(student)/components/CounterBanner.tsx new file mode 100644 index 00000000..75b59db3 --- /dev/null +++ b/app/(student)/components/CounterBanner.tsx @@ -0,0 +1,61 @@ +import React from 'react' +import { faCircle, + faChalkboard, + faUserGraduate, + faBookOpen, + faShieldHeart, +} from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from './MyFontAwesome'; +import CountUp from 'react-countup'; + +export default function CounterBanner() { + return ( +
+
+
+
+ + +
+
+
+
+ Курстар & видеосабактар +
+
+ +
+
+ + +
+
+
+
+ Катталган студенттер +
+
+ +
+
+ + +
+
+
+
+ Окутуучулар +
+
+ +
+
+ + +
+
+
%
+ Канааттануу деңгээли +
+
+
+
+ ) +} diff --git a/app/(student)/components/HomeClient.tsx b/app/(student)/components/HomeClient.tsx new file mode 100644 index 00000000..c57325ca --- /dev/null +++ b/app/(student)/components/HomeClient.tsx @@ -0,0 +1,164 @@ +"use client"; + +import AOS from "aos"; +import "aos/dist/aos.css"; +import { useEffect } from "react"; +import CounterBanner from "./CounterBanner"; +import Link from "next/link"; +import { faClock, faVideo,} from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from "./MyFontAwesome"; +import VideoPlay from "./VideoPlay"; +import Image from "next/image"; + +export default function HomeClient() { + useEffect(() => { + AOS.init(); + }, []); + + return ( +
+
+
+
+
+
+ + + ЫҢГАЙЛУУ ОКУУ ҮЧҮН ОНЛАЙН МЕЙКИНДИК + +
+

+ Аралыктан окутуу порталына кош келиңиз! +

+
+ {" "} + Университеттин онлайн билим берүү жаатындагы долбоорлорун + бириктирүүдөбүз: +
    +
  • ачык онлайн курстар
  • +
  • жогорку билим берүү программалары
  • +
+
+
+
+ +
+
+ +
+
+ Shape +
+ + Пользователь + +
+ Shape +
+ +
+ Shape +
+ +
+
+ 13000 +

lorem

+
+
+ +
+
+ Куттуктайбыз! +

Сиздин кабыл алуу ийгиликтүү аяктады

+
+
+ +
+
+ User experience className +

Today at 12.00 PM

+
+ + Join now + +
+
+
+
+
+
+
+ ); +} diff --git a/app/(student)/components/MyFontAwesome.tsx b/app/(student)/components/MyFontAwesome.tsx new file mode 100644 index 00000000..e3bb24f8 --- /dev/null +++ b/app/(student)/components/MyFontAwesome.tsx @@ -0,0 +1,17 @@ +"use client"; // обязательно в app/ структуре + +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { ComponentProps } from "react"; + +interface IconProps extends ComponentProps { + icon: IconProp; + className?: string; + size?: "xs" | "lg" | "sm" | "1x" | "2x" | "3x" | "4x" | "5x" | "6x" | "7x" | "8x" | "9x" | "10x"; +} + +export default function MyFontAwesome({ icon, className, size, ...props }:IconProps ) { + return ( + + ); +} \ No newline at end of file diff --git a/app/(student)/components/VideoPlay.tsx b/app/(student)/components/VideoPlay.tsx new file mode 100644 index 00000000..035e5c53 --- /dev/null +++ b/app/(student)/components/VideoPlay.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { faPlay} from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from './MyFontAwesome'; +import Image from "next/image"; +import { useState } from "react"; +import { Dialog } from 'primereact/dialog'; +// import 'primereact/resources/themes/lara-light-blue/theme.css'; // или другая тема +import 'primereact/resources/primereact.min.css'; +import 'primeicons/primeicons.css'; + +export default function VideoPlay() { + const [videoCall, setVideoCall] = useState(false); + + return ( +
+ {if (!videoCall) return; setVideoCall(false); }}> +
+ +
+
+
+
+
setVideoCall(true)} + > + {/* Волна */} + + + {/* Иконка-кнопка */} +
+ +
+
+
+ Логотип ОшГУ +
+
+ ) +} diff --git a/app/(student)/components/buttons/FancyLinkBtn.tsx b/app/(student)/components/buttons/FancyLinkBtn.tsx new file mode 100644 index 00000000..1073c2ce --- /dev/null +++ b/app/(student)/components/buttons/FancyLinkBtn.tsx @@ -0,0 +1,29 @@ +'use client'; + +import Link from "next/link"; +import { useState } from "react"; + +export default function FancyLinkBtn({backround, effectBackround, title}) { + const [position, setPosition] = useState(false); + + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/app/(student)/components/popUp/Tiered.tsx b/app/(student)/components/popUp/Tiered.tsx new file mode 100644 index 00000000..1260075f --- /dev/null +++ b/app/(student)/components/popUp/Tiered.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { useEffect, useRef, useState } from 'react'; +import { Button } from 'primereact/button'; +import { TieredMenu } from 'primereact/tieredmenu'; +import { faBars, faClose } from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from '../MyFontAwesome'; +import { useMediaQuery } from '@/hooks/useMediaQuery'; + +export default function Tiered({title, items, insideColor}) { + const [mobile, setMobile] = useState(false); + + const menu = useRef(null); + const media = useMediaQuery('(max-width: 1000px)'); + + const menuItems = items.map(item => ({ + ...item, + url: item.link && item.link + })); + + const toggleMenu = (e)=> { + menu.current.toggle(e); + setMobile(prev => !prev); + } + // Общий фонт который закрывает кнопку бургер меню, Close + return ( +
+ {title.name ? + } + + +
+ ); +} \ No newline at end of file diff --git a/app/(student)/layout.tsx b/app/(student)/layout.tsx new file mode 100644 index 00000000..45cb94cf --- /dev/null +++ b/app/(student)/layout.tsx @@ -0,0 +1,13 @@ +import BaseLayout from "./components/BaseLayout"; + +export default function Layout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( +
+ {children} +
+ ); +} \ No newline at end of file diff --git a/app/(student)/new/page.tsx b/app/(student)/new/page.tsx new file mode 100644 index 00000000..6b0987b4 --- /dev/null +++ b/app/(student)/new/page.tsx @@ -0,0 +1,11 @@ +'use client'; + +import React from 'react' + +export default function New() { + return ( +
+ New +
+ ) +} diff --git a/app/(student)/page.tsx b/app/(student)/page.tsx new file mode 100644 index 00000000..bd2f4a81 --- /dev/null +++ b/app/(student)/page.tsx @@ -0,0 +1,8 @@ +import HomeClient from "./components/HomeClient"; + +export default function Home() { + + return ( + + ); +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 4114afcf..5e9cecc2 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,9 @@ 'use client'; import { LayoutProvider } from '../layout/context/layoutcontext'; import { PrimeReactProvider } from 'primereact/api'; +import { config } from "@fortawesome/fontawesome-svg-core"; +import "@fortawesome/fontawesome-svg-core/styles.css"; // Импорт стилей +config.autoAddCss = false; import 'primereact/resources/primereact.css'; import 'primeflex/primeflex.css'; import 'primeicons/primeicons.css'; diff --git a/package-lock.json b/package-lock.json index 332e8ef7..241b058c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,15 +8,21 @@ "name": "sakai-react", "version": "10.1.0", "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", "@types/node": "20.3.1", "@types/react": "18.2.12", "@types/react-dom": "18.2.5", + "aos": "^2.3.4", "chart.js": "4.2.1", + "countup": "^1.8.2", "next": "13.4.8", "primeflex": "^3.3.1", "primeicons": "^6.0.1", "primereact": "10.2.1", "react": "18.2.0", + "react-countup": "^6.5.3", "react-dom": "18.2.0", "typescript": "5.1.3" }, @@ -103,6 +109,48 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz", + "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz", + "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz", + "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -561,6 +609,16 @@ "node": ">= 8" } }, + "node_modules/aos": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/aos/-/aos-2.3.4.tgz", + "integrity": "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw==", + "dependencies": { + "classlist-polyfill": "^1.0.3", + "lodash.debounce": "^4.0.6", + "lodash.throttle": "^4.0.1" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -907,6 +965,11 @@ "node": ">= 6" } }, + "node_modules/classlist-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", + "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -936,6 +999,16 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/countup": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/countup/-/countup-1.8.2.tgz", + "integrity": "sha512-1qOuy+h+dgLY4TroLb4ZC2hK7HYS2Z7mnSUvdzoYAU7EZbqOse1mKZta/KYPhDPfd9lPDyP3Tb4pH6a10RkoCw==" + }, + "node_modules/countup.js": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.2.tgz", + "integrity": "sha512-UtRoPH6udaru/MOhhZhI/GZHJKAyAxuKItD2Tr7AbrqrOPBX/uejWBBJt8q86169AMqKkE9h9/24kFWbUk/Bag==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2566,12 +2639,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3099,6 +3182,17 @@ "node": ">=0.10.0" } }, + "node_modules/react-countup": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/react-countup/-/react-countup-6.5.3.tgz", + "integrity": "sha512-udnqVQitxC7QWADSPDOxVWULkLvKUWrDapn5i53HE4DPRVgs+Y5rr4bo25qEl8jSh+0l2cToJgGMx+clxPM3+w==", + "dependencies": { + "countup.js": "^2.8.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", diff --git a/package.json b/package.json index 8071b50b..44eb0099 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,21 @@ "lint": "next lint" }, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", "@types/node": "20.3.1", "@types/react": "18.2.12", "@types/react-dom": "18.2.5", + "aos": "^2.3.4", "chart.js": "4.2.1", + "countup": "^1.8.2", "next": "13.4.8", "primeflex": "^3.3.1", "primeicons": "^6.0.1", "primereact": "10.2.1", "react": "18.2.0", + "react-countup": "^6.5.3", "react-dom": "18.2.0", "typescript": "5.1.3" }, @@ -28,4 +34,4 @@ "prettier": "^2.8.8", "sass": "^1.63.4" } -} \ No newline at end of file +} diff --git a/public/layout/images/home-banner-phone.png b/public/layout/images/home-banner-phone.png new file mode 100644 index 0000000000000000000000000000000000000000..399a19dcf39aaabbde410dda49bef65361bf272c GIT binary patch literal 45155 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 literal 0 HcmV?d00001 diff --git a/public/layout/images/logo-kg.svg b/public/layout/images/logo-kg.svg new file mode 100644 index 00000000..ac33ea12 --- /dev/null +++ b/public/layout/images/logo-kg.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + В + + + + + Р + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/layout/images/logo-remove-white.png b/public/layout/images/logo-remove-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3d28f7d584100fa710e5dcad4c9448c49f60319c GIT binary patch literal 60288 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 literal 0 HcmV?d00001 diff --git a/public/layout/images/man.png b/public/layout/images/man.png new file mode 100644 index 0000000000000000000000000000000000000000..0168ee167c95356cb8e67ee2cea3eb9a65478c45 GIT binary patch literal 17471 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 literal 0 HcmV?d00001 diff --git a/public/layout/images/shape.png b/public/layout/images/shape.png new file mode 100644 index 0000000000000000000000000000000000000000..a82ce023a4d747dc1f719de8472ed6cbe3815cea GIT binary patch literal 2305 zcmV+c3I6tpP)JA;Hq&=nMepQt@k!*;Vh{VB5;FM>UVT*$9J>Y5Aeo_tIok0hxIs#yPXaH`hKZb=Z`2wKK2iJaLU|}pM z0hlrL!L6Uz)p_O!8k840_Y>1C=+Lh>I!`=}J?I(~7k+T+Cw6tuqo9K_9|Pz4NryU5 zAHfvUhc>zN6T7-xeFPEZ*o)IOw2sNRXeT)V+*?E}9dY^KeePx^?;pV(xx) z?pdd(sE=d4L`~(Ovrnh2>BmoFFbNC4mME#r=GD9JYp8!F105OT#g<9|k2BQG-Xvcgc@ssts0M%5NBmfMBEY_G2BZ;YvGsi|(D&FmQbWW$1jO`Wep0zXmae)5e6+RTo?Pm1$kRcEHm z&UIrG%nlpq3Y;=oN~=o}0GdKJ#+%zRCm8(1t}aRdcnaA> zU6KH>G{!pAt!m5(=Y_0)Ii+q+O9J4$F;<+FR+l6I?h9Fyiu&w#b!Gket8+h@J_xHi zKd5T`>8s;Hc4DzzU2zT?XQ3RQKvm{(T3sB6^-^@`D1b|{1F)*|@`zXsmy9n$icF+# zf}wGOg9WQPWf*qs8d%j8c`8_ox|;jegq_Sxzzf{BChW{;s9QxbCv5c1gfbL4-NAxY zU1lB_Fm`oiimp!oAS~(@`5beiZ1h!WZI%S#hgI3VpBJg2LmdAO&!S< zh3s6bI*KDZz>LLKbtDOZU$IVPfg0c&~Y#$3kZ{brfwA}S}AH@~kZe-?z7?1j#mZCm^2SYt+ zYt;ECcY~2T!;==CAoLnXL5v!v_LLg;W*K$2BE#`aOBZ}e@qV8&brY{hU6=XPmLdp3 zCmHUgmb;t6@tRzZE@s?W6!)jCaerFs4y}I#f*_<>3uf+8mls9q3-Gys`(O{p^Qcys z-_ee!y#X;<>PIzj3xe=V{1+#XbKIU+9sx0)rcPC!W(sE#&gJ^MSKq=P8)c%Xfp9b6TGuzJf7&Pg5Vc7`+Z)$F&2*Gq|pG@Q(Hw z?%bXmhXVk2gQdqF(vISe*IMfeP+WO(8)X`}`T&3prlFE}^J;X@&I-`?c028N24-lT zzs{>KccHGC4;83=)aCgUW7N%|Nqro=sMC5Gh}q9AZ@uPqmIk8`{@ItXr*n5E4R>df zyX(A*{M%A*L61=vn79Z*_-X!|^~|F_{Gbf=edbAONA?ylFK4I{w^-!p_aAYES{-Kx zR}g-i|KMNL+`o>M+u(8={1^Eje&V@``ZhTCD_wF2Ob~hv>cs*}!3_6G%l$)YdD{73 zeM>Y;ouzQUB})F6f(H-;LHJu_xfj}5ASOetE=%3R^QhmJ;7(Hdsnv0(P&sOKYB>Z! z5dIe1z>EPiqV8W+$NfV^Zgt$Rg>b9m{>|tC2!hZkpy=Ttf#e)F)nzj2r4|EVfXYcH}qxC&WavbY( zV5jsRk~6x!?ShVs?b#1|ZpI#Zr+WgF~Rrw^1<`X`&@mnGj6c!XkC7wsmV1O4hbJ-J}l@9c?ayqSVN?sjxiHp#Z4J34;C z^G|kkM_&~m16y=-XJ^Ok*wbEUxab2V$)=Vr;};pdK+9f@W?!@R>jriL%FegjvqpBm z=RMu8kYrn)Mn-o)&0%D8e$4K^@9X-yKk+iMn@O@Iw{!&cN|!6_>B{%FfnC#C9y>#3 zKQv<(K=*W3+pY+#$4Rm&bd%POK9243@m$ieyS?4xnU0Q6t_HTJqZE5^1}_TSO_C%@ bl7Hz3mIGNh7!O9700000NkvXXu0mjf6B$k_ literal 0 HcmV?d00001 diff --git a/public/layout/images/shape1.png b/public/layout/images/shape1.png new file mode 100644 index 0000000000000000000000000000000000000000..bee24c6573993881efd3678a7b44598f614392bb GIT binary patch literal 382 zcmV-^0fGLBP){|)$kH;Y^X3`7vUwC7G8fzdu zlix6#n44j=BVD9}(U~XIiGzjR2vl@7&PAQqf<^26W5Izs4}aL{)8lc$!;Tu~e!)0X z<3bkflEOKx_@qteVZ|fDe;&IPtE-#n3+4zYykTE3Jyaf9Fk7hnk(9~7=C5>PwZY}v zHqRK?;2p5ZJvMoJ=XZXKdz;I7F}WPv!{&iJz~mLX)WYOf&Y^?J*Xvwz9BjYk-q?n<9JXf=`2PwJuf{>c)o>bEG@ ccJ)_uzu7rA;zwmh&;S4c07*qoM6N<$f<7gxu>b%7 literal 0 HcmV?d00001 diff --git a/public/layout/images/shape2.png b/public/layout/images/shape2.png new file mode 100644 index 0000000000000000000000000000000000000000..f1fe1c5b6d641f64442e6479ee8f0e2bebc56aa3 GIT binary patch literal 645 zcmV;00($+4P)3MLC)_G(CdVT0P=cim&F-Bp*9F z_GZKW5$^!Det7oHn_a_>^aRrHjQKP}uhfSR0RQ*05Wt-aFM&Vw9oz$@4FiE2b$JhN z*FHybWZ=f4JGA=x3fzPt#z%K+_g5GgwC3hIBf~KUR;kQrc5m6(sv>{o#~G{+ z5mRS51Lm?4w;LQvh$R!?Ih!SR=qcsCXOX~werjsMgD!4~Wr2ZB!9>}&!(4g>78n+7 zszuNG>2uQ*-gO@c0Mc{qcpgO(EPHye`<*30M>m^IMunul7u3PejEoEk(EVG^lWsrN zNN8rUHIu$n2%t4)w#aC{A#O30RUQ%3e1FW918iw;T%edG zq#mVjujfLq5uftxo$qbaT$2`9o=mcE=?4uH=FvwavhHWxWj-3H^II^l4j6r*!|hjS f#^|nW{TICgGb&vsttk2E00000NkvXXu0mjfbw?Z6 literal 0 HcmV?d00001 diff --git a/public/layout/svg/red-logo.svg b/public/layout/svg/red-logo.svg new file mode 100644 index 00000000..69deed08 --- /dev/null +++ b/public/layout/svg/red-logo.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/layout/svg/white-logo.svg b/public/layout/svg/white-logo.svg new file mode 100644 index 00000000..d76c8ff6 --- /dev/null +++ b/public/layout/svg/white-logo.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/layout/_button.scss b/styles/layout/_button.scss new file mode 100644 index 00000000..1d184d38 --- /dev/null +++ b/styles/layout/_button.scss @@ -0,0 +1,51 @@ +button { + outline: 0; + border: none; + + &:focus { + outline: 0; + border: 0; + } +} + +.default-btn { + padding: 15px 35px; + text-align: center; + color: var(--whiteColor); + font-size: var(--fontSize); + font-weight: 400; + transition: var(--transition); + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + z-index: 0; + box-shadow: none; + overflow: hidden; + white-space: nowrap; + cursor: pointer; +} + +.fancyEffect { + position: absolute; + top: 0; + bottom: 0; + left: 50%; + width: 550px; + height: 550px; + margin: auto; + border-radius: 50%; + z-index: -1; +} + +.fancyBefore { + transform-origin: top center; + transform: translateX(-50%) translateY(-5%) scale(0.4); + transition: transform 0.9s; +} + +.fancyAfter { + transition: transform 1s; + transform: translateX(-45%) translateY(0) scale(1); + transform-origin: bottom center; +} diff --git a/styles/layout/_topbar.scss b/styles/layout/_topbar.scss index 79402366..bf6f5d9c 100644 --- a/styles/layout/_topbar.scss +++ b/styles/layout/_topbar.scss @@ -22,7 +22,7 @@ border-radius: 12px; img { - height: 2.5rem; + // height: 2.5rem; margin-right: .5rem; } @@ -86,6 +86,21 @@ } } +.main-header { + position: fixed; + top: 50px; /* равняется высоте .top-bar */ + width: 100%; + background: #fff; + z-index: 10; /* чтобы header был над контентом */ + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + padding: 16px; + + .main-header.scrolled { + transform: translateY(50px); /* прячет шапку на высоту .top-bar */ + top: 0; + } +} + @media (max-width: 991px) { .layout-topbar { justify-content: space-between; diff --git a/styles/layout/_typography.scss b/styles/layout/_typography.scss index b9a0c8ff..a72d190a 100644 --- a/styles/layout/_typography.scss +++ b/styles/layout/_typography.scss @@ -3,7 +3,7 @@ h1, h2, h3, h4, h5, h6 { font-family: inherit; font-weight: 500; line-height: 1.2; - color: var(--surface-900); + // color: var(--surface-900); &:first-child { margin-top: 0; diff --git a/styles/layout/layout.scss b/styles/layout/layout.scss index fef2ed48..30218e29 100644 --- a/styles/layout/layout.scss +++ b/styles/layout/layout.scss @@ -1,3 +1,79 @@ + +:root { + --bodyFonts: "Jost", sans-serif; + --mainColor: #08A9E6; + --redColor: #EC272F; + --titleColor: #21225F; + --bodyColor: #555555; + --whiteColor: #ffffff; + --fontSize: 16px; + --transition: 0.5s; +} + +p { + color: var(--bodyColor); + margin-bottom: 10px; +} +p:last-child { + margin-bottom: 0; +} + +a { + display: inline-block; + transition: var(--transition); + text-decoration: none; +} +a:hover, a:focus { + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + color: var(--titleColor); +} + +.mainColor-hover:hover{ + color: #08A9E6; +} + +/* animate */ +.animateContent{ + animation: content linear 6s infinite; +} + +@keyframes content { + 10%{ + transform: translateX(2px); + } + 50%{ + transform: translateX(-4px); + } + 80%{ + transform: translateY(-2px); + } + 100%{ + transform: translateY(4px); + } +} + +.animateFaster{ + animation: faster linear 4s infinite forwards; +} + +@keyframes faster { + 10%{ + transform: translateX(-2px); + } + 50%{ + transform: translateX(4px); + } + 80%{ + transform: translateY(2px); + } + 100%{ + transform: translateY(-4px); + } +} + @import './_variables'; @import "./_mixins"; @import "./_main"; @@ -8,4 +84,5 @@ @import "./_footer"; @import "./_responsive"; @import "./_utils"; -@import "./_typography"; \ No newline at end of file +@import "./_typography"; +@import "./_button"; \ No newline at end of file From 8097b6c1b92cc16515df2ce440238f3e0a03b447 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sun, 1 Jun 2025 19:38:15 +0600 Subject: [PATCH 002/138] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=20=D1=81=D1=82=D1=83=D0=B4=D0=B5=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/layout.tsx | 2 +- app/(student)/layout.tsx | 8 +- app/(student)/new/page.tsx | 11 - app/(student)/page.tsx | 8 - app/{(student) => }/components/BaseLayout.tsx | 0 .../components/CounterBanner.tsx | 2 +- app/{(student) => }/components/HomeClient.tsx | 2 +- .../components/MyFontAwesome.tsx | 0 app/{(student) => }/components/VideoPlay.tsx | 3 +- .../components/buttons/FancyLinkBtn.tsx | 0 .../components/popUp/Tiered.tsx | 2 +- app/favicon.ico | Bin 1225 -> 0 bytes app/layout.tsx | 1 + app/page.tsx | 8 + layout/AppTopbar.tsx | 3 +- package-lock.json | 1060 +++++++++++++++-- package.json | 6 +- postcss.config.js | 6 + styles/globals.css | 78 ++ styles/layout/_topbar.scss | 2 +- styles/layout/layout.scss | 76 -- tailwind.config.js | 10 + 22 files changed, 1081 insertions(+), 207 deletions(-) delete mode 100644 app/(student)/new/page.tsx delete mode 100644 app/(student)/page.tsx rename app/{(student) => }/components/BaseLayout.tsx (100%) rename app/{(student) => }/components/CounterBanner.tsx (98%) rename app/{(student) => }/components/HomeClient.tsx (99%) rename app/{(student) => }/components/MyFontAwesome.tsx (100%) rename app/{(student) => }/components/VideoPlay.tsx (98%) rename app/{(student) => }/components/buttons/FancyLinkBtn.tsx (100%) rename app/{(student) => }/components/popUp/Tiered.tsx (97%) delete mode 100644 app/favicon.ico create mode 100644 app/page.tsx create mode 100644 postcss.config.js create mode 100644 styles/globals.css create mode 100644 tailwind.config.js diff --git a/app/(main)/layout.tsx b/app/(main)/layout.tsx index 5cb39fdb..122640dd 100644 --- a/app/(main)/layout.tsx +++ b/app/(main)/layout.tsx @@ -19,7 +19,7 @@ export const metadata: Metadata = { ttl: 604800 }, icons: { - icon: '/favicon.ico' + // icon: '' } }; diff --git a/app/(student)/layout.tsx b/app/(student)/layout.tsx index 45cb94cf..0eec769f 100644 --- a/app/(student)/layout.tsx +++ b/app/(student)/layout.tsx @@ -1,13 +1,15 @@ -import BaseLayout from "./components/BaseLayout"; +import Layout from "../../layout/layout"; -export default function Layout({ +export default function LayoutStudent({ children, }: Readonly<{ children: React.ReactNode; }>) { + return (
- {children} + {/* {children} */} + {children};
); } \ No newline at end of file diff --git a/app/(student)/new/page.tsx b/app/(student)/new/page.tsx deleted file mode 100644 index 6b0987b4..00000000 --- a/app/(student)/new/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; - -import React from 'react' - -export default function New() { - return ( -
- New -
- ) -} diff --git a/app/(student)/page.tsx b/app/(student)/page.tsx deleted file mode 100644 index bd2f4a81..00000000 --- a/app/(student)/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import HomeClient from "./components/HomeClient"; - -export default function Home() { - - return ( - - ); -} \ No newline at end of file diff --git a/app/(student)/components/BaseLayout.tsx b/app/components/BaseLayout.tsx similarity index 100% rename from app/(student)/components/BaseLayout.tsx rename to app/components/BaseLayout.tsx diff --git a/app/(student)/components/CounterBanner.tsx b/app/components/CounterBanner.tsx similarity index 98% rename from app/(student)/components/CounterBanner.tsx rename to app/components/CounterBanner.tsx index 75b59db3..58a13363 100644 --- a/app/(student)/components/CounterBanner.tsx +++ b/app/components/CounterBanner.tsx @@ -5,7 +5,7 @@ import { faCircle, faBookOpen, faShieldHeart, } from "@fortawesome/free-solid-svg-icons"; -import MyFontAwesome from './MyFontAwesome'; +import MyFontAwesome from '../../components/MyFontAwesome'; import CountUp from 'react-countup'; export default function CounterBanner() { diff --git a/app/(student)/components/HomeClient.tsx b/app/components/HomeClient.tsx similarity index 99% rename from app/(student)/components/HomeClient.tsx rename to app/components/HomeClient.tsx index c57325ca..dff8bed4 100644 --- a/app/(student)/components/HomeClient.tsx +++ b/app/components/HomeClient.tsx @@ -18,7 +18,7 @@ export default function HomeClient() { return (
-
+
diff --git a/app/(student)/components/MyFontAwesome.tsx b/app/components/MyFontAwesome.tsx similarity index 100% rename from app/(student)/components/MyFontAwesome.tsx rename to app/components/MyFontAwesome.tsx diff --git a/app/(student)/components/VideoPlay.tsx b/app/components/VideoPlay.tsx similarity index 98% rename from app/(student)/components/VideoPlay.tsx rename to app/components/VideoPlay.tsx index 035e5c53..024875db 100644 --- a/app/(student)/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -1,13 +1,14 @@ 'use client'; import { faPlay} from "@fortawesome/free-solid-svg-icons"; -import MyFontAwesome from './MyFontAwesome'; + import Image from "next/image"; import { useState } from "react"; import { Dialog } from 'primereact/dialog'; // import 'primereact/resources/themes/lara-light-blue/theme.css'; // или другая тема import 'primereact/resources/primereact.min.css'; import 'primeicons/primeicons.css'; +import MyFontAwesome from "./MyFontAwesome"; export default function VideoPlay() { const [videoCall, setVideoCall] = useState(false); diff --git a/app/(student)/components/buttons/FancyLinkBtn.tsx b/app/components/buttons/FancyLinkBtn.tsx similarity index 100% rename from app/(student)/components/buttons/FancyLinkBtn.tsx rename to app/components/buttons/FancyLinkBtn.tsx diff --git a/app/(student)/components/popUp/Tiered.tsx b/app/components/popUp/Tiered.tsx similarity index 97% rename from app/(student)/components/popUp/Tiered.tsx rename to app/components/popUp/Tiered.tsx index 1260075f..2a1718b7 100644 --- a/app/(student)/components/popUp/Tiered.tsx +++ b/app/components/popUp/Tiered.tsx @@ -4,7 +4,7 @@ import { useEffect, useRef, useState } from 'react'; import { Button } from 'primereact/button'; import { TieredMenu } from 'primereact/tieredmenu'; import { faBars, faClose } from "@fortawesome/free-solid-svg-icons"; -import MyFontAwesome from '../MyFontAwesome'; +import MyFontAwesome from '../../../components/MyFontAwesome'; import { useMediaQuery } from '@/hooks/useMediaQuery'; export default function Tiered({title, items, insideColor}) { diff --git a/app/favicon.ico b/app/favicon.ico deleted file mode 100644 index a614a31e44745fac24459b113a11e079c0e19cbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1225 zcmV;)1UCDLP)aQP;ly#o`xZBfi3gI0H}O=_D^^b?dL&#e0&x_%X?gYdegcmgL3H zF*+mn*(Ha2@okx3Am+dIqmy9#nzI%rZ-hHedH+ zeUcX!m08-C#DNQtVS01%h+8qak*js_T{}*}FBpJUAh5h?P-baaX6YmN7I!uya24Jz zv-B{WkQXQ6X8c~U0#D!%oQS`0at8u%BW6c316Y{k#l}`h*TExM`hK)~HAZhuO`u0G zs&NR9V{F{{y!d_qWqj^!*!Kz@HCf2>=okffKH98AO`yNteBFkdF*V6Ux{hS&05)~l z;iyQK(C??j=a(A3+PkO5=Z)tZ1SK7u^jTzeOKnjN;iZjCJ->H2!{~1tBzZAWXwzp0 z36xn1bFd=Gi_uA5TqA_@KSA8g%=mLPmX=xiCyh2Nvvf<67aN3AZkkXew?FMbmW_}SW^U5Xds9_)^KzeLFCl(>V{Ip}TAjwa*yG8*4R7Ddj0iy#XuE0YEBfoCVJwUg9J9< zrg$kCL{zKA*j4dve7#B#mv-#Lj7Z`Da;z(}bXy18>G))jK$)dmu|-g;F>S`{T1;$( zqO32YeU1%lAzWxK!;XpvacL`rdJsuoj7sw20h}X<)iGh85qGyI$%}6UMFSN*EoR|+ zT#ok~d*>S)N%dkvE3{!x#eyU+rbnAz;jXzISJ!usPM6ZU-OUiRAH!ctkB4}SevWaiklzEst%;C=7csvIP8S}@(v>6eJ7NNn z!~;t}!fGvW00000NkvXXu0mjf2cAs0 diff --git a/app/layout.tsx b/app/layout.tsx index 5e9cecc2..74fedd14 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,7 @@ 'use client'; import { LayoutProvider } from '../layout/context/layoutcontext'; import { PrimeReactProvider } from 'primereact/api'; +import '../styles/globals.css'; import { config } from "@fortawesome/fontawesome-svg-core"; import "@fortawesome/fontawesome-svg-core/styles.css"; // Импорт стилей config.autoAddCss = false; diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 00000000..45a50bc6 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import HomeClient from './components/HomeClient' + +export default function page() { + return ( + + ) +} diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index 9a2c8849..f63a5d92 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -21,7 +21,8 @@ const AppTopbar = forwardRef((props, ref) => { return (
- logo + {/* logo */} + logo SAKAI diff --git a/package-lock.json b/package-lock.json index 241b058c..01ec7a0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,10 +27,14 @@ "typescript": "5.1.3" }, "devDependencies": { + "@tailwindcss/postcss": "^4.1.8", + "autoprefixer": "^10.4.21", "eslint": "8.43.0", "eslint-config-next": "13.4.6", + "postcss": "^8.5.4", "prettier": "^2.8.8", - "sass": "^1.63.4" + "sass": "^1.63.4", + "tailwindcss": "^4.1.8" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -42,6 +46,31 @@ "node": ">=0.10.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", @@ -184,6 +213,66 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", @@ -387,6 +476,267 @@ "tslib": "^2.4.0" } }, + "node_modules/@tailwindcss/node": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz", + "integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.8" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz", + "integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-x64": "4.1.8", + "@tailwindcss/oxide-freebsd-x64": "4.1.8", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-x64-musl": "4.1.8", + "@tailwindcss/oxide-wasm32-wasi": "4.1.8", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz", + "integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz", + "integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz", + "integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz", + "integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz", + "integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz", + "integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz", + "integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz", + "integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz", + "integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz", + "integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.10", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", + "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", + "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.8.tgz", + "integrity": "sha512-vB/vlf7rIky+w94aWMw34bWW1ka6g6C3xIOdICKX2GC0VcLtL6fhlLiafF0DVIwa9V6EHz8kbWMkS2s2QvvNlw==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.8", + "@tailwindcss/oxide": "4.1.8", + "postcss": "^8.4.41", + "tailwindcss": "4.1.8" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -779,6 +1129,43 @@ "has-symbols": "^1.0.3" } }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -846,6 +1233,38 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -881,9 +1300,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001572", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz", - "integrity": "sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==", + "version": "1.0.30001720", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", + "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", "funding": [ { "type": "opencollective", @@ -965,6 +1384,15 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/classlist-polyfill": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", @@ -1097,6 +1525,15 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1130,6 +1567,12 @@ "csstype": "^3.0.2" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.161", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", + "integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1137,9 +1580,9 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -1264,6 +1707,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1811,6 +2263,19 @@ "is-callable": "^1.1.3" } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2522,106 +2987,343 @@ "set-function-name": "^2.0.1" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "dev": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "argparse": "^2.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "minimist": "^1.2.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, - "bin": { - "json5": "lib/cli.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "json-buffer": "3.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.10" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.8.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/locate-path": { @@ -2678,6 +3380,15 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2721,6 +3432,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2728,9 +3475,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -2800,6 +3547,35 @@ } } }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2809,6 +3585,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3037,9 +3822,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3054,9 +3839,10 @@ } }, "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "dev": true, "funding": [ { "type": "opencollective", @@ -3065,17 +3851,27 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3508,9 +4304,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -3667,6 +4463,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwindcss": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", + "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", + "dev": true + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -3676,6 +4478,32 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3848,6 +4676,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index 44eb0099..01e1fd49 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,13 @@ "typescript": "5.1.3" }, "devDependencies": { + "@tailwindcss/postcss": "^4.1.8", + "autoprefixer": "^10.4.21", "eslint": "8.43.0", "eslint-config-next": "13.4.6", + "postcss": "^8.5.4", "prettier": "^2.8.8", - "sass": "^1.63.4" + "sass": "^1.63.4", + "tailwindcss": "^4.1.8" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 00000000..8f3250b7 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + '@tailwindcss/postcss': {}, // Используем новый плагин + autoprefixer: {}, + } +} \ No newline at end of file diff --git a/styles/globals.css b/styles/globals.css new file mode 100644 index 00000000..063a1b0f --- /dev/null +++ b/styles/globals.css @@ -0,0 +1,78 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --bodyFonts: "Jost", sans-serif; + --mainColor: #08A9E6; + --redColor: #EC272F; + --titleColor: #21225F; + --bodyColor: #555555; + --whiteColor: #ffffff; + --fontSize: 16px; + --transition: 0.5s; +} + +p { + color: var(--bodyColor); + margin-bottom: 10px; +} +p:last-child { + margin-bottom: 0; +} + +a { + display: inline-block; + transition: var(--transition); + text-decoration: none; +} +a:hover, a:focus { + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + color: var(--titleColor); +} + +.mainColor-hover:hover{ + color: #08A9E6; +} + +/* animate */ +.animateContent{ + animation: content linear 6s infinite; +} + +@keyframes content { + 10%{ + transform: translateX(2px); + } + 50%{ + transform: translateX(-4px); + } + 80%{ + transform: translateY(-2px); + } + 100%{ + transform: translateY(4px); + } +} + +.animateFaster{ + animation: faster linear 4s infinite forwards; +} + +@keyframes faster { + 10%{ + transform: translateX(-2px); + } + 50%{ + transform: translateX(4px); + } + 80%{ + transform: translateY(2px); + } + 100%{ + transform: translateY(-4px); + } +} \ No newline at end of file diff --git a/styles/layout/_topbar.scss b/styles/layout/_topbar.scss index bf6f5d9c..3ae47918 100644 --- a/styles/layout/_topbar.scss +++ b/styles/layout/_topbar.scss @@ -1,6 +1,6 @@ .layout-topbar { position: fixed; - height: 5rem; + height: 6rem; z-index: 997; left: 0; top: 0; diff --git a/styles/layout/layout.scss b/styles/layout/layout.scss index 30218e29..0b5314a9 100644 --- a/styles/layout/layout.scss +++ b/styles/layout/layout.scss @@ -1,79 +1,3 @@ - -:root { - --bodyFonts: "Jost", sans-serif; - --mainColor: #08A9E6; - --redColor: #EC272F; - --titleColor: #21225F; - --bodyColor: #555555; - --whiteColor: #ffffff; - --fontSize: 16px; - --transition: 0.5s; -} - -p { - color: var(--bodyColor); - margin-bottom: 10px; -} -p:last-child { - margin-bottom: 0; -} - -a { - display: inline-block; - transition: var(--transition); - text-decoration: none; -} -a:hover, a:focus { - text-decoration: none; -} - -h1, h2, h3, h4, h5, h6 { - color: var(--titleColor); -} - -.mainColor-hover:hover{ - color: #08A9E6; -} - -/* animate */ -.animateContent{ - animation: content linear 6s infinite; -} - -@keyframes content { - 10%{ - transform: translateX(2px); - } - 50%{ - transform: translateX(-4px); - } - 80%{ - transform: translateY(-2px); - } - 100%{ - transform: translateY(4px); - } -} - -.animateFaster{ - animation: faster linear 4s infinite forwards; -} - -@keyframes faster { - 10%{ - transform: translateX(-2px); - } - 50%{ - transform: translateX(4px); - } - 80%{ - transform: translateY(2px); - } - 100%{ - transform: translateY(-4px); - } -} - @import './_variables'; @import "./_mixins"; @import "./_main"; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 00000000..de7789e0 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,10 @@ +module.exports = { + content: [ + "./app/**/*.{js,ts,jsx,tsx}", + "./layout/**/*.{js,ts,jsx,tsx}", + "./components/**/*.{js,ts,jsx,tsx}", + ], + corePlugins: { + preflight: false, // Важно! + }, +} \ No newline at end of file From 15fc38e7c71e40e874b761ed1482eea5c83b9845 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 2 Jun 2025 11:32:20 +0600 Subject: [PATCH 003/138] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=B5?= =?UTF-8?q?=D0=BB=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=81=D0=B5=D0=BC=D0=B0=D0=BD=D1=82=D0=B8=D0=BA=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8,=20=D0=BD=D0=BE=20=D0=BD=D0=B5=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D0=B5=D1=82=20tailwind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/BaseLayout.tsx | 13 +-- app/components/CounterBanner.tsx | 8 +- app/components/HomeClient.tsx | 35 ++++--- app/components/MyFontAwesome.tsx | 2 +- app/components/VideoPlay.tsx | 22 ++--- app/components/popUp/Tiered.tsx | 19 ++-- app/lorem/page.tsx | 7 ++ app/page.tsx | 6 +- hooks/useMediaQuery.tsx | 19 ++++ layout/AppFooter.tsx | 52 +++++++++- layout/AppTopbar.tsx | 157 ++++++++++++++++++++++++++++--- styles/globals.css | 3 +- styles/layout/_topbar.scss | 53 ++++------- tailwind.config.js | 10 ++ 14 files changed, 306 insertions(+), 100 deletions(-) create mode 100644 app/lorem/page.tsx create mode 100644 hooks/useMediaQuery.tsx diff --git a/app/components/BaseLayout.tsx b/app/components/BaseLayout.tsx index d7027d43..101fd3fb 100644 --- a/app/components/BaseLayout.tsx +++ b/app/components/BaseLayout.tsx @@ -1,17 +1,18 @@ "use client"; -// import Footer from "./Footer"; -// import Header from "./Header"; +import AppTopbar from "@/layout/AppTopbar"; +import HomeClient from "./HomeClient"; +import AppFooter from "@/layout/AppFooter"; -export default function BaseLayout({ children }: { children: React.ReactNode }) { +export default function BaseLayout() { return ( <>
- {/*
*/} +
- {children} +
- {/*
*/} +
); diff --git a/app/components/CounterBanner.tsx b/app/components/CounterBanner.tsx index 58a13363..ea617fbf 100644 --- a/app/components/CounterBanner.tsx +++ b/app/components/CounterBanner.tsx @@ -5,20 +5,20 @@ import { faCircle, faBookOpen, faShieldHeart, } from "@fortawesome/free-solid-svg-icons"; -import MyFontAwesome from '../../components/MyFontAwesome'; +import MyFontAwesome from './MyFontAwesome'; import CountUp from 'react-countup'; export default function CounterBanner() { return (
-
+
-
+
+
+
Курстар & видеосабактар
@@ -55,7 +55,7 @@ export default function CounterBanner() { Канааттануу деңгээли
-
+
) } diff --git a/app/components/HomeClient.tsx b/app/components/HomeClient.tsx index dff8bed4..a66607ec 100644 --- a/app/components/HomeClient.tsx +++ b/app/components/HomeClient.tsx @@ -16,21 +16,19 @@ export default function HomeClient() { }, []); return ( -
+
-
- Shape + Shape
- Shape + Shape
13000 @@ -159,6 +157,15 @@ export default function HomeClient() {
+ + {/* Counter Statistics */} + + + {/* Oshgu Video */} +
+

Видеоэкскурсия по главному зданию ОшГУ

+
+
); } diff --git a/app/components/MyFontAwesome.tsx b/app/components/MyFontAwesome.tsx index e3bb24f8..28e58167 100644 --- a/app/components/MyFontAwesome.tsx +++ b/app/components/MyFontAwesome.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { ComponentProps } from "react"; - + interface IconProps extends ComponentProps { icon: IconProp; className?: string; diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx index 024875db..ee722e28 100644 --- a/app/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -28,22 +28,22 @@ export default function VideoPlay() { >
-
-
-
+ {/*
*/} + {/*
setVideoCall(true)} - > + > */} {/* Волна */} - + {/* */} {/* Иконка-кнопка */} -
+ {/*
-
-
-
- Логотип ОшГУ +
*/} + {/*
+
*/} + {/* Логотип ОшГУ */}
) diff --git a/app/components/popUp/Tiered.tsx b/app/components/popUp/Tiered.tsx index 2a1718b7..b629c09f 100644 --- a/app/components/popUp/Tiered.tsx +++ b/app/components/popUp/Tiered.tsx @@ -3,8 +3,8 @@ import { useEffect, useRef, useState } from 'react'; import { Button } from 'primereact/button'; import { TieredMenu } from 'primereact/tieredmenu'; -import { faBars, faClose } from "@fortawesome/free-solid-svg-icons"; -import MyFontAwesome from '../../../components/MyFontAwesome'; +import { faBars, faClose, faEllipsisVertical } from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from '../MyFontAwesome'; import { useMediaQuery } from '@/hooks/useMediaQuery'; export default function Tiered({title, items, insideColor}) { @@ -29,10 +29,10 @@ export default function Tiered({title, items, insideColor}) { label={title.name && title.name} icon={title.name && "pi pi-list"} onClick={(e) => toggleMenu(e)} - className={`flex gap-2 text-[17px] text-[var(${insideColor})] hover:text-[var(--mainColor)]`} + className={`gap-2 p-2 bg-inherit text-[16px] text-[var(${insideColor})] hover:text-[var(--mainColor)]`} /> : } @@ -41,17 +41,18 @@ export default function Tiered({title, items, insideColor}) { popup ref={menu} breakpoint="1000px" - style={{ width: media ? '90%' : '' , marginLeft: media ? '5%' : ''}} - className={`pointer max-h-[200px] overflow-y-scroll`} + style={{ width: media ? '90%' : '' , left:'10px'}} + className={`pointer mt-4 max-h-[200px] overflow-y-scroll`} pt={{ - root: { className: `bg-white mt-4 border border-gray-300 rounded-md shadow-md`}, + root: { className: `bg-white border border-gray-300 rounded-md shadow-md`}, menu: { className: 'transition-all' }, - menuitem: { className: 'text-[var(--titleColor)] text-[14px] px-4 py-4 border-b hover:shadow-xl border-gray-200 hover:text-white hover:bg-[var(--mainColor)]' }, - action: { className: '' }, // для иконки + текста + menuitem: { className: 'text-[var(--titleColor)] text-[14px] px-1 py-2 border-b hover:shadow-xl border-gray-200 hover:text-white hover:bg-[var(--mainColor)]' }, + action: { className: 'flex gap-1' }, // для иконки + текста icon: { className: 'text-[var(--titleColor)] mx-1 hover:text-white' }, submenuIcon: { className: 'text-gray-400 ml-auto' } }} /> +
); } \ No newline at end of file diff --git a/app/lorem/page.tsx b/app/lorem/page.tsx new file mode 100644 index 00000000..539c1ccf --- /dev/null +++ b/app/lorem/page.tsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function page() { + return ( +
page
+ ) +} diff --git a/app/page.tsx b/app/page.tsx index 45a50bc6..39c48471 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,8 +1,10 @@ import React from 'react' -import HomeClient from './components/HomeClient' +import BaseLayout from './components/BaseLayout' export default function page() { return ( - +
+ +
) } diff --git a/hooks/useMediaQuery.tsx b/hooks/useMediaQuery.tsx new file mode 100644 index 00000000..89e61dca --- /dev/null +++ b/hooks/useMediaQuery.tsx @@ -0,0 +1,19 @@ +"use client"; + +import { useState, useEffect } from "react"; + +export function useMediaQuery(query:string) { + const [matches, setMatches] = useState(false); + + useEffect(() => { + const mediaQuery = window.matchMedia(query); + setMatches(mediaQuery.matches); + + const handler = (e:MediaQueryListEvent) => setMatches(e.matches); + mediaQuery.addEventListener("change", handler); + + return () => mediaQuery.removeEventListener("change", handler); + }, [query]); + + return matches; +} diff --git a/layout/AppFooter.tsx b/layout/AppFooter.tsx index 424b9987..4b84b090 100644 --- a/layout/AppFooter.tsx +++ b/layout/AppFooter.tsx @@ -2,16 +2,60 @@ import React, { useContext } from 'react'; import { LayoutContext } from './context/layoutcontext'; +import Image from 'next/image'; +import { faChalkboard, faPhone,} from "@fortawesome/free-solid-svg-icons"; +import MyFontAwesome from '@/app/components/MyFontAwesome'; +import Link from 'next/link'; const AppFooter = () => { const { layoutConfig } = useContext(LayoutContext); + + // dark mode + // Logo return ( -
- Logo - by - PrimeReact +
+
+
+ Логотип +
+ Кыргызстан, 723500, г. Ош, ул. Ленина, 331, ОшГУ Главный корпус + Общий отдел: +996 3222 7-07-12, + факс +996 3222 7-09-15, + edu@oshsu.kg +
+
+
+
+ +

Курстар

+
+
+ lorem ipsum + lorem ipsum + lorem ipsum +
+
+
+
+ +

Байланыш

+
+
+ lorem ipsum + lorem ipsum + lorem ipsum +
+
+ +

+ © 2025 ОшГУ | 2025 OshSU - IT Academy Ошский Государственный Университет oshsu.kg +

+
); }; diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index f63a5d92..f7ffa387 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -5,6 +5,10 @@ import { classNames } from 'primereact/utils'; import React, { forwardRef, useContext, useImperativeHandle, useRef } from 'react'; import { AppTopbarRef } from '@/types'; import { LayoutContext } from './context/layoutcontext'; +import Tiered from '@/app/components/popUp/Tiered'; +import { useMediaQuery } from '@/hooks/useMediaQuery'; +import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn'; +import { usePathname } from 'next/navigation'; const AppTopbar = forwardRef((props, ref) => { const { layoutConfig, layoutState, onMenuToggle, showProfileSidebar } = useContext(LayoutContext); @@ -18,27 +22,152 @@ const AppTopbar = forwardRef((props, ref) => { topbarmenubutton: topbarmenubuttonRef.current })); + const pathName = usePathname(); + const media = useMediaQuery('(max-width: 1000px)'); + + const items = [ + { + label: 'Ачык онлайн курстар', + icon: 'pi pi-file', + items: [], + link:'/login' + }, + { + label: 'Бакалавриат', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Магистратура', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Кошумча билим берүү', + icon: 'pi pi-file', + items: [] + }, + ]; + + const mobileMenu = [ + { + label: 'КАТАЛОГ', + icon: 'pi pi-list', + items: [ + { + label: 'Ачык онлайн курстар', + icon: 'pi pi-file', + items: [], + link:'/login' + }, + { + label: 'Бакалавриат', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Магистратура', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Кошумча билим берүү', + icon: 'pi pi-file', + items: [] + }, + ], + }, + { + label: 'Бакалавриат', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Магистратура', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Кошумча билим берүү', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Кошумча билим берүү', + icon: 'pi pi-file', + items: [] + }, + { + label: 'КАТАЛОГ', + icon: 'pi pi-list', + items: [ + { + label: 'Ачык онлайн курстар', + icon: 'pi pi-file', + items: [], + link:'/login' + }, + { + label: 'Бакалавриат', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Магистратура', + icon: 'pi pi-file', + items: [] + }, + { + label: 'Кошумча билим берүү', + icon: 'pi pi-file', + items: [] + }, + ], + }, + ]; + return (
{/* logo */} - logo - SAKAI + logo +

Цифровой кампус ОшГУ

- - - + {pathName !== '/' ? + : '' + }
- +
+ {media ? + + :
+ + + + ОшМУнун сайты + Байланыш +
+ } + + +
+
+ {/* - + */}
); diff --git a/styles/globals.css b/styles/globals.css index 063a1b0f..ba85d770 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -75,4 +75,5 @@ h1, h2, h3, h4, h5, h6 { 100%{ transform: translateY(-4px); } -} \ No newline at end of file +} + diff --git a/styles/layout/_topbar.scss b/styles/layout/_topbar.scss index 3ae47918..d6a02350 100644 --- a/styles/layout/_topbar.scss +++ b/styles/layout/_topbar.scss @@ -18,12 +18,12 @@ color: var(--surface-900); font-size: 1.5rem; font-weight: 500; - width: 300px; + // width: 300px; border-radius: 12px; img { // height: 2.5rem; - margin-right: .5rem; + // margin-right: .5rem; } &:focus { @@ -63,7 +63,7 @@ } .layout-menu-button { - margin-left: 2rem; + // margin-left: 2rem; } .layout-topbar-menu-button { @@ -81,60 +81,45 @@ display: flex; .layout-topbar-button { - margin-left: 1rem; + // margin-left: 1rem; } } } -.main-header { - position: fixed; - top: 50px; /* равняется высоте .top-bar */ - width: 100%; - background: #fff; - z-index: 10; /* чтобы header был над контентом */ - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - padding: 16px; - - .main-header.scrolled { - transform: translateY(50px); /* прячет шапку на высоту .top-bar */ - top: 0; - } -} - @media (max-width: 991px) { .layout-topbar { justify-content: space-between; .layout-topbar-logo { - width: auto; + // width: auto; order: 2; } .layout-menu-button { margin-left: 0; - order: 1; + order: 3; } .layout-topbar-menu-button { display: inline-flex; margin-left: 0; - order: 3; + // order: 1; } .layout-topbar-menu { margin-left: 0; - position: absolute; - flex-direction: column; - background-color: var(--surface-overlay); - box-shadow: 0px 3px 5px rgba(0,0,0,.02), 0px 0px 2px rgba(0,0,0,.05), 0px 1px 4px rgba(0,0,0,.08); - border-radius: 12px; - padding: 1rem; - right: 2rem; - top: 5rem; - min-width: 15rem; - display: none; - -webkit-animation: scalein 0.15s linear; - animation: scalein 0.15s linear; + // position: absolute; + // flex-direction: column; + // background-color: var(--surface-overlay); + // box-shadow: 0px 3px 5px rgba(0,0,0,.02), 0px 0px 2px rgba(0,0,0,.05), 0px 1px 4px rgba(0,0,0,.08); + // border-radius: 12px; + // padding: 1rem; + // right: 2rem; + // top: 5rem; + // min-width: 15rem; + // display: none; + // -webkit-animation: scalein 0.15s linear; + // animation: scalein 0.15s linear; &.layout-topbar-menu-mobile-active { display: block diff --git a/tailwind.config.js b/tailwind.config.js index de7789e0..813453ad 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -3,7 +3,17 @@ module.exports = { "./app/**/*.{js,ts,jsx,tsx}", "./layout/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", + "./app/components/**/*.{js,ts,jsx,tsx}", ], + theme: { + screens: { + sm: '640px', + md: '768px', + lg: '1024px', + xl: '1280px', + '2xl': '1536px', + } + }, corePlugins: { preflight: false, // Важно! }, From a059336a5cc5e8abe822958683aaadd35f324abf Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 2 Jun 2025 15:22:48 +0600 Subject: [PATCH 004/138] =?UTF-8?q?=D0=91=D0=B0=D0=B3=D0=B8=20=D1=83=D1=81?= =?UTF-8?q?=D0=BF=D0=B5=D1=88=D0=BD=D0=BE=20=D0=BF=D0=BE=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=D1=81=D0=B5=D0=BB=D0=B8=D1=81=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/HomeClient.tsx | 18 +++++++-------- app/components/VideoPlay.tsx | 29 +++++++++++++------------ app/components/buttons/FancyLinkBtn.tsx | 2 +- app/components/popUp/Tiered.tsx | 5 +++-- {styles => app}/globals.css | 5 ++--- app/layout.tsx | 6 ++--- layout/AppTopbar.tsx | 14 +----------- styles/layout/_typography.scss | 24 -------------------- tailwind.config.js | 20 ----------------- 9 files changed, 34 insertions(+), 89 deletions(-) rename {styles => app}/globals.css (94%) delete mode 100644 tailwind.config.js diff --git a/app/components/HomeClient.tsx b/app/components/HomeClient.tsx index a66607ec..0ecdc498 100644 --- a/app/components/HomeClient.tsx +++ b/app/components/HomeClient.tsx @@ -8,7 +8,6 @@ import Link from "next/link"; import { faClock, faVideo,} from "@fortawesome/free-solid-svg-icons"; import MyFontAwesome from "./MyFontAwesome"; import VideoPlay from "./VideoPlay"; -import Image from "next/image"; export default function HomeClient() { useEffect(() => { @@ -39,7 +38,7 @@ export default function HomeClient() { ЫҢГАЙЛУУ ОКУУ ҮЧҮН ОНЛАЙН МЕЙКИНДИК
-

Аралыктан окутуу порталына кош келиңиз! -

+
{" "} Университеттин онлайн билим берүү жаатындагы долбоорлорун бириктирүүдөбүз: -
    +
    • ачык онлайн курстар
    • жогорку билим берүү программалары
    @@ -112,15 +112,15 @@ export default function HomeClient() {
-
+
13000 -

lorem

+

Студент

@@ -131,7 +131,7 @@ export default function HomeClient() { data-aos-duration="1000" data-aos-once="true" > -
+
Куттуктайбыз!

Сиздин кабыл алуу ийгиликтүү аяктады

@@ -144,7 +144,7 @@ export default function HomeClient() { data-aos-duration="1000" data-aos-once="true" > -
+
User experience className

Today at 12.00 PM

diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx index ee722e28..d843bcf6 100644 --- a/app/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -15,11 +15,12 @@ export default function VideoPlay() { return (
- {if (!videoCall) return; setVideoCall(false); }}> + {if (!videoCall) return; setVideoCall(false); }}>
-
- {/*
*/} - {/*
+
+
setVideoCall(true)} - > */} + > {/* Волна */} - {/* */} + {/* Иконка-кнопка */} - {/*
+
-
*/} - {/*
-
*/} - {/* Логотип ОшГУ */} +
+
+
+ Логотип ОшГУ
) diff --git a/app/components/buttons/FancyLinkBtn.tsx b/app/components/buttons/FancyLinkBtn.tsx index 1073c2ce..9016c00f 100644 --- a/app/components/buttons/FancyLinkBtn.tsx +++ b/app/components/buttons/FancyLinkBtn.tsx @@ -17,7 +17,7 @@ export default function FancyLinkBtn({backround, effectBackround, title}) { backgroundColor:`var(${backround})`, }} > - {title} + {title} toggleMenu(e)} - className={`gap-2 p-2 bg-inherit text-[16px] text-[var(${insideColor})] hover:text-[var(--mainColor)]`} + style={{color:'var(--BodyColor)'}} + className={`gap-2 p-2 bg-white text-[16px]`} /> :
} - -
+
- {/* - - - - */}
); diff --git a/styles/layout/_typography.scss b/styles/layout/_typography.scss index a72d190a..6278de2f 100644 --- a/styles/layout/_typography.scss +++ b/styles/layout/_typography.scss @@ -10,30 +10,6 @@ h1, h2, h3, h4, h5, h6 { } } -h1 { - font-size: 2.5rem; -} - -h2 { - font-size: 2rem; -} - -h3 { - font-size: 1.75rem; -} - -h4 { - font-size: 1.5rem; -} - -h5 { - font-size: 1.25rem; -} - -h6 { - font-size: 1rem; -} - mark { background: #FFF8E1; padding: .25rem .4rem; diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index 813453ad..00000000 --- a/tailwind.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - content: [ - "./app/**/*.{js,ts,jsx,tsx}", - "./layout/**/*.{js,ts,jsx,tsx}", - "./components/**/*.{js,ts,jsx,tsx}", - "./app/components/**/*.{js,ts,jsx,tsx}", - ], - theme: { - screens: { - sm: '640px', - md: '768px', - lg: '1024px', - xl: '1280px', - '2xl': '1536px', - } - }, - corePlugins: { - preflight: false, // Важно! - }, -} \ No newline at end of file From 5058bdafaa0c60d052482017956b82e001cc9c46 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 2 Jun 2025 17:20:43 +0600 Subject: [PATCH 005/138] login page update --- app/(full-page)/auth/login/page.tsx | 47 ++++++++++++----------------- app/components/InfoBanner.tsx | 11 +++++++ app/globals.css | 33 ++++++++++++++++++++ 3 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 app/components/InfoBanner.tsx diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index d3dd85ca..86647115 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -8,6 +8,7 @@ import { Password } from 'primereact/password'; import { LayoutContext } from '../../../../layout/context/layoutcontext'; import { InputText } from 'primereact/inputtext'; import { classNames } from 'primereact/utils'; +import InfoBanner from '@/app/components/InfoBanner'; const LoginPage = () => { const [password, setPassword] = useState(''); @@ -15,38 +16,29 @@ const LoginPage = () => { const { layoutConfig } = useContext(LayoutContext); const router = useRouter(); - const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); + // const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); return ( -
-
- Sakai logo -
-
-
- Image -
Welcome, Isabel!
- Sign in to continue -
- +
+ +
+
+ +
+ +
-
-
); }; diff --git a/app/components/InfoBanner.tsx b/app/components/InfoBanner.tsx new file mode 100644 index 00000000..c3f57cf2 --- /dev/null +++ b/app/components/InfoBanner.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function InfoBanner({title}:{title:string}) { + console.log(title); + + return ( +
+

{title}

+
+ ); +}; diff --git a/app/globals.css b/app/globals.css index 2387162d..bc4d3859 100644 --- a/app/globals.css +++ b/app/globals.css @@ -76,3 +76,36 @@ h1, h2, h3, h4, h5, h6 { } } +.user-img { + position: relative; + margin-bottom: 30px; +} +.user-img img { + /* border: solid .5px ; */ + box-shadow: 0px 1px 9px 4px; + animation: border-transform 10s linear infinite alternate forwards; +} + +@keyframes border-transform { + 0%, 100% { + border-radius: 60% 40% 56% 33%/73% 82% 18% 27%; + } + 14% { + border-radius: 40% 60% 54% 46%/49% 60% 40% 51%; + } + 28% { + border-radius: 54% 46% 38% 62%/49% 70% 30% 51%; + } + 42% { + border-radius: 61% 39% 55% 45%/61% 38% 62% 39%; + } + 56% { + border-radius: 61% 39% 67% 33%/70% 50% 50% 30%; + } + 70% { + border-radius: 50% 50% 34% 66%/56% 68% 32% 44%; + } + 84% { + border-radius: 46% 54% 50% 50%/35% 61% 39% 65%; + } +} From 0279c5d25b6aed6e4671ade26e65a28bce9ae5b9 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Tue, 3 Jun 2025 09:52:27 +0600 Subject: [PATCH 006/138] =?UTF-8?q?=D0=9B=D0=BE=D0=B3=D0=B8=D0=BD=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=87=D1=82=D0=B8=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/auth/login/page.tsx | 90 ++++++++++++++++++++++------- app/components/InfoBanner.tsx | 1 - app/components/VideoPlay.tsx | 2 - app/globals.css | 5 ++ package-lock.json | 73 ++++++++++++++++++++++- package.json | 5 +- schemas/schema.tsx | 22 +++++++ 7 files changed, 171 insertions(+), 27 deletions(-) create mode 100644 schemas/schema.tsx diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index 86647115..878d108c 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -10,6 +10,11 @@ import { InputText } from 'primereact/inputtext'; import { classNames } from 'primereact/utils'; import InfoBanner from '@/app/components/InfoBanner'; +import { useForm } from 'react-hook-form'; +import { schema } from '@/schemas/schema'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { Controller } from 'react-hook-form'; + const LoginPage = () => { const [password, setPassword] = useState(''); const [checked, setChecked] = useState(false); @@ -18,6 +23,33 @@ const LoginPage = () => { const router = useRouter(); // const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); + const {register, handleSubmit, formState: { errors }, control} = useForm({ + resolver:yupResolver(schema), mode: 'onChange', + }); + + const onSubmit = async (data) => { + console.log(data); + + // console.log("Данные формы:", data); + try { + const res = await fetch('https://mooc.oshsu.kg/api/v2/login', { + method:"POST", + headers: { + 'Content-Type': 'application/json', + // 'mode':'no-cors', + }, + credentials: "include", + body: JSON.stringify({ + email : "kalilov054720@oshsu.kg", + password : "054720" + }), + // body: JSON.stringify(data), + }) + } catch(err){ + console.log("Ошибка ",err); + } + }; + return (
@@ -26,29 +58,43 @@ const LoginPage = () => {
-
diff --git a/app/components/InfoBanner.tsx b/app/components/InfoBanner.tsx index c3f57cf2..862aefc0 100644 --- a/app/components/InfoBanner.tsx +++ b/app/components/InfoBanner.tsx @@ -1,7 +1,6 @@ 'use client'; export default function InfoBanner({title}:{title:string}) { - console.log(title); return (
diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx index d843bcf6..8834a5aa 100644 --- a/app/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -18,8 +18,6 @@ export default function VideoPlay() { {if (!videoCall) return; setVideoCall(false); }}>
diff --git a/app/components/cards/LessonCard.tsx b/app/components/cards/LessonCard.tsx index d5e5f8ff..591a25a7 100644 --- a/app/components/cards/LessonCard.tsx +++ b/app/components/cards/LessonCard.tsx @@ -4,7 +4,6 @@ import { getConfirmOptions } from '@/utils/getConfirmOptions'; import { Button } from 'primereact/button'; import { faPlay } from '@fortawesome/free-solid-svg-icons'; import MyFontAwesome from '../MyFontAwesome'; -import { Divider } from 'primereact/divider'; export default function LessonCard({ status, diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 4447bed5..8f5e57b9 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -267,7 +267,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp typeColor={'var(--mainColor)'} lessonDate={'xx-xx'} urlForPDF={() => sentToPDF(item.document || '')} - urlForDownload='' + urlForDownload="" /> )) @@ -433,8 +433,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp type={{ typeValue: 'link', icon: 'pi pi-link' }} typeColor={'var(--mainColor)'} lessonDate={'xx-xx'} - urlForPDF={() => ('')} - urlForDownload='' + urlForPDF={() => ''} + urlForDownload="" /> )) @@ -555,8 +555,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const videoSection = () => { return (
-
- + {/* { toggleVideoType(e.value); @@ -564,16 +564,19 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp options={videoSelect} optionLabel="name" placeholder="Танданыз" + style={{backgroundColor: 'var(--mainColor', color: 'white'}} + panelStyle={{color: 'white'}} className="w-[213px] sm:w-full md:w-14rem" - /> + /> */}
- {selectedCity?.status ? ( -
+ {/* {!selectedCity?.status ? ( */} +
{ setVideoValue((prev) => ({ ...prev, video_link: e.target.value })); setValue('usefulLink', e.target.value, { shouldValidate: true }); @@ -581,22 +584,22 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp /> {errors.usefulLink?.message}
- ) : ( - {}} - accept="video/" - onSelect={(e) => - setVideoValue((prev) => ({ - ...prev, - file: e.files[0] - })) - } - /> - )} + {/* // ) : ( + // {}} + // accept="video/" + // onSelect={(e) => + // setVideoValue((prev) => ({ + // ...prev, + // file: e.files[0] + // })) + // } + // /> + // )} */}
@@ -650,8 +653,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp type={{ typeValue: 'video', icon: 'pi pi-video' }} typeColor={'var(--mainColor)'} lessonDate={'xx-xx'} - urlForPDF={() => ('')} - urlForDownload='' + urlForPDF={() => ''} + urlForDownload="" /> )) diff --git a/app/components/popUp/Redacting.tsx b/app/components/popUp/Redacting.tsx index b42664ec..aac69991 100644 --- a/app/components/popUp/Redacting.tsx +++ b/app/components/popUp/Redacting.tsx @@ -8,7 +8,7 @@ export default function Redacting({ redactor, textSize }: {redactor: MenuItem[], return (
- menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> + menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> { edu@oshsu.kg
-
+ {/*

@@ -51,7 +51,7 @@ const AppFooter = () => { lorem ipsum lorem ipsum

-
+
*/}

© 2025 ОшГУ | 2025 OshSU - IT Academy Ошский Государственный Университет oshsu.kg diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index c5ed3c2d..90fe5626 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -145,7 +145,7 @@ const AppTopbar = forwardRef((props, ref) => { {media ? ( ) : ( -

+
{/* ((props, ref) => { ОшМУнун сайты - + {/* Байланыш - + */}
)} diff --git a/layout/StudentLayout.tsx b/layout/StudentLayout.tsx index 7ea3df42..3a078e89 100644 --- a/layout/StudentLayout.tsx +++ b/layout/StudentLayout.tsx @@ -149,7 +149,7 @@ const StudentLayout = ({ children }: ChildContainerProps) => {
{children}
{/* */}
- + {/* */}
diff --git a/layout/layout.tsx b/layout/layout.tsx index e886a689..013f6a17 100644 --- a/layout/layout.tsx +++ b/layout/layout.tsx @@ -149,7 +149,7 @@ const Layout = ({ children }: ChildContainerProps) => {
{children}
{/* */}
- + {/* */}
From ada5b1a4146aff88c37cfb7fbdc2827c3a647b11 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 08:58:20 +0600 Subject: [PATCH 109/138] =?UTF-8?q?=D1=84=D0=BE=D1=82=D0=BE=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8=20=D0=BD=D0=B0=20=D0=BA=D1=83=D1=80=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 64 ++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index f32036de..86f89d0f 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -28,6 +28,9 @@ import { useMediaQuery } from '@/hooks/useMediaQuery'; export default function Course() { const { setMessage, course, setCourses, contextFetchCourse } = useContext(LayoutContext); + interface FileWithPreview extends File { + objectURL?: string; + } const [coursesValue, setValueCourses] = useState([]); const [hasCourses, setHasCourses] = useState(false); @@ -43,6 +46,7 @@ export default function Course() { perPage: 0 }); const [activeIndex, setActiveIndex] = useState(0); + const [imageState, setImageState] = useState(null); const [editingLesson, setEditingLesson] = useState({ title: '', @@ -117,11 +121,9 @@ export default function Course() { }; const handleFetchCourse = async (page = 1) => { - const data = await fetchCourses(page, 0); toggleSkeleton(); - console.log(course); - + if (course) { setHasCourses(false); setValueCourses(course.data); @@ -206,6 +208,7 @@ export default function Course() { }; const clearValues = () => { + setImageState(null); setCourseValue({ title: '', description: '', video_url: '', image: '' }); setEditingLesson({ title: '', description: '', video_url: '', image: '', created_at: '' }); setEditMode(false); @@ -236,7 +239,7 @@ export default function Course() { } }; - const onSelect = (e: FileUploadSelectEvent) => { + const onSelect = (e: FileUploadSelectEvent & { files: FileWithPreview[] }) => { editMode ? setEditingLesson((prev) => ({ ...prev, @@ -246,10 +249,13 @@ export default function Course() { ...prev, image: e.files[0] })); - - console.log('hi'); + setImageState(e.files[0].objectURL); }; + useEffect(() => { + console.log(imageState); + }, [imageState]); + const imageBodyTemplate = (product: CourseType) => { const image = product.image; @@ -290,9 +296,9 @@ export default function Course() { contextFetchCourse(); }, []); - useEffect(()=> { + useEffect(() => { handleFetchCourse(); - },[course]); + }, [course]); useEffect(() => { const title = editMode ? editingLesson.title.trim() : courseValue.title.trim(); @@ -339,11 +345,37 @@ export default function Course() { console.log('Для потока ', forStreamId); }, [forStreamId]); + const imagestateStyle = imageState ? 'flex gap-1 items-center justify-between' : ''; + return (
{/* modal window */}
+
+ {imagestateStyle && ( +
+ {typeof imageState === 'string' && + + } +
+ )} +
+ + + {courseValue.image || editingLesson.image ? ( +
+ {typeof editingLesson.image === 'string' && ( + <> + Сүрөт: {editingLesson.image} + + )} +
+ ) : ( + jpeg, png, jpg + )} +
+
{/*
*/}
@@ -405,22 +437,6 @@ export default function Course() { }} />
- -
- - - {courseValue.image || editingLesson.image ? ( -
- {typeof editingLesson.image === 'string' && ( - <> - Сүрөт: {editingLesson.image} - - )} -
- ) : ( - jpeg, png, jpg - )} -
{/*
*/}
From fb8573e24fd4f5fc7fd534fcdef723fb3c12f419 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 13:22:26 +0600 Subject: [PATCH 110/138] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B3=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/auth/login/page.tsx | 5 +- app/(main)/course/[courseTheme]/page.tsx | 17 ---- app/(main)/course/page.tsx | 39 +++++----- app/(student)/teaching/page.tsx | 3 +- app/components/NotFound.tsx | 2 +- app/components/PDFBook.tsx | 1 - app/components/cards/ItemCard.tsx | 98 +++++++++--------------- app/components/lessons/LessonTyping.tsx | 23 ++---- app/components/tables/StreamList.tsx | 48 ++++++------ app/globals.css | 6 +- layout/AppMenu.tsx | 2 +- layout/StudentLayout.tsx | 5 +- layout/context/layoutcontext.tsx | 27 ++++--- public/layout/svg/login-bg.svg | 1 + types/layout.d.ts | 8 +- types/myMainCourseType.tsx | 5 +- 16 files changed, 120 insertions(+), 170 deletions(-) create mode 100644 public/layout/svg/login-bg.svg diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index 690d00f8..e90d1c06 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -19,11 +19,13 @@ import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn'; import { getToken } from '@/utils/auth'; import { logout } from '@/utils/logout'; import { LoginType } from '@/types/login'; +import { useMediaQuery } from '@/hooks/useMediaQuery'; const LoginPage = () => { const { layoutConfig, setUser, setMessage, setGlobalLoading } = useContext(LayoutContext); const router = useRouter(); + const media = useMediaQuery('(max-width: 640px)'); // const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); const { @@ -40,7 +42,6 @@ const LoginPage = () => { console.log('Данные пользователя: ', value); const user = await login(value); - console.log(user); if (user && user.success) { document.cookie = `access_token=${user.token.access_token}; path=/; Secure; SameSite=Strict; expires=${user.token.expires_at}`; @@ -91,7 +92,7 @@ const LoginPage = () => { }; return ( -
+
{/* */}
diff --git a/app/(main)/course/[courseTheme]/page.tsx b/app/(main)/course/[courseTheme]/page.tsx index 86edb58e..2e5654ce 100644 --- a/app/(main)/course/[courseTheme]/page.tsx +++ b/app/(main)/course/[courseTheme]/page.tsx @@ -50,7 +50,6 @@ export default function CourseTheme() { const data = await fetchThemes(Number(courseTheme)); toggleSkeleton(); - console.log('id', selectedCourse); contextFetchThemes(Number(courseTheme)); if (data?.lessons) { @@ -120,7 +119,6 @@ export default function CourseTheme() { }; const handleUpdateTheme = async () => { - console.log('yeee'); const data = await updateTheme(Number(courseTheme), selectedCourse.id, editingThemes.title); if (data.success) { @@ -145,7 +143,6 @@ export default function CourseTheme() { }; const edit = (rowData: number | null) => { - console.log(rowData); setEditMode(true); setSelectedCourse({id: rowData}); @@ -160,18 +157,6 @@ export default function CourseTheme() { setSelectedCourse({ id: null }); }; - // const getConfirmOptions = (id: number) => ({ - // message: 'Сиз чын эле өчүрүүнү каалайсызбы??', - // header: 'Өчүрүү', - // icon: 'pi pi-info-circle', - // defaultFocus: 'reject', - // acceptClassName: 'p-button-danger', - // acceptLabel: 'Кийинки кадам', // кастомная надпись для "Yes" - // rejectLabel: 'Артка', - // accept: () => handleDeleteCourse(id), - // // reject: () => console.log('Удаление отменено') - // }); - useEffect(() => { handleFetchInfo(); handleFetchThemes(); @@ -180,7 +165,6 @@ export default function CourseTheme() { useEffect(() => { const handleShow = async () => { const data:{lessons: {data: {id: number, title: string}[]}} = await fetchThemes(Number(courseTheme)); - console.log(data); if (data?.lessons) { console.log('rab'); @@ -226,7 +210,6 @@ export default function CourseTheme() {
{themeInfo?.created_at} - Home/theme
diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 86f89d0f..02bfce2e 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -40,7 +40,7 @@ export default function Course() { const [formVisible, setFormVisible] = useState(false); const [forStart, setForStart] = useState(false); const [skeleton, setSkeleton] = useState(false); - const [pagination, setPagination] = useState({ + const [pagination, setPagination] = useState<{ currentPage: number; total: number; perPage: number }>({ currentPage: 1, total: 0, perPage: 0 @@ -125,13 +125,15 @@ export default function Course() { toggleSkeleton(); if (course) { + console.log(course); + setHasCourses(false); setValueCourses(course.data); - // setPagination({ - // currentPage: course.data, - // total: course?.data, - // perPage: course?.data - // }); + setPagination({ + currentPage: course.current_page, + total: course?.total, + perPage: course?.per_page + }); } else { setHasCourses(true); setMessage({ @@ -170,7 +172,7 @@ export default function Course() { if (data?.success) { toggleSkeleton(); // handleFetchCourse(); - contextFetchCourse(); + contextFetchCourse(1); setMessage({ state: true, value: { severity: 'success', summary: 'Ийгиликтүү кошулду!', detail: '' } @@ -191,7 +193,7 @@ export default function Course() { if (data?.success) { toggleSkeleton(); // handleFetchCourse(); - contextFetchCourse(); + contextFetchCourse(1); setMessage({ state: true, value: { severity: 'success', summary: 'Ийгиликтүү өчүрүлдү!', detail: '' } @@ -220,7 +222,7 @@ export default function Course() { if (data?.success) { toggleSkeleton(); // handleFetchCourse(); - contextFetchCourse(); + contextFetchCourse(1); clearValues(); setEditMode(false); setSelectedCourse(null); @@ -277,6 +279,8 @@ export default function Course() { // Ручное управление пагинацией const handlePageChange = (page: number) => { // handleFetchCourse(page); + contextFetchCourse(page); + console.log(page); }; const edit = (rowData: number | null) => { @@ -293,7 +297,7 @@ export default function Course() { }; useEffect(() => { - contextFetchCourse(); + contextFetchCourse(1); }, []); useEffect(() => { @@ -353,13 +357,7 @@ export default function Course() {
- {imagestateStyle && ( -
- {typeof imageState === 'string' && - - } -
- )} + {imagestateStyle &&
{typeof imageState === 'string' && }
}
@@ -496,7 +494,7 @@ export default function Course() { />
- + rowIndex + 1} header="Номер" style={{ width: '20px' }}> { const newValue = forStreamId?.id === rowData.id ? null : { id: rowData.id, title: rowData.title }; - console.log(rowData, forStreamId); - // Устанавливаем состояние setForStreamId(newValue); }} @@ -549,7 +545,8 @@ export default function Course() { rows={pagination.perPage} totalRecords={pagination.total} onPageChange={(e) => handlePageChange(e.page + 1)} - template="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink" + // template="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink" + template={media ? 'PrevPageLink NextPageLink' : 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink'} />
)} diff --git a/app/(student)/teaching/page.tsx b/app/(student)/teaching/page.tsx index 1a1aad21..470e83ab 100644 --- a/app/(student)/teaching/page.tsx +++ b/app/(student)/teaching/page.tsx @@ -31,7 +31,6 @@ export default function Teaching() { // functions const toggleSortSelect = (e: sortOptType) => { - console.log(e); setSelectedSort(e); }; @@ -110,7 +109,7 @@ export default function Teaching() { const x = displayData.map((semester: any, sIdx: number) => (

{semester.semester.name_kg}

-
+
{Object.values(semester) .filter((val: any) => val.subject) // только предметы .map((subj: any, subjIdx: number) => ( diff --git a/app/components/NotFound.tsx b/app/components/NotFound.tsx index a1de19d7..74b4e906 100644 --- a/app/components/NotFound.tsx +++ b/app/components/NotFound.tsx @@ -9,7 +9,7 @@ export const NotFound = ({ titleMessage }: { titleMessage: string }) => {

{titleMessage}

- + {/* */} Башкы баракчага кайтуу diff --git a/app/components/PDFBook.tsx b/app/components/PDFBook.tsx index 4bbf9a81..abbab375 100644 --- a/app/components/PDFBook.tsx +++ b/app/components/PDFBook.tsx @@ -157,7 +157,6 @@ export default function PDFViewer({ url }: { url: string }) { // media ? ( <> -

lorm

-//
-//
-//

{lessonName}

-//
-//
-//
-//
-// Окутуучу: -// {teacherName} -// {teacherLastName} -//
-//
-//
-// Тип: -// {lessonType} -//
-// { -// //
-//
-//
-//
- -//
-// ); -// } - 'use client'; -import { itemsCourseInfo } from '@/services/studentMain'; import Link from 'next/link'; import { Button } from 'primereact/button'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; export default function ItemCard({ lessonName, @@ -48,38 +9,51 @@ export default function ItemCard({ connection }: { lessonName: string; - streams: {id: number, teacher?: { name: string; last_name?: string }; subject_type_name?: { name_kg: string, short_name_kg: string } }[]; + streams: { id: number; teacher?: { name: string; last_name?: string }; subject_type_name?: { name_kg: string; short_name_kg: string } }[]; connection: { id: number; course_id: number; id_myedu_stream: number }[]; }) { - console.log('conn',connection); - + const [activeStreamIdx, setActiveStreamIdx] = useState(null); + const matchedIdx = streams.findIndex((stream) => connection.some((item) => item.id_myedu_stream === stream.id)); + + useEffect(() => { + if (matchedIdx !== -1) { + setActiveStreamIdx(matchedIdx); + } + }, [streams, connection]); return ( -
+
-

{lessonName}

+

{lessonName}

- {streams.map((stream, idx) => ( -
-
- Окутуучу: - {stream.teacher?.name} - {stream.teacher?.last_name} -
-
+ {streams.map((stream, idx) => { + const isActive = idx === activeStreamIdx; + return ( +
- Тип: - {stream.subject_type_name?.short_name_kg} + Окутуучу: + {stream.teacher?.name} + {stream.teacher?.last_name} +
+
+
+ Тип: + {stream.subject_type_name?.short_name_kg} +
+ {connection.map((item) => { + if (item.id_myedu_stream === stream.id) { + return ( + +
- {connection.map((item) => { - if (item.id_myedu_stream === stream.id) { - return
-
- ))} + ); + })}
); diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 8f5e57b9..c5424091 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -250,8 +250,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp
-
-
+
+
{docShow ? ( ) : ( @@ -417,8 +417,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp
-
-
+
+
{linksShow ? ( ) : ( @@ -621,19 +621,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp
-
-
- {/* selectedForEditing(id, type)} - onDelete={(id: number) => handleDeleteVideo(id)} - cardValue={{ title: 'item.title', id: 8, desctiption: 'item?.description', type: '', photo: ''}} - cardBg={'#fff'} - type={{ typeValue: 'Лекция', icon: 'pi pi-lecture' }} - typeColor={'var(--mainColor)'} - lessonDate={'xx-xx'} - /> */} - +
+
{videoShow ? ( ) : ( diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index cf0e4f42..955b6c23 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -14,7 +14,7 @@ import { streamsType } from '@/types/streamType'; export default function StreamList({ callIndex, courseValue, isMobile }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean }) { interface mainStreamsType { connect_id: number | null,stream_id:number, subject_name: {name_kg:string}, - subject_type_name:{short_name_kg:string}, teacher:{name:string}, language:{name:string}, + subject_type_name:{name_kg:string}, teacher:{name:string}, language:{name:string}, id_edu_year:number,id_period:number, semester:{name_kg:string}, edu_form:{name_kg:string} } @@ -156,7 +156,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI } }, [streams]); - const itemTemplate = (item:mainStreamsType, index: number) => { + const itemTemplate = (item:mainStreamsType, index: number) => { const bgClass = item.connect_id ? 'bg-[var(--greenBgColor)] border-b border-[gray]' : index % 2 == 1 ? 'bg-[#f5f5f5]' : ''; return ( @@ -180,8 +180,8 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI
- {item?.subject_type_name?.short_name_kg}: - {item?.teacher?.name} + {item?.subject_type_name?.name_kg} + {/* {item?.teacher?.name} */}
Үйрөтүлүү тили: @@ -189,7 +189,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI
Окуу жылы: - {item?.id_edu_year} + 20{item?.id_edu_year}
Период: @@ -251,7 +251,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI {hasStreams ? ( ) : ( -
+
{isMobile && (
)}
diff --git a/app/globals.css b/app/globals.css index 967962c1..fc77e25a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -44,7 +44,7 @@ h1, h2, h3, h4, h5, h6 { } .login-bg{ - background: url('/layout/images/login-bg.jpg') no-repeat center/cover; + background: url('/layout/svg/login-bg.svg') no-repeat center/cover; } /* animate */ @@ -344,6 +344,10 @@ h1, h2, h3, h4, h5, h6 { } } +.select-column .my-custom-table td{ + background-color: var(--greenBgColor); +} + .my-custom-table td, .my-custom-table th { /* border: 1px solid #ccc; */ diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx index 2e1a12a9..da735fba 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.tsx @@ -48,7 +48,7 @@ const AppMenu = () => { useEffect(() => { if (user?.is_working) { - contextFetchCourse(); + contextFetchCourse(1); } if (user?.is_student) { const isTopicsChildPage = pathname.startsWith('/teaching/'); diff --git a/layout/StudentLayout.tsx b/layout/StudentLayout.tsx index 3a078e89..7175ca42 100644 --- a/layout/StudentLayout.tsx +++ b/layout/StudentLayout.tsx @@ -1,14 +1,11 @@ /* eslint-disable react-hooks/exhaustive-deps */ 'use client'; -import { useRouter } from 'next/navigation'; import { useEventListener, useMountEffect, useUnmountEffect } from 'primereact/hooks'; import React, { useContext, useEffect, useRef, useState } from 'react'; import { classNames } from 'primereact/utils'; -import AppFooter from './AppFooter'; import AppSidebar from './AppSidebar'; import AppTopbar from './AppTopbar'; -import AppConfig from './AppConfig'; import { LayoutContext } from './context/layoutcontext'; import { PrimeReactContext } from 'primereact/api'; import { ChildContainerProps, LayoutState, AppTopbarRef } from '@/types'; @@ -136,7 +133,7 @@ const StudentLayout = ({ children }: ChildContainerProps) => { requireRole(); },[user]); - if(permission) return null; + // if(permission) return null; return ( diff --git a/layout/context/layoutcontext.tsx b/layout/context/layoutcontext.tsx index 810b2c23..eb3e50f3 100644 --- a/layout/context/layoutcontext.tsx +++ b/layout/context/layoutcontext.tsx @@ -66,16 +66,15 @@ export const LayoutProvider = ({ children }: ChildContainerProps) => { }; // fetch course - const [course, setCourses] = useState<{data: myMainCourseType[]}>({data: []}); + const [course, setCourses] = useState<{ current_page: number; total: number; per_page: number; data:myMainCourseType[] }>({ current_page: 1, total: 0, per_page: 10, data: [] }); - const contextFetchCourse = async (page = 1) => { + const contextFetchCourse = async (page: number) => { const data = await fetchCourses(page, 0); - + console.log(data.courses); + if (data?.courses) { // setCourses(data.courses.data); setCourses(data.courses); - } else { - } }; @@ -83,17 +82,21 @@ export const LayoutProvider = ({ children }: ChildContainerProps) => { const [contextThemes, setContextThemes] = useState([]); const contextFetchThemes = async (id: number | null) => { const data = await fetchThemes(Number(id) || null); - + setContextThemes(data); - } + }; + + useEffect(() => { + console.log('course ', course); + }, [course]); // fetch themes for student const [contextStudentThemes, setContextStudentThemes] = useState([]); const contextFetchStudentThemes = async (id: number) => { const data = await fetchStudentThemes(id); - + setContextStudentThemes(data); - } + }; const value: LayoutContextProps = { layoutConfig, @@ -108,18 +111,18 @@ export const LayoutProvider = ({ children }: ChildContainerProps) => { setGlobalLoading, message, setMessage, - + contextFetchCourse, course, setCourses, - + contextFetchThemes, contextThemes, setContextThemes, contextFetchStudentThemes, contextStudentThemes, - setContextStudentThemes, + setContextStudentThemes }; return ( diff --git a/public/layout/svg/login-bg.svg b/public/layout/svg/login-bg.svg new file mode 100644 index 00000000..5398aa5a --- /dev/null +++ b/public/layout/svg/login-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/types/layout.d.ts b/types/layout.d.ts index 81ae1627..f6a27da4 100644 --- a/types/layout.d.ts +++ b/types/layout.d.ts @@ -54,8 +54,12 @@ export interface LayoutContextProps { setGlobalLoading: React.Dispatch>; message: MessageType; setMessage: React.Dispatch>; - contextFetchCourse: ()=> void; - course: {data: myMainCourseType[]}; + contextFetchCourse: (id)=> void; + course: { current_page: number; + total: number; + per_page: number; + data: myMainCourseType[] + }; setCourses; contextFetchThemes: (id: number)=> void; contextThemes; diff --git a/types/myMainCourseType.tsx b/types/myMainCourseType.tsx index e14a4218..8f8280a0 100644 --- a/types/myMainCourseType.tsx +++ b/types/myMainCourseType.tsx @@ -15,7 +15,6 @@ export interface myMainCourseType { title: string; user_id: number; current_page?: number; - total?: number; - per_page?: number; - data?: test[]; + + // data?: test[]; } From 001e765fd0b6fa54d31c4aa0da428ada28b67fb4 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 14:43:23 +0600 Subject: [PATCH 111/138] =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 41 ++++++++++++++++--------- app/components/cards/ItemCard.tsx | 1 + app/components/lessons/LessonTyping.tsx | 7 ++++- app/globals.css | 2 +- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 02bfce2e..b94ead3f 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -125,8 +125,6 @@ export default function Course() { toggleSkeleton(); if (course) { - console.log(course); - setHasCourses(false); setValueCourses(course.data); setPagination({ @@ -210,6 +208,8 @@ export default function Course() { }; const clearValues = () => { + console.log('clear'); + setImageState(null); setCourseValue({ title: '', description: '', video_url: '', image: '' }); setEditingLesson({ title: '', description: '', video_url: '', image: '', created_at: '' }); @@ -242,16 +242,21 @@ export default function Course() { }; const onSelect = (e: FileUploadSelectEvent & { files: FileWithPreview[] }) => { - editMode - ? setEditingLesson((prev) => ({ - ...prev, - image: e.files[0] - })) - : setCourseValue((prev) => ({ - ...prev, - image: e.files[0] - })); - setImageState(e.files[0].objectURL); + console.log('rabotaet ', e); + if (e.files.length > 0) { + editMode + ? setEditingLesson((prev) => ({ + ...prev, + image: e.files[0] + })) + : setCourseValue((prev) => ({ + ...prev, + image: e.files[0] + })); + setImageState(e.files[0].objectURL); + } else { + console.log('noo'); + } }; useEffect(() => { @@ -494,7 +499,7 @@ export default function Course() { />
- + rowIndex + 1} header="Номер" style={{ width: '20px' }}> ) : ( <> - + rowIndex + 1} header="Номер" style={{ width: '20px' }}>
diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index c5424091..4de3d2b0 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -819,6 +819,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp { setEditingLesson((prev) => prev && { ...prev, title: e.target.value }); @@ -833,6 +834,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp { setEditingLesson((prev) => prev && { ...prev, url: e.target.value }); setValue('usefulLink', e.target.value, { shouldValidate: true }); @@ -841,6 +843,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp { setEditingLesson((prev) => prev && { ...prev, title: e.target.value }); @@ -853,10 +856,11 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp ) : selectType === 'video' ? ( <> {editingLesson?.video_type_id ? ( -
+
{ setEditingLesson((prev) => prev && { ...prev, video_link: e.target.value }); setValue('usefulLink', e.target.value, { shouldValidate: true }); @@ -889,6 +893,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp { setEditingLesson((prev) => prev && { ...prev, title: e.target.value }); diff --git a/app/globals.css b/app/globals.css index fc77e25a..4babec37 100644 --- a/app/globals.css +++ b/app/globals.css @@ -345,7 +345,7 @@ h1, h2, h3, h4, h5, h6 { } .select-column .my-custom-table td{ - background-color: var(--greenBgColor); + background-color: var(--greenBgColor) !important; } .my-custom-table td, From f6a2d0c898623d8766116b41bc22505b7189e83a Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 15:57:55 +0600 Subject: [PATCH 112/138] =?UTF-8?q?=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=20?= =?UTF-8?q?=D1=85=D1=83=D0=BA=20=D1=83=D0=BA=D0=BE=D1=80=D0=B0=D1=87=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D1=8E=D1=89=D0=B8=D0=B9=20=D1=82=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 4 ++- app/components/cards/LessonCard.tsx | 9 ++++--- app/components/lessons/LessonTyping.tsx | 9 ++++--- app/globals.css | 4 +++ hooks/useShortText.tsx | 33 +++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 hooks/useShortText.tsx diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index b94ead3f..4f1d1bb9 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -25,6 +25,7 @@ import StreamList from '@/app/components/tables/StreamList'; import { TabPanel, TabView } from 'primereact/tabview'; import { TabViewChange } from '@/types/tabViewChange'; import { useMediaQuery } from '@/hooks/useMediaQuery'; +import useShortText from '@/hooks/useShortText'; export default function Course() { const { setMessage, course, setCourses, contextFetchCourse } = useContext(LayoutContext); @@ -355,6 +356,7 @@ export default function Course() { }, [forStreamId]); const imagestateStyle = imageState ? 'flex gap-1 items-center justify-between' : ''; + const imageTitle = useShortText(typeof editingLesson.image === 'string' ? editingLesson.image : '', 30); return (
@@ -370,7 +372,7 @@ export default function Course() {
{typeof editingLesson.image === 'string' && ( <> - Сүрөт: {editingLesson.image} + {imageTitle} )}
diff --git a/app/components/cards/LessonCard.tsx b/app/components/cards/LessonCard.tsx index 591a25a7..fa7ff9fc 100644 --- a/app/components/cards/LessonCard.tsx +++ b/app/components/cards/LessonCard.tsx @@ -4,6 +4,7 @@ import { getConfirmOptions } from '@/utils/getConfirmOptions'; import { Button } from 'primereact/button'; import { faPlay } from '@fortawesome/free-solid-svg-icons'; import MyFontAwesome from '../MyFontAwesome'; +import useShortText from '@/hooks/useShortText'; export default function LessonCard({ status, @@ -29,6 +30,8 @@ export default function LessonCard({ urlForDownload: string }) { + const shortTitle = useShortText(cardValue.title, 10); + const toSentPDF = () => { urlForPDF(); }; @@ -99,13 +102,13 @@ export default function LessonCard({
{/*
{!cardValue.photo && }
*/} -
{cardValue.title}
+
{shortTitle}
{type.typeValue === 'link' && {cardValue?.url}}
{cardValue?.desctiption && cardValue.desctiption}
{status === 'working' && type.typeValue !== 'video' && ( -
+
- {lessonDate} + {lessonDate}
)}
diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 4de3d2b0..70840ec6 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -422,8 +422,9 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp {linksShow ? ( ) : ( - links.map((item: lessonType) => ( - <> + links.map((item: lessonType) => { + console.log(item); + return <> selectedForEditing(id, type)} @@ -432,12 +433,12 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp cardBg={'#7bb78112'} type={{ typeValue: 'link', icon: 'pi pi-link' }} typeColor={'var(--mainColor)'} - lessonDate={'xx-xx'} + lessonDate={new Date(item.created_at).toISOString().slice(0, 10)} urlForPDF={() => ''} urlForDownload="" /> - )) + }) )}
diff --git a/app/globals.css b/app/globals.css index 4babec37..e883080e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -423,6 +423,10 @@ h1, h2, h3, h4, h5, h6 { } } +.p-tooltip { + font-size: 12px; /* или любой нужный размер */ +} + /* styles/book.css */ /* Стили для контейнера всей книги */ diff --git a/hooks/useShortText.tsx b/hooks/useShortText.tsx new file mode 100644 index 00000000..e95ccce2 --- /dev/null +++ b/hooks/useShortText.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { Tooltip } from 'primereact/tooltip'; + +export default function useShortText(text: string, textLength: number) { + const [resultText, setResultText] = useState(''); + const [isLength, setIsLength] = useState(false); + + useEffect(() => { + if (text?.length > textLength) { + setIsLength(true); + return setResultText(text.slice(0, textLength)); + } else { + setResultText(text); + setIsLength(false); + } + }, [text]); + + return ( + <> + + {isLength ? ( +
+ {resultText} + +
+ ) : ( +
{resultText}
+ )} + + ); +} From 29c1ae65f5adf2da59c9340755e226a924aa708e Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 17:23:39 +0600 Subject: [PATCH 113/138] =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B6=D0=B0=D1=82=D0=B8=D0=B8=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D0=BD=D0=BD=D0=B5=D1=80=20=D0=B8=20=D0=B2=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=BC=D0=B5=D0=BD=D1=82=D0=B5=20=D0=BA=D0=BE=D0=B3?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B6=D0=B4=D0=B5=D0=BC=20=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/[courseTheme]/page.tsx | 64 ++++++----- app/(main)/course/page.tsx | 129 ++++++++++----------- app/components/cards/LessonCard.tsx | 48 +++++--- app/components/lessons/LessonTyping.tsx | 136 +++++++++++++---------- 4 files changed, 212 insertions(+), 165 deletions(-) diff --git a/app/(main)/course/[courseTheme]/page.tsx b/app/(main)/course/[courseTheme]/page.tsx index 2e5654ce..30b8aa74 100644 --- a/app/(main)/course/[courseTheme]/page.tsx +++ b/app/(main)/course/[courseTheme]/page.tsx @@ -18,6 +18,7 @@ import { NotFound } from '@/app/components/NotFound'; import Redacting from '@/app/components/popUp/Redacting'; import { getRedactor } from '@/utils/getRedactor'; import { getConfirmOptions } from '@/utils/getConfirmOptions'; +import { ProgressSpinner } from 'primereact/progressspinner'; export default function CourseTheme() { const [hasThemes, setHasThemes] = useState(false); @@ -29,6 +30,7 @@ export default function CourseTheme() { const [editMode, setEditMode] = useState(false); const [forStart, setForStart] = useState(true); const [skeleton, setSkeleton] = useState(false); + const [progressSpinner, setProgressSpinner] = useState(false); const [editingThemes, setEditingThemes] = useState<{ title: string }>({ title: '' }); @@ -50,7 +52,7 @@ export default function CourseTheme() { const data = await fetchThemes(Number(courseTheme)); toggleSkeleton(); - + contextFetchThemes(Number(courseTheme)); if (data?.lessons) { setHasThemes(false); @@ -119,7 +121,6 @@ export default function CourseTheme() { }; const handleUpdateTheme = async () => { - const data = await updateTheme(Number(courseTheme), selectedCourse.id, editingThemes.title); if (data.success) { toggleSkeleton(); @@ -143,16 +144,15 @@ export default function CourseTheme() { }; const edit = (rowData: number | null) => { - setEditMode(true); - setSelectedCourse({id: rowData}); + setSelectedCourse({ id: rowData }); // setThemeValue({ title: rowData.title || '' }); setFormVisible(true); }; const clearValues = () => { setThemeValue({ title: '', description: '', video_url: '' }); - setEditingThemes({ title: ''}); + setEditingThemes({ title: '' }); setEditMode(false); setSelectedCourse({ id: null }); }; @@ -164,16 +164,18 @@ export default function CourseTheme() { useEffect(() => { const handleShow = async () => { - const data:{lessons: {data: {id: number, title: string}[]}} = await fetchThemes(Number(courseTheme)); - + setProgressSpinner(true) + const data: { lessons: { data: { id: number; title: string }[] } } = await fetchThemes(Number(courseTheme)); + if (data?.lessons) { - console.log('rab'); - - const forEditing = data.lessons.data.find(item => item.id === selectedCourse.id) - + setProgressSpinner(false); + const forEditing = data.lessons.data.find((item) => item.id === selectedCourse.id); + setEditingThemes({ - title: forEditing?.title || '', + title: forEditing?.title || '' }); + } else { + setProgressSpinner(false); } }; @@ -181,7 +183,7 @@ export default function CourseTheme() { handleShow(); } }, [editMode]); - + useEffect(() => { const title = editMode ? editingThemes.title.trim() : themeValue.title.trim(); if (title.length > 0) { @@ -235,25 +237,29 @@ export default function CourseTheme() {
- { - // setCourseTitle(e.target.value); - editMode - ? setEditingThemes((prev) => ({ - ...prev, - title: e.target.value - })) - : setThemeValue((prev) => ({ - ...prev, - title: e.target.value - })); - }} - /> +
+ { + // setCourseTitle(e.target.value); + editMode + ? setEditingThemes((prev) => ({ + ...prev, + title: e.target.value + })) + : setThemeValue((prev) => ({ + ...prev, + title: e.target.value + })); + }} + /> + {progressSpinner && } +
- + {/* table section */} {hasThemes ? ( diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 4f1d1bb9..5e5f3ed0 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -26,6 +26,7 @@ import { TabPanel, TabView } from 'primereact/tabview'; import { TabViewChange } from '@/types/tabViewChange'; import { useMediaQuery } from '@/hooks/useMediaQuery'; import useShortText from '@/hooks/useShortText'; +import { ProgressSpinner } from 'primereact/progressspinner'; export default function Course() { const { setMessage, course, setCourses, contextFetchCourse } = useContext(LayoutContext); @@ -41,6 +42,7 @@ export default function Course() { const [formVisible, setFormVisible] = useState(false); const [forStart, setForStart] = useState(false); const [skeleton, setSkeleton] = useState(false); + const [progressSpinner, setProgressSpinner] = useState(false); const [pagination, setPagination] = useState<{ currentPage: number; total: number; perPage: number }>({ currentPage: 1, total: 0, @@ -260,10 +262,6 @@ export default function Course() { } }; - useEffect(() => { - console.log(imageState); - }, [imageState]); - const imageBodyTemplate = (product: CourseType) => { const image = product.image; @@ -286,7 +284,6 @@ export default function Course() { const handlePageChange = (page: number) => { // handleFetchCourse(page); contextFetchCourse(page); - console.log(page); }; const edit = (rowData: number | null) => { @@ -334,15 +331,19 @@ export default function Course() { useEffect(() => { const handleShow = async () => { + setProgressSpinner(true); const data = await fetchCourseInfo(selectedCourse); if (data?.success) { + setProgressSpinner(false); setEditingLesson({ title: data.course.title || '', video_url: data.course.video_url || '', description: data.course.description || '', image: data.course.image }); + } else { + setProgressSpinner(false); } }; @@ -384,63 +385,75 @@ export default function Course() { {/*
*/}
- { - editMode - ? setEditingLesson((prev) => ({ - ...prev, - title: e.target.value - })) - : setCourseValue((prev) => ({ - ...prev, - title: e.target.value - })); - }} - /> +
+ { + editMode + ? setEditingLesson((prev) => ({ + ...prev, + title: e.target.value + })) + : setCourseValue((prev) => ({ + ...prev, + title: e.target.value + })); + }} + /> + {progressSpinner && } +
- { - editMode - ? setEditingLesson((prev) => ({ - ...prev, - video_url: e.target.value - })) - : setCourseValue((prev) => ({ - ...prev, - video_url: e.target.value - })); - }} - /> +
+ { + editMode + ? setEditingLesson((prev) => ({ + ...prev, + video_url: e.target.value + })) + : setCourseValue((prev) => ({ + ...prev, + video_url: e.target.value + })); + }} + /> + {progressSpinner && } +
{/*
*/} {/*
*/}
- { - editMode - ? setEditingLesson((prev) => ({ - ...prev, - description: e.target.value - })) - : setCourseValue((prev) => ({ - ...prev, - description: e.target.value - })); - }} - /> +
+ { + editMode + ? setEditingLesson((prev) => ({ + ...prev, + description: e.target.value + })) + : setCourseValue((prev) => ({ + ...prev, + description: e.target.value + })); + }} + /> + {progressSpinner && } +
{/*
*/}
@@ -605,15 +618,7 @@ export default function Course() { ) : ( <> - + rowIndex + 1} header="Номер" style={{ width: '20px' }}> void; - urlForDownload: string + urlForDownload: string; }) { - const shortTitle = useShortText(cardValue.title, 10); + const [progressSpinner, setProgressSpinner] = useState(false); + + const toggleSpinner = () => { + setProgressSpinner(true); + setInterval(() => { + setProgressSpinner(false); + }, 2000); + }; const toSentPDF = () => { + toggleSpinner(); urlForPDF(); }; const lessonCardEvents = () => { - if(type.typeValue === 'doc'){ + if (type.typeValue === 'doc') { toSentPDF(); - } else if (type.typeValue === 'link'){ - window.location.href = cardValue?.url || '#'; + } else if (type.typeValue === 'link') { + // window.location.href = cardValue?.url || '#'; + window.open(cardValue?.url || '#', '_blank'); } }; @@ -117,15 +128,24 @@ export default function LessonCard({ {videoPreviw} {/* button */} - {btnLabel && <> - {status === 'student' && type.typeValue === 'doc' ? -
-
- :
+ + {' '} +
+ ) : ( +
); diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 70840ec6..ce08534c 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -21,6 +21,7 @@ import { Dropdown } from 'primereact/dropdown'; import PDFViewer from '../PDFBook'; import { useMediaQuery } from '@/hooks/useMediaQuery'; import { useRouter } from 'next/navigation'; +import { ProgressSpinner } from 'primereact/progressspinner'; export default function LessonTyping({ mainType, courseId, lessonId }: { mainType: string; courseId: string | null; lessonId: string | null }) { // types @@ -101,6 +102,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const [selectType, setSelectType] = useState(''); const [visible, setVisisble] = useState(false); const [editingLesson, setEditingLesson] = useState(null); + const [progressSpinner, setProgressSpinner] = useState(false); // functions const handleUpdate = () => { @@ -157,13 +159,41 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp } }; + const fileUploadRef = useRef(null); + const clearFile = () => { + fileUploadRef.current?.clear(); + if (visible) { + setEditingLesson( + (prev) => + prev && { + ...prev, + file: null + } + ); + } else { + setDocValue((prev) => ({ + ...prev, + file: null + })); + } + }; + const clearValues = () => { + clearFile(); + setDocValue({ title: '', description: '', file: null, url: '', video_link: '' }); setLinksValue({ title: '', description: '', file: null, url: '', video_link: '' }); setEditingLesson(null); setSelectId(null); setSelectType(''); }; + const toggleSpinner = () => { + setProgressSpinner(true); + setInterval(() => { + setProgressSpinner(false); + }, 1000); + }; + // DOC SECTION const sentToPDF = (url: string) => { @@ -186,25 +216,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp ); - const fileUploadRef = useRef(null); - const clearFile = () => { - fileUploadRef.current?.clear(); - if (visible) { - setEditingLesson( - (prev) => - prev && { - ...prev, - file: null - } - ); - } else { - setDocValue((prev) => ({ - ...prev, - file: null - })); - } - }; - const docSection = () => { return (
@@ -247,7 +258,10 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp setDocValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" />
{/*
@@ -283,7 +297,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp // fetch document const handleFetchDoc = async () => { // skeleton = false - const data = await fetchLesson('doc', courseId ? Number(courseId) : null, lessonId ? Number(lessonId) : null); if (data?.success) { @@ -310,6 +323,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp // add document const handleAddDoc = async () => { + toggleSpinner(); const token = getToken('access_token'); const data = await addLesson('doc', token, courseId ? Number(courseId) : null, lessonId ? Number(lessonId) : null, docValue, 0); @@ -413,7 +427,10 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp setLinksValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" />
-
@@ -424,20 +441,22 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp ) : ( links.map((item: lessonType) => { console.log(item); - return <> - selectedForEditing(id, type)} - onDelete={(id: number) => handleDeleteLink(id)} - cardValue={{ title: item.title, id: item.id, desctiption: item?.description, type: 'url', photo: item?.photo }} - cardBg={'#7bb78112'} - type={{ typeValue: 'link', icon: 'pi pi-link' }} - typeColor={'var(--mainColor)'} - lessonDate={new Date(item.created_at).toISOString().slice(0, 10)} - urlForPDF={() => ''} - urlForDownload="" - /> - + return ( + <> + selectedForEditing(id, type)} + onDelete={(id: number) => handleDeleteLink(id)} + cardValue={{ title: item.title, id: item.id, desctiption: item?.description, type: 'url', photo: item?.photo }} + cardBg={'#7bb78112'} + type={{ typeValue: 'link', icon: 'pi pi-link' }} + typeColor={'var(--mainColor)'} + lessonDate={new Date(item.created_at).toISOString().slice(0, 10)} + urlForPDF={() => ''} + urlForDownload="" + /> + + ); }) )}
@@ -476,10 +495,9 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp // add link const handleAddLink = async () => { + toggleSpinner(); const token = getToken('access_token'); - const data = await addLesson('url', token, courseId ? Number(courseId) : null, lessonId ? Number(lessonId) : null, linksValue, 0); - console.log(data); if (data.success) { handleFetchLink(); @@ -547,8 +565,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp // VIDEO SECTIONS const toggleVideoType = (e: videoType) => { - console.log(e); - setSelectedCity(e); setVideoValue({ title: '', description: '', file: null, url: '', video_link: '' }); }; @@ -571,23 +587,23 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp /> */}
{/* {!selectedCity?.status ? ( */} -
- { - setVideoValue((prev) => ({ ...prev, video_link: e.target.value })); - setValue('usefulLink', e.target.value, { shouldValidate: true }); - }} - /> - {errors.usefulLink?.message} -
+
+ { + setVideoValue((prev) => ({ ...prev, video_link: e.target.value })); + setValue('usefulLink', e.target.value, { shouldValidate: true }); + }} + /> + {errors.usefulLink?.message} +
{/* // ) : ( // setVideoValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" />
-
@@ -657,7 +676,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const handleVideoType = async () => { const data = await fetchVideoType(); - console.log(data); if (data && Array.isArray(data)) { setVideoTypes(data); @@ -693,11 +711,9 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp // add vieo const handleAddVideo = async () => { + toggleSpinner(); const token = getToken('access_token'); - const data = await addLesson('video', token, courseId ? Number(courseId) : null, lessonId ? Number(lessonId) : null, videoValue, selectedCity?.id); - console.log(data); - if (data.success) { handleFetchVideo(); setMessage({ From faa046ab4c05cbf5cb4472b2d920bc98716e1270 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 17:32:59 +0600 Subject: [PATCH 114/138] =?UTF-8?q?=D0=9D=D0=B0=D0=B2=D0=B8=D0=B3=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=B2=20=D1=81=D1=82=D1=83=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B5=20=D0=BF=D0=BE=D0=BA=D0=B0=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- layout/AppMenu.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx index da735fba..0d48f725 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.tsx @@ -109,8 +109,8 @@ const AppMenu = () => { forThemes.push({ label: item.title, id: item.id, - to: '/teaching/ ? ', - items: [] + to: `/teaching/lesson/${item.id}`, + // items: [] }) ); if (forThemes.length > 0) { From 8a9deefd28c02dac355f871a47fe2fcff7148230 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 18:59:50 +0600 Subject: [PATCH 115/138] =?UTF-8?q?=D0=BC=D0=B0=D0=BB=D0=B5=D0=BD=D1=8C?= =?UTF-8?q?=D0=BA=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20=D0=B2=D0=B5=D1=80=D1=81=D1=82=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/auth/login/page.tsx | 6 +++--- app/components/cards/LessonCard.tsx | 4 ++-- app/components/lessons/LessonTyping.tsx | 4 ++-- app/components/popUp/Redacting.tsx | 2 +- layout/AppMenu.tsx | 5 ++--- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index e90d1c06..2a4846c2 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -25,7 +25,7 @@ const LoginPage = () => { const { layoutConfig, setUser, setMessage, setGlobalLoading } = useContext(LayoutContext); const router = useRouter(); - const media = useMediaQuery('(max-width: 640px)'); + const media = useMediaQuery('(max-width: 1030px)'); // const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); const { @@ -100,7 +100,7 @@ const LoginPage = () => {
-

Кирүү

+

Кирүү

{/*
diff --git a/app/components/cards/LessonCard.tsx b/app/components/cards/LessonCard.tsx index 6db117ed..7e7a679e 100644 --- a/app/components/cards/LessonCard.tsx +++ b/app/components/cards/LessonCard.tsx @@ -99,8 +99,8 @@ export default function LessonCard({ return (
diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index ce08534c..6eb7465c 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -275,11 +275,11 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp status="working" onSelected={(id: number, type: string) => selectedForEditing(id, type)} onDelete={(id: number) => handleDeleteDoc(id)} - cardValue={{ title: item?.title, id: item.id, type: 'doc' }} + cardValue={{ title: item?.title, id: item.id, desctiption: item?.description, type: 'doc' }} cardBg={'#ddc4f51a'} type={{ typeValue: 'doc', icon: 'pi pi-file' }} typeColor={'var(--mainColor)'} - lessonDate={'xx-xx'} + lessonDate={new Date(item.created_at).toISOString().slice(0, 10)} urlForPDF={() => sentToPDF(item.document || '')} urlForDownload="" /> diff --git a/app/components/popUp/Redacting.tsx b/app/components/popUp/Redacting.tsx index aac69991..20acd346 100644 --- a/app/components/popUp/Redacting.tsx +++ b/app/components/popUp/Redacting.tsx @@ -8,7 +8,7 @@ export default function Redacting({ redactor, textSize }: {redactor: MenuItem[], return (
- menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> + menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> { useEffect(() => { console.log('Обновился и готов'); - + if (contextStudentThemes?.lessons) { const forThemes: any = []; contextStudentThemes.lessons.data?.map((item: any) => forThemes.push({ label: item.title, id: item.id, - to: `/teaching/lesson/${item.id}`, - // items: [] + to: `/teaching/lesson/${item.id}` }) ); if (forThemes.length > 0) { From 3bceca8e21ddd4281263a13031c833493eaea43c Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 25 Aug 2025 19:25:56 +0600 Subject: [PATCH 116/138] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D0=B5=D1=81=D1=81=D0=B8=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BA=D1=86=D0=B8=D0=B8=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/SessionManager.tsx | 13 +++++-------- layout/AppTopbar.tsx | 1 + layout/StudentLayout.tsx | 7 +++---- services/auth.tsx | 2 -- utils/axiosInstance.tsx | 16 ++++++++-------- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/app/components/SessionManager.tsx b/app/components/SessionManager.tsx index 79dae43b..93621e9d 100644 --- a/app/components/SessionManager.tsx +++ b/app/components/SessionManager.tsx @@ -19,7 +19,6 @@ const SessionManager = () => { }, [user]); useEffect(() => { - console.log('Роутинг'); setGlobalLoading(true); setTimeout(() => { setGlobalLoading(false); @@ -33,7 +32,9 @@ const SessionManager = () => { setGlobalLoading(true); try { if (res?.success) { - setGlobalLoading(false); + setTimeout(() => { + setGlobalLoading(false); + }, 1000); console.log('Данные пользователя успешно пришли ', res); const userVisit = localStorage.getItem('userVisit'); @@ -75,12 +76,8 @@ const SessionManager = () => { if (!token && pathname !== '/' && pathname !== '/auth/login') { console.log('Перенеправляю в login'); - // logout({ setUser, setGlobalLoading }); - // window.location.href = '/auth/login'; - setTimeout(() => { - setGlobalLoading(false); - }, 1000); - + logout({ setUser, setGlobalLoading }); + window.location.href = '/auth/login'; return; } setTimeout(() => { diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index 90fe5626..fb8256bb 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -119,6 +119,7 @@ const AppTopbar = forwardRef((props, ref) => { icon: 'pi pi-sign-out', items: [], command: () => { + window.location.href = '/auth/login'; logout({ setUser, setGlobalLoading }); } } diff --git a/layout/StudentLayout.tsx b/layout/StudentLayout.tsx index 7175ca42..185278ec 100644 --- a/layout/StudentLayout.tsx +++ b/layout/StudentLayout.tsx @@ -122,18 +122,17 @@ const StudentLayout = ({ children }: ChildContainerProps) => { const requireRole = () => { if(!user?.is_student){ - console.log('Не имеете доступ! student'); + console.warn('Не имеете доступ! student'); setPermission(false); - // window.location.href = '/auth/login'; + window.location.href = '/auth/login'; } - // setPermission(true); } useEffect(()=> { requireRole(); },[user]); - // if(permission) return null; + if(permission) return null; return ( diff --git a/services/auth.tsx b/services/auth.tsx index a20fef7a..aec595d3 100644 --- a/services/auth.tsx +++ b/services/auth.tsx @@ -10,8 +10,6 @@ let url = ''; // }); export const login = async (value:LoginType) => { - console.log(value); - url = process.env.NEXT_PUBLIC_BASE_URL + '/login?'; try { diff --git a/utils/axiosInstance.tsx b/utils/axiosInstance.tsx index 17800809..8420603d 100644 --- a/utils/axiosInstance.tsx +++ b/utils/axiosInstance.tsx @@ -3,7 +3,7 @@ import { getToken } from './auth'; const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_BASE_URL, - timeout: 10000, + timeout: 20000, }); axiosInstance.interceptors.request.use((config) => { @@ -25,21 +25,21 @@ axiosInstance.interceptors.response.use( if (status === 401) { console.warn('Неавторизован. Удаляю токен...'); - // document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; - // localStorage.removeItem('userVisit'); - // window.location.href = '/auth/login'; + window.location.href = '/auth/login'; + document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; + localStorage.removeItem('userVisit'); } if (status === 403) { + window.location.href = '/'; console.warn('Не имеет доступ. Перенаправляю...'); - // window.location.href = '/'; } if (status === 404) { console.warn('404 - Перенаправляю...'); - // document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; - // localStorage.removeItem('userVisit'); - // window.location.href = '/pages/notfound'; + window.location.href = '/pages/notfound'; + document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; + localStorage.removeItem('userVisit'); } return Promise.reject(error); From 04f6fc623fee728332eeb2c49a92c07f60b3ece1 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Tue, 26 Aug 2025 09:23:08 +0600 Subject: [PATCH 117/138] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D0=B5=D1=81=D1=81=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/auth/login/page.tsx | 4 ++-- app/components/SessionManager.tsx | 4 ++-- layout/StudentLayout.tsx | 15 ++++++++++----- layout/layout.tsx | 19 +++++++++++-------- utils/axiosInstance.tsx | 14 +++++++------- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index 2a4846c2..a829d655 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -99,7 +99,7 @@ const LoginPage = () => {
-
+

Кирүү

@@ -114,7 +114,7 @@ const LoginPage = () => { name="password" control={control} defaultValue="010270Ja" - render={({ field }) => } + render={({ field }) => } /> {errors.password && {errors.password.message}}
diff --git a/app/components/SessionManager.tsx b/app/components/SessionManager.tsx index 93621e9d..7919b2ac 100644 --- a/app/components/SessionManager.tsx +++ b/app/components/SessionManager.tsx @@ -76,8 +76,8 @@ const SessionManager = () => { if (!token && pathname !== '/' && pathname !== '/auth/login') { console.log('Перенеправляю в login'); - logout({ setUser, setGlobalLoading }); - window.location.href = '/auth/login'; + // logout({ setUser, setGlobalLoading }); + // window.location.href = '/auth/login'; return; } setTimeout(() => { diff --git a/layout/StudentLayout.tsx b/layout/StudentLayout.tsx index 185278ec..1f43a25b 100644 --- a/layout/StudentLayout.tsx +++ b/layout/StudentLayout.tsx @@ -121,18 +121,23 @@ const StudentLayout = ({ children }: ChildContainerProps) => { }); const requireRole = () => { - if(!user?.is_student){ - console.warn('Не имеете доступ! student'); + console.log('Ваш статус: ', user?.is_student); + + if(user){ + if(!user?.is_student){ + console.warn('Не имеете доступ! student'); + // window.location.href = '/auth/login'; + // setPermission(true); + } setPermission(false); - window.location.href = '/auth/login'; } } useEffect(()=> { requireRole(); - },[user]); + },[user, pathname]); - if(permission) return null; + // if(permission) return null; return ( diff --git a/layout/layout.tsx b/layout/layout.tsx index 013f6a17..e40fd328 100644 --- a/layout/layout.tsx +++ b/layout/layout.tsx @@ -19,7 +19,7 @@ const Layout = ({ children }: ChildContainerProps) => { const { setRipple } = useContext(PrimeReactContext); const topbarRef = useRef(null); const sidebarRef = useRef(null); - const [permission, setPermission] = useState(false); + const [permission, setPermission] = useState(true); const [bindMenuOutsideClickListener, unbindMenuOutsideClickListener] = useEventListener({ type: 'click', listener: (event) => { @@ -124,17 +124,20 @@ const Layout = ({ children }: ChildContainerProps) => { }); const requireRole = () => { - if(!user?.is_working){ - console.log('Не имеете доступ! working'); + console.log('Ваш статус: ', user?.is_working); + if(user){ + if(!user?.is_working){ + // window.location.href = '/auth/login'; + // setPermission(true); + console.log('Не имеете доступ! working'); + } setPermission(false); - // window.location.href = '/auth/login'; - } - setPermission(true); + } } useEffect(()=> { - requireRole(); - },[user]); + requireRole(); + },[user, pathname]); // if(permission) return null; diff --git a/utils/axiosInstance.tsx b/utils/axiosInstance.tsx index 8420603d..8f5cbfc7 100644 --- a/utils/axiosInstance.tsx +++ b/utils/axiosInstance.tsx @@ -25,21 +25,21 @@ axiosInstance.interceptors.response.use( if (status === 401) { console.warn('Неавторизован. Удаляю токен...'); - window.location.href = '/auth/login'; - document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; - localStorage.removeItem('userVisit'); + // window.location.href = '/auth/login'; + // document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; + // localStorage.removeItem('userVisit'); } if (status === 403) { - window.location.href = '/'; + // window.location.href = '/'; console.warn('Не имеет доступ. Перенаправляю...'); } if (status === 404) { console.warn('404 - Перенаправляю...'); - window.location.href = '/pages/notfound'; - document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; - localStorage.removeItem('userVisit'); + // window.location.href = '/pages/notfound'; + // document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; + // localStorage.removeItem('userVisit'); } return Promise.reject(error); From e3073ebd13970fdda961331837026fcf479ed24d Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Tue, 26 Aug 2025 17:46:35 +0600 Subject: [PATCH 118/138] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=8B=20=D0=B2=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B8=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BC=D0=BE=D0=B1=D0=B8=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/auth/login/page.tsx | 26 ++-- app/(full-page)/layout.tsx | 2 +- app/(main)/course/page.tsx | 175 ++++++++++++++------------- app/components/messages/Message.tsx | 4 +- app/components/tables/StreamList.tsx | 105 +++++++++++++--- app/globals.css | 43 ++++++- layout/AppTopbar.tsx | 5 - public/layout/svg/login-bg.svg | 2 +- 8 files changed, 231 insertions(+), 131 deletions(-) diff --git a/app/(full-page)/auth/login/page.tsx b/app/(full-page)/auth/login/page.tsx index a829d655..6e866044 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/app/(full-page)/auth/login/page.tsx @@ -2,13 +2,9 @@ 'use client'; import { useRouter } from 'next/navigation'; import React, { useContext, useState } from 'react'; -import { Checkbox } from 'primereact/checkbox'; -import { Button } from 'primereact/button'; import { Password } from 'primereact/password'; import { LayoutContext } from '../../../../layout/context/layoutcontext'; import { InputText } from 'primereact/inputtext'; -import { classNames } from 'primereact/utils'; -import InfoBanner from '@/app/components/InfoBanner'; import { useForm } from 'react-hook-form'; import { schema } from '@/schemas/authSchema'; @@ -16,7 +12,6 @@ import { yupResolver } from '@hookform/resolvers/yup'; import { Controller } from 'react-hook-form'; import { getUser, login } from '@/services/auth'; import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn'; -import { getToken } from '@/utils/auth'; import { logout } from '@/utils/logout'; import { LoginType } from '@/types/login'; import { useMediaQuery } from '@/hooks/useMediaQuery'; @@ -60,25 +55,25 @@ const LoginPage = () => { } else { setMessage({ state: true, - value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' } - }); // messege - Ошибка при авторизации + value: { severity: 'error', summary: 'Ошибка при авторизации', detail: 'Повторите позже' } + }); // messege - Ошибка при авторизации, повторите позже logout({ setUser, setGlobalLoading }); console.log('Ошибка при получении пользователя'); } } catch (error) { setMessage({ state: true, - value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' } - }); // messege - Ошибка при авторизации + value: { severity: 'error', summary: 'Ошибка при авторизации', detail: 'Повторите позже' } + }); // messege - Ошибка при авторизации, повторите позже logout({ setUser, setGlobalLoading }); console.log('Ошибка при получении пользователя'); } } } else { - console.log('Ошибка при авторизации'); + console.log('Ошибка при авторизации, повторите позже'); setMessage({ state: true, - value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' } + value: { severity: 'error', summary: 'Ошибка', detail: 'Введите корректные данные' } }); // messege - Ошибка при авторизации } }; @@ -87,20 +82,21 @@ const LoginPage = () => { console.log('Ошибки формы:', errors); setMessage({ state: true, - value: { severity: 'error', summary: 'Катаа', detail: 'ПОвтор' } + value: { severity: 'error', summary: 'Ошибка', detail: 'Введите корректные данные' } }); // messege - Ошибка при авторизации }; return ( -
+
+ {/*
*/} {/* */}
-
-

Кирүү

+
+

Кирүү

{/*
- )} -
+ <> +
+
+ + )} @@ -583,7 +594,7 @@ export default function Course() { className="p-tabview p-tabview-nav p-tabview-selected p-tabview-panels p-tabview-panel" >
- + {}} />
diff --git a/app/components/messages/Message.tsx b/app/components/messages/Message.tsx index 42baa0a2..908dd2f6 100644 --- a/app/components/messages/Message.tsx +++ b/app/components/messages/Message.tsx @@ -12,7 +12,7 @@ export default function Message() { const toast = useRef(null); const showError = () => { - toast.current?.show({ severity: message.value.severity as SeverityType, summary: message.value.summary, detail: message.value.detail, life: 3000 }); + toast.current?.show({ severity: message.value.severity as SeverityType, summary: message.value.summary, detail: message.value.detail, life: 30000 }); }; useEffect(() => { @@ -26,7 +26,7 @@ export default function Message() { return (
{/*
); } diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 955b6c23..66de54db 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -11,16 +11,73 @@ import GroupSkeleton from '../skeleton/GroupSkeleton'; import Link from 'next/link'; import { streamsType } from '@/types/streamType'; -export default function StreamList({ callIndex, courseValue, isMobile }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean }) { +export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: ()=> void }) { interface mainStreamsType { - connect_id: number | null,stream_id:number, subject_name: {name_kg:string}, - subject_type_name:{name_kg:string}, teacher:{name:string}, language:{name:string}, - id_edu_year:number,id_period:number, semester:{name_kg:string}, edu_form:{name_kg:string} + connect_id: number | null; + stream_id: number; + subject_name: { name_kg: string }; + subject_type_name: { name_kg: string }; + teacher: { name: string }; + language: { name: string }; + id_edu_year: number; + id_period: number; + semester: { name_kg: string }; + edu_form: { name_kg: string }; } + const shablon = [ + { + connect_id: 0, + stream_id: 2, + subject_name: { name_kg: 'test' }, + subject_type_name: { name_kg: 'test' }, + teacher: { name: 'test' }, + language: { name: 'test' }, + id_edu_year: 2, + id_period: 2, + semester: { name_kg: 'test' }, + edu_form: { name_kg: 'test' } + }, + { + connect_id: 0, + stream_id: 0, + subject_name: { name_kg: 'test' }, + subject_type_name: { name_kg: 'test' }, + teacher: { name: 'test' }, + language: { name: 'test' }, + id_edu_year: 2, + id_period: 2, + semester: { name_kg: 'test' }, + edu_form: { name_kg: 'test' } + }, + { + connect_id: 2, + stream_id: 2, + subject_name: { name_kg: 'test' }, + subject_type_name: { name_kg: 'test' }, + teacher: { name: 'test' }, + language: { name: 'test' }, + id_edu_year: 2, + id_period: 2, + semester: { name_kg: 'test' }, + edu_form: { name_kg: 'test' } + }, + { + connect_id: 2, + stream_id: 2, + subject_name: { name_kg: 'test' }, + subject_type_name: { name_kg: 'test' }, + teacher: { name: 'test' }, + language: { name: 'test' }, + id_edu_year: 2, + id_period: 2, + semester: { name_kg: 'test' }, + edu_form: { name_kg: 'test' } + }, + ]; const [streams, setStreams] = useState([]); const [streamValues, setStreamValues] = useState<{ stream: streamsType[] }>({ stream: [] }); - const [displayStreams, setDisplayStreams] = useState<{ course_id: number; stream_id: number; info: string | null; stream_title: string }[]>([]); + const [displayStreams, setDisplayStreams] = useState<{ course_id: number; stream_id: number; info: string | null; stream_title: string }[] | any>([]); const [hasStreams, setHasStreams] = useState(false); const [skeleton, setSkeleton] = useState(false); @@ -35,11 +92,11 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI }, 1000); }; - const profilactor = (data: {connect_id: number, course_id: number; stream_id: number; info: string | null}[]) => { + const profilactor = (data: { connect_id: number; course_id: number; stream_id: number; info: string | null }[]) => { const newStreams: { course_id: number; stream_id: number; info: string | null }[] = []; - + data.forEach((item) => { - if (item?.connect_id) { + if (item?.connect_id) { newStreams.push({ course_id: item?.course_id, stream_id: item.stream_id, @@ -100,8 +157,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI } }; - const handleEdit = (e:{checked:boolean}, id: number, title: string) => { - + const handleEdit = (e: { checked: boolean }, id: number, title: string) => { const forSentStreams = { course_id: courseValue!.id, stream_id: id, @@ -111,10 +167,15 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI if (e.checked) { // profilactor(); - setStreamValues((prev) => prev && ({ - ...prev, - stream: [...prev.stream, forSentStreams] - })); + setStreamValues( + (prev) => + prev && { + ...prev, + stream: [...prev.stream, forSentStreams] + } + ); + const x = {streamTitle} + insideDisplayStreams(); } else { setStreamValues( (prev) => @@ -136,7 +197,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI } }); - // setDisplayStreams(forDisplay); + setDisplayStreams(forDisplay); }, [streamValues]); useEffect(() => { @@ -156,7 +217,11 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI } }, [streams]); - const itemTemplate = (item:mainStreamsType, index: number) => { + useEffect(()=> { + console.log(displayStreams); + },[displayStreams]) + + const itemTemplate = (item: mainStreamsType, index: number) => { const bgClass = item.connect_id ? 'bg-[var(--greenBgColor)] border-b border-[gray]' : index % 2 == 1 ? 'bg-[#f5f5f5]' : ''; return ( @@ -177,7 +242,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI
-
+
{item?.subject_type_name?.name_kg} @@ -211,7 +276,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI ); }; - const listTemplate = (items:mainStreamsType[]) => { + const listTemplate = (items: mainStreamsType[]) => { if (!items || items.length === 0) return null; let list = items.map((product, index: number) => { @@ -248,7 +313,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI )} - {hasStreams ? ( + {!hasStreams ? ( ) : (
@@ -269,7 +334,7 @@ export default function StreamList({ callIndex, courseValue, isMobile }: { callI ) : ( <> - + )}
diff --git a/app/globals.css b/app/globals.css index e883080e..343c757f 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,7 +4,8 @@ :root { --bodyFonts: "Jost", sans-serif; --mainColor: #08A9E6; - --mainBgColor: #e6eef1; + /* --mainBgColor: #e6eef1; */ + --mainBgColor: #fff; --redColor: #EC272F; --redBgColor: #EC272F1A; --greenColor: rgb(46, 192, 46); @@ -44,7 +45,7 @@ h1, h2, h3, h4, h5, h6 { } .login-bg{ - background: url('/layout/svg/login-bg.svg') no-repeat center/cover; + background: url('/layout/svg/login-bg.svg') repeat left/cover; } /* animate */ @@ -136,6 +137,7 @@ h1, h2, h3, h4, h5, h6 { height: 60px; width: 60px; } + #preloader-area .spinner { position: absolute; z-index: 9999; @@ -195,12 +197,29 @@ h1, h2, h3, h4, h5, h6 { right: 0; } +@media screen and (max-width: 640px) { + #preloader-area{ + position: absolute; + left: 60%; + top: 50%; + width: 10px; + height: 10px; + } + + #preloader-area .spinner { + position: absolute; + z-index: 9999; + /* width: 3px; Уменьшаем с 6px до 3px */ + height: 45px; /* Уменьшаем с 90px до 45px */ + margin-top: -22.5px; /* Уменьшаем с -45px до -22.5px */ + } +} + .p-password .p-password-toggle-icon { top: 50% !important; transform: translateY(-50%); } - .loaded #preloader-area { opacity: 0; visibility: hidden; @@ -313,8 +332,6 @@ h1, h2, h3, h4, h5, h6 { width: 100%; } - - /* primeReact components */ .popup_menu_left{ width: 300px; @@ -368,6 +385,10 @@ h1, h2, h3, h4, h5, h6 { background-color: #f5f5f5; } +.my-custom-mobile-table:nth-child(even) { + background-color: red; +} + /* удаление встроенного underline при активаности для таб (TabView) */ .p-tabview-ink-bar { display: none !important; @@ -427,6 +448,18 @@ h1, h2, h3, h4, h5, h6 { font-size: 12px; /* или любой нужный размер */ } +@media screen and (max-width: 640px) { + .p-toast-message{ + font-size: 14px !important; + width: 290px !important; + margin: 0 auto; + } + + .p-toast-message-content{ + padding: 10px !important; + } +} + /* styles/book.css */ /* Стили для контейнера всей книги */ diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index fb8256bb..5f8beecf 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -91,11 +91,6 @@ const AppTopbar = forwardRef((props, ref) => { icon: '', items: [], url: 'https://oshsu.kg' - }, - { - label: 'Байланыш', - icon: '', - items: [] } ]; diff --git a/public/layout/svg/login-bg.svg b/public/layout/svg/login-bg.svg index 5398aa5a..f704ca1a 100644 --- a/public/layout/svg/login-bg.svg +++ b/public/layout/svg/login-bg.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 69ed0e84c41778458b3917877e65dcfe44cf68c9 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Wed, 27 Aug 2025 11:31:03 +0600 Subject: [PATCH 119/138] =?UTF-8?q?=D0=A5=D0=BB=D0=B5=D0=B1=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BA=D1=80=D0=BE=D1=88=D0=BA=D0=B8=20=D0=B8=20=D0=B4?= =?UTF-8?q?=D1=80=D1=83=D0=B3=D0=B8=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/[courseTheme]/[lessons]/page.tsx | 90 ++++++++++++++----- app/(main)/course/[courseTheme]/page.tsx | 71 +++++++++++---- .../[connect_id]/[stream_id]/page.tsx | 86 ++++++++++++++---- app/components/SessionManager.tsx | 2 +- app/components/messages/Message.tsx | 2 +- app/globals.css | 3 +- hooks/useBreadCrumbs.tsx | 72 +++++++++++++++ layout/layout.tsx | 14 +-- types/breadCrumbType.tsx | 6 ++ 9 files changed, 281 insertions(+), 65 deletions(-) create mode 100644 hooks/useBreadCrumbs.tsx create mode 100644 types/breadCrumbType.tsx diff --git a/app/(main)/course/[courseTheme]/[lessons]/page.tsx b/app/(main)/course/[courseTheme]/[lessons]/page.tsx index 83fa63b4..7fe5ce0d 100644 --- a/app/(main)/course/[courseTheme]/[lessons]/page.tsx +++ b/app/(main)/course/[courseTheme]/[lessons]/page.tsx @@ -7,7 +7,7 @@ import { Button } from 'primereact/button'; import Redacting from '@/app/components/popUp/Redacting'; import { addLesson, deleteLesson, fetchLesson, updateLesson } from '@/services/courses'; import { getToken } from '@/utils/auth'; -import { useParams } from 'next/navigation'; +import { useParams, usePathname } from 'next/navigation'; import { LayoutContext } from '@/layout/context/layoutcontext'; import useErrorMessage from '@/hooks/useErrorMessage'; import { getRedactor } from '@/utils/getRedactor'; @@ -15,6 +15,7 @@ import { getConfirmOptions } from '@/utils/getConfirmOptions'; import LessonTyping from '@/app/components/lessons/LessonTyping'; import { TabViewChange } from '@/types/tabViewChange'; import { useMediaQuery } from '@/hooks/useMediaQuery'; +import useBreadCrumbs from '@/hooks/useBreadCrumbs'; export default function Lesson() { const [activeIndex, setActiveIndex] = useState(0); @@ -34,6 +35,42 @@ export default function Lesson() { const courseId = params.courseTheme; const lessonId = params.lessons; + const teachingBreadCrumb = [ + { + id: 1, + url: '/', + title: 'Башкы баракча', + parent_id: null + }, + { + id: 2, + url: '/course', + title: 'Курстар', + parent_id: 1 + }, + { + id: 3, + url: `/course/${lessonId}`, + title: 'Темалар', + parent_id: 2 + }, + { + id: 4, + url: '/course/:course_id/:lesson_id', + title: 'Сабактар', + parent_id: 3 + }, + { + id: 5, + url: '/students/:course_id/:stream_id', + title: 'Студенттер', + parent_id: 2 + } + ]; + + const pathname = usePathname(); + const breadcrumb = useBreadCrumbs(teachingBreadCrumb,pathname); + const handleText = (e: string) => { setSentValues(e); }; @@ -154,28 +191,37 @@ export default function Lesson() { setContentShow(true); }; - const lessonInfo =
-
- -
-

{'Сабактын аталышы'}

-
- - - handleTabChange({index: 1})} className='cursor-pointer hover:text-[var(--mainColor)] transition-all'>Документтердин саны: ? - - - - handleTabChange({index: 2})} className='cursor-pointer hover:text-[var(--mainColor)] transition-all'>Шилтемелердин саны: ? - - - - handleTabChange({index: 3})} className='cursor-pointer hover:text-[var(--mainColor)] transition-all'>Видеолордун саны: ? - + const lessonInfo = ( +
+
+ +
+

{'Сабактын аталышы'}

+
+ + + handleTabChange({ index: 1 })} className="cursor-pointer hover:text-[var(--mainColor)] transition-all"> + Документтердин саны: ? + + + + + handleTabChange({ index: 2 })} className="cursor-pointer hover:text-[var(--mainColor)] transition-all"> + Шилтемелердин саны: ? + + + + + handleTabChange({ index: 3 })} className="cursor-pointer hover:text-[var(--mainColor)] transition-all"> + Видеолордун саны: ? + + +
+
{breadcrumb}
-
+ ); // USE EFFECTS @@ -243,7 +289,9 @@ export default function Lesson() {
)}
- ) : lessonInfo} + ) : ( + lessonInfo + )} {/* DOC */} diff --git a/app/(main)/course/[courseTheme]/page.tsx b/app/(main)/course/[courseTheme]/page.tsx index 30b8aa74..f299aa2a 100644 --- a/app/(main)/course/[courseTheme]/page.tsx +++ b/app/(main)/course/[courseTheme]/page.tsx @@ -10,7 +10,7 @@ import { DataTable } from 'primereact/datatable'; import { InputText } from 'primereact/inputtext'; import { LayoutContext } from '@/layout/context/layoutcontext'; import React, { useContext, useEffect, useState } from 'react'; -import { useParams } from 'next/navigation'; +import { useParams, usePathname } from 'next/navigation'; import { addThemes, deleteTheme, fetchCourseInfo, fetchThemes, updateTheme } from '@/services/courses'; import useErrorMessage from '@/hooks/useErrorMessage'; import { CourseCreateType } from '@/types/courseCreateType'; @@ -19,6 +19,7 @@ import Redacting from '@/app/components/popUp/Redacting'; import { getRedactor } from '@/utils/getRedactor'; import { getConfirmOptions } from '@/utils/getConfirmOptions'; import { ProgressSpinner } from 'primereact/progressspinner'; +import useBreadCrumbs from '@/hooks/useBreadCrumbs'; export default function CourseTheme() { const [hasThemes, setHasThemes] = useState(false); @@ -39,7 +40,42 @@ export default function CourseTheme() { const { courseTheme } = useParams() as { courseTheme: string }; + const teachingBreadCrumb = [ + { + id: 1, + url: '/', + title: 'Башкы баракча', + parent_id: null + }, + { + id: 2, + url: '/course', + title: 'Курстар', + parent_id: 1 + }, + { + id: 3, + url: `/course/:id`, + title: 'Темалар', + parent_id: 2 + }, + { + id: 4, + url: '/course/:course_id/:lesson_id', + title: 'Сабактар', + parent_id: 3 + }, + { + id: 5, + url: '/students/:course_id/:stream_id', + title: 'Студенттер', + parent_id: 2 + } + ]; + const showError = useErrorMessage(); + const pathname = usePathname(); + const breadcrumb = useBreadCrumbs(teachingBreadCrumb, pathname); const toggleSkeleton = () => { setSkeleton(true); @@ -158,13 +194,13 @@ export default function CourseTheme() { }; useEffect(() => { - handleFetchInfo(); - handleFetchThemes(); + // handleFetchInfo(); + // handleFetchThemes(); }, []); useEffect(() => { const handleShow = async () => { - setProgressSpinner(true) + setProgressSpinner(true); const data: { lessons: { data: { id: number; title: string }[] } } = await fetchThemes(Number(courseTheme)); if (data?.lessons) { @@ -203,21 +239,24 @@ export default function CourseTheme() { return (
{/* title section */} -
-
-

- {themeInfo?.title} -

-

{themeInfo?.description}

-
- - {themeInfo?.created_at} +
+
+
+

+ {themeInfo?.title} +

+

{themeInfo?.description}

+
+ + {themeInfo?.created_at} +
-
-
- +
+ +
+
{breadcrumb}
{/* add button*/} diff --git a/app/(main)/students/[connect_id]/[stream_id]/page.tsx b/app/(main)/students/[connect_id]/[stream_id]/page.tsx index 320fca8e..38c455a6 100644 --- a/app/(main)/students/[connect_id]/[stream_id]/page.tsx +++ b/app/(main)/students/[connect_id]/[stream_id]/page.tsx @@ -3,11 +3,12 @@ import InfoBanner from '@/app/components/InfoBanner'; import { NotFound } from '@/app/components/NotFound'; import GroupSkeleton from '@/app/components/skeleton/GroupSkeleton'; +import useBreadCrumbs from '@/hooks/useBreadCrumbs'; import useErrorMessage from '@/hooks/useErrorMessage'; +import { useMediaQuery } from '@/hooks/useMediaQuery'; import { LayoutContext } from '@/layout/context/layoutcontext'; import { fetchStreamStudents } from '@/services/streams'; -import Link from 'next/link'; -import { useParams } from 'next/navigation'; +import { useParams, usePathname } from 'next/navigation'; import { Button } from 'primereact/button'; import { Column } from 'primereact/column'; import { DataTable } from 'primereact/datatable'; @@ -39,7 +40,7 @@ export default function StudentList() { last_visist: 'xx-xx', info: true } - ] + ]; // const [studentList, setStudentList] = useState([]); const [hasList, setHasList] = useState(false); const [skeleton, setSkeleton] = useState(false); @@ -47,9 +48,46 @@ export default function StudentList() { const { setMessage, setGlobalLoading } = useContext(LayoutContext); const showError = useErrorMessage(); - const {connect_id, stream_id} = useParams(); + const { connect_id, stream_id } = useParams(); console.log('params: ', connect_id, stream_id); - + + const media = useMediaQuery('(max-width: 640px)'); + const teachingBreadCrumb = [ + { + id: 1, + url: '/', + title: 'Башкы баракча', + parent_id: null + }, + { + id: 2, + url: '/course', + title: 'Курстар', + parent_id: 1 + }, + { + id: 3, + url: `/course/:id`, + title: 'Темалар', + parent_id: 2 + }, + { + id: 4, + url: '/course/:course_id/:lesson_id', + title: 'Сабактар', + parent_id: 3 + }, + { + id: 5, + url: `/students/${connect_id}/${stream_id}`, + title: 'Студенттер', + parent_id: 2 + } + ]; + + const pathname = usePathname(); + const breadcrumb = useBreadCrumbs(teachingBreadCrumb, pathname); + // functions const toggleSkeleton = () => { setSkeleton(true); @@ -61,7 +99,7 @@ export default function StudentList() { const handleFetchStudents = async () => { const data = await fetchStreamStudents(connect_id ? Number(connect_id) : null, stream_id ? Number(stream_id) : null); console.log(data); - + toggleSkeleton(); if (data && data.students) { setHasList(false); @@ -88,13 +126,19 @@ export default function StudentList() { return (
{skeleton ? ( - - ) : ( - <> - {/* info section */} - - - ) } + + ) : ( + <> + {/* info section */} +
+ +
+

{'Угуучулардын тизмеси'}

+
{breadcrumb}
+
+
+ + )} {/* table section */} {!hasList ? ( @@ -107,11 +151,17 @@ export default function StudentList() { <> rowIndex + 1} header="Номер" style={{ width: '20px' }}> -
- {rowData.last_name} - {rowData.name} - {rowData.father_name} -
} + ( +
+ {rowData.last_name} + {rowData.name} + {rowData.father_name} +
+ )} >
(null); const showError = () => { - toast.current?.show({ severity: message.value.severity as SeverityType, summary: message.value.summary, detail: message.value.detail, life: 30000 }); + toast.current?.show({ severity: message.value.severity as SeverityType, summary: message.value.summary, detail: message.value.detail, life: 2000 }); }; useEffect(() => { diff --git a/app/globals.css b/app/globals.css index 343c757f..18560759 100644 --- a/app/globals.css +++ b/app/globals.css @@ -41,7 +41,8 @@ h1, h2, h3, h4, h5, h6 { } .mainColor-hover:hover{ - color: #08A9E6; + color: #08A9E6 !important; + transition: .5s; } .login-bg{ diff --git a/hooks/useBreadCrumbs.tsx b/hooks/useBreadCrumbs.tsx new file mode 100644 index 00000000..2b8fc5ad --- /dev/null +++ b/hooks/useBreadCrumbs.tsx @@ -0,0 +1,72 @@ +'use client'; + +import { breadCrumbType } from '@/types/breadCrumbType'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { useEffect, useState } from 'react'; + +export default function useBreadCrumbs(insideBreadCrumb: breadCrumbType[], currentUrl: string) { + const pathname = usePathname(); + + const [breadCrumb, setBreadCrumb] = useState([]); + + const matchUrl = (pattern: string, url: string) => { + // Заменяем все ":что-то" на "([^/]+)" (регулярка: один сегмент) + const regex = new RegExp('^' + pattern.replace(/:[^/]+/g, '[^/]+') + '$'); + return regex.test(url); + }; + + const getBreadcrumbs = (data: breadCrumbType[], currentUrl: string) => { + + // 1. Находим текущую страницу по URL (с учётом динамики) + const currentPage = data.find((item) => matchUrl(item.url, currentUrl)); + console.log(currentPage); + + if (!currentPage) return []; + + const breadcrumbs = []; + let currentItem: breadCrumbType = currentPage; + const visited = new Set(); + + while (currentItem) { + if (visited.has(currentItem.id)) { + // Зацикленность → выходим + console.warn('Цикл в дереве хлебных крошек!'); + break; + } + visited.add(currentItem.id); + + breadcrumbs.unshift(currentItem); + const parent = data.find((item) => item.id === currentItem.parent_id); + if (parent) currentItem = parent; + else break; + } + + return breadcrumbs; + }; + + useEffect(() => { + const forBreadcrumb = getBreadcrumbs(insideBreadCrumb, currentUrl); + console.log(forBreadcrumb); + setBreadCrumb(forBreadcrumb); + }, [pathname]); + + return ( +
+ {breadCrumb?.map((crumb: breadCrumbType, index) => ( +
+
+ {index < breadCrumb.length - 1 ? ( + + {crumb.title} + + ) : ( + {crumb.title} + )} +
+ {index < breadCrumb.length - 1 && / } +
+ ))} +
+ ); +} diff --git a/layout/layout.tsx b/layout/layout.tsx index e40fd328..b6fc8faa 100644 --- a/layout/layout.tsx +++ b/layout/layout.tsx @@ -125,19 +125,19 @@ const Layout = ({ children }: ChildContainerProps) => { const requireRole = () => { console.log('Ваш статус: ', user?.is_working); - if(user){ - if(!user?.is_working){ + if (user) { + if (!user?.is_working) { // window.location.href = '/auth/login'; // setPermission(true); console.log('Не имеете доступ! working'); } setPermission(false); - } - } + } + }; - useEffect(()=> { - requireRole(); - },[user, pathname]); + useEffect(() => { + requireRole(); + }, [user, pathname]); // if(permission) return null; diff --git a/types/breadCrumbType.tsx b/types/breadCrumbType.tsx new file mode 100644 index 00000000..55c31ceb --- /dev/null +++ b/types/breadCrumbType.tsx @@ -0,0 +1,6 @@ +export interface breadCrumbType { + id: number; + url: string; + title: string; + parent_id: number | null; +} From e0f1fa478405507fd214e71fbf5115a041581af2 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Wed, 27 Aug 2025 13:18:31 +0600 Subject: [PATCH 120/138] =?UTF-8?q?=D0=9C=D0=BE=D0=B1=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=83=D0=B4=D0=BE=D0=B1=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=B0=201.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/[courseTheme]/[lessons]/page.tsx | 10 +- app/(main)/course/[courseTheme]/page.tsx | 2 +- app/(main)/course/page.tsx | 3 +- app/components/HomeClient.tsx | 2 +- app/components/popUp/FormModal.tsx | 102 ++++++++++++------ app/components/tables/StreamList.tsx | 2 +- app/globals.css | 20 ++++ hooks/useBreadCrumbs.tsx | 6 +- 8 files changed, 103 insertions(+), 44 deletions(-) diff --git a/app/(main)/course/[courseTheme]/[lessons]/page.tsx b/app/(main)/course/[courseTheme]/[lessons]/page.tsx index 7fe5ce0d..c61bc859 100644 --- a/app/(main)/course/[courseTheme]/[lessons]/page.tsx +++ b/app/(main)/course/[courseTheme]/[lessons]/page.tsx @@ -193,7 +193,7 @@ export default function Lesson() { const lessonInfo = (
-
+

{'Сабактын аталышы'}

@@ -240,7 +240,7 @@ export default function Lesson() { {/* CKEDITOR */} {/* title section */} -
+

diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index db9e4f38..71041d71 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -504,6 +504,7 @@ export default function Course() { disabled={progressSpinner === true ? true : false} rows={5} cols={30} + className='w-[300px]' onChange={(e) => { editMode ? setEditingLesson((prev) => ({ @@ -690,7 +691,7 @@ export default function Course() {

{/* STREAMS SECTION */}
- + {}} />
)} diff --git a/app/components/HomeClient.tsx b/app/components/HomeClient.tsx index b3b74e96..43ccccc4 100644 --- a/app/components/HomeClient.tsx +++ b/app/components/HomeClient.tsx @@ -18,7 +18,7 @@ export default function HomeClient() { return (
- {/* {"Уроки"} */} + {"Уроки"}
diff --git a/app/components/popUp/FormModal.tsx b/app/components/popUp/FormModal.tsx index 9ec91e8d..d281290a 100644 --- a/app/components/popUp/FormModal.tsx +++ b/app/components/popUp/FormModal.tsx @@ -1,49 +1,87 @@ 'use client'; +import { useMediaQuery } from '@/hooks/useMediaQuery'; import { Button } from 'primereact/button'; import { Dialog } from 'primereact/dialog'; import { ReactNode, useEffect } from 'react'; -export default function FormModal({children, title, fetchValue, clearValues, visible, setVisible, start}: - { - children: ReactNode, - title: string, - fetchValue: ()=> void, - clearValues: ()=> void, - visible: boolean, - setVisible: (params: boolean)=> void, - start: boolean - } - ){ +export default function FormModal({ + children, + title, + fetchValue, + clearValues, + visible, + setVisible, + start +}: { + children: ReactNode; + title: string; + fetchValue: () => void; + clearValues: () => void; + visible: boolean; + setVisible: (params: boolean) => void; + start: boolean; +}) { + const media = useMediaQuery('(max-width:640px)'); const footerContent = (
-
); return (
- { - if (!visible) return; - setVisible(false); - clearValues(); - }} - footer={footerContent} - > - {children} - + {media ? ( + { + if (!visible) return; + setVisible(false); + clearValues(); + }} + footer={footerContent} + > + {children} + + ) : ( + { + if (!visible) return; + setVisible(false); + clearValues(); + }} + footer={footerContent} + > + {children} + + )}
); } diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 66de54db..54ed7e2a 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -174,7 +174,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis stream: [...prev.stream, forSentStreams] } ); - const x = {streamTitle} + // const x = {streamTitle} insideDisplayStreams(); } else { setStreamValues( diff --git a/app/globals.css b/app/globals.css index 18560759..2e1512d1 100644 --- a/app/globals.css +++ b/app/globals.css @@ -438,8 +438,17 @@ h1, h2, h3, h4, h5, h6 { @media screen and (max-width: 640px) { .my-custom-dialog{ + width: 350px; + } + .my-custom-document-dialog{ width: 300px; } +} + +@media screen and (max-width: 440px) { + .my-custom-dialog{ + width:320px; + } .my-custom-document-dialog{ width: 300px; } @@ -461,6 +470,17 @@ h1, h2, h3, h4, h5, h6 { } } +@media (max-width: 480px) { + .p-confirm-dialog { + width: 90% !important; + margin: 0 5% !important; + } + .p-confirm-dialog .p-button { + width: 100%; + margin-top: 0.5rem; + } +} + /* styles/book.css */ /* Стили для контейнера всей книги */ diff --git a/hooks/useBreadCrumbs.tsx b/hooks/useBreadCrumbs.tsx index 2b8fc5ad..86d3372c 100644 --- a/hooks/useBreadCrumbs.tsx +++ b/hooks/useBreadCrumbs.tsx @@ -52,10 +52,10 @@ export default function useBreadCrumbs(insideBreadCrumb: breadCrumbType[], curre }, [pathname]); return ( -
+
{breadCrumb?.map((crumb: breadCrumbType, index) => (
-
+
{index < breadCrumb.length - 1 ? ( {crumb.title} @@ -64,7 +64,7 @@ export default function useBreadCrumbs(insideBreadCrumb: breadCrumbType[], curre {crumb.title} )}
- {index < breadCrumb.length - 1 && / } + {index < breadCrumb.length - 1 && / }
))}
From 1576e8ca0aabb130b841b4f119ca888dd1998248 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Wed, 27 Aug 2025 22:44:08 +0600 Subject: [PATCH 121/138] =?UTF-8?q?=D0=BD=D0=B5=D0=BA=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D1=8B=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=B4=D0=B5=D0=BF=D0=BB?= =?UTF-8?q?=D0=BE=D1=8F,=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=B4=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D0=B9=D0=BD=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 ++++ .idea/codeStyles/Project.xml | 48 ++++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 ++ .idea/deployment.xml | 14 ++++++ .idea/inspectionProfiles/Project_Default.xml | 6 +++ .idea/modules.xml | 8 ++++ .idea/prettier.xml | 6 +++ .idea/sakai-react.iml | 12 +++++ .idea/vcs.xml | 6 +++ .idea/webServers.xml | 14 ++++++ app/(main)/course/page.tsx | 25 +++++++--- app/components/HomeClient.tsx | 2 +- app/components/PDFBook.tsx | 2 +- app/components/SessionManager.tsx | 4 +- app/components/VideoPlay.tsx | 2 +- app/components/lessons/LessonTyping.tsx | 1 + app/components/tables/StreamList.tsx | 4 +- app/globals.css | 25 ++++++++++ layout/AppFooter.tsx | 2 +- layout/AppTopbar.tsx | 31 +++---------- next.config.js | 4 +- package.json | 1 + services/auth.tsx | 6 ++- services/courses.tsx | 2 +- services/query-tests.http | 36 +++++++-------- 25 files changed, 212 insertions(+), 62 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/deployment.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/prettier.xml create mode 100644 .idea/sakai-react.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/webServers.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..75d97586 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 00000000..3bc60ed5 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..03d9549e --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..9d3a0203 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 00000000..b0c1c68f --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/sakai-react.iml b/.idea/sakai-react.iml new file mode 100644 index 00000000..24643cc3 --- /dev/null +++ b/.idea/sakai-react.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 00000000..083d91ec --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 71041d71..7996d588 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -420,7 +420,7 @@ export default function Course() { ); }; - const imagestateStyle = imageState ? 'flex gap-1 items-center justify-between' : ''; + const imagestateStyle = imageState ? 'flex gap-1 items-center justify-between flex-col sm:flex-row' : ''; const imageTitle = useShortText(typeof editingLesson.image === 'string' ? editingLesson.image : '', 30); return ( @@ -429,10 +429,14 @@ export default function Course() {
- {imagestateStyle &&
{typeof imageState === 'string' && }
} -
+ {imagestateStyle && ( +
+ {typeof imageState === 'string' && } +
+ )} +
- + {courseValue.image || editingLesson.image ? (
{typeof editingLesson.image === 'string' && ( @@ -504,7 +508,7 @@ export default function Course() { disabled={progressSpinner === true ? true : false} rows={5} cols={30} - className='w-[300px]' + className="w-[300px]" onChange={(e) => { editMode ? setEditingLesson((prev) => ({ @@ -576,12 +580,19 @@ export default function Course() { />
+ handlePageChange(e.page + 1)} + template={media ? 'FirstPageLink PrevPageLink NextPageLink LastPageLink' : 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink'} + /> )} @@ -691,7 +702,7 @@ export default function Course() {
{/* STREAMS SECTION */}
- {}} /> + {}} />
)} diff --git a/app/components/HomeClient.tsx b/app/components/HomeClient.tsx index 43ccccc4..0eab5958 100644 --- a/app/components/HomeClient.tsx +++ b/app/components/HomeClient.tsx @@ -18,7 +18,7 @@ export default function HomeClient() { return (
- {"Уроки"} + {/* {"Уроки"} */}
diff --git a/app/components/PDFBook.tsx b/app/components/PDFBook.tsx index abbab375..f1f80ce9 100644 --- a/app/components/PDFBook.tsx +++ b/app/components/PDFBook.tsx @@ -32,7 +32,7 @@ export default function PDFViewer({ url }: { url: string }) { try { // Проверяем, одна ли страница в документе - const newUrl = `http://api.mooc.oshsu.kg/temprory-file/${url}`; + const newUrl = `https://api.mooc.oshsu.kg/temprory-file/${url}`; const pdf = await pdfjsLib.getDocument(newUrl).promise; const tempPages = []; const firstPage = await pdf.getPage(1); diff --git a/app/components/SessionManager.tsx b/app/components/SessionManager.tsx index 8de43d5f..91eb9ead 100644 --- a/app/components/SessionManager.tsx +++ b/app/components/SessionManager.tsx @@ -76,8 +76,8 @@ const SessionManager = () => { if (!token && pathname !== '/' && pathname !== '/auth/login') { console.log('Перенеправляю в login'); - // logout({ setUser, setGlobalLoading }); - // window.location.href = '/auth/login'; + logout({ setUser, setGlobalLoading }); + window.location.href = '/auth/login'; return; } setTimeout(() => { diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx index 0b3f6094..e38163d8 100644 --- a/app/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -43,7 +43,7 @@ export default function VideoPlay() {
- Логотип ОшГУ + Логотип ОшГУ
) diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 6eb7465c..2a67e46f 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -226,6 +226,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp
)} - {!hasStreams ? ( + {hasStreams ? ( ) : (
@@ -334,7 +334,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis ) : ( <> - + )}
diff --git a/app/globals.css b/app/globals.css index 2e1512d1..2e9dec58 100644 --- a/app/globals.css +++ b/app/globals.css @@ -478,6 +478,17 @@ h1, h2, h3, h4, h5, h6 { .p-confirm-dialog .p-button { width: 100%; margin-top: 0.5rem; + padding: 4px 5px !important; + } +} + +@media (max-width: 480px) { + + .p-button-label { + font-size: 14px !important; + } + .p-button-icon{ + width: 14px !important; } } @@ -536,4 +547,18 @@ h1, h2, h3, h4, h5, h6 { border-radius: 12px; padding: 4px 12px; box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.02), 0px 0px 2px rgba(0, 0, 0, 0.05), 0px 1px 4px rgba(0, 0, 0, 0.08); +} + +.p-paginator .p-paginator-first, .p-paginator .p-paginator-prev, .p-paginator .p-paginator-next, .p-paginator .p-paginator-last{ + min-width: 2rem !important; +} + +/* file upload */ +@media screen and (max-width: 640px) { + .p-button-label .p-clickable{ + font-size: 14px !important; + } + .p-fileupload-choose{ + padding: 4px 5px; + } } \ No newline at end of file diff --git a/layout/AppFooter.tsx b/layout/AppFooter.tsx index a6730783..84a2679b 100644 --- a/layout/AppFooter.tsx +++ b/layout/AppFooter.tsx @@ -18,7 +18,7 @@ const AppFooter = () => {
- Логотип + Логотип
Кыргызстан, 723500, г. Ош, ул. Ленина, 331, ОшГУ Главный корпус Общий отдел: +996 3222 7-07-12, diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index 5f8beecf..04bb88ae 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -8,7 +8,7 @@ import { classNames } from 'primereact/utils'; import { AppTopbarRef } from '@/types'; import { LayoutContext } from './context/layoutcontext'; import { useMediaQuery } from '@/hooks/useMediaQuery'; -import { usePathname } from 'next/navigation'; +import { usePathname, useRouter } from 'next/navigation'; import { logout } from '@/utils/logout'; const AppTopbar = forwardRef((props, ref) => { @@ -28,29 +28,7 @@ const AppTopbar = forwardRef((props, ref) => { const pathName = usePathname(); const media = useMediaQuery('(max-width: 1000px)'); - const items = [ - { - label: 'Ачык онлайн курстар', - icon: 'pi pi-file', - items: [], - url: '/login' - }, - { - label: 'Бакалавриат', - icon: 'pi pi-file', - items: [] - }, - { - label: 'Магистратура', - icon: 'pi pi-file', - items: [] - }, - { - label: 'Кошумча билим берүү', - icon: 'pi pi-file', - items: [] - } - ]; + const router = useRouter() const mobileMenu = [ user @@ -84,7 +62,10 @@ const AppTopbar = forwardRef((props, ref) => { label: 'Кирүү', icon: 'pi pi-sign-in', items: [], - url: '/auth/login' + // url: '/auth/login' + command: ()=> { + router.push('/auth/login'); + } }, { label: 'ОшМУнун сайты', diff --git a/next.config.js b/next.config.js index 767719fc..92539f64 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,6 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { + output: 'export', +} module.exports = nextConfig diff --git a/package.json b/package.json index 9d95e74b..4057f700 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "next dev", "build": "next build", + "export": "next export", "start": "next start", "format": "prettier --write \"{app,demo,layout,types}/**/*.{js,ts,tsx,d.ts}\"", "lint": "next lint" diff --git a/services/auth.tsx b/services/auth.tsx index aec595d3..67fe48f9 100644 --- a/services/auth.tsx +++ b/services/auth.tsx @@ -11,7 +11,8 @@ let url = ''; export const login = async (value:LoginType) => { url = process.env.NEXT_PUBLIC_BASE_URL + '/login?'; - + console.log(url); + try { const res = await axiosInstance.post('/login?', value); const data = res.data; @@ -24,7 +25,8 @@ export const login = async (value:LoginType) => { export const getUser = async () => { url = process.env.NEXT_PUBLIC_BASE_URL + '/v1/user'; - + console.log(url); + try { const res = await axiosInstance.get(url); diff --git a/services/courses.tsx b/services/courses.tsx index c5be7db8..35da33e1 100644 --- a/services/courses.tsx +++ b/services/courses.tsx @@ -6,7 +6,7 @@ let url = ''; export const fetchCourses = async (page: number | null, limit: number | null) => { try { - const res = await axiosInstance.get(`/v1/teacher/courses?page=${Number(page)}&limit=${''}`); + const res = await axiosInstance.get(`/v1/teacher/courses?page=${Number(page)}&limit=${'3'}`); const data = await res.data; return data; diff --git a/services/query-tests.http b/services/query-tests.http index 8aa81c0b..94eeae42 100644 --- a/services/query-tests.http +++ b/services/query-tests.http @@ -1,24 +1,24 @@ -@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5teWVkdS5vc2hzdS5rZy9wdWJsaWMvYXBpL21vb2MvbG9naW4iLCJpYXQiOjE3NTU4NjAxNzUsImV4cCI6MTc1NTg4OTAzNSwibmJmIjoxNzU1ODYwMTc1LCJqdGkiOiJ4ZFhqRXF1UTJCUzhPM05lIiwic3ViIjoiNTAzMjciLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.JsSkS7lVmjhq_9v9sGrcPUn_neb09rKfPTY4UjyXrLg +# @token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5teWVkdS5vc2hzdS5rZy9wdWJsaWMvYXBpL21vb2MvbG9naW4iLCJpYXQiOjE3NTU4NjAxNzUsImV4cCI6MTc1NTg4OTAzNSwibmJmIjoxNzU1ODYwMTc1LCJqdGkiOiJ4ZFhqRXF1UTJCUzhPM05lIiwic3ViIjoiNTAzMjciLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.JsSkS7lVmjhq_9v9sGrcPUn_neb09rKfPTY4UjyXrLg -### +# ### -http://api.mooc.oshsu.kg/public/api/v1/open/video/types -Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5teWVkdS5vc2hzdS5rZy9wdWJsaWMvYXBpL21vb2MvbG9naW4iLCJpYXQiOjE3NTQzODYzMzAsImV4cCI6MTc1NDQxNTE5MCwibmJmIjoxNzU0Mzg2MzMwLCJqdGkiOiJjc0hhSkdqYVhsT1V1VkpPIiwic3ViIjoiNDY0NTYiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.E9dQ1RCISvf2psrA1iDf9CrYzExEKnZOgYq2XJ4cyXg -Content-Type: application/json +# http://api.mooc.oshsu.kg/public/api/v1/open/video/types +# Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5teWVkdS5vc2hzdS5rZy9wdWJsaWMvYXBpL21vb2MvbG9naW4iLCJpYXQiOjE3NTQzODYzMzAsImV4cCI6MTc1NDQxNTE5MCwibmJmIjoxNzU0Mzg2MzMwLCJqdGkiOiJjc0hhSkdqYVhsT1V1VkpPIiwic3ViIjoiNDY0NTYiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.E9dQ1RCISvf2psrA1iDf9CrYzExEKnZOgYq2XJ4cyXg +# Content-Type: application/json -### -# STREAMS GET +# ### +# # STREAMS GET -GET http://api.mooc.oshsu.kg/public/api/v1/teacher/stream?course_id=77 -Authorization: Bearer {{token}} -Content-Type: application/json +# GET http://api.mooc.oshsu.kg/public/api/v1/teacher/stream?course_id=77 +# Authorization: Bearer {{token}} +# Content-Type: application/json -### -# test -GET http://api.mooc.oshsu.kg/public/api/v1/student/course/lesson/show -Authorization: Bearer {{token}} -Content-Type: application/json +# ### +# # test +# GET http://api.mooc.oshsu.kg/public/api/v1/student/course/lesson/show +# Authorization: Bearer {{token}} +# Content-Type: application/json -{ - "lesson_id": 57 -} +# { +# "lesson_id": 57 +# } From 83152612e09626fdce63cc2500b927e9919729d1 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Wed, 27 Aug 2025 22:59:57 +0600 Subject: [PATCH 122/138] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D1=81=D0=B0=D0=BA=D0=B0=D0=B8=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(full-page)/landing/page.tsx | 557 ------------- app/(main)/blocks/page.tsx | 836 -------------------- app/(main)/documentation/index.module.css | 16 - app/(main)/documentation/page.tsx | 241 ------ app/(main)/pages/crud/page.tsx | 430 ---------- app/(main)/pages/empty/page.tsx | 16 - app/(main)/pages/timeline/page.tsx | 116 --- app/(main)/teacher/page.tsx | 393 --------- app/(main)/uikit/button/index.module.scss | 151 ---- app/(main)/uikit/button/page.tsx | 248 ------ app/(main)/uikit/charts/page.tsx | 283 ------- app/(main)/uikit/file/page.tsx | 35 - app/(main)/uikit/floatlabel/page.tsx | 215 ----- app/(main)/uikit/formlayout/page.tsx | 148 ---- app/(main)/uikit/input/page.tsx | 522 ------------ app/(main)/uikit/invalidstate/page.tsx | 186 ----- app/(main)/uikit/list/page.tsx | 192 ----- app/(main)/uikit/media/page.tsx | 109 --- app/(main)/uikit/menu/confirmation/page.tsx | 16 - app/(main)/uikit/menu/page.tsx | 584 -------------- app/(main)/uikit/menu/payment/page.tsx | 15 - app/(main)/uikit/menu/seat/page.tsx | 16 - app/(main)/uikit/message/page.tsx | 131 --- app/(main)/uikit/misc/page.tsx | 220 ------ app/(main)/uikit/overlay/page.tsx | 222 ------ app/(main)/uikit/panel/page.tsx | 233 ------ app/(main)/uikit/table/page.tsx | 464 ----------- app/(main)/uikit/tree/page.tsx | 42 - app/(main)/utilities/icons/page.tsx | 121 --- 29 files changed, 6758 deletions(-) delete mode 100644 app/(full-page)/landing/page.tsx delete mode 100644 app/(main)/blocks/page.tsx delete mode 100644 app/(main)/documentation/index.module.css delete mode 100644 app/(main)/documentation/page.tsx delete mode 100644 app/(main)/pages/crud/page.tsx delete mode 100644 app/(main)/pages/empty/page.tsx delete mode 100644 app/(main)/pages/timeline/page.tsx delete mode 100644 app/(main)/teacher/page.tsx delete mode 100644 app/(main)/uikit/button/index.module.scss delete mode 100644 app/(main)/uikit/button/page.tsx delete mode 100644 app/(main)/uikit/charts/page.tsx delete mode 100644 app/(main)/uikit/file/page.tsx delete mode 100644 app/(main)/uikit/floatlabel/page.tsx delete mode 100644 app/(main)/uikit/formlayout/page.tsx delete mode 100644 app/(main)/uikit/input/page.tsx delete mode 100644 app/(main)/uikit/invalidstate/page.tsx delete mode 100644 app/(main)/uikit/list/page.tsx delete mode 100644 app/(main)/uikit/media/page.tsx delete mode 100644 app/(main)/uikit/menu/confirmation/page.tsx delete mode 100644 app/(main)/uikit/menu/page.tsx delete mode 100644 app/(main)/uikit/menu/payment/page.tsx delete mode 100644 app/(main)/uikit/menu/seat/page.tsx delete mode 100644 app/(main)/uikit/message/page.tsx delete mode 100644 app/(main)/uikit/misc/page.tsx delete mode 100644 app/(main)/uikit/overlay/page.tsx delete mode 100644 app/(main)/uikit/panel/page.tsx delete mode 100644 app/(main)/uikit/table/page.tsx delete mode 100644 app/(main)/uikit/tree/page.tsx delete mode 100644 app/(main)/utilities/icons/page.tsx diff --git a/app/(full-page)/landing/page.tsx b/app/(full-page)/landing/page.tsx deleted file mode 100644 index 9377d188..00000000 --- a/app/(full-page)/landing/page.tsx +++ /dev/null @@ -1,557 +0,0 @@ -'use client'; -/* eslint-disable @next/next/no-img-element */ -import React, { useContext, useRef, useState } from 'react'; -import Link from 'next/link'; - -import { StyleClass } from 'primereact/styleclass'; -import { Button } from 'primereact/button'; -import { Ripple } from 'primereact/ripple'; -import { Divider } from 'primereact/divider'; -import { LayoutContext } from '../../../layout/context/layoutcontext'; -import { NodeRef } from '@/types'; -import { classNames } from 'primereact/utils'; - -const LandingPage = () => { - const [isHidden, setIsHidden] = useState(false); - const { layoutConfig } = useContext(LayoutContext); - const menuRef = useRef(null); - - const toggleMenuItemClick = () => { - setIsHidden((prevState) => !prevState); - }; - - return ( -
-
-
- - Sakai Logo - SAKAI - - - - - -
- -
-
-

- Eu sem integereget magna fermentum -

-

Sed blandit libero volutpat sed cras. Fames ac turpis egestas integer. Placerat in egestas erat...

- -
-
- Hero Image -
-
- -
-
-
-

Marvelous Features

- Placerat in egestas erat... -
- -
-
-
-
- -
-
Easy to Use
- Posuere morbi leo urna molestie. -
-
-
- -
-
-
-
- -
-
Fresh Design
- Semper risus in hendrerit. -
-
-
- -
-
-
-
- -
-
Well Documented
- Non arcu risus quis varius quam quisque. -
-
-
- -
-
-
-
- -
-
Responsive Layout
- Nulla malesuada pellentesque elit. -
-
-
- -
-
-
-
- -
-
Clean Code
- Condimentum lacinia quis vel eros. -
-
-
- -
-
-
-
- -
-
Dark Mode
- Convallis tellus id interdum velit laoreet. -
-
-
- -
-
-
-
- -
-
Ready to Use
- Mauris sit amet massa vitae. -
-
-
- -
-
-
-
- -
-
Modern Practices
- Elementum nibh tellus molestie nunc non. -
-
-
- -
-
-
-
- -
-
Privacy
- Neque egestas congue quisque. -
-
-
- -
-
-

Joséphine Miller

- Peak Interactive -

- “Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - laborum.” -

- Company logo -
-
-
-
- -
-
-

Powerful Everywhere

- Amet consectetur adipiscing elit... -
- -
-
- mockup mobile -
- -
-
- -
-

Congue Quisque Egestas

- - Lectus arcu bibendum at varius vel pharetra vel turpis nunc. Eget aliquet nibh praesent tristique magna sit amet purus gravida. Sit amet mattis vulputate enim nulla aliquet. - -
-
- -
-
-
- -
-

Celerisque Eu Ultrices

- - Adipiscing commodo elit at imperdiet dui. Viverra nibh cras pulvinar mattis nunc sed blandit libero. Suspendisse in est ante in. Mauris pharetra et ultrices neque ornare aenean euismod elementum nisi. - -
- -
- mockup -
-
-
- -
-
-

Matchless Pricing

- Amet consectetur adipiscing elit... -
- -
-
-
-

Free

- free -
- $0 - per month - -
- -
    -
  • - - Responsive Layout -
  • -
  • - - Unlimited Push Messages -
  • -
  • - - 50 Support Ticket -
  • -
  • - - Free Shipping -
  • -
-
-
- -
-
-

Startup

- startup -
- $1 - per month - -
- -
    -
  • - - Responsive Layout -
  • -
  • - - Unlimited Push Messages -
  • -
  • - - 50 Support Ticket -
  • -
  • - - Free Shipping -
  • -
-
-
- -
-
-

Enterprise

- enterprise -
- $999 - per month - -
- -
    -
  • - - Responsive Layout -
  • -
  • - - Unlimited Push Messages -
  • -
  • - - 50 Support Ticket -
  • -
  • - - Free Shipping -
  • -
-
-
-
-
- -
-
-
- ); -}; - -export default LandingPage; diff --git a/app/(main)/blocks/page.tsx b/app/(main)/blocks/page.tsx deleted file mode 100644 index ebd5a25c..00000000 --- a/app/(main)/blocks/page.tsx +++ /dev/null @@ -1,836 +0,0 @@ -'use client'; -import React, { useState } from 'react'; - -import { InputText } from 'primereact/inputtext'; -import { Chip } from 'primereact/chip'; -import { Checkbox } from 'primereact/checkbox'; -import { Button } from 'primereact/button'; -import BlockViewer from '../../../demo/components/BlockViewer'; - -const Free = () => { - const [checked, setChecked] = useState(false); - - const block1 = ` -
-
-
- Create the screens -
your visitors deserve to see
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

- -
-
-
- hero-1 -
-
- `; - - const block2 = ` -
-
- One Product, - Many Solutions -
-
Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
-
-
- - - -
Built for Developers
- Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. -
-
- - - -
End-to-End Encryption
- Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis. -
-
- - - -
Easy to Use
- Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper. -
-
- - - -
Fast & Global Support
- Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus. -
-
- - - -
Open Source
- Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. -
-
- - - -
Trusted Securitty
- Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend. -
-
-
- `; - - const block3 = ` -
-
Pricing Plans
-
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
- -
-
-
-
-
Basic
-
Plan description
-
-
- $9 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
-
-
-
-
- -
-
-
-
Premium
-
Plan description
-
-
- $29 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
  • - - Duis ultricies lacus sed -
  • -
-
-
-
-
- -
-
-
-
Enterprise
-
Plan description
-
-
- $49 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
  • - - Duis ultricies lacus sed -
  • -
  • - - Imperdiet proin -
  • -
  • - - Nisi scelerisque -
  • -
-
-
-
-
-
-
- `; - - const block4 = ` -
-
 POWERED BY DISCORD
-
Join Our Design Community
-
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
-
- `; - - const block5 = ` -
-
🔥 Hot Deals!
-
- Libero voluptatum atque exercitationem praesentium provident odit. -
- - Learn More - - - - -
- `; - - const block6 = ` -
- -
-
-
Customers
-
-
- - 332 Active Users -
-
- - 9402 Sessions -
-
- - 2.32m Avg. Duration -
-
-
-
-
-
-
- `; - - const block7 = ` -
-
-
-
-
- Orders -
152
-
-
- -
-
- 24 new - since last visit -
-
-
-
-
-
- Revenue -
$2.100
-
-
- -
-
- %52+ - since last week -
-
-
-
-
-
- Customers -
28441
-
-
- -
-
- 520 - newly registered -
-
-
-
-
-
- Comments -
152 Unread
-
-
- -
-
- 85 - responded -
-
-
- `; - - const block8 = ` -
-
-
- hyper -
Welcome Back
- Don't have an account? - Create today! -
- -
- - - - - - -
-
- setChecked(e.checked)} checked={checked} className="mr-2" /> - -
- Forgot your password? -
- -
-
-
- `; - - const block9 = ` -
-
Movie Information
-
Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.
-
    -
  • -
    Title
    -
    Heat
    -
    -
    -
  • -
  • -
    Genre
    -
    - - - -
    -
    -
    -
  • -
  • -
    Director
    -
    Michael Mann
    -
    -
    -
  • -
  • -
    Actors
    -
    Robert De Niro, Al Pacino
    -
    -
    -
  • -
  • -
    Plot
    -
    - A group of professional bank robbers start to feel the heat from police - when they unknowingly leave a clue at their latest heist.
    -
    -
    -
  • -
-
- `; - - const block10 = ` -
-
Card Title
-
Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.
-
-
- `; - - return ( - <> - -
-
-
- Create the screens -
your visitors deserve to see
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

- -
-
-
- hero-1 -
-
-
- - -
-
- One Product, - Many Solutions -
-
Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
-
-
- - - -
Built for Developers
- Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. -
-
- - - -
End-to-End Encryption
- Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis. -
-
- - - -
Easy to Use
- Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper. -
-
- - - -
Fast & Global Support
- Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus. -
-
- - - -
Open Source
- Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. -
-
- - - -
Trusted Securitty
- Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend. -
-
-
-
- - -
-
Pricing Plans
-
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
- -
-
-
-
-
Basic
-
Plan description
-
-
- $9 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
-
-
-
-
- -
-
-
-
Premium
-
Plan description
-
-
- $29 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
  • - - Duis ultricies lacus sed -
  • -
-
-
-
-
- -
-
-
-
Enterprise
-
Plan description
-
-
- $49 - per month -
-
-
    -
  • - - Arcu vitae elementum -
  • -
  • - - Dui faucibus in ornare -
  • -
  • - - Morbi tincidunt augue -
  • -
  • - - Duis ultricies lacus sed -
  • -
  • - - Imperdiet proin -
  • -
  • - - Nisi scelerisque -
  • -
-
-
-
-
-
-
-
- - -
-
-  POWERED BY DISCORD -
-
Join Our Design Community
-
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
-
-
- - -
-
🔥 Hot Deals!
-
- Libero voluptatum atque exercitationem praesentium provident odit. -
- - Learn More - - - - -
-
- - -
- -
-
-
Customers
-
-
- - 332 Active Users -
-
- - 9402 Sessions -
-
- - 2.32m Avg. Duration -
-
-
-
-
-
-
-
- - -
-
-
-
-
- Orders -
152
-
-
- -
-
- 24 new - since last visit -
-
-
-
-
-
- Revenue -
$2.100
-
-
- -
-
- %52+ - since last week -
-
-
-
-
-
- Customers -
28441
-
-
- -
-
- 520 - newly registered -
-
-
-
-
-
- Comments -
152 Unread
-
-
- -
-
- 85 - responded -
-
-
-
- - -
-
-
- hyper -
Welcome Back
- Do not have an account? - Create today! -
- -
- - - - - - -
-
- setChecked(e.checked as boolean)} checked={checked} className="mr-2" /> - -
- Forgot your password? -
- -
-
-
-
- - -
-
Movie Information
-
Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.
-
    -
  • -
    Title
    -
    Heat
    -
    -
    -
  • -
  • -
    Genre
    -
    - - - -
    -
    -
    -
  • -
  • -
    Director
    -
    Michael Mann
    -
    -
    -
  • -
  • -
    Actors
    -
    Robert De Niro, Al Pacino
    -
    -
    -
  • -
  • -
    Plot
    -
    A group of professional bank robbers start to feel the heat from police when they unknowingly leave a clue at their latest heist.
    -
    -
    -
  • -
-
-
- - -
-
Card Title
-
Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.
-
-
-
- - ); -}; - -export default Free; diff --git a/app/(main)/documentation/index.module.css b/app/(main)/documentation/index.module.css deleted file mode 100644 index acaa1030..00000000 --- a/app/(main)/documentation/index.module.css +++ /dev/null @@ -1,16 +0,0 @@ -@media screen and (max-width: 991px) { - .video-container { - position: relative; - width: 100%; - height: 0; - padding-bottom: 56.25%; - } - - .video { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } -} \ No newline at end of file diff --git a/app/(main)/documentation/page.tsx b/app/(main)/documentation/page.tsx deleted file mode 100644 index b958c674..00000000 --- a/app/(main)/documentation/page.tsx +++ /dev/null @@ -1,241 +0,0 @@ -/* eslint-disable @next/next/no-sync-scripts */ -import React from 'react'; - -const Documentation = () => { - return ( - <> -
-
-
-

Current Version

-

Next v13, React v18, Typescript with PrimeReact v10

- -
Getting Started
-

- Sakai is an application template for React based on the popular{' '} - - Next.js - {' '} - framework with new{' '} - - App Router - - . To get started, clone the{' '} - - repository - {' '} - from GitHub and install the dependencies with npm or yarn. -

-
-                            {`"npm install" or "yarn"`}
-                        
- -

- Next step is running the application using the start script and navigate to http://localhost:3000/ to view the application. That is it, you may now start with the development of your application using the Sakai - template. -

- -
-                            {`"npm run dev" or "yarn dev"`}
-                        
- -
Dependencies
-

Dependencies of Sakai are listed below and needs to be defined at package.json.

- -
-                            {`"primereact": "^9.6.2",                    //required: PrimeReact components
-"primeicons": "^6.0.1",                    //required: Icons
-"primeflex": "^3.3.0",                     //required: Utility CSS classes
-`}
-                        
- -
Structure
-

Sakai consist of a couple of folders where demos and core layout have been separated.

-

- There are two{' '} - - route groups - {' '} - under the app folder; {`(main)`} represents the pages that reside in the main dashboard layout whereas {`(full-page)`}{' '} - groups the pages with full page content such as landing page or a login page. -

-
    -
  • - layout/: Main layout files -
  • -
  • - demo/: Contains demo related utilities and helpers -
  • -
  • - app/: Demo pages -
  • -
  • - public/demo: Assets used in demos -
  • -
  • - public/layout: Assets used in layout such as a logo -
  • -
  • - styles/demo: Styles used in demos only -
  • -
  • - styles/layout: SCSS files of the core layout -
  • -
-
Route Groups
-

- Root Layout is the main of the application and it is defined at app/layout.tsx file. It contains the style imports and layout context provider. -

-
-                            
-                                {`"use client"
-import { LayoutProvider } from "./layout/context/layoutcontext";
-import { PrimeReactProvider } from "primereact/api";
-import "primereact/resources/primereact.css";
-...
-import "../styles/layout/layout.scss";
-import "../styles/demo/Demos.scss";
-
-interface RootLayoutProps {
-  children: React.ReactNode;
-}
-
-export default function RootLayout({ children }: RootLayoutProps) {
-  return (
-    
-      
-        
-      
-      
-        
-            {children}
-        
-      
-    
-  );
-}
-
-`}
-                            
-                        
-

- The pages that are using the layout elements need to be defined under the app/{'(main)'}/ folder. Those pages use the{' '} - app/{'(main)'}/layout.tsx as the root layout. -

-
-                            
-                                {`import { Metadata } from 'next';
-import Layout from "../../layout/layout";
-
-interface MainLayoutProps {
-  children: React.ReactNode;
-}
-
-export const metadata: Metadata = {
-    title: "Sakai by PrimeReact | Free Admin Template for Next.js",
-    ...
-  };
-
-export default function MainLayout({ children }: MainLayoutProps) {
-  return {children};
-}
-`}
-                            
-                        
-

- Only the pages that are using config sidebar wihout layout elements need to be defined under the app/{'(full-page)'}/ folder. Those pages use the{' '} - app/{'(full-page)'}/layout.tsx as the root layout. -

-
-                            
-                                {`import { Metadata } from 'next';
-import AppConfig from "../../layout/AppConfig";
-import React from "react";
-
-interface FullPageLayoutProps {
-  children: React.ReactNode;
-}
-
-export const metadata: Metadata = {
-    title: "Sakai by PrimeReact | Free Admin Template for Next.js",
-    ...
-  };
-
-export default function FullPageLayout({ children }: FullPageLayoutProps) {
-  return (
-    
-      {children}
-      
-    
-  );
-}
-`}
-                            
-                        
-
Default Configuration
-

- Initial layout configuration can be defined at the layout/context/layoutcontext.js file, this step is optional and only necessary when customizing the defaults. -

- -
-                            
-                                {`"use client";
-import React, { useState } from 'react';
-import Head from 'next/head';
-export const LayoutContext = React.createContext();
-
-export const LayoutProvider = (props) => {
-    const [layoutConfig, setLayoutConfig] = useState({
-        ripple: false,                          //toggles ripple on and off
-        inputStyle: 'outlined',                 //default style for input elements
-        menuMode: 'static',                     //layout mode of the menu, valid values are "static" or "overlay"
-        colorScheme: 'light',                   //color scheme of the template, valid values are "light", "dim" and "dark"
-        theme: 'lara-light-indigo',             //default component theme for PrimeReact
-        scale: 14                               //size of the body font size to scale the whole application
-    });
-}`}
-                            
-                        
- -
Menu
-

- Main menu is defined at AppMenu.js file based on{' '} - - MenuModel API - - . -

- -
PrimeReact Theme
-

- Sakai theming is based on the PrimeReact theme being used. -

- -
SASS Variables
-

- In case you'd like to customize the main layout variables, open _variables.scss file under layout folder. Saving the changes will be reflected instantly at your browser. -

- -
layout/_variables.scss
-
-                            
-                                {`
-/* General */
-$scale:14px;                    /* initial font size */ 
-$borderRadius:12px;             /* border radius of layout element e.g. card, sidebar */ 
-$transitionDuration:.2s;        /* transition duration of layout elements e.g. sidebar */ 
-`}
-                            
-                        
-
-
-
- - ); -}; - -export default Documentation; diff --git a/app/(main)/pages/crud/page.tsx b/app/(main)/pages/crud/page.tsx deleted file mode 100644 index 52cf6e5e..00000000 --- a/app/(main)/pages/crud/page.tsx +++ /dev/null @@ -1,430 +0,0 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; -import { Button } from 'primereact/button'; -import { Column } from 'primereact/column'; -import { DataTable } from 'primereact/datatable'; -import { Dialog } from 'primereact/dialog'; -import { FileUpload } from 'primereact/fileupload'; -import { InputNumber, InputNumberValueChangeEvent } from 'primereact/inputnumber'; -import { InputText } from 'primereact/inputtext'; -import { InputTextarea } from 'primereact/inputtextarea'; -import { RadioButton, RadioButtonChangeEvent } from 'primereact/radiobutton'; -import { Rating } from 'primereact/rating'; -import { Toast } from 'primereact/toast'; -import { Toolbar } from 'primereact/toolbar'; -import { classNames } from 'primereact/utils'; -import React, { useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../../../demo/service/ProductService'; -import { Demo } from '@/types'; - -/* @todo Used 'as any' for types here. Will fix in next version due to onSelectionChange event type issue. */ -const Crud = () => { - let emptyProduct: Demo.Product = { - id: '', - name: '', - image: '', - description: '', - category: '', - price: 0, - quantity: 0, - rating: 0, - inventoryStatus: 'INSTOCK' - }; - - const [products, setProducts] = useState(null); - const [productDialog, setProductDialog] = useState(false); - const [deleteProductDialog, setDeleteProductDialog] = useState(false); - const [deleteProductsDialog, setDeleteProductsDialog] = useState(false); - const [product, setProduct] = useState(emptyProduct); - const [selectedProducts, setSelectedProducts] = useState(null); - const [submitted, setSubmitted] = useState(false); - const [globalFilter, setGlobalFilter] = useState(''); - const toast = useRef(null); - const dt = useRef>(null); - - useEffect(() => { - ProductService.getProducts().then((data) => setProducts(data as any)); - }, []); - - const formatCurrency = (value: number) => { - return value.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); - }; - - const openNew = () => { - setProduct(emptyProduct); - setSubmitted(false); - setProductDialog(true); - }; - - const hideDialog = () => { - setSubmitted(false); - setProductDialog(false); - }; - - const hideDeleteProductDialog = () => { - setDeleteProductDialog(false); - }; - - const hideDeleteProductsDialog = () => { - setDeleteProductsDialog(false); - }; - - const saveProduct = () => { - setSubmitted(true); - - if (product.name.trim()) { - let _products = [...(products as any)]; - let _product = { ...product }; - if (product.id) { - const index = findIndexById(product.id); - - _products[index] = _product; - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Updated', - life: 3000 - }); - } else { - _product.id = createId(); - _product.image = 'product-placeholder.svg'; - _products.push(_product); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Created', - life: 3000 - }); - } - - setProducts(_products as any); - setProductDialog(false); - setProduct(emptyProduct); - } - }; - - const editProduct = (product: Demo.Product) => { - setProduct({ ...product }); - setProductDialog(true); - }; - - const confirmDeleteProduct = (product: Demo.Product) => { - setProduct(product); - setDeleteProductDialog(true); - }; - - const deleteProduct = () => { - let _products = (products as any)?.filter((val: any) => val.id !== product.id); - setProducts(_products); - setDeleteProductDialog(false); - setProduct(emptyProduct); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Deleted', - life: 3000 - }); - }; - - const findIndexById = (id: string) => { - let index = -1; - for (let i = 0; i < (products as any)?.length; i++) { - if ((products as any)[i].id === id) { - index = i; - break; - } - } - - return index; - }; - - const createId = () => { - let id = ''; - let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 5; i++) { - id += chars.charAt(Math.floor(Math.random() * chars.length)); - } - return id; - }; - - const exportCSV = () => { - dt.current?.exportCSV(); - }; - - const confirmDeleteSelected = () => { - setDeleteProductsDialog(true); - }; - - const deleteSelectedProducts = () => { - let _products = (products as any)?.filter((val: any) => !(selectedProducts as any)?.includes(val)); - setProducts(_products); - setDeleteProductsDialog(false); - setSelectedProducts(null); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Products Deleted', - life: 3000 - }); - }; - - const onCategoryChange = (e: RadioButtonChangeEvent) => { - let _product = { ...product }; - _product['category'] = e.value; - setProduct(_product); - }; - - const onInputChange = (e: React.ChangeEvent, name: string) => { - const val = (e.target && e.target.value) || ''; - let _product = { ...product }; - _product[`${name}`] = val; - - setProduct(_product); - }; - - const onInputNumberChange = (e: InputNumberValueChangeEvent, name: string) => { - const val = e.value || 0; - let _product = { ...product }; - _product[`${name}`] = val; - - setProduct(_product); - }; - - const leftToolbarTemplate = () => { - return ( - -
-
-
- ); - }; - - const rightToolbarTemplate = () => { - return ( - - - - - ); - }; - - const customizedMarker = (item: CustomEvent) => { - return ( - - - - ); - }; - - return ( -
-
-
-
-
Left Align
- item.status} /> -
-
-
-
-
Right Align
- item.status} /> -
-
-
-
-
Alternate Align
- item.status} /> -
-
- -
-
-
Opposite Content
- item.status} content={(item) => {item.date}} /> -
-
- -
-
-
Customized
- -
-
-
-
-
Horizontal
-
Top Align
- item} /> - -
Bottom Align
- item} /> - -
Alternate Align
- item} opposite={ } /> -
-
-
-
- ); -}; - -export default TimelineDemo; diff --git a/app/(main)/teacher/page.tsx b/app/(main)/teacher/page.tsx deleted file mode 100644 index a06710d5..00000000 --- a/app/(main)/teacher/page.tsx +++ /dev/null @@ -1,393 +0,0 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; -import { Button } from 'primereact/button'; -import { Chart } from 'primereact/chart'; -import { Column } from 'primereact/column'; -import { DataTable } from 'primereact/datatable'; -import { Menu } from 'primereact/menu'; -import React, { useContext, useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../../demo/service/ProductService'; -import { LayoutContext } from '../../../layout/context/layoutcontext'; -import Link from 'next/link'; -import { Demo } from '@/types'; -import { ChartData, ChartOptions } from 'chart.js'; - -const lineData: ChartData = { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [ - { - label: 'First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - fill: false, - backgroundColor: '#2f4860', - borderColor: '#2f4860', - tension: 0.4 - }, - { - label: 'Second Dataset', - data: [28, 48, 40, 19, 86, 27, 90], - fill: false, - backgroundColor: '#00bb7e', - borderColor: '#00bb7e', - tension: 0.4 - } - ] -}; - -const Dashboard = () => { - const [products, setProducts] = useState([]); - const menu1 = useRef(null); - const menu2 = useRef(null); - const [lineOptions, setLineOptions] = useState({}); - const { layoutConfig } = useContext(LayoutContext); - - const applyLightTheme = () => { - const lineOptions: ChartOptions = { - plugins: { - legend: { - labels: { - color: '#495057' - } - } - }, - scales: { - x: { - ticks: { - color: '#495057' - }, - grid: { - color: '#ebedef' - } - }, - y: { - ticks: { - color: '#495057' - }, - grid: { - color: '#ebedef' - } - } - } - }; - - setLineOptions(lineOptions); - }; - - const applyDarkTheme = () => { - const lineOptions = { - plugins: { - legend: { - labels: { - color: '#ebedef' - } - } - }, - scales: { - x: { - ticks: { - color: '#ebedef' - }, - grid: { - color: 'rgba(160, 167, 181, .3)' - } - }, - y: { - ticks: { - color: '#ebedef' - }, - grid: { - color: 'rgba(160, 167, 181, .3)' - } - } - } - }; - - setLineOptions(lineOptions); - }; - - useEffect(() => { - ProductService.getProductsSmall().then((data) => setProducts(data)); - }, []); - - useEffect(() => { - if (layoutConfig.colorScheme === 'light') { - applyLightTheme(); - } else { - applyDarkTheme(); - } - }, [layoutConfig.colorScheme]); - - const formatCurrency = (value: number) => { - return value?.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); - }; - - return ( -
-
-
-
-
- Orders -
152
-
-
- -
-
- 24 new - since last visit -
-
-
-
-
-
- Revenue -
$2.100
-
-
- -
-
- %52+ - since last week -
-
-
-
-
-
- Customers -
28441
-
-
- -
-
- 520 - newly registered -
-
-
-
-
-
- Comments -
152 Unread
-
-
- -
-
- 85 - responded -
-
- -
-
-
Recent Sales
- - {data.image}} /> - - formatCurrency(data.price)} /> - ( - <> -
-
-
-
Best Selling Products
-
-
-
-
    -
  • -
    - Space T-Shirt -
    Clothing
    -
    -
    -
    -
    -
    - %50 -
    -
  • -
  • -
    - Portal Sticker -
    Accessories
    -
    -
    -
    -
    -
    - %16 -
    -
  • -
  • -
    - Supernova Sticker -
    Accessories
    -
    -
    -
    -
    -
    - %67 -
    -
  • -
  • -
    - Wonders Notebook -
    Office
    -
    -
    -
    -
    -
    - %35 -
    -
  • -
  • -
    - Mat Black Case -
    Accessories
    -
    -
    -
    -
    -
    - %75 -
    -
  • -
  • -
    - Robots T-Shirt -
    Clothing
    -
    -
    -
    -
    -
    - %40 -
    -
  • -
-
-
- -
-
-
Sales Overview
- -
- -
-
-
Notifications
-
-
-
- - TODAY -
    -
  • -
    - -
    - - Richard Jones - - {' '} - has purchased a blue t-shirt for 79$ - - -
  • -
  • -
    - -
    - - Your request for withdrawal of 2500$ has been initiated. - -
  • -
- - YESTERDAY -
    -
  • -
    - -
    - - Keyser Wick - - {' '} - has purchased a black jacket for 59$ - - -
  • -
  • -
    - -
    - - Jane Davis - has posted a new questions about your product. - -
  • -
-
-
-
-
TAKE THE NEXT STEP
-
Try PrimeBlocks
-
-
- - Get Started - -
-
-
-
- ); -}; - -export default Dashboard; diff --git a/app/(main)/uikit/button/index.module.scss b/app/(main)/uikit/button/index.module.scss deleted file mode 100644 index 2ee14829..00000000 --- a/app/(main)/uikit/button/index.module.scss +++ /dev/null @@ -1,151 +0,0 @@ -.p-button{ - padding: 0%; -&.google { - background: linear-gradient(to left, var(--purple-600) 50%, var(--purple-700) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - border-color: var(--purple-700); - display: flex; - align-items: stretch; - padding: 0; - - - &:enabled:hover { - background: linear-gradient(to left, var(--purple-600) 50%, var(--purple-700) 50%); - background-size: 200% 100%; - background-position: left bottom; - border-color: var(--purple-700); - } - - &:focus { - box-shadow: 0 0 0 1px var(--purple-400); - } -} - -&.twitter { - background: linear-gradient(to left, var(--blue-400) 50%, var(--blue-500) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - border-color: var(--blue-500); - padding: 0; - display: flex; - align-items: stretch; - - &:enabled:hover { - background: linear-gradient(to left, var(--blue-400) 50%, var(--blue-500) 50%); - background-size: 200% 100%; - background-position: left bottom; - border-color: var(--blue-500); - } - - &:focus { - box-shadow: 0 0 0 1px var(--blue-200); - } -} - -&.discord { - background: linear-gradient(to left, var(--bluegray-700) 50%, var(--bluegray-800) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - border-color: var(--bluegray-800); - padding: 0; - display: flex; - align-items: stretch; - - &:enabled:hover { - background: linear-gradient(to left, var(--bluegray-700) 50%, var(--bluegray-800) 50%); - background-size: 200% 100%; - background-position: left bottom; - border-color: var(--bluegray-800); - } - - &:focus { - box-shadow: 0 0 0 1px var(--purple-500); - } -} - -.template-button .p-button.twitter { - background: linear-gradient(to left, var(--blue-400) 50%, var(--blue-500) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - color: #fff; - border-color: var(--blue-500); -} -.template-button .p-button.twitter:hover { - background-position: left bottom; -} -.template-button .p-button.twitter i { - background-color: var(--blue-500); -} -.template-button .p-button.twitter:focus { - box-shadow: 0 0 0 1px var(--blue-200); -} -.template-button .p-button.slack { - background: linear-gradient(to left, var(--orange-400) 50%, var(--orange-500) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - color: #fff; - border-color: var(--orange-500); -} -.template-button .p-button.slack:hover { - background-position: left bottom; -} -.template-button .p-button.slack i { - background-color: var(--orange-500); -} -.template-button .p-button.slack:focus { - box-shadow: 0 0 0 1px var(--orange-200); -} -.template-button .p-button.amazon { - background: linear-gradient(to left, var(--yellow-400) 50%, var(--yellow-500) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - color: #000; - border-color: var(--yellow-500); -} -.template-button .p-button.amazon:hover { - background-position: left bottom; -} -.template-button .p-button.amazon i { - background-color: var(--yellow-500); -} -.template-button .p-button.amazon:focus { - box-shadow: 0 0 0 1px var(--yellow-200); -} -.template-button .p-button.discord { - background: linear-gradient(to left, var(--bluegray-700) 50%, var(--bluegray-800) 50%); - background-size: 200% 100%; - background-position: right bottom; - transition: background-position 0.5s ease-out; - color: #fff; - border-color: var(--bluegray-800); -} -.template-button .p-button.discord:hover { - background-position: left bottom; -} -.template-button .p-button.discord i { - background-color: var(--bluegray-800); -} -.template-button .p-button.discord:focus { - box-shadow: 0 0 0 1px var(--bluegray-500); -} -@media screen and (max-width: 960px) { - -button .p-button { - margin-bottom: 0.5rem; - } - -button .p-button:not(.p-button-icon-only) { - display: flex; - flex-wrap: wrap; - - } - -button .p-buttonset .p-button { - margin-bottom: 0; - } -} -} \ No newline at end of file diff --git a/app/(main)/uikit/button/page.tsx b/app/(main)/uikit/button/page.tsx deleted file mode 100644 index 69196ed2..00000000 --- a/app/(main)/uikit/button/page.tsx +++ /dev/null @@ -1,248 +0,0 @@ -'use client'; -import React, { useState } from 'react'; -import { SplitButton } from 'primereact/splitbutton'; -import { Button } from 'primereact/button'; -import styles from './index.module.scss'; -import { classNames } from 'primereact/utils'; - -const ButtonDemo = () => { - const [loading1, setLoading1] = useState(false); - const [loading2, setLoading2] = useState(false); - const [loading3, setLoading3] = useState(false); - const [loading4, setLoading4] = useState(false); - - const onLoadingClick1 = () => { - setLoading1(true); - - setTimeout(() => { - setLoading1(false); - }, 2000); - }; - - const onLoadingClick2 = () => { - setLoading2(true); - - setTimeout(() => { - setLoading2(false); - }, 2000); - }; - - const onLoadingClick3 = () => { - setLoading3(true); - - setTimeout(() => { - setLoading3(false); - }, 2000); - }; - - const onLoadingClick4 = () => { - setLoading4(true); - - setTimeout(() => { - setLoading4(false); - }, 2000); - }; - - const items = [ - { - label: 'Update', - icon: 'pi pi-refresh' - }, - { - label: 'Delete', - icon: 'pi pi-times' - }, - { - label: 'Home', - icon: 'pi pi-home' - } - ]; - - return ( -
-
-
-
Default
-
- - - -
-
- -
-
Severities
-
-
-
- -
-
Text
-
-
-
- -
-
Outlined
-
-
-
- -
-
Button Group
- -
- -
-
SplitButton
-
- - - - - -
-
- -
-
Template
-
- - - -
-
-
- -
-
-
Icons
-
- - - -
-
- -
-
Raised
-
-
-
- -
-
Rounded
-
-
-
- -
-
Rounded Icons
-
-
-
- -
-
Rounded Text
-
-
-
- -
-
Rounded Outlined
-
-
-
- -
-
Loading
-
-
-
-
-
- ); -}; - -export default ButtonDemo; diff --git a/app/(main)/uikit/charts/page.tsx b/app/(main)/uikit/charts/page.tsx deleted file mode 100644 index 7ccc85af..00000000 --- a/app/(main)/uikit/charts/page.tsx +++ /dev/null @@ -1,283 +0,0 @@ -'use client'; -import { ChartData, ChartOptions } from 'chart.js'; -import { Chart } from 'primereact/chart'; -import React, { useContext, useEffect, useState } from 'react'; -import { LayoutContext } from '../../../../layout/context/layoutcontext'; -import type { ChartDataState, ChartOptionsState } from '@/types'; - -const ChartDemo = () => { - const [options, setOptions] = useState({}); - const [data, setChartData] = useState({}); - const { layoutConfig } = useContext(LayoutContext); - - useEffect(() => { - const documentStyle = getComputedStyle(document.documentElement); - const textColor = documentStyle.getPropertyValue('--text-color') || '#495057'; - const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary') || '#6c757d'; - const surfaceBorder = documentStyle.getPropertyValue('--surface-border') || '#dfe7ef'; - const barData: ChartData = { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [ - { - label: 'My First dataset', - backgroundColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - borderColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - data: [65, 59, 80, 81, 56, 55, 40] - }, - { - label: 'My Second dataset', - backgroundColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - borderColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - data: [28, 48, 40, 19, 86, 27, 90] - } - ] - }; - - const barOptions: ChartOptions = { - plugins: { - legend: { - labels: { - color: textColor - } - } - }, - scales: { - x: { - ticks: { - color: textColorSecondary, - font: { - weight: '500' - } - }, - grid: { - display: false - }, - border: { - display: false - } - }, - y: { - ticks: { - color: textColorSecondary - }, - grid: { - color: surfaceBorder - }, - border: { - display: false - } - } - } - }; - - const pieData: ChartData = { - labels: ['A', 'B', 'C'], - datasets: [ - { - data: [540, 325, 702], - backgroundColor: [documentStyle.getPropertyValue('--indigo-500') || '#6366f1', documentStyle.getPropertyValue('--purple-500') || '#a855f7', documentStyle.getPropertyValue('--teal-500') || '#14b8a6'], - hoverBackgroundColor: [documentStyle.getPropertyValue('--indigo-400') || '#8183f4', documentStyle.getPropertyValue('--purple-400') || '#b975f9', documentStyle.getPropertyValue('--teal-400') || '#41c5b7'] - } - ] - }; - - const pieOptions: ChartOptions = { - plugins: { - legend: { - labels: { - usePointStyle: true, - color: textColor - } - } - } - }; - - const lineData: ChartData = { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [ - { - label: 'First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - fill: false, - backgroundColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - borderColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - tension: 0.4 - }, - { - label: 'Second Dataset', - data: [28, 48, 40, 19, 86, 27, 90], - fill: false, - backgroundColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - borderColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - tension: 0.4 - } - ] - }; - - const lineOptions: ChartOptions = { - plugins: { - legend: { - labels: { - color: textColor - } - } - }, - scales: { - x: { - ticks: { - color: textColorSecondary - }, - grid: { - color: surfaceBorder - }, - border: { - display: false - } - }, - y: { - ticks: { - color: textColorSecondary - }, - grid: { - color: surfaceBorder - }, - border: { - display: false - } - } - } - }; - - const polarData: ChartData = { - datasets: [ - { - data: [11, 16, 7, 3], - backgroundColor: [ - documentStyle.getPropertyValue('--indigo-500') || '#6366f1', - documentStyle.getPropertyValue('--purple-500') || '#a855f7', - documentStyle.getPropertyValue('--teal-500') || '#14b8a6', - documentStyle.getPropertyValue('--orange-500') || '#f97316' - ], - label: 'My dataset' - } - ], - labels: ['Indigo', 'Purple', 'Teal', 'Orange'] - }; - - const polarOptions: ChartOptions = { - plugins: { - legend: { - labels: { - color: textColor - } - } - }, - scales: { - r: { - grid: { - color: surfaceBorder - } - } - } - }; - - const radarData: ChartData = { - labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'], - datasets: [ - { - label: 'My First dataset', - borderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - pointBackgroundColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - pointBorderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - pointHoverBackgroundColor: textColor, - pointHoverBorderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - data: [65, 59, 90, 81, 56, 55, 40] - }, - { - label: 'My Second dataset', - borderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - pointBackgroundColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - pointBorderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - pointHoverBackgroundColor: textColor, - pointHoverBorderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - data: [28, 48, 40, 19, 96, 27, 100] - } - ] - }; - - const radarOptions: ChartOptions = { - plugins: { - legend: { - labels: { - color: textColor - } - } - }, - scales: { - r: { - grid: { - color: textColorSecondary - } - } - } - }; - - setOptions({ - barOptions, - pieOptions, - lineOptions, - polarOptions, - radarOptions - }); - setChartData({ - barData, - pieData, - lineData, - polarData, - radarData - }); - }, [layoutConfig]); - - return ( -
-
-
-
Linear Chart
- -
-
-
-
-
Bar Chart
- -
-
-
-
-
Pie Chart
- -
-
-
-
-
Doughnut Chart
- -
-
-
-
-
Polar Area Chart
- -
-
-
-
-
Radar Chart
- -
-
-
- ); -}; - -export default ChartDemo; diff --git a/app/(main)/uikit/file/page.tsx b/app/(main)/uikit/file/page.tsx deleted file mode 100644 index 9dd41f9b..00000000 --- a/app/(main)/uikit/file/page.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; - -import React, { useRef } from 'react'; -import { FileUpload } from 'primereact/fileupload'; -import { Toast } from 'primereact/toast'; - -const FileDemo = () => { - const toast = useRef(null); - - const onUpload = () => { - toast.current?.show({ - severity: 'info', - summary: 'Success', - detail: 'File Uploaded', - life: 3000 - }); - }; - - return ( -
- -
-
-
Advanced
- - -
Basic
- -
-
-
- ); -}; - -export default FileDemo; diff --git a/app/(main)/uikit/floatlabel/page.tsx b/app/(main)/uikit/floatlabel/page.tsx deleted file mode 100644 index 1dec3af6..00000000 --- a/app/(main)/uikit/floatlabel/page.tsx +++ /dev/null @@ -1,215 +0,0 @@ -"use client"; -import type { Demo } from "@/types"; -import { - AutoComplete, - AutoCompleteCompleteEvent, -} from "primereact/autocomplete"; -import { Calendar } from "primereact/calendar"; -import { Chips } from "primereact/chips"; -import { Dropdown } from "primereact/dropdown"; -import { InputMask } from "primereact/inputmask"; -import { InputNumber } from "primereact/inputnumber"; -import { InputText } from "primereact/inputtext"; -import { InputTextarea } from "primereact/inputtextarea"; -import { MultiSelect } from "primereact/multiselect"; -import { useEffect, useState } from "react"; -import { CountryService } from "../../../../demo/service/CountryService"; - -const FloatLabelDemo = () => { - const [countries, setCountries] = useState([]); - const [filteredCountries, setFilteredCountries] = useState( - [] - ); - const [value1, setValue1] = useState(""); - const [value2, setValue2] = useState(null); - const [value3, setValue3] = useState(""); - const [value4, setValue4] = useState(""); - const [value5, setValue5] = useState(null); - const [value6, setValue6] = useState([]); - const [value7, setValue7] = useState(""); - const [value8, setValue8] = useState(null); - const [value9, setValue9] = useState(""); - const [value10, setValue10] = useState(null); - const [value11, setValue11] = useState(null); - const [value12, setValue12] = useState(""); - - const cities = [ - { name: "New York", code: "NY" }, - { name: "Rome", code: "RM" }, - { name: "London", code: "LDN" }, - { name: "Istanbul", code: "IST" }, - { name: "Paris", code: "PRS" }, - ]; - - useEffect(() => { - CountryService.getCountries().then((countries) => { - setCountries(countries); - }); - }, []); - - const searchCountry = (event: AutoCompleteCompleteEvent) => { - const filtered = []; - const query = event.query; - for (let i = 0; i < countries.length; i++) { - const country = countries[i]; - if (country.name.toLowerCase().indexOf(query.toLowerCase()) === 0) { - filtered.push(country); - } - } - setFilteredCountries(filtered); - }; - - return ( -
-
Float Label
-

- All input text components support floating labels by adding ( - .p-float-label) to wrapper class. -

-
-
- - setValue1(e.target.value)} - /> - - -
-
- - setValue2(e.value)} - // suggestions={filteredCountries} - completeMethod={searchCountry} - field="name" - > - - -
-
- - - setValue3(e.target.value)} - /> - - -
-
- - - setValue4(e.target.value)} - /> - - -
-
- - setValue5(e.value ?? "")} - > - - -
-
- - setValue6(e.value ?? [])} - > - - -
-
- - setValue7(e.value ?? "")} - > - - -
-
- - - setValue8(e.target.value ?? null) - } - > - - -
-
-
- - - - - setValue9(e.target.value)} - /> - - -
-
-
- - setValue10(e.value)} - optionLabel="name" - > - - -
-
- - setValue11(e.value)} - optionLabel="name" - > - - -
-
- - setValue12(e.target.value)} - > - - -
-
-
- ); -}; - -export default FloatLabelDemo; diff --git a/app/(main)/uikit/formlayout/page.tsx b/app/(main)/uikit/formlayout/page.tsx deleted file mode 100644 index 01e98052..00000000 --- a/app/(main)/uikit/formlayout/page.tsx +++ /dev/null @@ -1,148 +0,0 @@ -'use client'; - -import React, { useState, useEffect, useMemo } from 'react'; -import { InputText } from 'primereact/inputtext'; -import { Button } from 'primereact/button'; -import { InputTextarea } from 'primereact/inputtextarea'; -import { Dropdown } from 'primereact/dropdown'; - -interface DropdownItem { - name: string; - code: string; -} - -const FormLayoutDemo = () => { - const [dropdownItem, setDropdownItem] = useState(null); - const dropdownItems: DropdownItem[] = useMemo( - () => [ - { name: 'Option 1', code: 'Option 1' }, - { name: 'Option 2', code: 'Option 2' }, - { name: 'Option 3', code: 'Option 3' } - ], - [] - ); - - useEffect(() => { - setDropdownItem(dropdownItems[0]); - }, [dropdownItems]); - - return ( -
-
-
-
Vertical
-
- - -
-
- - -
-
- - -
-
- -
-
Vertical Grid
-
-
- - -
-
- - -
-
-
-
- -
-
-
Horizontal
-
- -
- -
-
-
- -
- -
-
-
- -
-
Inline
-
-
- - -
-
- - -
- -
-
- -
-
Help Text
-
- - - Enter your username to reset your password. -
-
-
- -
-
-
Advanced
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - setDropdownItem(e.value)} options={dropdownItems} optionLabel="name" placeholder="Select One"> -
-
- - -
-
-
-
-
- ); -}; - -export default FormLayoutDemo; diff --git a/app/(main)/uikit/input/page.tsx b/app/(main)/uikit/input/page.tsx deleted file mode 100644 index dd0c4688..00000000 --- a/app/(main)/uikit/input/page.tsx +++ /dev/null @@ -1,522 +0,0 @@ -"use client"; -import type { Demo, Page } from "@/types"; -import { - AutoComplete, - AutoCompleteCompleteEvent, -} from "primereact/autocomplete"; -import { Button } from "primereact/button"; -import { Calendar } from "primereact/calendar"; -import { Checkbox, CheckboxChangeEvent } from "primereact/checkbox"; -import { Chips } from "primereact/chips"; -import { - ColorPicker, - ColorPickerHSBType, - ColorPickerRGBType, -} from "primereact/colorpicker"; -import { Dropdown } from "primereact/dropdown"; -import { InputNumber } from "primereact/inputnumber"; -import { InputSwitch } from "primereact/inputswitch"; -import { InputText } from "primereact/inputtext"; -import { InputTextarea } from "primereact/inputtextarea"; -import { Knob } from "primereact/knob"; -import { ListBox } from "primereact/listbox"; -import { MultiSelect } from "primereact/multiselect"; -import { RadioButton } from "primereact/radiobutton"; -import { Rating } from "primereact/rating"; -import { SelectButton } from "primereact/selectbutton"; -import { Slider } from "primereact/slider"; -import { ToggleButton } from "primereact/togglebutton"; -import { useEffect, useState } from "react"; -import { CountryService } from "../../../../demo/service/CountryService"; - -interface InputValue { - name: string; - code: string; -} - -const InputDemo: Page = () => { - const [floatValue, setFloatValue] = useState(""); - const [autoValue, setAutoValue] = useState([]); - const [selectedAutoValue, setSelectedAutoValue] = useState(null); - const [autoFilteredValue, setAutoFilteredValue] = useState( - [] - ); - const [calendarValue, setCalendarValue] = useState(null); - const [inputNumberValue, setInputNumberValue] = useState( - null - ); - const [chipsValue, setChipsValue] = useState([]); - const [sliderValue, setSliderValue] = useState(""); - const [ratingValue, setRatingValue] = useState(null); - const [colorValue, setColorValue] = useState< - string | ColorPickerRGBType | ColorPickerHSBType - >("1976D2"); - const [knobValue, setKnobValue] = useState(20); - const [radioValue, setRadioValue] = useState(null); - const [checkboxValue, setCheckboxValue] = useState([]); - const [switchValue, setSwitchValue] = useState(false); - const [listboxValue, setListboxValue] = useState(null); - const [dropdownValue, setDropdownValue] = useState(null); - const [multiselectValue, setMultiselectValue] = useState(null); - const [toggleValue, setToggleValue] = useState(false); - const [selectButtonValue1, setSelectButtonValue1] = useState(null); - const [selectButtonValue2, setSelectButtonValue2] = useState(null); - const [inputGroupValue, setInputGroupValue] = useState(false); - - const listboxValues: InputValue[] = [ - { name: "New York", code: "NY" }, - { name: "Rome", code: "RM" }, - { name: "London", code: "LDN" }, - { name: "Istanbul", code: "IST" }, - { name: "Paris", code: "PRS" }, - ]; - - const dropdownValues: InputValue[] = [ - { name: "New York", code: "NY" }, - { name: "Rome", code: "RM" }, - { name: "London", code: "LDN" }, - { name: "Istanbul", code: "IST" }, - { name: "Paris", code: "PRS" }, - ]; - - const multiselectValues: InputValue[] = [ - { name: "Australia", code: "AU" }, - { name: "Brazil", code: "BR" }, - { name: "China", code: "CN" }, - { name: "Egypt", code: "EG" }, - { name: "France", code: "FR" }, - { name: "Germany", code: "DE" }, - { name: "India", code: "IN" }, - { name: "Japan", code: "JP" }, - { name: "Spain", code: "ES" }, - { name: "United States", code: "US" }, - ]; - - const selectButtonValues1: InputValue[] = [ - { name: "Option 1", code: "O1" }, - { name: "Option 2", code: "O2" }, - { name: "Option 3", code: "O3" }, - ]; - - const selectButtonValues2: InputValue[] = [ - { name: "Option 1", code: "O1" }, - { name: "Option 2", code: "O2" }, - { name: "Option 3", code: "O3" }, - ]; - - useEffect(() => { - CountryService.getCountries().then((data) => setAutoValue(data)); - }, []); - - const searchCountry = (event: AutoCompleteCompleteEvent) => { - setTimeout(() => { - if (!event.query.trim().length) { - setAutoFilteredValue([...autoValue]); - } else { - setAutoFilteredValue( - autoValue.filter((country) => { - return country.name - .toLowerCase() - .startsWith(event.query.toLowerCase()); - }) - ); - } - }, 250); - }; - - const onCheckboxChange = (e: CheckboxChangeEvent) => { - let selectedValue = [...checkboxValue]; - if (e.checked) selectedValue.push(e.value); - else selectedValue.splice(selectedValue.indexOf(e.value), 1); - - setCheckboxValue(selectedValue); - }; - - const itemTemplate = (option: InputValue) => { - return ( -
- {option.name} - (e.currentTarget.src = - "https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png") - } - className={`flag flag-${option.code.toLowerCase()}`} - style={{ width: "21px" }} - /> - {option.name} -
- ); - }; - - return ( -
-
-
-
InputText
-
-
- -
-
- -
-
- -
-
- -
Icons
-
-
- - - - -
-
- - - - -
-
- - - - - -
-
- -
Float Label
- - setFloatValue(e.target.value)} - /> - - - -
Textarea
- - - {/*
AutoComplete
- setSelectedAutoValue(e.value)} - suggestions={autoFilteredValue} - completeMethod={searchCountry} - field="name" - /> */} - -
Calendar
- setCalendarValue(e.value ?? null)} - /> - -
InputNumber
- - setInputNumberValue(e.value ?? null) - } - showButtons - mode="decimal" - > - -
Chips
- setChipsValue(e.value ?? [])} - /> -
- -
-
-
-
Slider
- - setSliderValue(parseInt(e.target.value, 10)) - } - /> - - setSliderValue(e.value as number) - } - /> -
-
-
Rating
- setRatingValue(e.value ?? 0)} - /> -
-
-
ColorPicker
- setColorValue(e.value ?? "")} - style={{ width: "2rem" }} - /> -
-
-
Knob
- setKnobValue(e.value)} - step={10} - min={-50} - max={50} - /> -
-
-
-
- -
-
-
RadioButton
-
-
-
- setRadioValue(e.value)} - /> - -
-
-
-
- setRadioValue(e.value)} - /> - -
-
-
-
- setRadioValue(e.value)} - /> - -
-
-
- -
Checkbox
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- -
Input Switch
- setSwitchValue(e.value ?? false)} - /> -
- -
-
Listbox
- setListboxValue(e.value)} - options={listboxValues} - optionLabel="name" - filter - /> - -
Dropdown
- setDropdownValue(e.value)} - options={dropdownValues} - optionLabel="name" - placeholder="Select" - /> - -
MultiSelect
- setMultiselectValue(e.value)} - options={multiselectValues} - itemTemplate={itemTemplate} - optionLabel="name" - placeholder="Select Countries" - filter - className="multiselect-custom" - display="chip" - /> -
- -
-
ToggleButton
- setToggleValue(e.value)} - onLabel="Yes" - offLabel="No" - /> - -
SelectButton
- setSelectButtonValue1(e.value)} - options={selectButtonValues1} - optionLabel="name" - /> - -
SelectButton - Multiple
- setSelectButtonValue2(e.value)} - options={selectButtonValues2} - optionLabel="name" - multiple - /> -
-
- -
-
-
Input Groups
-
-
-
- - - - -
-
- -
-
- - - - - - - - $ - .00 -
-
- -
-
-
-
- -
-
- - - setInputGroupValue( - e.checked ?? false - ) - } - /> - - -
-
-
-
-
-
- ); -}; - -export default InputDemo; diff --git a/app/(main)/uikit/invalidstate/page.tsx b/app/(main)/uikit/invalidstate/page.tsx deleted file mode 100644 index 43ca3188..00000000 --- a/app/(main)/uikit/invalidstate/page.tsx +++ /dev/null @@ -1,186 +0,0 @@ -"use client"; - -import type { Demo } from "@/types"; -import { - AutoComplete, - AutoCompleteCompleteEvent, -} from "primereact/autocomplete"; -import { Calendar } from "primereact/calendar"; -import { Chips } from "primereact/chips"; -import { Dropdown } from "primereact/dropdown"; -import { InputMask } from "primereact/inputmask"; -import { InputNumber } from "primereact/inputnumber"; -import { InputText } from "primereact/inputtext"; -import { InputTextarea } from "primereact/inputtextarea"; -import { MultiSelect } from "primereact/multiselect"; -import { Password } from "primereact/password"; -import { useEffect, useState } from "react"; -import { CountryService } from "../../../../demo/service/CountryService"; - -const InvalidStateDemo = () => { - const [countries, setCountries] = useState([]); - const [filteredCountries, setFilteredCountries] = useState( - [] - ); - const [value1, setValue1] = useState(""); - const [value2, setValue2] = useState(null); - const [value3, setValue3] = useState(null); - const [value4, setValue4] = useState([]); - const [value5, setValue5] = useState(""); - const [value6, setValue6] = useState(""); - const [value7, setValue7] = useState(0); - const [value8, setValue8] = useState(null); - const [value9, setValue9] = useState(null); - const [value10, setValue10] = useState(""); - - const cities = [ - { name: "New York", code: "NY" }, - { name: "Rome", code: "RM" }, - { name: "London", code: "LDN" }, - { name: "Istanbul", code: "IST" }, - { name: "Paris", code: "PRS" }, - ]; - - useEffect(() => { - CountryService.getCountries().then((countries) => { - setCountries(countries); - }); - }, []); - - const searchCountry = (event: AutoCompleteCompleteEvent) => { - // in a real application, make a request to a remote url with the query and - // return filtered results, for demo we filter at client side - const filtered = []; - const query = event.query; - for (let i = 0; i < countries.length; i++) { - const country = countries[i]; - if (country.name.toLowerCase().indexOf(query.toLowerCase()) === 0) { - filtered.push(country); - } - } - setFilteredCountries(filtered); - }; - - const onCalendarChange = (e: any) => { - setValue3(e.value!); - }; - - return ( -
-
Invalid State
-
-
-
- - setValue1(e.target.value)} - className="p-invalid" - /> -
-
- - setValue2(e.value)} - // suggestions={filteredCountries} - completeMethod={searchCountry} - field="name" - className="p-invalid" - /> -
-
- - -
-
- - setValue4(e.value ?? [])} - className="p-invalid" - /> -
-
- - setValue5(e.target.value)} - className="p-invalid" - /> -
-
- -
-
- - setValue6(e.value ?? "")} - className="p-invalid" - /> -
-
- - - setValue7(e.target.value ?? 0) - } - className="p-invalid" - /> -
-
- - setValue8(e.value)} - optionLabel="name" - className="p-invalid" - /> -
-
- - setValue9(e.value)} - optionLabel="name" - className="p-invalid" - /> -
-
- - setValue10(e.target.value)} - className="p-invalid" - /> -
-
-
-
- ); -}; - -export default InvalidStateDemo; diff --git a/app/(main)/uikit/list/page.tsx b/app/(main)/uikit/list/page.tsx deleted file mode 100644 index ca05aa44..00000000 --- a/app/(main)/uikit/list/page.tsx +++ /dev/null @@ -1,192 +0,0 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import { DataView, DataViewLayoutOptions } from 'primereact/dataview'; -import { Button } from 'primereact/button'; -import { Dropdown, DropdownChangeEvent } from 'primereact/dropdown'; -import { Rating } from 'primereact/rating'; -import { PickList } from 'primereact/picklist'; -import { OrderList } from 'primereact/orderlist'; -import { ProductService } from '../../../../demo/service/ProductService'; -import { InputText } from 'primereact/inputtext'; -import type { Demo } from '@/types'; - -const ListDemo = () => { - const listValue = [ - { name: 'San Francisco', code: 'SF' }, - { name: 'London', code: 'LDN' }, - { name: 'Paris', code: 'PRS' }, - { name: 'Istanbul', code: 'IST' }, - { name: 'Berlin', code: 'BRL' }, - { name: 'Barcelona', code: 'BRC' }, - { name: 'Rome', code: 'RM' } - ]; - - const [picklistSourceValue, setPicklistSourceValue] = useState(listValue); - const [picklistTargetValue, setPicklistTargetValue] = useState([]); - const [orderlistValue, setOrderlistValue] = useState(listValue); - const [dataViewValue, setDataViewValue] = useState([]); - const [globalFilterValue, setGlobalFilterValue] = useState(''); - const [filteredValue, setFilteredValue] = useState(null); - const [layout, setLayout] = useState<'grid' | 'list' | (string & Record)>('grid'); - const [sortKey, setSortKey] = useState(null); - const [sortOrder, setSortOrder] = useState<0 | 1 | -1 | null>(null); - const [sortField, setSortField] = useState(''); - - const sortOptions = [ - { label: 'Price High to Low', value: '!price' }, - { label: 'Price Low to High', value: 'price' } - ]; - - useEffect(() => { - ProductService.getProducts().then((data) => setDataViewValue(data)); - setGlobalFilterValue(''); - }, []); - - useEffect(() => { - ProductService.getProducts().then((data) => setDataViewValue(data)); - setGlobalFilterValue(''); - }, []); - - const onFilter = (e: React.ChangeEvent) => { - const value = e.target.value; - setGlobalFilterValue(value); - if (value.length === 0) { - setFilteredValue(null); - } else { - const filtered = dataViewValue?.filter((product) => { - const productNameLowercase = product.name.toLowerCase(); - const searchValueLowercase = value.toLowerCase(); - return productNameLowercase.includes(searchValueLowercase); - }); - - setFilteredValue(filtered); - } - }; - - const onSortChange = (event: DropdownChangeEvent) => { - const value = event.value; - - if (value.indexOf('!') === 0) { - setSortOrder(-1); - setSortField(value.substring(1, value.length)); - setSortKey(value); - } else { - setSortOrder(1); - setSortField(value); - setSortKey(value); - } - }; - - const dataViewHeader = ( -
- - - - - - setLayout(e.value)} /> -
- ); - - const dataviewListItem = (data: Demo.Product) => { - return ( -
-
- {data.name} -
-
{data.name}
-
{data.description}
- -
- - {data.category} -
-
-
- ${data.price} - - {data.inventoryStatus} -
-
-
- ); - }; - - const dataviewGridItem = (data: Demo.Product) => { - return ( -
-
-
-
- - {data.category} -
- {data.inventoryStatus} -
-
- {data.name} -
{data.name}
-
{data.description}
- -
-
- ${data.price} -
-
-
- ); - }; - - const itemTemplate = (data: Demo.Product, layout: 'grid' | 'list' | (string & Record)) => { - if (!data) { - return; - } - - if (layout === 'list') { - return dataviewListItem(data); - } else if (layout === 'grid') { - return dataviewGridItem(data); - } - }; - - return ( -
-
-
-
DataView
- -
-
- -
-
-
PickList
- {/*
{item.name}
} - onChange={(e) => { - setPicklistSourceValue(e.source); - setPicklistTargetValue(e.target); - }} - sourceStyle={{ height: '200px' }} - targetStyle={{ height: '200px' }} - >
*/} -
-
- -
-
-
OrderList
- {/*
{item.name}
} onChange={(e) => setOrderlistValue(e.value)}>
*/} -
-
-
- ); -}; - -export default ListDemo; diff --git a/app/(main)/uikit/media/page.tsx b/app/(main)/uikit/media/page.tsx deleted file mode 100644 index 269f5da1..00000000 --- a/app/(main)/uikit/media/page.tsx +++ /dev/null @@ -1,109 +0,0 @@ -'use client'; - -import { Button } from 'primereact/button'; -import { Carousel } from 'primereact/carousel'; -import { Galleria } from 'primereact/galleria'; -import { Image } from 'primereact/image'; -import React, { useEffect, useState } from 'react'; -import { PhotoService } from '../../../../demo/service/PhotoService'; -import { ProductService } from '../../../../demo/service/ProductService'; -import type { Demo } from '@/types'; - -const MediaDemo = () => { - const [products, setProducts] = useState([]); - const [images, setImages] = useState([]); - - const galleriaResponsiveOptions = [ - { - breakpoint: '1024px', - numVisible: 5 - }, - { - breakpoint: '960px', - numVisible: 4 - }, - { - breakpoint: '768px', - numVisible: 3 - }, - { - breakpoint: '560px', - numVisible: 1 - } - ]; - const carouselResponsiveOptions = [ - { - breakpoint: '1024px', - numVisible: 3, - numScroll: 3 - }, - { - breakpoint: '768px', - numVisible: 2, - numScroll: 2 - }, - { - breakpoint: '560px', - numVisible: 1, - numScroll: 1 - } - ]; - - useEffect(() => { - ProductService.getProductsSmall().then((products) => setProducts(products)); - - PhotoService.getImages().then((images) => setImages(images)); - }, []); - - const carouselItemTemplate = (product: Demo.Product) => { - return ( -
-
- {product.name} -
-
-

{product.name}

-
${product.price}
- {product.inventoryStatus} -
- - - -
-
-
- ); - }; - - const galleriaItemTemplate = (item: Demo.Photo) => {item.alt}; - const galleriaThumbnailTemplate = (item: Demo.Photo) => {item.alt}; - - return ( -
-
-
-
Carousel
- -
-
- -
-
-
Image
-
- Image -
-
-
- -
-
-
Galleria
- -
-
-
- ); -}; - -export default MediaDemo; diff --git a/app/(main)/uikit/menu/confirmation/page.tsx b/app/(main)/uikit/menu/confirmation/page.tsx deleted file mode 100644 index 8b5b8d2f..00000000 --- a/app/(main)/uikit/menu/confirmation/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; - -import React from 'react'; -import Menu from '../page'; -function ConfirmationDemo() { - return ( - -
- -

Confirmation Component Content via Child Route

-
-
- ); -} - -export default ConfirmationDemo; diff --git a/app/(main)/uikit/menu/page.tsx b/app/(main)/uikit/menu/page.tsx deleted file mode 100644 index c49836bd..00000000 --- a/app/(main)/uikit/menu/page.tsx +++ /dev/null @@ -1,584 +0,0 @@ -'use client'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { Menubar } from 'primereact/menubar'; -import { InputText } from 'primereact/inputtext'; -import { BreadCrumb } from 'primereact/breadcrumb'; -import { Steps } from 'primereact/steps'; -import { TabMenu } from 'primereact/tabmenu'; -import { TieredMenu } from 'primereact/tieredmenu'; -import { Menu } from 'primereact/menu'; -import { Button } from 'primereact/button'; -import { ContextMenu } from 'primereact/contextmenu'; -import { MegaMenu } from 'primereact/megamenu'; -import { PanelMenu } from 'primereact/panelmenu'; -import { useRouter } from 'next/navigation'; -import { usePathname } from 'next/navigation'; - -const MenuDemo = ({ children }: any) => { - const [activeIndex, setActiveIndex] = useState(0); - const menu = useRef(null); - const contextMenu = useRef(null); - const router = useRouter(); - const pathname = usePathname(); - - const checkActiveIndex = useCallback(() => { - const paths = pathname.split('/'); - const currentPath = paths[paths.length - 1]; - - switch (currentPath) { - case 'seat': - setActiveIndex(1); - break; - case 'payment': - setActiveIndex(2); - break; - case 'confirmation': - setActiveIndex(3); - break; - default: - break; - } - }, [pathname]); - - useEffect(() => { - checkActiveIndex(); - }, [checkActiveIndex]); - - const nestedMenuitems = [ - { - label: 'Customers', - icon: 'pi pi-fw pi-table', - items: [ - { - label: 'New', - icon: 'pi pi-fw pi-user-plus', - items: [ - { - label: 'Customer', - icon: 'pi pi-fw pi-plus' - }, - { - label: 'Duplicate', - icon: 'pi pi-fw pi-copy' - } - ] - }, - { - label: 'Edit', - icon: 'pi pi-fw pi-user-edit' - } - ] - }, - { - label: 'Orders', - icon: 'pi pi-fw pi-shopping-cart', - items: [ - { - label: 'View', - icon: 'pi pi-fw pi-list' - }, - { - label: 'Search', - icon: 'pi pi-fw pi-search' - } - ] - }, - { - label: 'Shipments', - icon: 'pi pi-fw pi-envelope', - items: [ - { - label: 'Tracker', - icon: 'pi pi-fw pi-compass' - }, - { - label: 'Map', - icon: 'pi pi-fw pi-map-marker' - }, - { - label: 'Manage', - icon: 'pi pi-fw pi-pencil' - } - ] - }, - { - label: 'Profile', - icon: 'pi pi-fw pi-user', - items: [ - { - label: 'Settings', - icon: 'pi pi-fw pi-cog' - }, - { - label: 'Billing', - icon: 'pi pi-fw pi-file' - } - ] - }, - { - label: 'Quit', - icon: 'pi pi-fw pi-sign-out' - } - ]; - - const breadcrumbHome = { icon: 'pi pi-home', to: '/' }; - const breadcrumbItems = [{ label: 'Computer' }, { label: 'Notebook' }, { label: 'Accessories' }, { label: 'Backpacks' }, { label: 'Item' }]; - - const wizardItems = [ - { label: 'Personal', command: () => router.push('/uikit/menu') }, - { label: 'Seat', command: () => router.push('/uikit/menu/seat') }, - { label: 'Payment', command: () => router.push('/uikit/menu/payment') }, - { - label: 'Confirmation', - command: () => router.push('/uikit/menu/confirmation') - } - ]; - - const tieredMenuItems = [ - { - label: 'Customers', - icon: 'pi pi-fw pi-table', - items: [ - { - label: 'New', - icon: 'pi pi-fw pi-user-plus', - items: [ - { - label: 'Customer', - icon: 'pi pi-fw pi-plus' - }, - { - label: 'Duplicate', - icon: 'pi pi-fw pi-copy' - } - ] - }, - { - label: 'Edit', - icon: 'pi pi-fw pi-user-edit' - } - ] - }, - { - label: 'Orders', - icon: 'pi pi-fw pi-shopping-cart', - items: [ - { - label: 'View', - icon: 'pi pi-fw pi-list' - }, - { - label: 'Search', - icon: 'pi pi-fw pi-search' - } - ] - }, - { - label: 'Shipments', - icon: 'pi pi-fw pi-envelope', - items: [ - { - label: 'Tracker', - icon: 'pi pi-fw pi-compass' - }, - { - label: 'Map', - icon: 'pi pi-fw pi-map-marker' - }, - { - label: 'Manage', - icon: 'pi pi-fw pi-pencil' - } - ] - }, - { - label: 'Profile', - icon: 'pi pi-fw pi-user', - items: [ - { - label: 'Settings', - icon: 'pi pi-fw pi-cog' - }, - { - label: 'Billing', - icon: 'pi pi-fw pi-file' - } - ] - }, - { - separator: true - }, - { - label: 'Quit', - icon: 'pi pi-fw pi-sign-out' - } - ]; - - const overlayMenuItems = [ - { - label: 'Save', - icon: 'pi pi-save' - }, - { - label: 'Update', - icon: 'pi pi-refresh' - }, - { - label: 'Delete', - icon: 'pi pi-trash' - }, - { - separator: true - }, - { - label: 'Home', - icon: 'pi pi-home' - } - ]; - - const menuitems = [ - { - label: 'Customers', - items: [ - { - label: 'New', - icon: 'pi pi-fw pi-plus' - }, - { - label: 'Edit', - icon: 'pi pi-fw pi-user-edit' - } - ] - }, - { - label: 'Orders', - items: [ - { - label: 'View', - icon: 'pi pi-fw pi-list' - }, - { - label: 'Search', - icon: 'pi pi-fw pi-search' - } - ] - } - ]; - - const contextMenuItems = [ - { - label: 'Save', - icon: 'pi pi-save' - }, - { - label: 'Update', - icon: 'pi pi-refresh' - }, - { - label: 'Delete', - icon: 'pi pi-trash' - }, - { - separator: true - }, - { - label: 'Options', - icon: 'pi pi-cog' - } - ]; - - const megamenuItems = [ - { - label: 'Fashion', - icon: 'pi pi-fw pi-tag', - items: [ - [ - { - label: 'Woman', - items: [{ label: 'Woman Item' }, { label: 'Woman Item' }, { label: 'Woman Item' }] - }, - { - label: 'Men', - items: [{ label: 'Men Item' }, { label: 'Men Item' }, { label: 'Men Item' }] - } - ], - [ - { - label: 'Kids', - items: [{ label: 'Kids Item' }, { label: 'Kids Item' }] - }, - { - label: 'Luggage', - items: [{ label: 'Luggage Item' }, { label: 'Luggage Item' }, { label: 'Luggage Item' }] - } - ] - ] - }, - { - label: 'Electronics', - icon: 'pi pi-fw pi-desktop', - items: [ - [ - { - label: 'Computer', - items: [{ label: 'Computer Item' }, { label: 'Computer Item' }] - }, - { - label: 'Camcorder', - items: [{ label: 'Camcorder Item' }, { label: 'Camcorder Item' }, { label: 'Camcorder Item' }] - } - ], - [ - { - label: 'TV', - items: [{ label: 'TV Item' }, { label: 'TV Item' }] - }, - { - label: 'Audio', - items: [{ label: 'Audio Item' }, { label: 'Audio Item' }, { label: 'Audio Item' }] - } - ], - [ - { - label: 'Sports.7', - items: [{ label: 'Sports.7.1' }, { label: 'Sports.7.2' }] - } - ] - ] - }, - { - label: 'Furniture', - icon: 'pi pi-fw pi-image', - items: [ - [ - { - label: 'Living Room', - items: [{ label: 'Living Room Item' }, { label: 'Living Room Item' }] - }, - { - label: 'Kitchen', - items: [{ label: 'Kitchen Item' }, { label: 'Kitchen Item' }, { label: 'Kitchen Item' }] - } - ], - [ - { - label: 'Bedroom', - items: [{ label: 'Bedroom Item' }, { label: 'Bedroom Item' }] - }, - { - label: 'Outdoor', - items: [{ label: 'Outdoor Item' }, { label: 'Outdoor Item' }, { label: 'Outdoor Item' }] - } - ] - ] - }, - { - label: 'Sports', - icon: 'pi pi-fw pi-star', - items: [ - [ - { - label: 'Basketball', - items: [{ label: 'Basketball Item' }, { label: 'Basketball Item' }] - }, - { - label: 'Football', - items: [{ label: 'Football Item' }, { label: 'Football Item' }, { label: 'Football Item' }] - } - ], - [ - { - label: 'Tennis', - items: [{ label: 'Tennis Item' }, { label: 'Tennis Item' }] - } - ] - ] - } - ]; - - const panelMenuitems = [ - { - label: 'Customers', - icon: 'pi pi-fw pi-table', - items: [ - { - label: 'New', - icon: 'pi pi-fw pi-user-plus', - items: [ - { - label: 'Customer', - icon: 'pi pi-fw pi-plus' - }, - { - label: 'Duplicate', - icon: 'pi pi-fw pi-copy' - } - ] - }, - { - label: 'Edit', - icon: 'pi pi-fw pi-user-edit' - } - ] - }, - { - label: 'Orders', - icon: 'pi pi-fw pi-shopping-cart', - items: [ - { - label: 'View', - icon: 'pi pi-fw pi-list' - }, - { - label: 'Search', - icon: 'pi pi-fw pi-search' - } - ] - }, - { - label: 'Shipments', - icon: 'pi pi-fw pi-envelope', - items: [ - { - label: 'Tracker', - icon: 'pi pi-fw pi-compass' - }, - { - label: 'Map', - icon: 'pi pi-fw pi-map-marker' - }, - { - label: 'Manage', - icon: 'pi pi-fw pi-pencil' - } - ] - }, - { - label: 'Profile', - icon: 'pi pi-fw pi-user', - items: [ - { - label: 'Settings', - icon: 'pi pi-fw pi-cog' - }, - { - label: 'Billing', - icon: 'pi pi-fw pi-file' - } - ] - } - ]; - - const toggleMenu = (event: React.MouseEvent) => { - menu.current?.toggle(event); - }; - - const onContextRightClick = (event: React.MouseEvent) => { - contextMenu.current?.show(event); - }; - - const menubarEndTemplate = () => { - return ( - - - - - ); - }; - - return ( -
-
-
-
Menubar
- -
-
- -
-
-
Breadcrumb
- -
-
- -
-
-
Steps
- setActiveIndex(e.index)} readOnly={false} /> - {pathname === '/uikit/menu' ? ( -
- -

Personal Component Content via Child Route

-
- ) : ( - <>{children} - )} -
-
- -
-
-
TabMenu
- setActiveIndex(e.index)} /> - {pathname === '/uikit/menu' ? ( -
- -

Personal Component Content via Child Route

-
- ) : ( - <>{children} - )} -
-
- -
-
-
Tiered Menu
- -
-
- -
-
-
Plain Menu
- -
-
- -
-
-
Overlay Menu
- - -
- -
-
ContextMenu
- Right click to display. - -
-
- -
-
-
MegaMenu - Horizontal
- - -
MegaMenu - Vertical
- -
-
- -
-
-
PanelMenu
- -
-
-
- ); -}; - -export default MenuDemo; diff --git a/app/(main)/uikit/menu/payment/page.tsx b/app/(main)/uikit/menu/payment/page.tsx deleted file mode 100644 index 4f19d0b7..00000000 --- a/app/(main)/uikit/menu/payment/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -'use client'; -import React from 'react'; -import Menu from '../page'; -function PaymentDemo() { - return ( - -
- -

Payment Component Content via Child Route

-
-
- ); -} - -export default PaymentDemo; diff --git a/app/(main)/uikit/menu/seat/page.tsx b/app/(main)/uikit/menu/seat/page.tsx deleted file mode 100644 index a4dd25cf..00000000 --- a/app/(main)/uikit/menu/seat/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; - -import React from 'react'; -import Menu from '../page'; -function SeatDemo() { - return ( - -
- -

Seat Component Content via Child Route

-
-
- ); -} - -export default SeatDemo; diff --git a/app/(main)/uikit/message/page.tsx b/app/(main)/uikit/message/page.tsx deleted file mode 100644 index 772cb852..00000000 --- a/app/(main)/uikit/message/page.tsx +++ /dev/null @@ -1,131 +0,0 @@ -'use client'; -import React, { useRef, useState } from 'react'; -import { Toast } from 'primereact/toast'; -import { Messages } from 'primereact/messages'; -import { Message } from 'primereact/message'; -import { InputText } from 'primereact/inputtext'; -import { Button } from 'primereact/button'; - -const MessagesDemo = () => { - const [username, setUsername] = useState(''); - const [email, setEmail] = useState(''); - const toast = useRef(null); - const message = useRef(null); - - const addSuccessMessage = () => { - message.current?.show({ severity: 'success', content: 'Message Detail' }); - }; - - const addInfoMessage = () => { - message.current?.show({ severity: 'info', content: 'Message Detail' }); - }; - - const addWarnMessage = () => { - message.current?.show({ severity: 'warn', content: 'Message Detail' }); - }; - - const addErrorMessage = () => { - message.current?.show({ severity: 'error', content: 'Message Detail' }); - }; - - const showSuccess = () => { - toast.current?.show({ - severity: 'success', - summary: 'Success Message', - detail: 'Message Detail', - life: 3000 - }); - }; - - const showInfo = () => { - toast.current?.show({ - severity: 'info', - summary: 'Info Message', - detail: 'Message Detail', - life: 3000 - }); - }; - - const showWarn = () => { - toast.current?.show({ - severity: 'warn', - summary: 'Warn Message', - detail: 'Message Detail', - life: 3000 - }); - }; - - const showError = () => { - toast.current?.show({ - severity: 'error', - summary: 'Error Message', - detail: 'Message Detail', - life: 3000 - }); - }; - - return ( -
-
-
-
Toast
-
- -
-
-
- -
-
-
Messages
-
-
- -
-
- -
-
-
Inline
-
- - setUsername(e.target.value)} required className="p-invalid" /> - -
-
- - setEmail(e.target.value)} required className="p-invalid" /> - -
-
-
- -
-
-
Help Text
-
- - - - Enter your username to reset your password. - -
-
-
-
- ); -}; - -export default MessagesDemo; diff --git a/app/(main)/uikit/misc/page.tsx b/app/(main)/uikit/misc/page.tsx deleted file mode 100644 index 92c72d8b..00000000 --- a/app/(main)/uikit/misc/page.tsx +++ /dev/null @@ -1,220 +0,0 @@ -'use client'; - -import React, { useState, useEffect, useRef } from 'react'; -import { ProgressBar } from 'primereact/progressbar'; -import { Button } from 'primereact/button'; -import { Badge } from 'primereact/badge'; -import { Tag } from 'primereact/tag'; -import { Avatar } from 'primereact/avatar'; -import { AvatarGroup } from 'primereact/avatargroup'; -import { Chip } from 'primereact/chip'; -import { Skeleton } from 'primereact/skeleton'; -import { ScrollPanel } from 'primereact/scrollpanel'; -import { ScrollTop } from 'primereact/scrolltop'; - -const MiscDemo = () => { - const [value, setValue] = useState(0); - const intervalRef = useRef(null); - - useEffect(() => { - const interval = setInterval(() => { - setValue((prevValue) => { - const newVal = prevValue + Math.floor(Math.random() * 10) + 1; - return newVal >= 100 ? 100 : newVal; - }); - }, 2000); - - intervalRef.current = interval; - - return () => { - clearInterval(intervalRef.current as NodeJS.Timeout); - intervalRef.current = null; - }; - }, []); - - return ( -
-
-
-
ProgressBar
-
-
- -
-
- -
-
-
-
-
-
-

Badge

-
Numbers
-
- - - - - -
- -
Positioned Badge
-
- - - - - - - - - -
- -
Button Badge
-
- - -
-
Sizes
-
- - - -
-
- -
-

Avatar

-
Avatar Group
- - - - - - - - - -
Label - Circle
-
- - - -
- -
Icon - Badge
- - - -
- -
-

ScrollTop

- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae et leo duis ut diam. Ultricies mi quis hendrerit dolor magna eget est lorem. Amet - consectetur adipiscing elit ut. Nam libero justo laoreet sit amet. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Est ultricies integer quis auctor elit sed vulputate. Consequat ac felis donec et. Tellus - orci ac auctor augue mauris. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tincidunt arcu non sodales neque sodales. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices. Sodales ut - etiam sit amet nisl purus. Cursus sit amet dictum sit amet. Tristique senectus et netus et malesuada fames ac turpis egestas. Et tortor consequat id porta nibh venenatis cras sed. Diam maecenas ultricies mi eget mauris. - Eget egestas purus viverra accumsan in nisl nisi. Suscipit adipiscing bibendum est ultricies integer. Mattis aliquam faucibus purus in massa tempor nec. -

- -
-
-
-
-
-

Tag

-
Tags
-
- - - - - -
- -
Pills
-
- - - - - -
- -
Icons
-
- - - - - -
-
- -
-

Chip

-
Basic
-
- - - - -
- -
Icon
-
- - - - -
- -
Image
-
- - - - -
- -
Styling
-
- - - - -
-
- -
-

Skeleton

-
-
- -
- - - -
-
- -
- - -
-
-
-
-
- ); -}; - -export default MiscDemo; diff --git a/app/(main)/uikit/overlay/page.tsx b/app/(main)/uikit/overlay/page.tsx deleted file mode 100644 index 173512dd..00000000 --- a/app/(main)/uikit/overlay/page.tsx +++ /dev/null @@ -1,222 +0,0 @@ -'use client'; - -import { Button } from 'primereact/button'; -import { Column } from 'primereact/column'; -import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup'; -import { DataTable, DataTableSelectEvent } from 'primereact/datatable'; -import { Dialog } from 'primereact/dialog'; -import { InputText } from 'primereact/inputtext'; -import { OverlayPanel } from 'primereact/overlaypanel'; -import { Sidebar } from 'primereact/sidebar'; -import { Toast } from 'primereact/toast'; -import React, { useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../../../demo/service/ProductService'; -import type { Demo } from '@/types'; - -type ButtonEvent = React.MouseEvent; -const OverlayDemo = () => { - const [displayBasic, setDisplayBasic] = useState(false); - const [displayConfirmation, setDisplayConfirmation] = useState(false); - const [visibleLeft, setVisibleLeft] = useState(false); - const [visibleRight, setVisibleRight] = useState(false); - const [visibleTop, setVisibleTop] = useState(false); - const [visibleBottom, setVisibleBottom] = useState(false); - const [visibleFullScreen, setVisibleFullScreen] = useState(false); - const [products, setProducts] = useState([]); - const [selectedProduct, setSelectedProduct] = useState(null); - const op = useRef(null); - const op2 = useRef(null); - const toast = useRef(null); - - const accept = () => { - toast.current?.show({ - severity: 'info', - summary: 'Confirmed', - detail: 'You have accepted', - life: 3000 - }); - }; - - const reject = () => { - toast.current?.show({ - severity: 'error', - summary: 'Rejected', - detail: 'You have rejected', - life: 3000 - }); - }; - - const confirm = (event: React.MouseEvent) => { - confirmPopup({ - target: event.currentTarget, - message: 'Are you sure you want to proceed?', - icon: 'pi pi-exclamation-triangle', - accept, - reject - }); - }; - - useEffect(() => { - ProductService.getProductsSmall().then((data) => setProducts(data)); - }, []); - - const toggle = (event: ButtonEvent) => { - op.current?.toggle(event); - }; - - const toggleDataTable = (event: ButtonEvent) => { - op2.current?.toggle(event); - }; - - const formatCurrency = (value: number) => { - return value.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); - }; - - const onProductSelect = (event: DataTableSelectEvent) => { - op2.current?.hide(); - toast.current?.show({ - severity: 'info', - summary: 'Product Selected', - detail: event.data.name, - life: 3000 - }); - }; - - const onSelectionChange = (e: any): void => { - setSelectedProduct(e.value as Demo.Product); - }; - - const basicDialogFooter =
-
-
-
-
Overlay Panel
-
-
-
-
-
-
-
-
- -
-
-
Confirmation
-
-
-
Sidebar
- setVisibleLeft(false)} baseZIndex={1000}> -

Left Sidebar

-
- - setVisibleRight(false)} baseZIndex={1000} position="right"> -

Right Sidebar

-
- - setVisibleTop(false)} baseZIndex={1000} position="top"> -

Top Sidebar

-
- - setVisibleBottom(false)} baseZIndex={1000} position="bottom"> -

Bottom Sidebar

-
- - setVisibleFullScreen(false)} baseZIndex={1000} fullScreen> -

Full Screen

-
- -
-
- -
-
-
Tooltip
-
- - - - -
-
-
-
- - -
-
ConfirmPopup
- - -
-
-
- - ); -}; - -export default OverlayDemo; diff --git a/app/(main)/uikit/panel/page.tsx b/app/(main)/uikit/panel/page.tsx deleted file mode 100644 index 5a852b75..00000000 --- a/app/(main)/uikit/panel/page.tsx +++ /dev/null @@ -1,233 +0,0 @@ -'use client'; - -import React, { useRef } from 'react'; -import { Toolbar } from 'primereact/toolbar'; -import { Button } from 'primereact/button'; -import { SplitButton } from 'primereact/splitbutton'; -import { Accordion, AccordionTab } from 'primereact/accordion'; -import { TabView, TabPanel } from 'primereact/tabview'; -import { Panel } from 'primereact/panel'; -import { Fieldset } from 'primereact/fieldset'; -import { Card } from 'primereact/card'; -import { Divider } from 'primereact/divider'; -import { InputText } from 'primereact/inputtext'; -import { Splitter, SplitterPanel } from 'primereact/splitter'; -import { Menu } from 'primereact/menu'; - -const PanelDemo = () => { - const menu1 = useRef(null); - const toolbarItems = [ - { - label: 'Save', - icon: 'pi pi-check' - }, - { - label: 'Update', - icon: 'pi pi-sync' - }, - { - label: 'Delete', - icon: 'pi pi-trash' - }, - { - label: 'Home Page', - icon: 'pi pi-home' - } - ]; - - const toolbarLeftTemplate = () => { - return ( - <> -
- ); - - return ( -
-
-
-
Toolbar
- -
-
-
-
-
AccordionPanel
- - -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea - commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim - id est laborum. -

-
- -

- Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. - Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi. -

-
- -

- At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt - in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo - minus. -

-
-
-
-
-
TabView
- - -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea - commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim - id est laborum. -

-
- -

- Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. - Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi. -

-
- -

- At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt - in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo - minus. -

-
-
-
-
-
-
-
Panel
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo - consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - laborum. -

-
-
-
-
Fieldset
-
-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo - consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - laborum. -

-
-
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo - consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -

-
-
- -
-
-
Divider
-
-
-
-
- - -
-
- - -
- -
-
-
- - OR - -
-
-

- Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. - Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi. -

- - - Badge - - -

- At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt - in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo - minus. -

- - - - - -

- Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut - reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. Donec vel volutpat ipsum. Integer nunc magna, posuere ut tincidunt eget, egestas vitae sapien. Morbi dapibus luctus odio. -

-
-
-
-
- -
-
-
Splitter
- - -
Panel 1
-
- - - -
Panel 2
-
- -
Panel 3
-
-
-
-
-
-
-
- ); -}; - -export default PanelDemo; diff --git a/app/(main)/uikit/table/page.tsx b/app/(main)/uikit/table/page.tsx deleted file mode 100644 index cb399065..00000000 --- a/app/(main)/uikit/table/page.tsx +++ /dev/null @@ -1,464 +0,0 @@ -'use client'; -import { CustomerService } from '../../../../demo/service/CustomerService'; -import { ProductService } from '../../../../demo/service/ProductService'; -import { FilterMatchMode, FilterOperator } from 'primereact/api'; -import { Button } from 'primereact/button'; -import { Calendar } from 'primereact/calendar'; -import { Column, ColumnFilterApplyTemplateOptions, ColumnFilterClearTemplateOptions, ColumnFilterElementTemplateOptions } from 'primereact/column'; -import { DataTable, DataTableExpandedRows, DataTableFilterMeta } from 'primereact/datatable'; -import { Dropdown } from 'primereact/dropdown'; -import { InputNumber } from 'primereact/inputnumber'; -import { InputText } from 'primereact/inputtext'; -import { MultiSelect } from 'primereact/multiselect'; -import { ProgressBar } from 'primereact/progressbar'; -import { Rating } from 'primereact/rating'; -import { Slider } from 'primereact/slider'; -import { ToggleButton } from 'primereact/togglebutton'; -import { TriStateCheckbox } from 'primereact/tristatecheckbox'; -import { classNames } from 'primereact/utils'; -import React, { useEffect, useState } from 'react'; -import type { Demo } from '@/types'; - -const TableDemo = () => { - const [customers1, setCustomers1] = useState([]); - const [customers2, setCustomers2] = useState([]); - const [customers3, setCustomers3] = useState([]); - const [filters1, setFilters1] = useState({}); - const [loading1, setLoading1] = useState(true); - const [loading2, setLoading2] = useState(true); - const [idFrozen, setIdFrozen] = useState(false); - const [products, setProducts] = useState([]); - const [globalFilterValue1, setGlobalFilterValue1] = useState(''); - const [expandedRows, setExpandedRows] = useState([]); - const [allExpanded, setAllExpanded] = useState(false); - - const representatives = [ - { name: 'Amy Elsner', image: 'amyelsner.png' }, - { name: 'Anna Fali', image: 'annafali.png' }, - { name: 'Asiya Javayant', image: 'asiyajavayant.png' }, - { name: 'Bernardo Dominic', image: 'bernardodominic.png' }, - { name: 'Elwin Sharvill', image: 'elwinsharvill.png' }, - { name: 'Ioni Bowcher', image: 'ionibowcher.png' }, - { name: 'Ivan Magalhaes', image: 'ivanmagalhaes.png' }, - { name: 'Onyama Limba', image: 'onyamalimba.png' }, - { name: 'Stephen Shaw', image: 'stephenshaw.png' }, - { name: 'XuXue Feng', image: 'xuxuefeng.png' } - ]; - - const statuses = ['unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal']; - - const clearFilter1 = () => { - initFilters1(); - }; - - const onGlobalFilterChange1 = (e: React.ChangeEvent) => { - const value = e.target.value; - let _filters1 = { ...filters1 }; - (_filters1['global'] as any).value = value; - - setFilters1(_filters1); - setGlobalFilterValue1(value); - }; - - const renderHeader1 = () => { - return ( -
-
- ); - }; - - useEffect(() => { - setLoading2(true); - - CustomerService.getCustomersLarge().then((data) => { - setCustomers1(getCustomers(data)); - setLoading1(false); - }); - CustomerService.getCustomersLarge().then((data) => { - setCustomers2(getCustomers(data)); - setLoading2(false); - }); - CustomerService.getCustomersMedium().then((data) => setCustomers3(data)); - ProductService.getProductsWithOrdersSmall().then((data) => setProducts(data)); - - initFilters1(); - }, []); - - const balanceTemplate = (rowData: Demo.Customer) => { - return ( -
- {formatCurrency(rowData.balance as number)} -
- ); - }; - - const getCustomers = (data: Demo.Customer[]) => { - return [...(data || [])].map((d) => { - d.date = new Date(d.date); - return d; - }); - }; - - const formatDate = (value: Date) => { - return value.toLocaleDateString('en-US', { - day: '2-digit', - month: '2-digit', - year: 'numeric' - }); - }; - - const formatCurrency = (value: number) => { - return value.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); - }; - - const initFilters1 = () => { - setFilters1({ - global: { value: null, matchMode: FilterMatchMode.CONTAINS }, - name: { - operator: FilterOperator.AND, - constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] - }, - 'country.name': { - operator: FilterOperator.AND, - constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] - }, - representative: { value: null, matchMode: FilterMatchMode.IN }, - date: { - operator: FilterOperator.AND, - constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] - }, - balance: { - operator: FilterOperator.AND, - constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] - }, - status: { - operator: FilterOperator.OR, - constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] - }, - activity: { value: null, matchMode: FilterMatchMode.BETWEEN }, - verified: { value: null, matchMode: FilterMatchMode.EQUALS } - }); - setGlobalFilterValue1(''); - }; - - const countryBodyTemplate = (rowData: Demo.Customer) => { - return ( - - flag - {rowData.country.name} - - ); - }; - - const filterClearTemplate = (options: ColumnFilterClearTemplateOptions) => { - return ; - }; - - const filterApplyTemplate = (options: ColumnFilterApplyTemplateOptions) => { - return ; - }; - - const representativeBodyTemplate = (rowData: Demo.Customer) => { - const representative = rowData.representative; - return ( - - {representative.name} ((e.target as HTMLImageElement).src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} - width={32} - style={{ verticalAlign: 'middle' }} - /> - {representative.name} - - ); - }; - - const representativeFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return ( - <> -
Agent Picker
- options.filterCallback(e.value)} optionLabel="name" placeholder="Any" className="p-column-filter" /> - - ); - }; - - const representativesItemTemplate = (option: any) => { - return ( -
- {option.name} - {option.name} -
- ); - }; - - const dateBodyTemplate = (rowData: Demo.Customer) => { - return formatDate(rowData.date); - }; - - const dateFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />; - }; - - const balanceBodyTemplate = (rowData: Demo.Customer) => { - return formatCurrency(rowData.balance as number); - }; - - const balanceFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return options.filterCallback(e.value, options.index)} mode="currency" currency="USD" locale="en-US" />; - }; - - const statusBodyTemplate = (rowData: Demo.Customer) => { - return {rowData.status}; - }; - - const statusFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return options.filterCallback(e.value, options.index)} itemTemplate={statusItemTemplate} placeholder="Select a Status" className="p-column-filter" showClear />; - }; - - const statusItemTemplate = (option: any) => { - return {option}; - }; - - const activityBodyTemplate = (rowData: Demo.Customer) => { - return ; - }; - - const activityFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return ( - - options.filterCallback(e.value)} range className="m-3"> -
- {options.value ? options.value[0] : 0} - {options.value ? options.value[1] : 100} -
-
- ); - }; - - const verifiedBodyTemplate = (rowData: Demo.Customer) => { - return ( - - ); - }; - - const verifiedFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { - return options.filterCallback(e.value)} />; - }; - - const toggleAll = () => { - if (allExpanded) collapseAll(); - else expandAll(); - }; - - const expandAll = () => { - let _expandedRows = {} as { [key: string]: boolean }; - products.forEach((p) => (_expandedRows[`${p.id}`] = true)); - - setExpandedRows(_expandedRows); - setAllExpanded(true); - }; - - const collapseAll = () => { - setExpandedRows([]); - setAllExpanded(false); - }; - - const amountBodyTemplate = (rowData: Demo.Customer) => { - return formatCurrency(rowData.amount as number); - }; - - const statusOrderBodyTemplate = (rowData: Demo.Customer) => { - return {rowData.status}; - }; - - const searchBodyTemplate = () => { - return
+ )} +
+
+ ); + }; + return (
{/* title section */} @@ -249,14 +286,15 @@ export default function CourseTheme() {

{themeInfo?.description}

- - {themeInfo?.created_at} + + {themeInfo?.created_at && new Date(themeInfo?.created_at).toISOString().slice(0, 10)}
- -
- -
+ {themeInfo?.image && ( +
+ +
+ )}
{breadcrumb}
@@ -309,6 +347,16 @@ export default function CourseTheme() {
{skeleton ? ( + ) : media ? ( + <> + + ) : ( rowIndex + 1} header="Номер" style={{ width: '20px' }}> diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 7996d588..2acca02b 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -29,6 +29,7 @@ import useShortText from '@/hooks/useShortText'; import { ProgressSpinner } from 'primereact/progressspinner'; import { RadioButton } from 'primereact/radiobutton'; import { DataView } from 'primereact/dataview'; +import { displayType } from '@/types/displayType'; export default function Course() { const { setMessage, course, setCourses, contextFetchCourse } = useContext(LayoutContext); @@ -36,10 +37,6 @@ export default function Course() { objectURL?: string; } - interface forDisplayType { - streamTitle: string; - } - const [coursesValue, setValueCourses] = useState([]); const [hasCourses, setHasCourses] = useState(false); const [courseValue, setCourseValue] = useState({ title: '', description: '', video_url: '', image: '' }); @@ -56,7 +53,7 @@ export default function Course() { }); const [activeIndex, setActiveIndex] = useState(0); const [imageState, setImageState] = useState(null); - const [displayStrem, setDisplayStreams] = useState([]); + const [displayStrem, setDisplayStreams] = useState([]); const [editingLesson, setEditingLesson] = useState({ title: '', @@ -131,10 +128,6 @@ export default function Course() { }, 1000); }; - const handleDisplay = (value: forDisplayType[]) => { - setDisplayStreams(value); - }; - const handleFetchCourse = async (page = 1) => { const data = await fetchCourses(page, 0); toggleSkeleton(); @@ -308,6 +301,11 @@ export default function Course() { setActiveIndex(e.index); }; + const displayInfo = (value: displayType[]) => { + console.log('info ', value); + setDisplayStreams(value); + }; + useEffect(() => { contextFetchCourse(1); }, []); @@ -368,7 +366,7 @@ export default function Course() { const itemTemplate = (shablonData: any) => { return (
-
+
{/* Номер (rowIndex) можно добавить через внешний счетчик или props, но для DataView это сложнее */} {/* Заголовок */} @@ -530,6 +528,32 @@ export default function Course() {
+
+ {forStreamId?.title && ( +
+
+ + Тандалган курстун аталышы: {forStreamId?.title} +
+
+
+
+ {displayStrem?.length < 1 && Курска байлоо үчүн агымдарды тандаңыз} + {displayStrem.map((item, idx) => { + if (idx < 1) { + return ( + <> +
{item?.stream_title}...
+ + ); + } + // {displayStrem.length >= 3 && '...'} + })} +
+
+
+ )} +
{media ? ( <> {/* mobile table section */} {/* mobile table section */} - {false ? ( + {hasCourses ? ( <>
)} diff --git a/app/(main)/students/[connect_id]/[stream_id]/page.tsx b/app/(main)/students/[connect_id]/[stream_id]/page.tsx index 38c455a6..cdf33b14 100644 --- a/app/(main)/students/[connect_id]/[stream_id]/page.tsx +++ b/app/(main)/students/[connect_id]/[stream_id]/page.tsx @@ -56,7 +56,8 @@ export default function StudentList() { { id: 1, url: '/', - title: 'Башкы баракча', + title: '', + icon: true, parent_id: null }, { @@ -131,7 +132,6 @@ export default function StudentList() { <> {/* info section */}
-

{'Угуучулардын тизмеси'}

{breadcrumb}
diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index a008acf6..7d4e6efe 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -270,8 +270,9 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp {docShow ? ( ) : ( - documents.map((item: lessonType) => ( - <> + documents.map((item: lessonType) => { + console.log(item.created_at); + return <> selectedForEditing(id, type)} @@ -285,7 +286,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp urlForDownload="" /> - )) + }) )}
diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 2972a785..10fd2519 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -10,8 +10,9 @@ import { NotFound } from '../NotFound'; import GroupSkeleton from '../skeleton/GroupSkeleton'; import Link from 'next/link'; import { streamsType } from '@/types/streamType'; +import { displayType } from '@/types/displayType'; -export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: ()=> void }) { +export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: (id:displayType[]) => void }) { interface mainStreamsType { connect_id: number | null; stream_id: number; @@ -73,13 +74,13 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis id_period: 2, semester: { name_kg: 'test' }, edu_form: { name_kg: 'test' } - }, + } ]; const [streams, setStreams] = useState([]); const [streamValues, setStreamValues] = useState<{ stream: streamsType[] }>({ stream: [] }); - const [displayStreams, setDisplayStreams] = useState<{ course_id: number; stream_id: number; info: string | null; stream_title: string }[] | any>([]); + const [displayStreams, setDisplayStreams] = useState([]); const [hasStreams, setHasStreams] = useState(false); - + const [selectedStreams, setSelectedStreams] = useState([]); const [skeleton, setSkeleton] = useState(false); const { setMessage } = useContext(LayoutContext); @@ -92,15 +93,17 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis }, 1000); }; - const profilactor = (data: { connect_id: number; course_id: number; stream_id: number; info: string | null }[]) => { - const newStreams: { course_id: number; stream_id: number; info: string | null }[] = []; - + const profilactor = (data: { connect_id: number; course_id: number; stream_id: number; info: string | null, subject_name: {name_kg:string} }[]) => { + const newStreams: { course_id: number; stream_id: number; info: string | null, stream_title: string }[] = []; + console.log(data); + data.forEach((item) => { if (item?.connect_id) { newStreams.push({ course_id: item?.course_id, stream_id: item.stream_id, - info: '' + info: '', + stream_title: item?.subject_name.name_kg }); } }); @@ -175,7 +178,6 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis } ); // const x = {streamTitle} - insideDisplayStreams(); } else { setStreamValues( (prev) => @@ -189,12 +191,10 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis useEffect(() => { console.log('отправляемый поток ', streamValues); - const forDisplay = streamValues.stream.map((item, idx) => { - if (idx <= 2) { + const forDisplay = streamValues.stream.filter((item, idx) => { + // if (idx <= 2) { return item; - } else { - return null; - } + // } }); setDisplayStreams(forDisplay); @@ -217,13 +217,15 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis } }, [streams]); - useEffect(()=> { + useEffect(() => { console.log(displayStreams); - },[displayStreams]) + insideDisplayStreams(displayStreams); + }, [displayStreams]); const itemTemplate = (item: mainStreamsType, index: number) => { const bgClass = item.connect_id ? 'bg-[var(--greenBgColor)] border-b border-[gray]' : index % 2 == 1 ? 'bg-[#f5f5f5]' : ''; - + console.log(item); + return (
@@ -339,13 +341,13 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis )}
- {courseValue?.title && ( + {/* {courseValue?.title && (
Тандалган курстун аталышы: {courseValue?.title}
- {/*
+
{streamValues.stream?.length < 1 && Курска байлоо үчүн агымдарды тандаңыз} @@ -354,9 +356,9 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis })}
{displayStreams.length >= 3 && '...'}
-
*/} +
- )} + )} */}
)}
diff --git a/hooks/useBreadCrumbs.tsx b/hooks/useBreadCrumbs.tsx index 86d3372c..923a1d92 100644 --- a/hooks/useBreadCrumbs.tsx +++ b/hooks/useBreadCrumbs.tsx @@ -57,11 +57,11 @@ export default function useBreadCrumbs(insideBreadCrumb: breadCrumbType[], curre
{index < breadCrumb.length - 1 ? ( - + {crumb.title} ) : ( - {crumb.title} + {crumb.title} )}
{index < breadCrumb.length - 1 && / } diff --git a/types/breadCrumbType.tsx b/types/breadCrumbType.tsx index 55c31ceb..a1cfb7a0 100644 --- a/types/breadCrumbType.tsx +++ b/types/breadCrumbType.tsx @@ -3,4 +3,5 @@ export interface breadCrumbType { url: string; title: string; parent_id: number | null; + icon?: boolean } diff --git a/types/displayType.tsx b/types/displayType.tsx new file mode 100644 index 00000000..1251a2b6 --- /dev/null +++ b/types/displayType.tsx @@ -0,0 +1,6 @@ +export interface displayType { + course_id: number; + stream_id: number; + info: string | null; + stream_title: string; +} From 1babdb1a49c5f7cbe841a121be3b4713b384d12f Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Fri, 29 Aug 2025 12:01:05 +0600 Subject: [PATCH 129/138] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 16 +-- app/components/tables/StreamList.tsx | 149 ++++++++++++++++++--------- services/streams.tsx | 1 + 3 files changed, 111 insertions(+), 55 deletions(-) diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 2acca02b..c2721867 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -528,16 +528,16 @@ export default function Course() {
-
+
{forStreamId?.title && (
-
- - Тандалган курстун аталышы: {forStreamId?.title} +
+ + Тандалган курстун аталышы: {forStreamId?.title}
-
-
-
+
+
+
{displayStrem?.length < 1 && Курска байлоо үчүн агымдарды тандаңыз} {displayStrem.map((item, idx) => { if (idx < 1) { @@ -630,7 +630,7 @@ export default function Course() { className="p-tabview p-tabview-nav p-tabview-selected p-tabview-panels p-tabview-panel" >
- {}} /> + displayInfo(value)} />
diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 10fd2519..676ded19 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -12,7 +12,7 @@ import Link from 'next/link'; import { streamsType } from '@/types/streamType'; import { displayType } from '@/types/displayType'; -export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: (id:displayType[]) => void }) { +export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: (id: displayType[]) => void }) { interface mainStreamsType { connect_id: number | null; stream_id: number; @@ -24,6 +24,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis id_period: number; semester: { name_kg: string }; edu_form: { name_kg: string }; + courseValue?: number; } const shablon = [ @@ -82,6 +83,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis const [hasStreams, setHasStreams] = useState(false); const [selectedStreams, setSelectedStreams] = useState([]); const [skeleton, setSkeleton] = useState(false); + const [pendingChanges, setPendingChanges] = useState([]); const { setMessage } = useContext(LayoutContext); const showError = useErrorMessage(); @@ -93,10 +95,10 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis }, 1000); }; - const profilactor = (data: { connect_id: number; course_id: number; stream_id: number; info: string | null, subject_name: {name_kg:string} }[]) => { - const newStreams: { course_id: number; stream_id: number; info: string | null, stream_title: string }[] = []; + const profilactor = (data: { connect_id: number; course_id: number; stream_id: number; info: string | null; subject_name: { name_kg: string } }[]) => { + const newStreams: { course_id: number; stream_id: number; info: string | null; stream_title: string }[] = []; console.log(data); - + data.forEach((item) => { if (item?.connect_id) { newStreams.push({ @@ -108,15 +110,23 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis } }); - setStreamValues((prev) => ({ - ...prev, - stream: [...prev.stream, ...newStreams] - })); + // setStreamValues((prev) => ({ + // ...prev, + // stream: [...prev.stream, ...newStreams] + // })); + // setPendingChanges((prev)=> [...prev, ...newStreams]); + + setPendingChanges((prev) => { + const pendingIds = new Set(prev.map((p) => p.stream_id)); + const uniqueNewStreams = newStreams.filter((s) => !pendingIds.has(s.stream_id)); + return [...prev, ...uniqueNewStreams]; + }); }; const handleFetchStreams = async () => { const data = await fetchStreams(courseValue ? courseValue.id : null); - setStreamValues({ stream: [] }); + // setStreamValues({ stream: [] }); + setPendingChanges([]); if (data) { profilactor(data); @@ -140,7 +150,8 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis }; const handleConnect = async () => { - const data = await connectStreams(streamValues); + const data = await connectStreams({ stream: pendingChanges }); + // const data = await connectStreams(streamValues); if (data?.success) { toggleSkeleton(); @@ -160,48 +171,73 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis } }; - const handleEdit = (e: { checked: boolean }, id: number, title: string) => { + const handleEdit = (e: { checked: boolean }, item: mainStreamsType) => { + const { stream_id, subject_name } = item; + const isChecked = e.checked; + const forSentStreams = { course_id: courseValue!.id, - stream_id: id, + stream_id: stream_id, info: '', - stream_title: title + stream_title: subject_name.name_kg }; - if (e.checked) { - // profilactor(); - setStreamValues( - (prev) => - prev && { - ...prev, - stream: [...prev.stream, forSentStreams] - } - ); - // const x = {streamTitle} - } else { - setStreamValues( - (prev) => - prev && { - ...prev, - stream: [...prev.stream.filter((item) => item?.stream_id !== id)] - } - ); - } - }; + setPendingChanges((prev) => { + const isCurrentlyPending = prev.some((s) => s.stream_id === stream_id); - useEffect(() => { - console.log('отправляемый поток ', streamValues); - const forDisplay = streamValues.stream.filter((item, idx) => { - // if (idx <= 2) { - return item; - // } + if (isChecked) { + // Если чекбокс отмечается + if (!isCurrentlyPending) { + return [...prev, forSentStreams]; + } + } else { + // Если чекбокс снимается, удаляем объект из временного состояния + return prev.filter((s) => s.stream_id !== stream_id); + } + + return prev; }); - setDisplayStreams(forDisplay); - }, [streamValues]); + // if (e.checked) { + // // profilactor(); + // setStreamValues( + // (prev) => + // prev && { + // ...prev, + // stream: [...prev.stream, forSentStreams] + // } + // ); + // // const x = {streamTitle} + // } else { + // setStreamValues( + // (prev) => + // prev && { + // ...prev, + // stream: [...prev.stream.filter((item) => item?.stream_id !== id)] + // } + // ); + // } + }; + + // useEffect(() => { + // console.log('отправляемый поток ', streamValues); + // // const forDisplay = streamValues.stream.filter((item, idx) => { + // // // if (idx <= 2) { + // // return item; + // // // } + // // }); + + // // setDisplayStreams(forDisplay); + + // }, [streamValues]); + + useEffect(() => { + console.log('отправляемый поток ', pendingChanges); + setDisplayStreams(pendingChanges); // Или filter/map по вашему усмотрению + }, [pendingChanges]); useEffect(() => { - setStreamValues({ stream: [] }); + // setStreamValues({ stream: [] }); setDisplayStreams([]); toggleSkeleton(); if (courseValue?.id) { @@ -224,8 +260,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis const itemTemplate = (item: mainStreamsType, index: number) => { const bgClass = item.connect_id ? 'bg-[var(--greenBgColor)] border-b border-[gray]' : index % 2 == 1 ? 'bg-[#f5f5f5]' : ''; - console.log(item); - + return (
@@ -235,10 +270,30 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis { + // handleEdit(e.target, item.stream_id, item?.subject_name.name_kg); + // setStreams((prev) => prev.map((el) => (el.stream_id === item.stream_id ? { ...el, connect_id: el.connect_id ? null : 1 } : el))); + // }} + // vtoroy gde obratno ne ot + // checked={ + // // Проверяем, есть ли этот элемент в вашем массиве для отправки (streamValues). + // // Это отвечает за "включение" чекбокса для новых элементов. + // streamValues?.stream?.some((s) => s.stream_id === item.stream_id) || + // // ...ИЛИ если этот элемент уже пришёл с сервера (есть connect_id), НО + // // его НЕТ в вашем массиве для отправки, что означает, что вы его не "отжали". + // (Boolean(item.connect_id) && !streamValues?.stream?.some((s) => s.stream_id === item.stream_id)) + // } + // checked={ + // // Проверяем, есть ли объект в нашем буфере + // pendingChanges.some((s) => s.stream_id === item.stream_id) || + // // ...ИЛИ если его нет в буфере, проверяем, есть ли он на сервере + // (Boolean(item.connect_id) && !pendingChanges.some((s) => s.stream_id === item.stream_id)) + // } + checked={pendingChanges.some((s) => s.stream_id === item.stream_id)} onChange={(e) => { - handleEdit(e.target, item.stream_id, item?.subject_name.name_kg); - setStreams((prev) => prev.map((el) => (el.stream_id === item.stream_id ? { ...el, connect_id: el.connect_id ? null : 1 } : el))); + handleEdit(e.target, item); }} /> diff --git a/services/streams.tsx b/services/streams.tsx index fe0a1e54..b69037c4 100644 --- a/services/streams.tsx +++ b/services/streams.tsx @@ -17,6 +17,7 @@ export const fetchStreams = async (id: number | null) => { } }; +// export const connectStreams = async (value: {stream: streamsType[]}) => { export const connectStreams = async (value: {stream: streamsType[]}) => { console.log(value); From 6288b8713deeb370ebed30e68ad67e663012a40b Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Fri, 29 Aug 2025 17:12:45 +0600 Subject: [PATCH 130/138] =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=81=D1=82=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20?= =?UTF-8?q?=D0=BA=D1=83=D1=80=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/[courseTheme]/[lessons]/page.tsx | 8 +- app/(main)/course/page.tsx | 21 +- .../[studentThemeId]/[lesson_id]/page.tsx | 6 +- app/components/PDFBook.tsx | 245 +++++++++--------- app/components/cards/LessonCard.tsx | 5 +- app/components/lessons/LessonTyping.tsx | 22 +- app/components/tables/StreamList.tsx | 17 +- app/globals.css | 11 + hooks/useShortText.tsx | 2 +- layout/AppMenu.tsx | 4 - layout/AppTopbar.tsx | 3 +- schemas/authSchema.tsx | 17 +- services/courses.tsx | 2 +- 13 files changed, 190 insertions(+), 173 deletions(-) diff --git a/app/(main)/course/[courseTheme]/[lessons]/page.tsx b/app/(main)/course/[courseTheme]/[lessons]/page.tsx index f87161c4..8c91fe8a 100644 --- a/app/(main)/course/[courseTheme]/[lessons]/page.tsx +++ b/app/(main)/course/[courseTheme]/[lessons]/page.tsx @@ -241,7 +241,7 @@ export default function Lesson() { {/* CKEDITOR */} ) : ( <> -
+
- displayInfo(value)} /> + displayInfo(value)} toggleIndex={()=> setActiveIndex(0)}/>
@@ -726,7 +737,7 @@ export default function Course() {
{/* STREAMS SECTION */}
- displayInfo(value)} /> + displayInfo(value)} toggleIndex={()=> {}}/>
)} diff --git a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx index a97c4d0f..5cece8c4 100644 --- a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx +++ b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx @@ -244,7 +244,7 @@ export default function StudentLessons() { {/* DOC */} ([]); const [skeleton, setSkeleton] = useState(false); + const [hasPdf, setHasPdf] = useState(false); const containerRef = useRef(null); const [bookSize, setBookSize] = useState({ width: 0, height: 0, aspectRatio: 0 }); const FIXED_BOOK_HEIGHT = 800; // Фиксированная высота книги - const media = useMediaQuery('(max-width: 640px)'); useEffect(() => { @@ -52,6 +56,11 @@ export default function PDFViewer({ url }: { url: string }) { if (!context) { // в последний раз добавил эту строку если что + setHasPdf(true); + setMessage({ + state: true, + value: { severity: 'error', summary: 'Ошибка', detail: 'Документти жүктөө же көрсөтүү катасы' } + }); throw new Error('Canvas context is not supported.'); } @@ -75,16 +84,24 @@ export default function PDFViewer({ url }: { url: string }) { // Обновляем состояние с данными только после успешной загрузки setPages(tempPages); - if (containerRef.current) { // в последний раз добавил эту проверку если что + if (containerRef.current) { + // в последний раз добавил эту проверку если что setBookSize({ width: containerRef.current.offsetWidth, height: FIXED_BOOK_HEIGHT, aspectRatio: aspectRatio }); + setHasPdf(false); } setSkeleton(false); } catch (error) { console.error('Ошибка при загрузке или рендеринге PDF:', error); + setHasPdf(true); + setSkeleton(false); + setMessage({ + state: true, + value: { severity: 'error', summary: 'Ошибка', detail: 'Документти жүктөө же көрсөтүү катасы' } + }); } finally { setSkeleton(false); } @@ -102,37 +119,13 @@ export default function PDFViewer({ url }: { url: string }) { setBookSize({ width, height, aspectRatio: width / height }); } }; - - // Вызываем сразу после монтирования updateBookSize(); - window.addEventListener('resize', updateBookSize); return () => window.removeEventListener('resize', updateBookSize); }, [bookSize.aspectRatio]); - // useEffect(() => { - // const updateBookSize = () => { - // if (containerRef.current && bookSize.aspectRatio > 0) { - // const containerWidth = containerRef.current.offsetWidth; - // const bookHeight = containerWidth / bookSize.aspectRatio; // пропорциональная высота - - // setBookSize((prev) => ({ - // ...prev, - // width: containerWidth, - // height: bookHeight - // })); - // } - // }; - - // updateBookSize(); // сразу после монтирования - // window.addEventListener('resize', updateBookSize); - // return () => window.removeEventListener('resize', updateBookSize); - // }, [bookSize.aspectRatio]); - return ( - //
- {/* style={{ width: '100%', backgroundColor: 'red', maxWidth: 1000, margin: '0 auto', border: 'solid 1px' }} */} - {skeleton ? ( - - ) : // - // {pages.map((page, index) => ( - //
- //
- // {' '} - // {/* Добавляем класс для содержимого страницы */} - // {page} - //
- //
- // ))} - //
- media ? ( + {hasPdf ? ( + + ) : ( <> - {}} - onChangeOrientation={() => {}} - onChangeState={() => {}} - onInit={() => {}} - onUpdate={() => {}} - startPage={0} - drawShadow={true} - flippingTime={900} - showPageCorners={true} - disableFlipByClick={false} - > - {pages.map((page, index) => ( -
-
- {' '} - {/* Добавляем класс для содержимого страницы */} - {page} + {skeleton ? ( +
+ +
+ ) : media ? ( + <> + {}} + onChangeOrientation={() => {}} + onChangeState={() => {}} + onInit={() => {}} + onUpdate={() => {}} + startPage={0} + drawShadow={true} + flippingTime={900} + showPageCorners={true} + disableFlipByClick={false} + > + {pages.map((page, index) => ( +
+
+ {' '} + {/* Добавляем класс для содержимого страницы */} + {page} +
+
+ ))} +
+ + ) : ( + {}} + onChangeOrientation={() => {}} + onChangeState={() => {}} + onInit={() => {}} + onUpdate={() => {}} + startPage={0} + drawShadow={true} + flippingTime={900} + showPageCorners={true} + disableFlipByClick={false} + > + {pages.map((page, index) => ( +
+
+ {' '} + {/* Добавляем класс для содержимого страницы */} + {page} +
-
- ))} - + ))} + + )} - ) : ( - {}} - onChangeOrientation={() => {}} - onChangeState={() => {}} - onInit={() => {}} - onUpdate={() => {}} - startPage={0} - drawShadow={true} - flippingTime={900} - showPageCorners={true} - disableFlipByClick={false} - > - {pages.map((page, index) => ( -
-
- {' '} - {/* Добавляем класс для содержимого страницы */} - {page} -
-
- ))} -
)}
//
diff --git a/app/components/cards/LessonCard.tsx b/app/components/cards/LessonCard.tsx index 7e7a679e..7d55c2fd 100644 --- a/app/components/cards/LessonCard.tsx +++ b/app/components/cards/LessonCard.tsx @@ -32,6 +32,7 @@ export default function LessonCard({ urlForDownload: string; }) { const shortTitle = useShortText(cardValue.title, 10); + const shortDescription = useShortText(cardValue.desctiption ? cardValue.desctiption : '', 17); const [progressSpinner, setProgressSpinner] = useState(false); const toggleSpinner = () => { @@ -113,9 +114,9 @@ export default function LessonCard({
{/*
{!cardValue.photo && }
*/} -
{shortTitle}
+
{shortTitle}
{type.typeValue === 'link' && {cardValue?.url}} -
{cardValue?.desctiption && cardValue.desctiption}
+
{cardValue?.desctiption && cardValue?.desctiption !== 'null' && shortDescription}
{status === 'working' && type.typeValue !== 'video' && (
diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index 7d4e6efe..b85f1c4e 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -22,6 +22,7 @@ import PDFViewer from '../PDFBook'; import { useMediaQuery } from '@/hooks/useMediaQuery'; import { useRouter } from 'next/navigation'; import { ProgressSpinner } from 'primereact/progressspinner'; +import useShortText from '@/hooks/useShortText'; export default function LessonTyping({ mainType, courseId, lessonId }: { mainType: string; courseId: string | null; lessonId: string | null }) { // types @@ -103,7 +104,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const [visible, setVisisble] = useState(false); const [editingLesson, setEditingLesson] = useState(null); const [progressSpinner, setProgressSpinner] = useState(false); - + // functions const handleUpdate = () => { if (selectType === 'doc') { @@ -116,8 +117,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }; const selectedForEditing = (id: number, type: string) => { - console.log('Открытие окна... ', id, type); - setSelectId(id); setSelectType(type); editing(type, id); @@ -133,7 +132,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const lesson: editingType = type === 'doc' - ? { key: 'documents', file: 'document_path', url: '', link: '', video_type_id: 1 } + ? { key: 'documents', file: 'document', url: '', link: '', video_type_id: 1 } : type === 'url' ? { key: 'links', file: '', url: 'url', link: '', video_type_id: 1 } : type === 'video' @@ -149,7 +148,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp setEditingLesson({ title: arr.title, - description: arr?.description, + description: arr?.description, document: arr[lesson.file], url: arr[lesson.url], video_link: arr[lesson.link], @@ -271,7 +270,6 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp ) : ( documents.map((item: lessonType) => { - console.log(item.created_at); return <> { + console.log(documents); + },[documents]) + // update document const handleUpdateLesson = async () => { const token = getToken('access_token'); @@ -810,16 +812,14 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp return { name: item.title, status: item.is_link, id: item.id }; }); - setVideoSelect(forSelect); - console.log(forSelect); - + setVideoSelect(forSelect); setSelectedCity(forSelect[0]); } }, [videoTypes]); return (
- +
{selectType === 'doc' ? ( @@ -851,7 +851,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }} /> {errors.title?.message} - setEditingLesson((prev) => prev && { ...prev, description: e.target.value })} className="w-full" /> + setEditingLesson((prev) => prev && { ...prev, description: e.target.value })} className="w-full" /> ) : selectType === 'url' ? ( <> diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 676ded19..5387d0d1 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -12,7 +12,7 @@ import Link from 'next/link'; import { streamsType } from '@/types/streamType'; import { displayType } from '@/types/displayType'; -export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: (id: displayType[]) => void }) { +export default function StreamList({ callIndex, courseValue, isMobile, insideDisplayStreams, toggleIndex }: { callIndex: number; courseValue: { id: number | null; title: string } | null; isMobile: boolean; insideDisplayStreams: (id: displayType[]) => void, toggleIndex: ()=> void }) { interface mainStreamsType { connect_id: number | null; stream_id: number; @@ -360,9 +360,6 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis icon="pi pi-link" onClick={() => { handleConnect(); - // setEditMode(false); - // clearValues(); - // setFormVisible(true); }} />
@@ -375,14 +372,24 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis ) : (
{isMobile && ( -
+
)} diff --git a/app/globals.css b/app/globals.css index 0879a4fb..122cec4b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -567,4 +567,15 @@ h1, h2, h3, h4, h5, h6 { .p-fileupload-choose{ padding: 4px 5px; } +} + +/* menu item , sidebar */ +.p-menuitem-link, .p-menuitem-icon{ + font-size: 13px !important; +} + +@media screen and (max-width: 640px) { + .layout-menuitem-text{ + font-size: 13px !important; + } } \ No newline at end of file diff --git a/hooks/useShortText.tsx b/hooks/useShortText.tsx index c224d81b..2ee45c6d 100644 --- a/hooks/useShortText.tsx +++ b/hooks/useShortText.tsx @@ -21,7 +21,7 @@ export default function useShortText(text: string, textLength: number) { <> {isLength ? ( -
+
{resultText}
diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx index 64225a25..85d1f9d0 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.tsx @@ -93,11 +93,7 @@ const AppMenu = () => { label: item.title, id: item.id, to: `/course/${clickedCourseId}/${item.id}`, - command: () => { - console.log('clicked theme', item.id); - } })); - console.log(newThemes); setCourseList((prev) => prev.map((course) => diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx index 04bb88ae..c2ab5c0b 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.tsx @@ -39,7 +39,7 @@ const AppTopbar = forwardRef((props, ref) => { { label: '', template: ( -
+
{user?.last_name} {user?.name} @@ -51,6 +51,7 @@ const AppTopbar = forwardRef((props, ref) => { { label: 'Чыгуу', icon: 'pi pi-sign-out', + className: 'text-[12px]', items: [], command: () => { logout({ setUser, setGlobalLoading }); diff --git a/schemas/authSchema.tsx b/schemas/authSchema.tsx index 6d8159a5..28a7dc0b 100644 --- a/schemas/authSchema.tsx +++ b/schemas/authSchema.tsx @@ -8,15 +8,16 @@ export const schema = yup.object().shape({ /^[a-zA-Z0-9._%+-]+@oshsu\.kg$/, 'email "@oshsu.kg" форматында болуш керек' ) - .matches( - /^[a-zA-Z0-9._%+-]+@oshsu\.kg$/, // Стандартный формат email (только буквы, цифры, точки, подчеркивания и плюсы) - 'email "@oshsu.kg" форматында жана тыюу салынган символдор камтылбашы керек' - ), + // .matches( + // /^[a-zA-Z0-9._%+-]+@oshsu\.kg$/, // Стандартный формат email (только буквы, цифры, точки, подчеркивания и плюсы) + // 'email "@oshsu.kg" форматында жана тыюу салынган символдор камтылбашы керек' + // ) + , password: yup.string() .required('Сырсөз талап кылынат!') .max(20, 'Сырсөз эң көп дегенде 20 белгиден турушу керек') - .matches( - /^[^!@#$%^&*()_+={}[\]:;"'`<>,.?/\\|]*$/, - 'Сырсөздө тыюу салынган символдор камтылбашы керек' - ), + // .matches( + // /^[^!@#$%^&*()_+={}[\]:;"'`<>,.?/\\|]*$/, + // 'Сырсөздө тыюу салынган символдор камтылбашы керек' + // ), }); \ No newline at end of file diff --git a/services/courses.tsx b/services/courses.tsx index 12e7ad26..46fc15dc 100644 --- a/services/courses.tsx +++ b/services/courses.tsx @@ -281,7 +281,7 @@ export const updateLesson = async (type: string, token: string | null, course_id } else if(type === 'doc'){ url = `/v1/teacher/document/update?lesson_id=${lesson_id}&document_id=${contentId}&document=${value.file}`; formData.append('lesson_id', String(lesson_id)); - formData.append('document', value.file); + formData.append('document', value.file || ''); formData.append('document_id', String(contentId)); formData.append('title', String(value.title)); formData.append('description', String(value.description)); From 53add8334bc4fedb113149589acfcb4d1ab1582e Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sat, 30 Aug 2025 10:41:12 +0600 Subject: [PATCH 131/138] =?UTF-8?q?=D0=92=D0=B8=D0=B4=D0=B5=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B8=20=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B6=D0=B0=D1=8E=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/VideoPlay.tsx | 29 +++++---- app/components/cards/LessonCard.tsx | 26 ++++---- app/components/lessons/LessonTyping.tsx | 84 ++++++++++++++++++------- app/globals.css | 5 +- services/courses.tsx | 2 +- types/lessonType.tsx | 1 + 6 files changed, 95 insertions(+), 52 deletions(-) diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx index e38163d8..fb87d29f 100644 --- a/app/components/VideoPlay.tsx +++ b/app/components/VideoPlay.tsx @@ -1,21 +1,29 @@ 'use client'; -import { faPlay} from "@fortawesome/free-solid-svg-icons"; +import { faPlay } from '@fortawesome/free-solid-svg-icons'; -import Image from "next/image"; -import { useState } from "react"; +import Image from 'next/image'; +import { useState } from 'react'; import { Dialog } from 'primereact/dialog'; // import 'primereact/resources/themes/lara-light-blue/theme.css'; // или другая тема import 'primereact/resources/primereact.min.css'; import 'primeicons/primeicons.css'; -import MyFontAwesome from "./MyFontAwesome"; +import MyFontAwesome from './MyFontAwesome'; export default function VideoPlay() { const [videoCall, setVideoCall] = useState(false); return (
- {if (!videoCall) return; setVideoCall(false); }}> + { + if (!videoCall) return; + setVideoCall(false); + }} + >
+
+
{videoShow ? ( ) : ( @@ -670,7 +702,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp lessonDate={'xx-xx'} urlForPDF={() => ''} urlForDownload="" - /> + videoVisible={()=> handleVideoCall(String(item?.link))} + /> )) )} @@ -789,6 +822,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp if (mainType === 'doc') handleFetchDoc(); if (mainType === 'link') handleFetchLink(); if (mainType === 'video') { + console.log(video); + handleFetchVideo(); handleVideoType(); } @@ -812,7 +847,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp return { name: item.title, status: item.is_link, id: item.id }; }); - setVideoSelect(forSelect); + setVideoSelect(forSelect); setSelectedCity(forSelect[0]); } }, [videoTypes]); @@ -851,7 +886,12 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }} /> {errors.title?.message} - setEditingLesson((prev) => prev && { ...prev, description: e.target.value })} className="w-full" /> + setEditingLesson((prev) => prev && { ...prev, description: e.target.value })} + className="w-full" + /> ) : selectType === 'url' ? ( <> diff --git a/app/globals.css b/app/globals.css index 122cec4b..d23f6aac 100644 --- a/app/globals.css +++ b/app/globals.css @@ -539,8 +539,9 @@ h1, h2, h3, h4, h5, h6 { -moz-border-radius: 0px 0px 200px 200px; } -.udalismelo{ - background-color: #cde7e3; +.lesson-card-border { + border: solid 2px rgb(224, 224, 224); + } .poka{ diff --git a/services/courses.tsx b/services/courses.tsx index 46fc15dc..12e7ad26 100644 --- a/services/courses.tsx +++ b/services/courses.tsx @@ -281,7 +281,7 @@ export const updateLesson = async (type: string, token: string | null, course_id } else if(type === 'doc'){ url = `/v1/teacher/document/update?lesson_id=${lesson_id}&document_id=${contentId}&document=${value.file}`; formData.append('lesson_id', String(lesson_id)); - formData.append('document', value.file || ''); + formData.append('document', value.file); formData.append('document_id', String(contentId)); formData.append('title', String(value.title)); formData.append('description', String(value.description)); diff --git a/types/lessonType.tsx b/types/lessonType.tsx index 1ed6e5dd..514cc476 100644 --- a/types/lessonType.tsx +++ b/types/lessonType.tsx @@ -12,4 +12,5 @@ export interface lessonType { document_path?: string; url?: string; photo?: string; + link?:string; } From 9a26320cf8cf2c98696d4dda7202a0702557a5d7 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sat, 30 Aug 2025 11:07:36 +0600 Subject: [PATCH 132/138] =?UTF-8?q?=D0=92=D0=B8=D0=B4=D0=B5=D0=BE=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B1=D0=B0=D1=82=D1=8B=D0=B2=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D1=80=D0=B0=D0=B7=D0=BD=D1=8B=D0=B5=20=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BB=D0=BA=D0=B8=20=D1=8E=D1=82=D1=83=D0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/lessons/LessonTyping.tsx | 39 +++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index ca66dbca..a6d53a8a 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -579,10 +579,37 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }; const handleVideoCall = (value: string | null) => { - console.log('value', value); - setVideoLink(typeof value === 'string' ? value : ''); + if (!value) { + setMessage({ + state: true, + value: { severity: 'error', summary: 'Видеону иштетүүдө ката', detail: '' } + }); + } + + const url = new URL(typeof value === 'string' ? value : ''); + let videoId = null; + + if (url.hostname === 'youtu.be') { + // короткая ссылка, видео ID — в пути + videoId = url.pathname.slice(1); // убираем первый слеш + } else if (url.hostname === 'www.youtube.com' || url.hostname === 'youtube.com') { + // стандартная ссылка, видео ID в параметре v + videoId = url.searchParams.get('v'); + } + + if (!videoId) { + setMessage({ + state: true, + value: { severity: 'error', summary: 'Видеону иштетүүдө ката', detail: '' } + }); + return null; // не удалось получить ID + } + // return `https://www.youtube.com/embed/${videoId}`; + + console.log('value', videoId); + setVideoLink(`https://www.youtube.com/embed/${videoId}`); setVideoCall(true); - } + }; const videoSection = () => { return ( @@ -702,8 +729,8 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp lessonDate={'xx-xx'} urlForPDF={() => ''} urlForDownload="" - videoVisible={()=> handleVideoCall(String(item?.link))} - /> + videoVisible={() => handleVideoCall(String(item?.link))} + /> )) )} @@ -823,7 +850,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp if (mainType === 'link') handleFetchLink(); if (mainType === 'video') { console.log(video); - + handleFetchVideo(); handleVideoType(); } From 33877ad95665023c349ef0a931acec24f6c915ca Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sat, 30 Aug 2025 12:53:13 +0600 Subject: [PATCH 133/138] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20=D1=83=D1=80=D0=BE=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2,=20=D0=B0=D0=B4=D0=B0=D0=BF=D1=82=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=D0=BD=D0=BF=D1=83=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 5 +- app/components/lessons/LessonTyping.tsx | 70 ++++++++++++++++++++----- app/components/popUp/Redacting.tsx | 2 +- app/components/tables/StreamList.tsx | 5 +- app/globals.css | 15 +++++- types/fileuploadPreview.tsx | 3 ++ 6 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 types/fileuploadPreview.tsx diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index 41f8dd1f..fe352508 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -30,13 +30,10 @@ import { ProgressSpinner } from 'primereact/progressspinner'; import { RadioButton } from 'primereact/radiobutton'; import { DataView } from 'primereact/dataview'; import { displayType } from '@/types/displayType'; +import { FileWithPreview } from '@/types/fileuploadPreview'; export default function Course() { const { setMessage, course, setCourses, contextFetchCourse } = useContext(LayoutContext); - interface FileWithPreview extends File { - objectURL?: string; - } - const [coursesValue, setValueCourses] = useState([]); const [hasCourses, setHasCourses] = useState(false); const [courseValue, setCourseValue] = useState({ title: '', description: '', video_url: '', image: '' }); diff --git a/app/components/lessons/LessonTyping.tsx b/app/components/lessons/LessonTyping.tsx index a6d53a8a..128b92ca 100644 --- a/app/components/lessons/LessonTyping.tsx +++ b/app/components/lessons/LessonTyping.tsx @@ -2,7 +2,7 @@ import { LayoutContext } from '@/layout/context/layoutcontext'; import { Button } from 'primereact/button'; -import { FileUpload } from 'primereact/fileupload'; +import { FileUpload, FileUploadSelectEvent } from 'primereact/fileupload'; import { InputText } from 'primereact/inputtext'; import React, { useContext, useEffect, useRef, useState } from 'react'; import LessonCard from '../cards/LessonCard'; @@ -24,6 +24,7 @@ import { useRouter } from 'next/navigation'; import { ProgressSpinner } from 'primereact/progressspinner'; import useShortText from '@/hooks/useShortText'; import { Dialog } from 'primereact/dialog'; +import { FileWithPreview } from '@/types/fileuploadPreview'; export default function LessonTyping({ mainType, courseId, lessonId }: { mainType: string; courseId: string | null; lessonId: string | null }) { // types @@ -98,6 +99,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp video_link: '' }); const [videoShow, setVideoShow] = useState(false); + const [imageState, setImageState] = useState(null); // auxiliary const showError = useErrorMessage(); @@ -107,6 +109,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const [visible, setVisisble] = useState(false); const [editingLesson, setEditingLesson] = useState(null); const [progressSpinner, setProgressSpinner] = useState(false); + const [additional, setAdditional] = useState<{ doc: boolean; link: boolean; video: boolean }>({ doc: false, link: false, video: false }); // functions const handleUpdate = () => { @@ -164,6 +167,7 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp const fileUploadRef = useRef(null); const clearFile = () => { fileUploadRef.current?.clear(); + setImageState(null); if (visible) { setEditingLesson( (prev) => @@ -257,11 +261,16 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }} /> {errors.title?.message} + {additional.doc && setDocValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" />} - setDocValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" /> -
+
{/*
@@ -433,12 +442,20 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }} /> {errors.title?.message} - - setLinksValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" /> -
-
-
@@ -611,6 +628,12 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp setVideoCall(true); }; + const onSelect = (e: FileUploadSelectEvent & { files: FileWithPreview[] }) => { + if (e.files.length > 0) { + setImageState(e.files[0].objectURL); + } + }; + const videoSection = () => { return (
@@ -675,10 +698,29 @@ export default function LessonTyping({ mainType, courseId, lessonId }: { mainTyp }} /> {errors.title?.message} - - setVideoValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" /> -
-
+ {additional.video && ( +
+ setVideoValue((prev) => ({ ...prev, description: e.target.value }))} className="w-full" /> +
+
+ + {imageState &&
+
+ {imageState ? : } +
+
+
+ )} + +
+ {/*
diff --git a/app/components/popUp/Redacting.tsx b/app/components/popUp/Redacting.tsx index 20acd346..39988e4f 100644 --- a/app/components/popUp/Redacting.tsx +++ b/app/components/popUp/Redacting.tsx @@ -8,7 +8,7 @@ export default function Redacting({ redactor, textSize }: {redactor: MenuItem[], return (
- menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> + menuLeft.current?.toggle(event)} aria-controls="popup_menu_left" aria-haspopup /> {item?.teacher?.name} */}
- Үйрөтүлүү тили: + Окутуу тили: {item?.language?.name}
@@ -315,7 +316,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis
Период: - {item?.id_period} + {item?.period.name_kg}
diff --git a/app/globals.css b/app/globals.css index d23f6aac..a7321de2 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,8 +4,10 @@ :root { --bodyFonts: "Jost", sans-serif; --mainColor: #08A9E6; - /* --mainBgColor: #e6eef1; */ - --mainBgColor: #fff; + --mainBorder: #83d6f4; + --mainBgColor: #e6eef1; + /* --mainBgColor: #fff; */ + --redColor: #EC272F; --redBgColor: #EC272F1A; --greenColor: rgb(46, 192, 46); @@ -579,4 +581,13 @@ h1, h2, h3, h4, h5, h6 { .layout-menuitem-text{ font-size: 13px !important; } +} + +/* input */ + +@media screen and (max-width: 640px) { + .p-inputtext{ + font-size: 14px !important; + padding: 8px; + } } \ No newline at end of file diff --git a/types/fileuploadPreview.tsx b/types/fileuploadPreview.tsx new file mode 100644 index 00000000..f1b5d78c --- /dev/null +++ b/types/fileuploadPreview.tsx @@ -0,0 +1,3 @@ +export interface FileWithPreview extends File { + objectURL?: string; +} From 0f15eca0d3c2c112ff458bbe4e235fe87e6e76ac Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Sat, 30 Aug 2025 16:39:12 +0600 Subject: [PATCH 134/138] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D0=B2=D0=B8=D0=B3?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D1=81=D1=82=D1=83=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[studentThemeId]/[lesson_id]/page.tsx | 5 ++++- app/(student)/teaching/page.tsx | 5 ++++- app/components/cards/ItemCard.tsx | 17 +++++++++-------- app/components/tables/StreamList.tsx | 2 +- layout/AppMenu.tsx | 4 ++-- services/streams.tsx | 2 +- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx index 5cece8c4..6a301832 100644 --- a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx +++ b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx @@ -19,6 +19,9 @@ import { useContext, useEffect, useState } from 'react'; export default function StudentLessons() { const { lesson_id } = useParams(); + const params = useParams(); + console.log(params); + const router = useRouter(); const [activeIndex, setActiveIndex] = useState(0); @@ -119,7 +122,7 @@ export default function StudentLessons() { const navigateMainLesson = async (id: number | null) => { setSkeleton(true); - router.push(`/teaching/lesson/${id}`); + router.push(`/teaching/lesson/${lesson_id}/${id}`); }; const handleTabChange = (e: TabViewChange) => { diff --git a/app/(student)/teaching/page.tsx b/app/(student)/teaching/page.tsx index 3cffc3d0..6dfa66af 100644 --- a/app/(student)/teaching/page.tsx +++ b/app/(student)/teaching/page.tsx @@ -47,6 +47,7 @@ export default function Teaching() { toggleSkeleton(); if (data) { // валидность проверить + console.log(data); setLessons(data); setHasLessons(false); } else { @@ -104,7 +105,9 @@ export default function Teaching() { const selected = lessons[selectedSort.code]; displayData = selected && selected.semester ? [selected] : []; } - + console.log('streams', displayData); + console.log('connection', connection); + // превращаем в jsx const x = displayData.map((semester: any, sIdx: number) => (
diff --git a/app/components/cards/ItemCard.tsx b/app/components/cards/ItemCard.tsx index ecb2a13a..2bd46194 100644 --- a/app/components/cards/ItemCard.tsx +++ b/app/components/cards/ItemCard.tsx @@ -12,15 +12,14 @@ export default function ItemCard({ streams: { id: number; teacher?: { name: string; last_name?: string }; subject_type_name?: { name_kg: string; short_name_kg: string } }[]; connection: { id: number; course_id: number; id_myedu_stream: number }[]; }) { - const [activeStreamIdx, setActiveStreamIdx] = useState(null); + const [activeStreamIds, setActiveStreamIds] = useState([]); const matchedIdx = streams.findIndex((stream) => connection.some((item) => item.id_myedu_stream === stream.id)); useEffect(() => { - if (matchedIdx !== -1) { - setActiveStreamIdx(matchedIdx); - } - }, [streams, connection]); + const matchedIds = streams.filter((stream) => connection.some((item) => item.id_myedu_stream === stream.id)).map((stream) => stream.id); + setActiveStreamIds(matchedIds); + }, [streams, connection]); return (
@@ -29,12 +28,12 @@ export default function ItemCard({
{streams.map((stream, idx) => { - const isActive = idx === activeStreamIdx; + const isActive = activeStreamIds.includes(stream.id); return ( -
+
Окутуучу: -
+
{stream.teacher?.name} {stream.teacher?.last_name}
@@ -46,12 +45,14 @@ export default function ItemCard({
{connection.map((item) => { if (item.id_myedu_stream === stream.id) { + console.log('Здесь кнопка должна появиться:', item.id_myedu_stream + '=' + stream.id); return (
diff --git a/app/components/tables/StreamList.tsx b/app/components/tables/StreamList.tsx index 97c5607e..c591ad10 100644 --- a/app/components/tables/StreamList.tsx +++ b/app/components/tables/StreamList.tsx @@ -151,7 +151,7 @@ export default function StreamList({ callIndex, courseValue, isMobile, insideDis }; const handleConnect = async () => { - const data = await connectStreams({ stream: pendingChanges }); + const data = await connectStreams({course_id: courseValue?.id ? courseValue?.id : null, stream: pendingChanges }); // const data = await connectStreams(streamValues); if (data?.success) { diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx index 85d1f9d0..ce36299b 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.tsx @@ -37,7 +37,7 @@ const AppMenu = () => { : user?.is_student ? [ { label: 'Окуу планы', icon: 'pi pi-fw pi-calendar-clock', to: '/teaching' }, - pathname.startsWith('/teaching/') ? { label: 'Темалар', icon: 'pi pi-fw pi-calendar-lessons', items: themesStudentList?.length > 0 ? themesStudentList : [] } : { label: '' } + pathname.startsWith('/teaching/') ? { label: 'Темалар', icon: 'pi pi-fw pi-book', items: themesStudentList?.length > 0 ? themesStudentList : [] } : { label: '' } ] : []; @@ -114,7 +114,7 @@ const AppMenu = () => { forThemes.push({ label: item.title, id: item.id, - to: `/teaching/lesson/${item.id}` + to: `/teaching/lesson/${studentThemeCourse}/${item.id}` }) ); if (forThemes.length > 0) { diff --git a/services/streams.tsx b/services/streams.tsx index b69037c4..6d6de776 100644 --- a/services/streams.tsx +++ b/services/streams.tsx @@ -18,7 +18,7 @@ export const fetchStreams = async (id: number | null) => { }; // export const connectStreams = async (value: {stream: streamsType[]}) => { -export const connectStreams = async (value: {stream: streamsType[]}) => { +export const connectStreams = async (value: {course_id: number | null, stream: streamsType[]}) => { console.log(value); // const formData = new FormData(); From 45ae7e7e3c75389f4fd042390c93bb25fc58f513 Mon Sep 17 00:00:00 2001 From: BekzhanKutmanov Date: Mon, 1 Sep 2025 14:47:36 +0600 Subject: [PATCH 135/138] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= =?UTF-8?q?=20=D0=BA=20=D0=B2=D0=B8=D0=B4=D0=B5=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(main)/course/page.tsx | 62 ++++-- .../[studentThemeId]/[lesson_id]/page.tsx | 203 +++++++++++++++--- .../[studentThemeId]/page.tsx | 71 ++++-- app/(student)/teaching/page.tsx | 8 +- app/components/SessionManager.tsx | 4 +- app/components/cards/ItemCard.tsx | 2 +- app/components/cards/LessonCard.tsx | 9 +- app/components/lessons/LessonTyping.tsx | 22 +- app/components/tables/StreamList.tsx | 1 - hooks/useShortText.tsx | 2 +- layout/AppMenu.tsx | 4 +- layout/AppTopbar.tsx | 9 +- layout/context/layoutcontext.tsx | 31 ++- services/courses.tsx | 8 +- services/studentLessons.tsx | 15 ++ types/layout.d.ts | 3 + types/lessonStateType.tsx | 1 + types/lessonType.tsx | 2 +- utils/axiosInstance.tsx | 4 +- 19 files changed, 368 insertions(+), 93 deletions(-) diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx index fe352508..d9c7dc6c 100644 --- a/app/(main)/course/page.tsx +++ b/app/(main)/course/page.tsx @@ -51,6 +51,7 @@ export default function Course() { const [activeIndex, setActiveIndex] = useState(0); const [imageState, setImageState] = useState(null); const [displayStrem, setDisplayStreams] = useState([]); + const [visible, setVisisble] = useState(false); const [editingLesson, setEditingLesson] = useState({ title: '', @@ -125,6 +126,27 @@ export default function Course() { }, 1000); }; + const fileUploadRef = useRef(null); + const clearFile = () => { + fileUploadRef.current?.clear(); + setImageState(null); + if (editMode) { + setEditingLesson( + (prev) => + prev && { + ...prev, + image: '' + } + ); + // query + } else { + setCourseValue((prev) => ({ + ...prev, + image: '' + })); + } + }; + const handleFetchCourse = async (page = 1) => { const data = await fetchCourses(page, 0); toggleSkeleton(); @@ -299,7 +321,6 @@ export default function Course() { }; const displayInfo = (value: displayType[]) => { - console.log('info ', value); setDisplayStreams(value); }; @@ -339,6 +360,8 @@ export default function Course() { const data = await fetchCourseInfo(selectedCourse); if (data?.success) { + console.log('udali', data); + setProgressSpinner(false); setEditingLesson({ title: data.course.title || '', @@ -415,8 +438,8 @@ export default function Course() { ); }; - const imagestateStyle = imageState ? 'flex gap-1 items-center justify-between flex-col sm:flex-row' : ''; - const imageTitle = useShortText(typeof editingLesson.image === 'string' ? editingLesson.image : '', 30); + const imagestateStyle = imageState || editingLesson.image ? 'flex gap-1 items-center justify-between flex-col sm:flex-row' : ''; + const imageTitle = useShortText(typeof editingLesson.image === 'string' ? editingLesson.image : '', 20); return (
@@ -424,14 +447,18 @@ export default function Course() {
- {imagestateStyle && ( + {/* {imagestateStyle && ( */}
- {typeof imageState === 'string' && } + {/* {typeof imageState === 'string' && } */} + {typeof imageState === 'string' ? + + : + }
- )} + {/* )} */}
- + {courseValue.image || editingLesson.image ? (
{typeof editingLesson.image === 'string' && ( @@ -443,6 +470,7 @@ export default function Course() { ) : ( jpeg, png, jpg )} +
{(editingLesson.image || imageState) &&
{/*
*/} @@ -530,9 +558,11 @@ export default function Course() {
- Тандалган курстун аталышы: {forStreamId?.title} + + Тандалган курстун аталышы: {forStreamId?.title} +
-
+
{displayStrem?.length < 1 && Курска байлоо үчүн агымдарды тандаңыз} @@ -547,7 +577,7 @@ export default function Course() { // {displayStrem.length >= 3 && '...'} })}
-
+
)}
@@ -593,8 +623,8 @@ export default function Course() {
{/* STREAMS SECTION */}
- displayInfo(value)} toggleIndex={()=> {}}/> + displayInfo(value)} toggleIndex={() => {}} />
)} diff --git a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx index 6a301832..bbd10872 100644 --- a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx +++ b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/[lesson_id]/page.tsx @@ -3,31 +3,34 @@ import LessonCard from '@/app/components/cards/LessonCard'; import { NotFound } from '@/app/components/NotFound'; import GroupSkeleton from '@/app/components/skeleton/GroupSkeleton'; +import useBreadCrumbs from '@/hooks/useBreadCrumbs'; import useErrorMessage from '@/hooks/useErrorMessage'; import { useMediaQuery } from '@/hooks/useMediaQuery'; import useShortText from '@/hooks/useShortText'; import { LayoutContext } from '@/layout/context/layoutcontext'; -import { fetchDocuments, fetchLinks } from '@/services/studentLessons'; +import { fetchDocuments, fetchLinks, fetchVideo } from '@/services/studentLessons'; import { fetchMainLesson } from '@/services/studentMain'; import { lessonType } from '@/types/lessonType'; import { TabViewChange } from '@/types/tabViewChange'; -import { useParams, useRouter } from 'next/navigation'; +import { useParams, usePathname, useRouter } from 'next/navigation'; import { Button } from 'primereact/button'; +import { Dialog } from 'primereact/dialog'; import { ProgressBar } from 'primereact/progressbar'; import { TabPanel, TabView } from 'primereact/tabview'; import { useContext, useEffect, useState } from 'react'; export default function StudentLessons() { - const { lesson_id } = useParams(); + const { lesson_id, studentThemeId } = useParams(); const params = useParams(); - console.log(params); - const router = useRouter(); const [activeIndex, setActiveIndex] = useState(0); - const [mainLesson, setMainLesson] = useState<{title: string}>({title: ''}); + const [mainLesson, setMainLesson] = useState<{ title: string }>({ title: '' }); const [hasLessons, setHasLessons] = useState(false); const [skeleton, setSkeleton] = useState(false); + const x = localStorage.getItem('currentBreadCrumb'); + const parseX = JSON.parse(x); + const [streamId, setStreamId] = useState(parseX.studentStream || ''); // doc const [documents, setDocuments] = useState([]); @@ -37,13 +40,49 @@ export default function StudentLessons() { const [link, setLink] = useState([]); const [linkShow, setLinkShow] = useState(false); - const [navigaion, setNavigation] = useState<{prev: number | null,next: number | null}>({ prev: null, next: null }); + // video + const [video, setVideo] = useState([]); + const [videoShow, setVideoShow] = useState(false); + const [videoCall, setVideoCall] = useState(false); + const [videoLink, setVideoLink] = useState(''); + const [navigaion, setNavigation] = useState<{ prev: number | null; next: number | null }>({ prev: null, next: null }); - const { setMessage, contextFetchStudentThemes, contextStudentThemes } = useContext(LayoutContext); + const { setMessage, contextFetchStudentThemes, contextStudentThemes, crumbUrls } = useContext(LayoutContext); const showError = useErrorMessage(); + const teachingBreadCrumb = [ + { + id: 1, + url: '/', + title: '', + icon: true, + parent_id: null + }, + { + id: 2, + url: '/teaching', + title: 'Окуу план', + parent_id: 1 + }, + { + id: 3, + url: `/teaching/${studentThemeId}/${streamId && streamId}`, + title: 'Темалар', + parent_id: 2 + }, + { + id: 4, + url: '/teaching/lesson/:course_id/:lesson_id', + title: 'Сабактар', + parent_id: 3 + } + ]; + + const pathname = usePathname(); + const breadcrumb = useBreadCrumbs(teachingBreadCrumb, pathname); + const media = useMediaQuery('(max-width: 640px)'); - const titleShort = useShortText(mainLesson?.title, 25); + const titleShort = useShortText(mainLesson?.title, 35); const toggleSkeleton = () => { setSkeleton(true); @@ -52,9 +91,41 @@ export default function StudentLessons() { }, 1000); }; + const handleVideoCall = (value: string | null) => { + if (!value) { + setMessage({ + state: true, + value: { severity: 'error', summary: 'Видеону иштетүүдө ката', detail: '' } + }); + } + + const url = new URL(typeof value === 'string' ? value : ''); + let videoId = null; + + if (url.hostname === 'youtu.be') { + // короткая ссылка, видео ID — в пути + videoId = url.pathname.slice(1); // убираем первый слеш + } else if (url.hostname === 'www.youtube.com' || url.hostname === 'youtube.com') { + // стандартная ссылка, видео ID в параметре v + videoId = url.searchParams.get('v'); + } + + if (!videoId) { + setMessage({ + state: true, + value: { severity: 'error', summary: 'Видеону иштетүүдө ката', detail: '' } + }); + return null; // не удалось получить ID + } + // return `https://www.youtube.com/embed/${videoId}`; + + console.log('value', videoId); + setVideoLink(`https://www.youtube.com/embed/${videoId}`); + setVideoCall(true); + }; + const handleMainLesson = async () => { const data = await fetchMainLesson(lesson_id ? Number(lesson_id) : null); - console.log(data); if (data && data?.id) { if (data.next_id) { setNavigation((prev) => ({ ...prev, next: data.next_id })); @@ -120,6 +191,27 @@ export default function StudentLessons() { } }; + // fetch link + const handleFetchVideo = async () => { + const data = await fetchVideo(lesson_id ? Number(lesson_id) : null); + setSkeleton(true); + if (data && Array.isArray(data)) { + setVideo(data); + setVideoShow(false); + setSkeleton(false); + } else { + setSkeleton(false); + setVideoShow(true); + setMessage({ + state: true, + value: { severity: 'error', summary: 'Ошибка', detail: 'Проблема с соединением. Повторите заново' } + }); + if (data?.response?.status) { + showError(data.response.status); + } + } + }; + const navigateMainLesson = async (id: number | null) => { setSkeleton(true); router.push(`/teaching/lesson/${lesson_id}/${id}`); @@ -130,23 +222,35 @@ export default function StudentLessons() { handleFetchDoc(); } else if (e.index === 1) { handleFetchLink(); + } else if (e.index === 2) { + handleFetchVideo(); } setActiveIndex(e.index); }; + useEffect(() => { + const x = localStorage.getItem('currentBreadCrumb'); + const parseX = JSON.parse(x); + console.log('Eto x', parseX); + console.log('Eto x', x); + + setStreamId(parseX.studentStream); + }, [pathname]); + useEffect(() => { handleMainLesson(); handleFetchDoc(); }, []); useEffect(() => { - console.log('Навигация ', navigaion); - }, [navigaion]); + console.log('streamId ', streamId); + }, [streamId]); useEffect(() => { link.length < 1 ? setLinkShow(true) : setLinkShow(false); documents.length < 1 ? setDocShow(true) : setDocShow(false); - }, [link, documents]); + video.length < 1 ? setVideoShow(true) : setVideoShow(false); + }, [link, documents, video]); // doc section const sentToPDF = (url: string) => { @@ -159,7 +263,7 @@ export default function StudentLessons() {
{docShow ? ( - + ) : ( documents.map((item: lessonType) => ( <> @@ -188,8 +292,8 @@ export default function StudentLessons() {
- {docShow ? ( - + {linkShow ? ( + ) : ( link.map((item: lessonType) => ( <> @@ -197,7 +301,7 @@ export default function StudentLessons() { status="student" // onSelected={(id: number, type: string) => selectedForEditing(id, type)} // onDelete={(id: number) => handleDeleteDoc(id)} - cardValue={{ title: item?.title, id: item.id, type: 'doc', url: item?.url && item.url }} + cardValue={{ title: item?.title, id: item.id, type: 'link', url: item?.url && item.url }} cardBg={'#ddc4f51a'} type={{ typeValue: 'link', icon: 'pi pi-file' }} typeColor={'var(--mainColor)'} @@ -213,17 +317,69 @@ export default function StudentLessons() {
); + // video section + const videoSecion = ( +
+
+
+ { + if (!videoCall) return; + setVideoCall(false); + }} + > +
+ +
+
+ {videoShow ? ( + + ) : ( + video.map((item: lessonType) => ( + <> + selectedForEditing(id, type)} + // onDelete={(id: number) => handleDeleteDoc(id)} + cardValue={{ title: item?.title, id: item.id, type: 'video', url: item?.url && item.url, photo: item?.cover_url }} + cardBg={'#fff'} + type={{ typeValue: 'video', icon: 'pi pi-video' }} + typeColor={'var(--mainColor)'} + lessonDate={'xx-xx'} + urlForPDF={() => {}} + urlForDownload={item?.document_path || ''} + videoVisible={() => handleVideoCall(String(item?.link))} + /> + + )) + )} +
+
+
+ ); + return (
{/* info section */} {skeleton ? ( ) : ( -
+

{titleShort}

-
Home/theme
+
{breadcrumb}
)} @@ -274,14 +430,7 @@ export default function StudentLessons() { header="Видео" className="p-tabview p-tabview-nav p-tabview-selected p-tabview-panels p-tabview-panel" > - {/* {contentShow && } */} - {/* && ( -
-
- -
-
- ) */} + {skeleton ? : videoSecion}
diff --git a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/page.tsx b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/page.tsx index fe3347db..a6c0a59b 100644 --- a/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/page.tsx +++ b/app/(student)/teaching/[studentThemeCourse]/[studentThemeId]/page.tsx @@ -2,31 +2,55 @@ import { NotFound } from '@/app/components/NotFound'; import GroupSkeleton from '@/app/components/skeleton/GroupSkeleton'; +import useBreadCrumbs from '@/hooks/useBreadCrumbs'; import useErrorMessage from '@/hooks/useErrorMessage'; import { useMediaQuery } from '@/hooks/useMediaQuery'; import useShortText from '@/hooks/useShortText'; import { LayoutContext } from '@/layout/context/layoutcontext'; import { itemsCourseInfo } from '@/services/studentMain'; import Link from 'next/link'; -import { useParams } from 'next/navigation'; +import { useParams, usePathname } from 'next/navigation'; import { useContext, useEffect, useState } from 'react'; export default function StudentThemes() { - const [themes, setThemes] = useState<{image: string, description: string, title: string,}>({image: '', description: '', title: ''}); + const [themes, setThemes] = useState<{ image: string; description: string; title: string }>({ image: '', description: '', title: '' }); const [hasCourses, setHasCourses] = useState(false); const [skeleton, setSkeleton] = useState(false); const [themesStudentList, setThemesStudentList] = useState([]); const params = useParams(); - // console.log(params); const courseId = params.studentThemeCourse; const streamId = params.studentThemeId; + const teachingBreadCrumb = [ + { + id: 1, + url: '/', + title: '', + icon: true, + parent_id: null + }, + { + id: 2, + url: '/teaching', + title: 'Окуу план', + parent_id: 1 + }, + { + id: 3, + url: `/teaching/:course_id/:lesson_id`, + title: 'Темалар', + parent_id: 2 + } + ]; + + const pathname = usePathname(); + const breadcrumb = useBreadCrumbs(teachingBreadCrumb, pathname); - const { setMessage, contextFetchStudentThemes, contextStudentThemes } = useContext(LayoutContext); + const { setMessage, contextFetchStudentThemes, contextStudentThemes, crumbUrls, contextAddCrumb } = useContext(LayoutContext); const showError = useErrorMessage(); const media = useMediaQuery('(max-width: 640px)'); - const titleShort = useShortText(themes?.title, 20); + const titleShort = useShortText(themes?.title, 35); const titleInfoClass = `${themes?.image ? 'items-center justify-between' : 'justify-center'}`; const titleImageClass = `${true ? 'md:w-1/3' : ''}`; @@ -38,6 +62,15 @@ export default function StudentThemes() { }, 1000); }; + useEffect(()=> { + const isTopicsChildPage = /^\/teaching\/[^/]+\/[^/]+$/.test(pathname); + console.log(streamId); + + if(isTopicsChildPage && streamId){ + contextAddCrumb({type: 'studentStream', crumbUrl: streamId }) + } + },[]) + const handleCourseInfo = async () => { const data = await itemsCourseInfo(courseId ? Number(courseId) : null, streamId ? Number(streamId) : null); @@ -58,7 +91,7 @@ export default function StudentThemes() { useEffect(() => { handleCourseInfo(); - if(courseId){ + if (courseId) { console.log(courseId); contextFetchStudentThemes(courseId); } @@ -78,20 +111,24 @@ export default function StudentThemes() { {skeleton ? ( ) : ( -
-
+
+
-

{titleShort}

+

+ {titleShort} +

{themes?.description}

-
Home/theme
-
- Фото -
+ {themes?.image && ( +
+ Фото +
+ )}
+
{breadcrumb}
)} @@ -104,15 +141,17 @@ export default function StudentThemes() { ) : (
- {themesStudentList?.map((item: {id: number, title: string}) => ( + {themesStudentList?.map((item: { id: number; title: string }) => (
- Сабактын аталышы: + Теманын аталышы:
- {item.title} + + {item.title} +
diff --git a/app/(student)/teaching/page.tsx b/app/(student)/teaching/page.tsx index 6dfa66af..fce8e21a 100644 --- a/app/(student)/teaching/page.tsx +++ b/app/(student)/teaching/page.tsx @@ -44,12 +44,15 @@ export default function Teaching() { // fetch lessons const handleFetchLessons = async () => { const data = await fetchItemsLessons(); - toggleSkeleton(); + setSkeleton(true) + console.log(data); + if (data) { // валидность проверить console.log(data); setLessons(data); setHasLessons(false); + setSkeleton(false) } else { setHasLessons(true); setMessage({ @@ -59,6 +62,7 @@ export default function Teaching() { if (data?.response?.status) { showError(data.response.status); } + setSkeleton(false); } }; @@ -126,6 +130,8 @@ export default function Teaching() { }, [lessons, selectedSort]); useEffect(() => { + console.log('kfjlsdj;'); + handleFetchLessons(); handleFetchConnectId(); }, []); diff --git a/app/components/SessionManager.tsx b/app/components/SessionManager.tsx index 91eb9ead..baa126e3 100644 --- a/app/components/SessionManager.tsx +++ b/app/components/SessionManager.tsx @@ -69,7 +69,9 @@ const SessionManager = () => { }, []); useEffect(() => { - setGlobalLoading(true); + if(!pathname.startsWith('/teaching/lesson/')){ + setGlobalLoading(true); + } console.log('Переход в', pathname); const token = getToken('access_token'); diff --git a/app/components/cards/ItemCard.tsx b/app/components/cards/ItemCard.tsx index 2bd46194..0ff8b466 100644 --- a/app/components/cards/ItemCard.tsx +++ b/app/components/cards/ItemCard.tsx @@ -45,7 +45,7 @@ export default function ItemCard({
{connection.map((item) => { if (item.id_myedu_stream === stream.id) { - console.log('Здесь кнопка должна появиться:', item.id_myedu_stream + '=' + stream.id); + // console.log('Здесь кнопка должна появиться:', item.id_myedu_stream + '=' + stream.id); return (
+ )}
- )} - /> - + ); + })} +
)}
)} diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx index 1aa937c9..15471116 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.tsx @@ -78,7 +78,7 @@ const AppMenu = () => { to: `/course/${clickedCourseId}`, items: [], // пока пусто command: () => { - contextFetchThemes(item.id); + contextFetchThemes(item.id); setClickedCourseId(item.id); } })