-
-

-
Welcome, Isabel!
-
Sign in to continue
-
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ control
+ } = useForm({
+ resolver: yupResolver(schema),
+ mode: 'onChange'
+ });
-
-
-
+ const onSubmit = async (value: LoginType) => {
+ console.log('Данные пользователя: ', value);
-
-
setPassword(e.target.value)} placeholder="Password" toggleMask className="w-full mb-5" inputClassName="w-full p-3 md:w-30rem">
+ 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}`;
+
+ const token = user.token.access_token;
+ if (token) {
+ const res = await getUser(token);
+ try {
+ if (res?.success) {
+ console.log(res);
+ if (res?.user.is_working) {
+ window.location.href = '/course';
+ }
+ } else {
+ logout({ setUser, setGlobalLoading });
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' }
+ }); // messege - Ошибка при авторизации
+ console.log('Ошибка при получении пользователя');
+ }
+ } catch (error) {
+ logout({ setUser, setGlobalLoading });
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' }
+ }); // messege - Ошибка при авторизации
+ console.log('Ошибка при получении пользователя');
+ }
+ }
+ } else {
+ console.log('Ошибка при авторизации');
+ }
+ };
+
+ const onError = (errors:any) => {
+ console.log('Ошибки формы:', errors);
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Катаа', detail: 'ПОвтор' }
+ }); // messege - Ошибка при авторизации
+ };
-
-
+ return (
+
+
+
+
+

+
+
+
+
+
+
diff --git a/app/(full-page)/pages/notfound/page.tsx b/app/(full-page)/pages/notfound/page.tsx
index 52c0b4ce..77df8132 100644
--- a/app/(full-page)/pages/notfound/page.tsx
+++ b/app/(full-page)/pages/notfound/page.tsx
@@ -1,54 +1,63 @@
import React from 'react';
import Link from 'next/link';
+import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn';
-const NotFoundPage = () => {
- return (
-
-
-

-
-
-
404
-
Not Found
-
Requested resource is not available
-
-
-
-
-
- Frequently Asked Questions
- Ultricies mi quis hendrerit dolor.
-
-
-
-
-
-
-
- Solution Center
- Phasellus faucibus scelerisque eleifend.
-
-
-
-
-
-
-
- Permission Manager
- Accumsan in nisl nisi scelerisque
-
-
-
-
-
+const NotFoundPage = ({titleMessege}) => {
+ return
;
+ // return (
+ //
+ //
+ //

+ //
+ //
+ //
404
+ //
Not Found
+ //
Requested resource is not available
+ //
+ //
+ //
+ //
+ //
+ // Frequently Asked Questions
+ // Ultricies mi quis hendrerit dolor.
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // Solution Center
+ // Phasellus faucibus scelerisque eleifend.
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // Permission Manager
+ // Accumsan in nisl nisi scelerisque
+ //
+ //
+ //
+ //
+ //
+ //
+ // );
+};
export default NotFoundPage;
diff --git a/app/(main)/course/[courseTheme]/page.tsx b/app/(main)/course/[courseTheme]/page.tsx
new file mode 100644
index 00000000..f25916a6
--- /dev/null
+++ b/app/(main)/course/[courseTheme]/page.tsx
@@ -0,0 +1,260 @@
+'use client';
+
+import ConfirmModal from '@/app/components/popUp/ConfirmModal';
+import FormModal from '@/app/components/popUp/FormModal';
+import GroupSkeleton from '@/app/components/skeleton/GroupSkeleton';
+import Link from 'next/link';
+import { Button } from 'primereact/button';
+import { Column } from 'primereact/column';
+import { DataTable } from 'primereact/datatable';
+import { InputText } from 'primereact/inputtext';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+import React, { useContext, useEffect, useState } from 'react';
+import { getToken } from '@/utils/auth';
+import { useParams } from 'next/navigation';
+import { addThemes, deleteTheme, fetchCourseInfo, fetchThemes, updateTheme } from '@/services/courses';
+import NotFoundPage from '@/app/(full-page)/pages/notfound/page';
+
+export default function CourseTheme() {
+ const [hasThemes, setHasThemes] = useState(false);
+ const [themes, setThemes] = useState([]);
+ const [themeValue, setThemeValue] = useState({ title: '' });
+ const [themeInfo, setThemeInfo] = useState();
+ const [courseTitle, setCourseTitle] = useState('');
+ const [selectedCourse, setSelectedCourse] = useState(null);
+ const [formVisible, setFormVisible] = useState(false);
+ const [editMode, setEditMode] = useState(false);
+ const [forStart, setForStart] = useState(false);
+ const [skeleton, setSkeleton] = useState(false);
+ const { setMessage } = useContext(LayoutContext);
+
+ const { courseTheme } = useParams() as { courseTheme: string };
+
+ const handleFetchThemes = async () => {
+ const token = getToken('access_token');
+ const data = await fetchThemes(token, courseTheme);
+
+ if (data.lessons) {
+ setThemes(data.lessons.data);
+ setHasThemes(false);
+ } else {
+ setHasThemes(true);
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Проблема с соединением. Повторите заново' }
+ }); // messege - Ошибка загрузки курсов
+ }
+ };
+
+ const handleFetchInfo = async () => {
+ const token = getToken('access_token');
+ const data = await fetchCourseInfo(token, courseTheme);
+
+ setThemeInfo(data.course);
+ };
+
+ const handleAddTheme = async () => {
+ if (themeValue.title.length < 1) {
+ alert('hi');
+ return null;
+ }
+
+ const token = getToken('access_token');
+ const data = await addThemes(token, courseTheme, themeValue.title);
+ console.log(data);
+
+ if (data.success) {
+ toggleSkeleton();
+ handleFetchThemes();
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү кошулду!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при при добавлении' }
+ }); // messege - Ошибка при добавлении
+ }
+ };
+
+ const handleDeleteCourse = async (id: number) => {
+ const token = getToken('access_token');
+
+ const data = await deleteTheme(token, id);
+ if (data.success) {
+ toggleSkeleton();
+ handleFetchThemes();
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү өчүрүлдү!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при при удалении' }
+ }); // messege - Ошибка при добавлении
+ }
+ };
+
+ const handleUpdateTheme = async () => {
+ const token = getToken('access_token');
+
+ const data = await updateTheme(token, courseTheme, selectedCourse.id, themeValue);
+ if (data.success) {
+ toggleSkeleton();
+ handleFetchThemes();
+ clearValues();
+ setEditMode(false);
+ setSelectedCourse(null);
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү өзгөртүлдү!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка при при изменении темы', detail: 'Заполняйте поля правильно' }
+ }); // messege - Ошибка при изменении курса
+ }
+ };
+
+ const clearValues = () => {
+ setThemeValue({ title: '' });
+ setCourseTitle('');
+ setEditMode(false);
+ setSelectedCourse(null);
+ };
+
+ const getConfirmOptions = (id) => ({
+ message: 'Сиз чын эле өчүрүүнү каалайсызбы??',
+ header: 'Өчүрүү',
+ icon: 'pi pi-info-circle',
+ defaultFocus: 'reject',
+ acceptClassName: 'p-button-danger',
+ acceptLabel: 'Кийинки кадам', // кастомная надпись для "Yes"
+ rejectLabel: 'Артка',
+ accept: () => handleDeleteCourse(id),
+ reject: () => console.log('Удаление отменено')
+ });
+
+ const toggleSkeleton = () => {
+ setSkeleton(true);
+ setTimeout(() => {
+ setSkeleton(false);
+ }, 1000);
+ };
+
+ useEffect(() => {
+ handleFetchInfo();
+ handleFetchThemes();
+ }, []);
+
+ useEffect(() => {
+ const title = courseTitle.trim();
+ title.length > 0 ? setForStart(false) : setForStart(true);
+ }, [courseTitle]);
+
+ useEffect(() => {
+ themes.length < 1 ? setHasThemes(true)
+ : setHasThemes(false);
+ }, [themes]);
+
+ const titleInfoClass = `${!themeInfo?.image ? 'items-center' : 'w-full'} ${themeInfo?.image ? 'w-1/2' : 'w-full'}`;
+ const titleImageClass = `${themeInfo?.image ? 'md:w-1/3' : ''}`;
+
+ return (
+
+ {/* title section */}
+
+
+
+ {themeInfo?.title}
+
+
{themeInfo?.description}
+
+
+ {themeInfo?.created_at}
+ Home/theme
+
+
+
+
+

+
+
+
+ {/* add button*/}
+
+ );
+}
diff --git a/app/(main)/course/lessons/[lessons]/page.tsx b/app/(main)/course/lessons/[lessons]/page.tsx
new file mode 100644
index 00000000..6b37aade
--- /dev/null
+++ b/app/(main)/course/lessons/[lessons]/page.tsx
@@ -0,0 +1,278 @@
+'use client';
+
+import { useEffect, useRef, useState } from 'react';
+import { TabView, TabPanel } from 'primereact/tabview';
+import CKEditorWrapper from '@/app/components/CKEditorWrapper.tsx';
+import { Button } from 'primereact/button';
+import { useForm } from 'react-hook-form';
+import { yupResolver } from '@hookform/resolvers/yup';
+import { lessonSchema } from '@/schemas/lessonSchema';
+import { InputText } from 'primereact/inputtext';
+import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn';
+import { LoginType } from '@/types/login';
+import useTypingEffect from '@/hooks/useTypingEffect';
+import Test from '@/app/components/Test';
+import { FileUpload } from 'primereact/fileupload';
+import PrototypeCard from '@/app/components/cards/PrototypeCard';
+import LessonCard from '@/app/components/cards/LessonCard';
+import Tiered from '@/app/components/popUp/Tiered';
+import { Menu } from 'primereact/menu';
+import Redacting from '@/app/components/popUp/Redacting';
+
+export default function Lesson() {
+ const [activeIndex, setActiveIndex] = useState
(0);
+ const [contentShow, setContentShow] = useState(true);
+ const [textShow, setTextShow] = useState(false);
+
+ // for typing effects
+ const [videoTyping, setVideoTyping] = useState(true);
+ const [linkTyping, setLinkTyping] = useState(true);
+ const [docTyping, setDocTyping] = useState(true);
+
+ const handleTabChange = (e) => {
+ // console.log('Переход на шаг:', e);
+ // // fetchDataForStep(e.index);
+ setActiveIndex(e.index);
+ };
+
+ const handleText = (e: string) => {
+ setTextValue(e);
+ };
+
+ const addVideo = () => {};
+
+ const {
+ register,
+ handleSubmit,
+ setValue,
+ trigger,
+ formState: { errors }
+ } = useForm({
+ resolver: yupResolver(lessonSchema),
+ mode: 'onChange'
+ });
+
+ const handleVideoChange = (value: string) => {
+ console.log(value);
+ setValue('videoReq', value, { shouldValidate: true });
+ };
+
+ const videoTyped = useTypingEffect('this is video', videoTyping);
+ const linkTyped = useTypingEffect('ёп тыгыдык дыгыдык', linkTyping);
+ const docTyped = useTypingEffect('this is document ', docTyping);
+
+ const [sentValues, setSentValues] = useState({
+ text: { typingId: '', text: '', register: '' },
+ doc: { typingId: 'docTyping', doc: '', register: '' },
+ link: { typingId: 'linkTyping', link: '', register: 'usefulLink' },
+ video: { typingId: 'videoTyping', video: '', register: 'videoReq' }
+ });
+
+ useEffect(() => {
+ switch (activeIndex) {
+ case 3:
+ setVideoTyping((prev) => !prev); // включить эффект
+ break;
+ case 2:
+ setLinkTyping((prev) => !prev);
+ break;
+ case 1:
+ setDocTyping((prev) => !prev);
+ break;
+ default:
+ setLinkTyping((prev) => !prev);
+ setDocTyping((prev) => !prev);
+ setVideoTyping((prev) => !prev); // выключить при уходе
+ }
+ }, [activeIndex]);
+
+ const redactor = [
+ {
+ label: '',
+ icon: 'pi pi-pencil',
+ command: () => {
+ alert('redactor');
+ }
+ },
+ {
+ label: '',
+ icon: 'pi pi-user',
+ command: () => {
+ alert('delete');
+ }
+ }
+ ];
+
+ useEffect(() => {
+ console.log(sentValues['video'].register);
+ }, [sentValues]);
+
+ const typedJsx = (type: string) => {
+ const typingMap: Record = {
+ videoTyping: videoTyping && videoTyped,
+ linkTyping: linkTyping && linkTyped,
+ docTyping: docTyping && docTyped
+ };
+ const value = sentValues[type]?.[type] ?? '';
+
+ const currentTypingId = sentValues[type].typingId;
+ const placeholder = typingMap[currentTypingId] || '';
+ return (
+
+
+ {type === 'doc' ? (
+ <>
+
+ {sentValues[type].typingId === 'docTyping' && docTyping ? docTyped : ''}
+ >
+ ) : (
+ <>
+ {
+ if (type === 'video') setVideoTyping(false);
+ if (type === 'link') setLinkTyping(false);
+ }}
+ onChange={(e) => {
+ const val = e.target.value;
+ setSentValues((prev) => ({
+ ...prev,
+ [type]: {
+ ...prev[type],
+ [type]: val
+ }
+ }));
+
+ if (type === 'video') setVideoLink(val);
+ if (type === 'link') setUsefullLink(val);
+
+ setValue(sentValues[type].register, val, { shouldValidate: true });
+ }}
+ className="w-full p-2 sm:p-3"
+ />
+ {errors[sentValues[type].register] && {errors[sentValues[type].register].message}}
+ >
+ )}
+
+
+
+
+ );
+ };
+
+ return (
+
+
handleTabChange(e)}
+ activeIndex={activeIndex}
+ className=""
+ pt={{
+ nav: { className: 'flex flex-wrap justify-around' },
+ panelContainer: { className: 'flex-1 pl-4' }
+ }}
+ >
+ {/* CKEDITOR */}
+
+ {contentShow && (
+
+
setTextShow((prev) => !prev)}>click
+ {textShow ? (
+
+
+
+
+
+ Текст
+
+
+
+ {/*
*/}
+
+
+
+ xx-xx-xx
+
+
+
+
+
+ ) : (
+
+
+
+
+ )}
+
+ )}
+
+
+ {/* DOC */}
+
+ {contentShow && (
+
+ {typedJsx('doc')}
+
+
+
+
+ )}
+
+
+ {/* USEFUL LINKS */}
+
+ {contentShow && (
+
+ {typedJsx('link')}
+
+
+
+
+ )}
+
+
+ {/* VIDEO */}
+
+ {contentShow && (
+
+ {typedJsx('video')}
+
+
+
+
+ )}
+
+
+
+ );
+}
diff --git a/app/(main)/course/page.tsx b/app/(main)/course/page.tsx
new file mode 100644
index 00000000..07ca179a
--- /dev/null
+++ b/app/(main)/course/page.tsx
@@ -0,0 +1,391 @@
+'use client';
+
+import FormModal from '@/app/components/popUp/FormModal';
+import { addCourse, deleteCourse, fetchCourseInfo, fetchCourses, updateCourse } from '@/services/courses';
+import { getToken } from '@/utils/auth';
+import { Button } from 'primereact/button';
+import { FileUpload, FileUploadSelectEvent } from 'primereact/fileupload';
+import { InputText } from 'primereact/inputtext';
+import { useContext, useEffect, useState } from 'react';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+import { InputTextarea } from 'primereact/inputtextarea';
+import { DataTable } from 'primereact/datatable';
+import { Column } from 'primereact/column';
+import GroupSkeleton from '@/app/components/skeleton/GroupSkeleton';
+import Link from 'next/link';
+import { CourseCreateType } from '@/types/courseCreateType';
+import { CourseType } from '@/types/courseType';
+import { Paginator } from 'primereact/paginator';
+import NotFoundPage from '@/app/(full-page)/pages/notfound/page';
+import Redacting from '@/app/components/popUp/Redacting';
+import { confirmDialog } from 'primereact/confirmdialog';
+import { getRedactor } from '@/utils/getRedactor';
+import { getConfirmOptions } from '@/utils/getConfirmOptions';
+
+export default function Course() {
+ const [courses, setCourses] = useState([]);
+ const [hasCourses, setHasCourses] = useState(false);
+ const [courseValue, setCourseValue] = useState({ title: '', description: '', video_url: '', image: '' });
+ const [courseTitle, setCourseTitle] = useState('');
+ const [video_url, setVideo_url] = useState('');
+ const [description, setDesciption] = useState('');
+ const [editMode, setEditMode] = useState(false);
+ const [selectedCourse, setSelectedCourse] = useState(null);
+ const [formVisible, setFormVisible] = useState(false);
+ const [image, setImage] = useState('');
+ const [forStart, setForStart] = useState(false);
+ const [skeleton, setSkeleton] = useState(false);
+ const [courseCash, setCourseCash] = useState<{ [key: number]: any[] }>({});
+ const [pagination, setPagination] = useState({
+ currentPage: 1,
+ total: 0,
+ perPage: 0
+ });
+
+ const { setMessage } = useContext(LayoutContext);
+
+ const fetchData = async (page = 1) => {
+ console.log('Запрашиваем курсы...');
+
+ const token = getToken('access_token');
+ const headers: HeadersInit = token ? { Authorization: `Bearer ${token}` } : {};
+
+ try {
+ console.log('Номер запрашиваемой страницы ', page);
+
+ const res = await fetch(`http://api.mooc.oshsu.kg/public/api/v1/teacher/courses?page=${Number(page)}&limit=3`, {
+ headers
+ });
+ const data = await res.json();
+
+ if (data.courses) {
+ setHasCourses(false);
+ setCourses(data.courses.data);
+ setPagination({
+ currentPage: data.courses.current_page,
+ total: data.courses.total,
+ perPage: data.courses.per_page
+ });
+ setCourseCash((prev) => ({ ...prev, [page]: data.courses.data }));
+ localStorage.setItem('lastPage', JSON.stringify(page));
+ } else {
+ setHasCourses(true);
+ setCourseCash({});
+ localStorage.removeItem('lastPage');
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Проблема с соединением. Повторите заново' }
+ }); // messege - Ошибка загрузки курсов
+ }
+ } catch (error) {
+ console.error('Ошибка загрузки:', error);
+ localStorage.removeItem('lastPage');
+ setCourseCash({});
+ setHasCourses(true);
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Повторите заново' }
+ }); // messege - Ошибка загрузки курсов
+ }
+ };
+
+ const handleAddCourse = async () => {
+ if (courseValue.title.length < 1) {
+ alert('hi');
+ return null;
+ }
+ const token = getToken('access_token');
+ const data = await addCourse(token, courseValue);
+ if (data.success) {
+ toggleSkeleton();
+ fetchData();
+ setCourseCash({});
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү кошулду!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при при добавлении' }
+ }); // messege - Ошибка при добавлении
+ }
+ };
+
+ const handleDeleteCourse = async (id: number) => {
+ const token = getToken('access_token');
+
+ const data = await deleteCourse(token, id);
+ if (data.success) {
+ toggleSkeleton();
+ fetchData();
+ setCourseCash({});
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү өчүрүлдү!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при при удалении' }
+ }); // messege - Ошибка при добавлении
+ }
+ };
+
+ const handleUpdateCourse = async () => {
+ const token = getToken('access_token');
+
+ const data = await updateCourse(token, selectedCourse, courseValue);
+ if (data.success) {
+ toggleSkeleton();
+ fetchData();
+ clearValues();
+ setEditMode(false);
+ setSelectedCourse(null);
+ setCourseCash({});
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Ийгиликтүү өзгөртүлдү!', detail: '' }
+ }); // messege - Успех!
+ } else {
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка при при изменении курса', detail: 'Заполняйте поля правильно' }
+ }); // messege - Ошибка при изменении курса
+ }
+ };
+
+ const clearValues = () => {
+ setCourseValue({ title: '', description: '', video_url: '', image: '' });
+ setCourseTitle('');
+ setVideo_url('');
+ setDesciption('');
+ setImage('');
+ setEditMode(false);
+ setSelectedCourse(null);
+ setCourseCash({});
+ };
+
+ const onSelect = (e: FileUploadSelectEvent) => {
+ setImage(e.files[0].name); // сохраняешь файл
+ console.log(e.files[0]);
+
+ setCourseValue((prev) => ({
+ ...prev,
+ image: e.files[0]
+ }));
+ };
+
+ const imageBodyTemplate = (product: CourseType) => {
+ const image = product.image;
+
+ if (typeof image === 'string') {
+ return (
+
+

+
+ );
+ }
+
+ return (
+
+

+
+ );
+ };
+
+ const toggleSkeleton = () => {
+ setSkeleton(true);
+ setTimeout(() => {
+ setSkeleton(false);
+ }, 1000);
+ };
+
+ // Ручное управление пагинацией
+ const handlePageChange = (page: number) => {
+ console.log(courseCash, courseCash[page]);
+
+ if (page in courseCash) {
+ setCourses(courseCash[page]);
+ setPagination((prev) => ({ ...prev, currentPage: page }));
+ } else {
+ fetchData(page);
+ }
+ };
+
+ useEffect(() => {
+ const title = courseTitle.trim();
+ if (title.length > 0) {
+ setForStart(false);
+ } else {
+ setForStart(true);
+ }
+ }, [courseTitle]);
+
+ useEffect(() => {
+ fetchData();
+ }, []);
+
+ useEffect(() => {
+ console.log('Курсы ', courses);
+ courses.length < 1 ? setHasCourses(true) : setHasCourses(false);
+ }, [courses]);
+
+ useEffect(() => {
+ const handleShow = async () => {
+ const token = getToken('access_token');
+ console.log('this is id baby', selectedCourse);
+ const data = await fetchCourseInfo(token, selectedCourse);
+ console.log(data);
+ setCourseTitle(data.course.title || '');
+ setVideo_url(data.course.video_url || '');
+ setDesciption(data.course.description || '');
+ setImage(data.course.image);
+ };
+
+ if (editMode) {
+ handleShow();
+ }
+ }, [editMode]);
+
+ const edit = (rowData) => {
+ setEditMode(true);
+ setSelectedCourse(rowData.id);
+ setCourseValue({
+ title: rowData.title || '',
+ description: rowData.description || '',
+ video_url: rowData.video_url || '',
+ image: rowData.image || ''
+ });
+ setFormVisible(true);
+ };
+
+ return (
+
+
+
+
+
+
+ {
+ setCourseTitle(e.target.value);
+ setCourseValue((prev) => ({
+ ...prev,
+ title: e.target.value
+ }));
+ }}
+ />
+
+
+
+ {
+ setVideo_url(e.target.value);
+ setCourseValue((prev) => ({
+ ...prev,
+ video_url: e.target.value
+ }));
+ }}
+ />
+
+
+
+
+
+
+ {
+ setDesciption(e.target.value);
+ setCourseValue((prev) => ({
+ ...prev,
+ description: e.target.value
+ }));
+ }}
+ />
+
+
+
+
+
+ {image ? (
+
+ Сүрөт: {image}
+
+ ) : (
+
jpeg, png, jpg
+ )}
+
+
+
+
+
+
+
Курстар
+
+ {
+ setEditMode(false);
+ clearValues();
+ setFormVisible(true);
+ }}
+ />
+
+
+ {hasCourses ? (
+
+ ) : (
+
+ {skeleton ? (
+
+ ) : (
+ <>
+
+
+ (
+
+ {rowData.title}
+
+ )}
+ >
+
+ (
+
+
+
+ )}
+ />
+
+
handlePageChange(e.page + 1)}
+ template="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink"
+ />
+ >
+ )}
+
+ )}
+
+ );
+}
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/(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)/layout.tsx b/app/(student)/layout.tsx
new file mode 100644
index 00000000..0eec769f
--- /dev/null
+++ b/app/(student)/layout.tsx
@@ -0,0 +1,15 @@
+import Layout from "../../layout/layout";
+
+export default function LayoutStudent({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+
+ return (
+
+ {/* {children} */}
+ {children};
+
+ );
+}
\ No newline at end of file
diff --git a/app/components/BaseLayout.tsx b/app/components/BaseLayout.tsx
new file mode 100644
index 00000000..101fd3fb
--- /dev/null
+++ b/app/components/BaseLayout.tsx
@@ -0,0 +1,19 @@
+"use client";
+
+import AppTopbar from "@/layout/AppTopbar";
+import HomeClient from "./HomeClient";
+import AppFooter from "@/layout/AppFooter";
+
+export default function BaseLayout() {
+ return (
+ <>
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/app/components/CKEditorWrapper.tsx.tsx b/app/components/CKEditorWrapper.tsx.tsx
new file mode 100644
index 00000000..6f6f26bf
--- /dev/null
+++ b/app/components/CKEditorWrapper.tsx.tsx
@@ -0,0 +1,28 @@
+'use client';
+import useTypingEffect from '@/hooks/useTypingEffect';
+import { Editor } from 'primereact/editor';
+import { useEffect, useState } from 'react';
+
+export default function CKEditorWrapper({textValue}) {
+ const [text, setText] = useState('');
+ const [toggleTyping, setToggleTyping] = useState(true);
+
+ const typedText = useTypingEffect(
+ 'Текстти ушул жерге жазыныз',
+ toggleTyping
+ );
+
+ useEffect(()=> {
+ // console.log(text);
+ // textValue(text);
+
+ },[typedText,text]);
+
+ return (
+
+ {typedText.length > 0 ? ${typedText}`} onClick={()=> setToggleTyping(false)} className='w-[800px] h-[300px]' />
+ : setText(e.htmlValue)} className='w-[800px] h-[300px]'/>
+ }
+
+ );
+}
diff --git a/app/components/CounterBanner.tsx b/app/components/CounterBanner.tsx
new file mode 100644
index 00000000..70317ba5
--- /dev/null
+++ b/app/components/CounterBanner.tsx
@@ -0,0 +1,57 @@
+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/components/HomeClient.tsx b/app/components/HomeClient.tsx
new file mode 100644
index 00000000..e10cb6d1
--- /dev/null
+++ b/app/components/HomeClient.tsx
@@ -0,0 +1,137 @@
+'use client';
+
+import AOS from 'aos';
+import 'aos/dist/aos.css';
+import { useContext, useEffect, useState } 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 { Button } from 'primereact/button';
+import FancyLinkBtn from './buttons/FancyLinkBtn';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+
+export default function HomeClient() {
+ const { user } = useContext(LayoutContext);
+
+ useEffect(() => {
+ AOS.init();
+ }, []);
+
+ return (
+
+
+
+
+
+
+

+
+ ЫҢГАЙЛУУ ОКУУ ҮЧҮН ОНЛАЙН МЕЙКИНДИК
+
+
+
+ Аралыктан окутуу порталына кош келиңиз!
+
+
+ {' '}
+ Университеттин онлайн билим берүү жаатындагы долбоорлорун бириктирүүдөбүз:
+
+ - ачык онлайн курстар
+ - жогорку билим берүү программалары
+
+ {user &&
+
+
+
+ }
+
+
+
+
+
+
+
+ {/*
+

+
*/}
+
+

+
+
+

+
+
+
+

+
+
+ {/*
*/}
+
+ {/*
+
+
Куттуктайбыз!
+
Сиздин кабыл алуу ийгиликтүү аяктады
+
+
*/}
+
+ {/*
+
+
User experience className
+
Today at 12.00 PM
+
+
+ Join now
+
+
*/}
+
+
+
+
+
+
+ {/* Counter Statistics */}
+
+
+ {/* Oshgu Video */}
+
+
+ Видеоэкскурсия по главному зданию ОшГУ
+
+
+
+
+ );
+}
diff --git a/app/components/InfoBanner.tsx b/app/components/InfoBanner.tsx
new file mode 100644
index 00000000..862aefc0
--- /dev/null
+++ b/app/components/InfoBanner.tsx
@@ -0,0 +1,10 @@
+'use client';
+
+export default function InfoBanner({title}:{title:string}) {
+
+ return (
+
+
{title}
+
+ );
+};
diff --git a/app/components/MyFontAwesome.tsx b/app/components/MyFontAwesome.tsx
new file mode 100644
index 00000000..28e58167
--- /dev/null
+++ b/app/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/components/SessionManager.tsx b/app/components/SessionManager.tsx
new file mode 100644
index 00000000..741cddac
--- /dev/null
+++ b/app/components/SessionManager.tsx
@@ -0,0 +1,98 @@
+'use client';
+
+import { getToken } from '@/utils/auth';
+import { useContext, useEffect } from 'react';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+import { getUser } from '@/services/auth';
+import { logout } from '@/utils/logout';
+
+const SessionManager = () => {
+ const { setMessage } = useContext(LayoutContext);
+ const { user, setUser } = useContext(LayoutContext);
+ const { setGlobalLoading } = useContext(LayoutContext);
+
+ useEffect(() => {
+ console.log('Пользователь ', user);
+ }, [user]);
+
+ useEffect(() => {
+ console.log('Роутинг!');
+
+ const init = async () => {
+ const token = getToken('access_token');
+ if (token) {
+ const res = await getUser(token);
+ setGlobalLoading(true);
+ try {
+ if (res?.success) {
+ setGlobalLoading(false);
+ const userVisit = localStorage.getItem('userVisit');
+ console.log('Данные успешно пришли ', res);
+
+ if (!userVisit) {
+ localStorage.setItem('userVisit', JSON.stringify(true));
+
+ setMessage({
+ state: true,
+ value: { severity: 'success', summary: 'Успешная авторизация!', detail: '' }
+ }); // messege - Успех!
+ }
+ setUser(res.user);
+ } else {
+ logout({setUser, setGlobalLoading});
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' }
+ }); // messege - Ошибка при авторизации
+ console.log('Ошибка при получении пользователя');
+ }
+ } catch (error) {
+ logout({setUser, setGlobalLoading});
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Ошибка', detail: 'Ошибка при авторизации' }
+ }); // messege - Ошибка при авторизации
+ console.log('Ошибка при получении пользователя');
+ }
+ } else {
+ setGlobalLoading(false);
+ }
+ };
+ init();
+ }, []);
+
+ useEffect(() => {
+ const checkToken = () => {
+ const token = getToken('access_token');
+
+ if (!token) {
+ const userVisit = localStorage.getItem('userVisit');
+ if(userVisit){
+ setMessage({
+ state: true,
+ value: { severity: 'error', summary: 'Сессия завершилось', detail: 'Войдите заново' }
+ }); // messege - Время сесси завершилось
+ }
+ logout({setUser, setGlobalLoading});
+ console.log('Токен отсутствует - завершаем сессию');
+ return false; // сигнал для остановки интервала
+ }
+ return true;
+ };
+
+ // немедленная проверка
+ if (!checkToken()) return;
+
+ const interval = setInterval(() => {
+ if (!checkToken()) {
+ clearInterval(interval);
+ }
+ }, 5000);
+
+ return () => clearInterval(interval);
+ }, []);
+
+ return null;
+};
+
+export default SessionManager;
diff --git a/app/components/Test.tsx b/app/components/Test.tsx
new file mode 100644
index 00000000..3fb9ea34
--- /dev/null
+++ b/app/components/Test.tsx
@@ -0,0 +1,5 @@
+import React from 'react';
+
+export default function Test({ children }) {
+ return {children}
;
+}
diff --git a/app/components/VideoPlay.tsx b/app/components/VideoPlay.tsx
new file mode 100644
index 00000000..fb45968c
--- /dev/null
+++ b/app/components/VideoPlay.tsx
@@ -0,0 +1,49 @@
+'use client';
+
+import { faPlay} from "@fortawesome/free-solid-svg-icons";
+
+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);
+
+ return (
+
+
+
+
+
setVideoCall(true)}
+ >
+ {/* Волна */}
+
+
+ {/* Иконка-кнопка */}
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/app/components/buttons/FancyLinkBtn.tsx b/app/components/buttons/FancyLinkBtn.tsx
new file mode 100644
index 00000000..e93e325f
--- /dev/null
+++ b/app/components/buttons/FancyLinkBtn.tsx
@@ -0,0 +1,32 @@
+'use client';
+
+import Link from 'next/link';
+import { useState } from 'react';
+
+export default function FancyLinkBtn({ btnWidth, backround, effectBg, title }) {
+ const [position, setPosition] = useState(false);
+
+ return (
+
+ setPosition(true)}
+ onMouseLeave={() => setPosition(false)}
+ className="default-btn p-[7px] md:p-[10px] font-bold"
+ onClick={() => setPosition((prev) => !prev)}
+ style={{
+ backgroundColor: `var(${backround})`,
+ width: `${ btnWidth }`,
+ }}
+ type='submit'
+ >
+ {/* */}
+ {title}
+ {/* */}
+
+
+
+ );
+}
diff --git a/app/components/cards/LessonCard.tsx b/app/components/cards/LessonCard.tsx
new file mode 100644
index 00000000..936aa38c
--- /dev/null
+++ b/app/components/cards/LessonCard.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import Redacting from '../popUp/Redacting';
+
+export default function LessonCard({ cardValue, cardBg, typeColor, type, lessonDate }) {
+ const redactor = [
+ {
+ label: '',
+ icon: 'pi pi-pencil',
+ command: () => {
+ alert('redactor');
+ }
+ },
+ {
+ label: '',
+ icon: 'pi pi-user',
+ command: () => {
+ alert('delete');
+ }
+ }
+ ];
+
+ return (
+
+
+
+
+ {type.typeValue}
+
+
+ {/*
*/}
+
+
+
+ );
+}
diff --git a/app/components/cards/PrototypeCard.tsx b/app/components/cards/PrototypeCard.tsx
new file mode 100644
index 00000000..994ea944
--- /dev/null
+++ b/app/components/cards/PrototypeCard.tsx
@@ -0,0 +1,21 @@
+import { Skeleton } from 'primereact/skeleton';
+import React from 'react';
+import MySkeleton from '../skeleton/MySkeleton';
+
+export default function PrototypeCard({ value }: { value: string }) {
+
+ return (
+
+
+
+
+
+
+
+
+
+
{value ? value : }
+
+
+ );
+}
diff --git a/app/components/loading/GlobalLoading.tsx b/app/components/loading/GlobalLoading.tsx
new file mode 100644
index 00000000..65be1f01
--- /dev/null
+++ b/app/components/loading/GlobalLoading.tsx
@@ -0,0 +1,27 @@
+import React, { useContext } from 'react';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+
+export default function GlobalLoading() {
+ const { globalLoading } = useContext(LayoutContext);
+
+ if(globalLoading){
+ return (
+ <>
+
+ >
+ );
+ }
+}
diff --git a/app/components/messages/Message.tsx b/app/components/messages/Message.tsx
new file mode 100644
index 00000000..9224acf4
--- /dev/null
+++ b/app/components/messages/Message.tsx
@@ -0,0 +1,29 @@
+'use client';
+import { Button } from 'primereact/button';
+import { Toast } from 'primereact/toast';
+import { useContext, useEffect, useRef } from 'react';
+import { LayoutContext } from '@/layout/context/layoutcontext';
+
+export default function Message() {
+ const { message } = useContext(LayoutContext);
+ const toast = useRef(null);
+
+ const showError = () => {
+ toast.current?.show({ severity: message.value.severity, summary: message.value.summary, detail: message.value.detail, life: 3000 });
+ };
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ showError();
+ }, 0); // откладываем до следующей итерации event loop
+
+ return () => clearTimeout(timer);
+ }, [message]);
+
+ return (
+
+ {/* */}
+
+
+ );
+}
diff --git a/app/components/popUp/ConfirmModal.tsx b/app/components/popUp/ConfirmModal.tsx
new file mode 100644
index 00000000..668509ff
--- /dev/null
+++ b/app/components/popUp/ConfirmModal.tsx
@@ -0,0 +1,17 @@
+'use client';
+import { confirmDialog } from 'primereact/confirmdialog';
+import { Button } from 'primereact/button';
+
+export default function ConfirmModal({confirmVisible}) {
+ const handleClick = () => {
+ console.log('hi');
+
+ confirmDialog(confirmVisible);
+ };
+
+ return (
+
+
+
+ );
+}
diff --git a/app/components/popUp/FormModal.tsx b/app/components/popUp/FormModal.tsx
new file mode 100644
index 00000000..705ece44
--- /dev/null
+++ b/app/components/popUp/FormModal.tsx
@@ -0,0 +1,37 @@
+'use client';
+
+import { Button } from 'primereact/button';
+import { Dialog } from 'primereact/dialog';
+
+export default function FormModal({children, title, fetchValue, clearValues, visible, setVisible, start}) {
+
+ const footerContent = (
+
+ {
+ setVisible(false);
+ clearValues();
+ }}/>
+ { {
+ setVisible(false);
+ fetchValue();
+ }} autoFocus />}
+
+ );
+
+ return (
+
+
+
+ );
+}
diff --git a/app/components/popUp/Redacting.tsx b/app/components/popUp/Redacting.tsx
new file mode 100644
index 00000000..1264c0f9
--- /dev/null
+++ b/app/components/popUp/Redacting.tsx
@@ -0,0 +1,38 @@
+import { Menu } from 'primereact/menu';
+import React, { useRef } from 'react';
+
+export default function Redacting({ redactor, textSize }) {
+ const menuLeft = useRef(null);
+
+ return (
+
+ menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
+
+
+ );
+}
diff --git a/app/components/popUp/Tiered.tsx b/app/components/popUp/Tiered.tsx
new file mode 100644
index 00000000..459debdd
--- /dev/null
+++ b/app/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 { 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 (
+
+ toggleMenu(e)}
+ style={{color: 'black', fontSize: title.name ? '16px' : '20px'}}
+ className={`${ title.font } ${
+ title.name ?
+ 'flex gap-2 items-center pb-3 px-0'
+ : 'text-blue-300'
+ } bg-white p-2`}
+ />
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/components/skeleton/GroupSkeleton.tsx b/app/components/skeleton/GroupSkeleton.tsx
new file mode 100644
index 00000000..7a79e32c
--- /dev/null
+++ b/app/components/skeleton/GroupSkeleton.tsx
@@ -0,0 +1,14 @@
+import React, { useState } from 'react';
+import { Skeleton } from 'primereact/skeleton';
+
+export default function GroupSkeleton({ count, size }:{count:number, size:{width:string, height: string}}) {
+ const usingSkeleton = (i:number) => {
+ return (
+
+
+
+ );
+ };
+
+ return {Array.from({ length: count }).map((_, i) => usingSkeleton(i))}
;
+}
diff --git a/app/components/skeleton/MySkeleton.tsx b/app/components/skeleton/MySkeleton.tsx
new file mode 100644
index 00000000..751a781a
--- /dev/null
+++ b/app/components/skeleton/MySkeleton.tsx
@@ -0,0 +1,6 @@
+import React, { useState } from 'react';
+import { Skeleton } from 'primereact/skeleton';
+
+export default function MySkeleton({ size }:{size:{width:string,height:string}}) {
+ return ;
+}
diff --git a/app/favicon.ico b/app/favicon.ico
deleted file mode 100644
index a614a31e..00000000
Binary files a/app/favicon.ico and /dev/null differ
diff --git a/app/globals.css b/app/globals.css
new file mode 100644
index 00000000..30fdd650
--- /dev/null
+++ b/app/globals.css
@@ -0,0 +1,375 @@
+@import 'primeflex/primeflex.css';
+@import 'tailwindcss/index.css';
+
+:root {
+ --bodyFonts: "Jost", sans-serif;
+ --mainColor: #08A9E6;
+ --redColor: #EC272F;
+ --redBgColor: #EC272F1A;
+ --titleColor: #21225F;
+ --bodyColor: #555555;
+ --whiteColor: #ffffff;
+ --borderBottomColor: #e5e7eb;
+ --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);
+ }
+}
+
+.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%;
+ }
+}
+
+#preloader {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 9999;
+}
+
+#preloader-area {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ height: 60px;
+ width: 60px;
+}
+#preloader-area .spinner {
+ position: absolute;
+ z-index: 9999;
+ width: 6px;
+ height: 90px;
+ margin-top: -45px;
+ border-radius: 10px;
+ background-color: var(--whiteColor);
+ animation: rotate40deg 0.8s infinite;
+ animation-direction: alternate-reverse;
+}
+#preloader-area .spinner:nth-child(1) {
+ margin-left: 0px;
+}
+#preloader-area .spinner:nth-child(2) {
+ margin-left: -14px;
+ animation-delay: 0.1s;
+}
+#preloader-area .spinner:nth-child(3) {
+ margin-left: -28px;
+ animation-delay: 0.2s;
+}
+#preloader-area .spinner:nth-child(4) {
+ margin-left: -42px;
+ animation-delay: 0.3s;
+}
+#preloader-area .spinner:nth-child(5) {
+ margin-left: -56px;
+ animation-delay: 0.4s;
+}
+#preloader-area .spinner:nth-child(6) {
+ margin-left: -70px;
+ animation-delay: 0.5s;
+}
+#preloader-area .spinner:nth-child(7) {
+ margin-left: -84px;
+ animation-delay: 0.6s;
+}
+#preloader-area .spinner:nth-child(8) {
+ margin-left: -98px;
+ animation-delay: 0.7s;
+}
+
+#preloader .preloader-section {
+ position: fixed;
+ top: 0;
+ width: 51%;
+ height: 100%;
+ background-color: var(--mainColor);
+ z-index: 999;
+ transform: translateX(0);
+}
+#preloader .preloader-section.preloader-left {
+ left: 0;
+}
+#preloader .preloader-section.preloader-right {
+ right: 0;
+}
+
+.p-password .p-password-toggle-icon {
+ top: 50% !important;
+ transform: translateY(-50%);
+}
+
+
+.loaded #preloader-area {
+ opacity: 0;
+ visibility: hidden;
+ transition: all 0.3s ease-out;
+}
+.loaded #preloader .preloader-section.preloader-left {
+ transform: translateX(-100%);
+ transition: all 0.8s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+.loaded #preloader .preloader-section.preloader-right {
+ transform: translateX(100%);
+ transition: all 0.8s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+
+.loaded #preloader {
+ visibility: hidden;
+ transform: translateY(-100%);
+ transition: all 0.3s 1s ease-out;
+}
+
+@keyframes rotate40deg {
+ 0% {
+ height: 5px;
+ margin-top: 0;
+ transform: rotate(40deg);
+ }
+ 100% {
+ height: 90px;
+ transform: rotate(0deg);
+ }
+}
+@keyframes ripple {
+ 0% {
+ transform: scale(1);
+ }
+ 75% {
+ transform: scale(1.5);
+ opacity: 1;
+ }
+ 100% {
+ transform: scale(1.75);
+ opacity: 0;
+ }
+}
+@keyframes moveleftbounce {
+ 0% {
+ transform: translateX(0px);
+ }
+ 50% {
+ transform: translateX(20px);
+ }
+ 100% {
+ transform: translateX(0px);
+ }
+}
+@keyframes fadeInUp {
+ 0% {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+@keyframes fadeInDown {
+ 0% {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+@keyframes movebounce {
+ 0% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(15px);
+ }
+ 100% {
+ transform: translateY(0);
+ }
+}
+@keyframes rotate-in {
+ 0% {
+ transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+ }
+ 50% {
+ transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
+ }
+ 100% {
+ transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
+ }
+}
+@keyframes rotated360 {
+ 0% {
+ transform: rotateZ(0deg);
+ }
+ 100% {
+ transform: rotateZ(-360deg);
+ }
+}
+
+/* primeReact components */
+.popup_menu_left{
+ width: 300px;
+ display: none;
+}
+
+.p-menuitem-icon{
+ margin: 0;
+}
+
+/* prototype effect */
+.shadowAnimate {
+ box-shadow: 1px 1px 6px 1px ;
+ transition: all 2s;
+ animation: shadowSkale 2s ease-in infinite;
+}
+
+@keyframes shadowSkale {
+ 0% {
+ box-shadow: 1px 1px 6px 1px ;
+ }
+ 50% {
+ box-shadow: 1px 1px 6px 2px ;
+ }
+ 100%{
+ box-shadow: 1px 1px 6px 1px ;
+ }
+}
+
+.my-custom-table td,
+.my-custom-table th {
+ /* border: 1px solid #ccc; */
+ padding: 6px;
+}
+
+.my-custom-table thead {
+ /* background-color: #f5f5f5; */
+}
+
+.my-custom-table .p-datatable-tbody > tr:nth-child(even) {
+ /* background-color: rgb(255, 239, 239); */
+ background-color: #f5f5f5;
+}
+
+/* удаление встроенного underline при активаности для таб (TabView) */
+.p-tabview-ink-bar {
+ display: none !important;
+}
+
+.p-tabview-panels{
+ /* height: ; */
+}
+
+.tab-custom-text{
+ color: rgb(245, 206, 77) !important;
+}
+
+.tab-custom-text-2{
+ color: blueviolet !important;
+ /* color: rgb(221, 196, 245) !important; */
+}
+
+.tab-custom-text-3{
+ color: green !important;
+}
+
+.tab-custom-text-4{
+ color: var(--redColor) !important;
+}
+
+.poka{
+ background-color: rgb(211, 232, 202) !important;
+ /* background-color: rgb(243, 145, 145) !important; */
+}
\ No newline at end of file
diff --git a/app/layout.tsx b/app/layout.tsx
index 4114afcf..1d243994 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,12 +1,16 @@
'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';
import '../styles/layout/layout.scss';
import '../styles/demo/Demos.scss';
+import './globals.css';
+
interface RootLayoutProps {
children: React.ReactNode;
}
diff --git a/app/page.tsx b/app/page.tsx
new file mode 100644
index 00000000..ddd8c663
--- /dev/null
+++ b/app/page.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+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/hooks/useTypingEffect.tsx b/hooks/useTypingEffect.tsx
new file mode 100644
index 00000000..a5dac639
--- /dev/null
+++ b/hooks/useTypingEffect.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import { useEffect, useRef, useState } from 'react';
+
+export default function useTypingEffect(word: string, stop: boolean) {
+ const [typedText, setTypedText] = useState('');
+ const stopRef = useRef(stop);
+ const indexRef = useRef(0);
+ const intervalRef = useRef(null);
+
+ useEffect(() => {
+ stopRef.current = stop;
+
+ if (!stop) {
+ if (intervalRef.current) clearInterval(intervalRef.current);
+ setTypedText('');
+ indexRef.current = 0;
+ return;
+ }
+
+ intervalRef.current = setInterval(() => {
+ if (indexRef.current >= word.length) {
+ clearInterval(intervalRef.current!);
+ return;
+ }
+
+ setTypedText((prev) => {
+ const nextChar = word[indexRef.current];
+ indexRef.current++;
+ const nextText = prev + nextChar;
+
+ if (nextText.length > 50) {
+ clearInterval(intervalRef.current!);
+ alert('baby');
+ return '';
+ }
+
+ return nextText;
+ });
+ }, 60);
+
+ return () => clearInterval(intervalRef.current!);
+ }, [stop, word]);
+
+ return typedText
+}
\ No newline at end of file
diff --git a/layout/AppFooter.tsx b/layout/AppFooter.tsx
index 424b9987..9e41bccd 100644
--- a/layout/AppFooter.tsx
+++ b/layout/AppFooter.tsx
@@ -2,16 +2,62 @@
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
+ //
+
return (
-
-

- by
-
PrimeReact
-
+
);
};
diff --git a/layout/AppMenu.tsx b/layout/AppMenu.tsx
index b581ecf2..14f85869 100644
--- a/layout/AppMenu.tsx
+++ b/layout/AppMenu.tsx
@@ -4,7 +4,6 @@ import React, { useContext } from 'react';
import AppMenuitem from './AppMenuitem';
import { LayoutContext } from './context/layoutcontext';
import { MenuProvider } from './context/menucontext';
-import Link from 'next/link';
import { AppMenuItem } from '@/types';
const AppMenu = () => {
@@ -12,163 +11,31 @@ const AppMenu = () => {
const model: AppMenuItem[] = [
{
- label: 'Home',
- items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }]
+ label: 'Баракчалар',
+ items: [{ label: 'Башкы баракча', icon: 'pi pi-fw pi-home', to: '/' }]
},
{
- label: 'UI Components',
+ label: '',
items: [
- { label: 'Form Layout', icon: 'pi pi-fw pi-id-card', to: '/uikit/formlayout' },
- { label: 'Input', icon: 'pi pi-fw pi-check-square', to: '/uikit/input' },
- { label: 'Float Label', icon: 'pi pi-fw pi-bookmark', to: '/uikit/floatlabel' },
- { label: 'Invalid State', icon: 'pi pi-fw pi-exclamation-circle', to: '/uikit/invalidstate' },
- { label: 'Button', icon: 'pi pi-fw pi-mobile', to: '/uikit/button', class: 'rotated-icon' },
- { label: 'Table', icon: 'pi pi-fw pi-table', to: '/uikit/table' },
- { label: 'List', icon: 'pi pi-fw pi-list', to: '/uikit/list' },
- { label: 'Tree', icon: 'pi pi-fw pi-share-alt', to: '/uikit/tree' },
- { label: 'Panel', icon: 'pi pi-fw pi-tablet', to: '/uikit/panel' },
- { label: 'Overlay', icon: 'pi pi-fw pi-clone', to: '/uikit/overlay' },
- { label: 'Media', icon: 'pi pi-fw pi-image', to: '/uikit/media' },
- { label: 'Menu', icon: 'pi pi-fw pi-bars', to: '/uikit/menu', preventExact: true },
- { label: 'Message', icon: 'pi pi-fw pi-comment', to: '/uikit/message' },
- { label: 'File', icon: 'pi pi-fw pi-file', to: '/uikit/file' },
- { label: 'Chart', icon: 'pi pi-fw pi-chart-bar', to: '/uikit/charts' },
- { label: 'Misc', icon: 'pi pi-fw pi-circle', to: '/uikit/misc' }
+ { label: 'Dashboard', icon: 'pi pi-fw pi-id-card', to: '/' },
+ { label: 'Курстар', icon: 'pi pi-fw pi-id-card', to: '/course' },
+ // { label: 'Input', icon: 'pi pi-fw pi-check-square', to: '/uikit/input' },
+ // { label: 'Float Label', icon: 'pi pi-fw pi-bookmark', to: '/uikit/floatlabel' },
+ // { label: 'Invalid State', icon: 'pi pi-fw pi-exclamation-circle', to: '/uikit/invalidstate' },
+ // { label: 'Button', icon: 'pi pi-fw pi-mobile', to: '/uikit/button', class: 'rotated-icon' },
+ // { label: 'Table', icon: 'pi pi-fw pi-table', to: '/uikit/table' },
+ // { label: 'List', icon: 'pi pi-fw pi-list', to: '/uikit/list' },
+ // { label: 'Tree', icon: 'pi pi-fw pi-share-alt', to: '/uikit/tree' },
+ // { label: 'Panel', icon: 'pi pi-fw pi-tablet', to: '/uikit/panel' },
+ // { label: 'Overlay', icon: 'pi pi-fw pi-clone', to: '/uikit/overlay' },
+ // { label: 'Media', icon: 'pi pi-fw pi-image', to: '/uikit/media' },
+ // { label: 'Menu', icon: 'pi pi-fw pi-bars', to: '/uikit/menu', preventExact: true },
+ // { label: 'Message', icon: 'pi pi-fw pi-comment', to: '/uikit/message' },
+ // { label: 'File', icon: 'pi pi-fw pi-file', to: '/uikit/file' },
+ // { label: 'Chart', icon: 'pi pi-fw pi-chart-bar', to: '/uikit/charts' },
+ // { label: 'Misc', icon: 'pi pi-fw pi-circle', to: '/uikit/misc' }
]
},
- {
- label: 'Prime Blocks',
- items: [
- { label: 'Free Blocks', icon: 'pi pi-fw pi-eye', to: '/blocks', badge: 'NEW' },
- { label: 'All Blocks', icon: 'pi pi-fw pi-globe', url: 'https://blocks.primereact.org', target: '_blank' }
- ]
- },
- {
- label: 'Utilities',
- items: [
- { label: 'PrimeIcons', icon: 'pi pi-fw pi-prime', to: '/utilities/icons' },
- { label: 'PrimeFlex', icon: 'pi pi-fw pi-desktop', url: 'https://primeflex.org/', target: '_blank' }
- ]
- },
- {
- label: 'Pages',
- icon: 'pi pi-fw pi-briefcase',
- to: '/pages',
- items: [
- {
- label: 'Landing',
- icon: 'pi pi-fw pi-globe',
- to: '/landing'
- },
- {
- label: 'Auth',
- icon: 'pi pi-fw pi-user',
- items: [
- {
- label: 'Login',
- icon: 'pi pi-fw pi-sign-in',
- to: '/auth/login'
- },
- {
- label: 'Error',
- icon: 'pi pi-fw pi-times-circle',
- to: '/auth/error'
- },
- {
- label: 'Access Denied',
- icon: 'pi pi-fw pi-lock',
- to: '/auth/access'
- }
- ]
- },
- {
- label: 'Crud',
- icon: 'pi pi-fw pi-pencil',
- to: '/pages/crud'
- },
- {
- label: 'Timeline',
- icon: 'pi pi-fw pi-calendar',
- to: '/pages/timeline'
- },
- {
- label: 'Not Found',
- icon: 'pi pi-fw pi-exclamation-circle',
- to: '/pages/notfound'
- },
- {
- label: 'Empty',
- icon: 'pi pi-fw pi-circle-off',
- to: '/pages/empty'
- }
- ]
- },
- {
- label: 'Hierarchy',
- items: [
- {
- label: 'Submenu 1',
- icon: 'pi pi-fw pi-bookmark',
- items: [
- {
- label: 'Submenu 1.1',
- icon: 'pi pi-fw pi-bookmark',
- items: [
- { label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' },
- { label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' },
- { label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' }
- ]
- },
- {
- label: 'Submenu 1.2',
- icon: 'pi pi-fw pi-bookmark',
- items: [{ label: 'Submenu 1.2.1', icon: 'pi pi-fw pi-bookmark' }]
- }
- ]
- },
- {
- label: 'Submenu 2',
- icon: 'pi pi-fw pi-bookmark',
- items: [
- {
- label: 'Submenu 2.1',
- icon: 'pi pi-fw pi-bookmark',
- items: [
- { label: 'Submenu 2.1.1', icon: 'pi pi-fw pi-bookmark' },
- { label: 'Submenu 2.1.2', icon: 'pi pi-fw pi-bookmark' }
- ]
- },
- {
- label: 'Submenu 2.2',
- icon: 'pi pi-fw pi-bookmark',
- items: [{ label: 'Submenu 2.2.1', icon: 'pi pi-fw pi-bookmark' }]
- }
- ]
- }
- ]
- },
- {
- label: 'Get Started',
- items: [
- {
- label: 'Documentation',
- icon: 'pi pi-fw pi-question',
- to: '/documentation'
- },
- {
- label: 'Figma',
- url: 'https://www.dropbox.com/scl/fi/bhfwymnk8wu0g5530ceas/sakai-2023.fig?rlkey=u0c8n6xgn44db9t4zkd1brr3l&dl=0',
- icon: 'pi pi-fw pi-pencil',
- target: '_blank'
- },
- {
- label: 'View Source',
- icon: 'pi pi-fw pi-search',
- url: 'https://github.com/primefaces/sakai-react',
- target: '_blank'
- }
- ]
- }
];
return (
@@ -177,10 +44,6 @@ const AppMenu = () => {
{model.map((item, i) => {
return !item?.seperator ? : ;
})}
-
-
-
-
);
diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.tsx
index 9a2c8849..38da5e27 100644
--- a/layout/AppTopbar.tsx
+++ b/layout/AppTopbar.tsx
@@ -1,13 +1,19 @@
/* eslint-disable @next/next/no-img-element */
import Link from 'next/link';
-import { classNames } from 'primereact/utils';
import React, { forwardRef, useContext, useImperativeHandle, useRef } from 'react';
+import Tiered from '@/app/components/popUp/Tiered';
+import FancyLinkBtn from '@/app/components/buttons/FancyLinkBtn';
+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 { logout } from '@/utils/logout';
const AppTopbar = forwardRef((props, ref) => {
- const { layoutConfig, layoutState, onMenuToggle, showProfileSidebar } = useContext(LayoutContext);
+ const { layoutConfig, layoutState, onMenuToggle, showProfileSidebar, user, setUser, setGlobalLoading } = useContext(LayoutContext);
+
const menubuttonRef = useRef(null);
const topbarmenuRef = useRef(null);
const topbarmenubuttonRef = useRef(null);
@@ -18,36 +24,162 @@ 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 = [
+ user
+ ? {
+ label: 'Профиль',
+ icon: 'pi pi-user',
+ items: [
+ {
+ label: (
+
+
+ {user?.last_name}
+ {user?.name}
+
+
{user?.email}
+
+ )
+ },
+ {
+ label: 'Чыгуу',
+ icon: 'pi pi-sign-out',
+ items: [],
+ command: () => {
+ logout({ setUser, setGlobalLoading });
+ }
+ }
+ ]
+ }
+ : {
+ label: 'Кирүү',
+ icon: 'pi pi-sign-in',
+ items: [],
+ link: '/auth/login'
+ },
+ {
+ label: 'ОшМУнун сайты',
+ icon: '',
+ items: [],
+ link: 'https://oshsu.kg'
+ },
+ {
+ label: 'Байланыш',
+ icon: '',
+ items: []
+ }
+ ];
+
+ // profile
+ const profileItems = [
+ {
+ label: (
+
+
+ {user?.last_name}
+ {user?.name}
+
+
{user?.email}
+
+ )
+ },
+ {
+ label: 'Чыгуу',
+ icon: 'pi pi-sign-out',
+ items: [],
+ command: () => {
+ logout({ setUser, setGlobalLoading });
+ }
+ }
+ ];
+
return (
-

-
SAKAI
+ {/*

*/}
+

+
Цифровой кампус ОшГУ
-
-
-
-
-
-
-
+ {pathName !== '/' ? (
+
+
+
+ ) : (
+ ''
+ )}
-
-
- Calendar
-
-
-
- Profile
-
-
-
-
- Settings
-
-
+
+ {media ? (
+
+ ) : (
+
+ {/*
+ */}
+
+ ОшМУнун сайты
+
+
+ Байланыш
+
+
+ )}
+
+ {user && user ? (
+
+
+
+ ) : (
+
+
+
+
+
+ )}
+
);
diff --git a/layout/context/layoutcontext.tsx b/layout/context/layoutcontext.tsx
index 58e491dc..3581eb9d 100644
--- a/layout/context/layoutcontext.tsx
+++ b/layout/context/layoutcontext.tsx
@@ -1,6 +1,13 @@
'use client';
-import React, { useState, createContext } from 'react';
+import React, { useState, createContext, useEffect } from 'react';
import { LayoutState, ChildContainerProps, LayoutConfig, LayoutContextProps } from '@/types';
+import SessionManager from '@/app/components/SessionManager';
+import GlobalLoading from '@/app/components/loading/GlobalLoading';
+import Message from '@/app/components/messages/Message';
+import { ConfirmDialog } from 'primereact/confirmdialog';
+import { User } from '@/types/user';
+import { MessageType } from '@/types/messageType';
+
export const LayoutContext = createContext({} as LayoutContextProps);
export const LayoutProvider = ({ children }: ChildContainerProps) => {
@@ -22,6 +29,15 @@ export const LayoutProvider = ({ children }: ChildContainerProps) => {
menuHoverActive: false
});
+ // 👇 Добавляем пользователя
+ const [user, setUser] = useState(null);
+
+ // Глобальная загрузка
+ const [globalLoading, setGlobalLoading] = useState(true);
+
+ // Сообщение об ошибке/успехе
+ const [message, setMessage] = useState({state:false, value:{}});
+
const onMenuToggle = () => {
if (isOverlay()) {
setLayoutState((prevLayoutState) => ({ ...prevLayoutState, overlayMenuActive: !prevLayoutState.overlayMenuActive }));
@@ -52,8 +68,20 @@ export const LayoutProvider = ({ children }: ChildContainerProps) => {
layoutState,
setLayoutState,
onMenuToggle,
- showProfileSidebar
+ showProfileSidebar,
+ user,
+ setUser,
+ globalLoading,
+ setGlobalLoading,
+ message,
+ setMessage
};
- return {children};
+ return
+
+
+
+ {message.state && }
+ {children}
+ ;
};
diff --git a/layout/layout.tsx b/layout/layout.tsx
index 8421b2ca..ef069787 100644
--- a/layout/layout.tsx
+++ b/layout/layout.tsx
@@ -131,7 +131,7 @@ const Layout = ({ children }: ChildContainerProps) => {
diff --git a/package-lock.json b/package-lock.json
index 332e8ef7..f2d66700 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,23 +8,37 @@
"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",
+ "@hookform/resolvers": "^5.1.1",
"@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",
+ "primeflex": "^4.0.0",
+ "primeicons": "^7.0.0",
+ "primereact": "^10.9.6",
+ "quill": "^2.0.3",
"react": "18.2.0",
+ "react-countup": "^6.5.3",
"react-dom": "18.2.0",
- "typescript": "5.1.3"
+ "react-hook-form": "^7.58.1",
+ "typescript": "5.1.3",
+ "yup": "^1.6.1"
},
"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": {
@@ -36,6 +50,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",
@@ -103,6 +142,59 @@
"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/@hookform/resolvers": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.1.1.tgz",
+ "integrity": "sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==",
+ "dependencies": {
+ "@standard-schema/utils": "^0.3.0"
+ },
+ "peerDependencies": {
+ "react-hook-form": "^7.55.0"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
@@ -136,6 +228,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",
@@ -331,6 +483,11 @@
"integrity": "sha512-UY+FGM/2jjMkzQLn8pxcHGMaVLh9aEitG3zY2CiY7XHdLiz3bZOwa6oDxNqEMv7zZkV+cj5DOdz0cQ1BP5Hjgw==",
"dev": true
},
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="
+ },
"node_modules/@swc/helpers": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz",
@@ -339,6 +496,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",
@@ -561,6 +979,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",
@@ -721,6 +1149,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",
@@ -788,6 +1253,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",
@@ -823,9 +1320,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",
@@ -907,6 +1404,20 @@
"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",
+ "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 +1447,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",
@@ -1024,6 +1545,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",
@@ -1057,6 +1587,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",
@@ -1064,9 +1600,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",
@@ -1191,6 +1727,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",
@@ -1614,12 +2159,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
+ },
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@@ -1738,6 +2293,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",
@@ -2449,6 +3017,15 @@
"set-function-name": "^2.0.1"
}
},
+ "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",
@@ -2489,66 +3066,294 @@
"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"
+ "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,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "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,
+ "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": {
@@ -2566,12 +3371,38 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
+ },
+ "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.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
+ },
"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",
@@ -2595,6 +3426,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",
@@ -2638,6 +3478,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",
@@ -2645,9 +3521,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",
@@ -2717,6 +3593,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",
@@ -2726,6 +3631,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",
@@ -2899,6 +3813,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/parchment": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
+ "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A=="
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -2954,9 +3873,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",
@@ -2971,9 +3890,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",
@@ -2982,17 +3902,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",
@@ -3018,19 +3948,19 @@
}
},
"node_modules/primeflex": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz",
- "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ=="
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-4.0.0.tgz",
+ "integrity": "sha512-UOEZCRjR36+sm5bUpDhS1xbA068l9VC6y1aTNVqQPtXuKIdPTqAWHRUxj3mKAoPrQ9W373ooJJMgNVXfiaw04g=="
},
"node_modules/primeicons": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz",
- "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA=="
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz",
+ "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw=="
},
"node_modules/primereact": {
- "version": "10.2.1",
- "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.2.1.tgz",
- "integrity": "sha512-F25053E1z+fod6V7AJ1Ix/DwSPkFQotk2+Idm0XkFsN+gQEywH7DgtbvNKpUA+LEq48h2+/WVK3D0V8IAm1Npg==",
+ "version": "10.9.6",
+ "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.9.6.tgz",
+ "integrity": "sha512-0Jjz/KzfUURSHaPTXJwjL2Dc7CDPnbO17MivyJz7T5smGAMLY5d+IqpQhV61R22G/rDmhMh3+32LCNva2M8fRw==",
"dependencies": {
"@types/react-transition-group": "^4.4.1",
"react-transition-group": "^4.4.1"
@@ -3039,9 +3969,9 @@
"node": ">=14.0.0"
},
"peerDependencies": {
- "@types/react": "^17.0.0 || ^18.0.0",
- "react": "^17.0.0 || ^18.0.0",
- "react-dom": "^17.0.0 || ^18.0.0"
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -3059,6 +3989,11 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -3088,6 +4023,33 @@
}
]
},
+ "node_modules/quill": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz",
+ "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
+ "dependencies": {
+ "eventemitter3": "^5.0.1",
+ "lodash-es": "^4.17.21",
+ "parchment": "^3.0.0",
+ "quill-delta": "^5.1.0"
+ },
+ "engines": {
+ "npm": ">=8.2.3"
+ }
+ },
+ "node_modules/quill-delta": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
+ "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
+ "dependencies": {
+ "fast-diff": "^1.3.0",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.isequal": "^4.5.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
@@ -3099,6 +4061,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",
@@ -3111,6 +4084,21 @@
"react": "^18.2.0"
}
},
+ "node_modules/react-hook-form": {
+ "version": "7.58.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.58.1.tgz",
+ "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -3414,9 +4402,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"
}
@@ -3573,6 +4561,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",
@@ -3582,12 +4576,43 @@
"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",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
+ "node_modules/tiny-case": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
+ "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -3600,6 +4625,11 @@
"node": ">=8.0"
}
},
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
+ },
"node_modules/tsconfig-paths": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
@@ -3754,6 +4784,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",
@@ -3890,6 +4950,28 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/yup": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz",
+ "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==",
+ "dependencies": {
+ "property-expr": "^2.0.5",
+ "tiny-case": "^1.0.3",
+ "toposort": "^2.0.2",
+ "type-fest": "^2.19.0"
+ }
+ },
+ "node_modules/yup/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/zod": {
"version": "3.21.4",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
diff --git a/package.json b/package.json
index 8071b50b..4537b719 100644
--- a/package.json
+++ b/package.json
@@ -10,22 +10,36 @@
"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",
+ "@hookform/resolvers": "^5.1.1",
"@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",
+ "primeflex": "^4.0.0",
+ "primeicons": "^7.0.0",
+ "primereact": "^10.9.6",
+ "quill": "^2.0.3",
"react": "18.2.0",
+ "react-countup": "^6.5.3",
"react-dom": "18.2.0",
- "typescript": "5.1.3"
+ "react-hook-form": "^7.58.1",
+ "typescript": "5.1.3",
+ "yup": "^1.6.1"
},
"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"
}
-}
\ No newline at end of file
+}
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/public/layout/images/home-banner-phone.png b/public/layout/images/home-banner-phone.png
new file mode 100644
index 00000000..399a19dc
Binary files /dev/null and b/public/layout/images/home-banner-phone.png differ
diff --git a/public/layout/images/home-two.png b/public/layout/images/home-two.png
new file mode 100644
index 00000000..3372a6ad
Binary files /dev/null and b/public/layout/images/home-two.png differ
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 00000000..3d28f7d5
Binary files /dev/null and b/public/layout/images/logo-remove-white.png differ
diff --git a/public/layout/images/logo-remove.png b/public/layout/images/logo-remove.png
new file mode 100644
index 00000000..929f087a
Binary files /dev/null and b/public/layout/images/logo-remove.png differ
diff --git a/public/layout/images/man.png b/public/layout/images/man.png
new file mode 100644
index 00000000..0168ee16
Binary files /dev/null and b/public/layout/images/man.png differ
diff --git a/public/layout/images/no-image.png b/public/layout/images/no-image.png
new file mode 100644
index 00000000..3f257212
Binary files /dev/null and b/public/layout/images/no-image.png differ
diff --git a/public/layout/images/shape.png b/public/layout/images/shape.png
new file mode 100644
index 00000000..a82ce023
Binary files /dev/null and b/public/layout/images/shape.png differ
diff --git a/public/layout/images/shape1.png b/public/layout/images/shape1.png
new file mode 100644
index 00000000..bee24c65
Binary files /dev/null and b/public/layout/images/shape1.png differ
diff --git a/public/layout/images/shape2.png b/public/layout/images/shape2.png
new file mode 100644
index 00000000..f1fe1c5b
Binary files /dev/null and b/public/layout/images/shape2.png differ
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/schemas/authSchema.tsx b/schemas/authSchema.tsx
new file mode 100644
index 00000000..6d8159a5
--- /dev/null
+++ b/schemas/authSchema.tsx
@@ -0,0 +1,22 @@
+import * as yup from 'yup';
+
+export const schema = yup.object().shape({
+ email: yup.string()
+ .email('email туура эмес форматта')
+ .required('email талап кылынат!')
+ .matches(
+ /^[a-zA-Z0-9._%+-]+@oshsu\.kg$/,
+ 'email "@oshsu.kg" форматында болуш керек'
+ )
+ .matches(
+ /^[a-zA-Z0-9._%+-]+@oshsu\.kg$/, // Стандартный формат email (только буквы, цифры, точки, подчеркивания и плюсы)
+ 'email "@oshsu.kg" форматында жана тыюу салынган символдор камтылбашы керек'
+ ),
+ password: yup.string()
+ .required('Сырсөз талап кылынат!')
+ .max(20, 'Сырсөз эң көп дегенде 20 белгиден турушу керек')
+ .matches(
+ /^[^!@#$%^&*()_+={}[\]:;"'`<>,.?/\\|]*$/,
+ 'Сырсөздө тыюу салынган символдор камтылбашы керек'
+ ),
+});
\ No newline at end of file
diff --git a/schemas/lessonSchema.tsx b/schemas/lessonSchema.tsx
new file mode 100644
index 00000000..256a7c01
--- /dev/null
+++ b/schemas/lessonSchema.tsx
@@ -0,0 +1,16 @@
+import * as yup from 'yup';
+
+export const lessonSchema = yup.object().shape({
+ videoReq: yup.string()
+ .required('Талап кылынат!')
+ .matches(
+ /^https?:\/\/.+/,
+ 'Видео шилтеме "http://" "https://" форматында болуш керек'
+ ),
+ usefulLink: yup.string()
+ .required('Талап кылынат!')
+ .matches(
+ /^[^!@#$%^&*()_+={}[\]:;"'`<>,.?/\\|]*$/,
+ 'Сырсөздө тыюу салынган символдор камтылбашы керек'
+ ),
+});
\ No newline at end of file
diff --git a/services/auth.tsx b/services/auth.tsx
new file mode 100644
index 00000000..72fa6843
--- /dev/null
+++ b/services/auth.tsx
@@ -0,0 +1,50 @@
+import { LoginType } from "@/types/login";
+
+let url = '';
+
+// const params = new URLSearchParams({
+// category_id: String(id),
+// active: '' + param.active,
+// ending: '' + param.ending,
+// });
+
+export const login = async (value:LoginType) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + '/login?';
+
+ try {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(value)
+ });
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при авторизации', err);
+ return [];
+ }
+};
+
+export const getUser = async (token:string) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + '/v1/user';
+
+ const headers: HeadersInit = token
+ ? {
+ Authorization: `Bearer ${token}`
+ }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при получении пользователя', err);
+ return [];
+ }
+};
diff --git a/services/courses.tsx b/services/courses.tsx
new file mode 100644
index 00000000..a14e15a9
--- /dev/null
+++ b/services/courses.tsx
@@ -0,0 +1,234 @@
+import { AuthBaseType } from "@/types/authBaseType";
+import { CourseCreateType } from "@/types/courseCreateType";
+
+let url = '';
+
+type OnlyTitle = Pick
;
+
+export const fetchCourses = async (token:string | null) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + '/v1/teacher/courses';
+
+ const headers: HeadersInit = token
+ ? {
+ Authorization: `Bearer ${token}`
+ }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при получении курсов', err);
+ return [];
+ }
+};
+
+export const addCourse = async (token:string | null, value:CourseCreateType) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + '/v1/teacher/courses/store';
+ console.log(value);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ console.log(value);
+
+ const formData = new FormData();
+ formData.append('title', value.title);
+ formData.append('description', value.description);
+ formData.append('image', value.image);
+ formData.append('video_url', value.video_url);
+
+ try {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers,
+ body: formData
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при добавлении курса', err);
+ return [];
+ }
+};
+
+export const deleteCourse = async (token:string | null, id:number) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/courses/delete?course_id=${id}`;
+ console.log(id);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ method: 'DELETE',
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при удалении курса', err);
+ return [];
+ }
+};
+
+export const updateCourse = async (token: string | null, id:number | null, value) => {
+ console.log(value);
+
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/courses/update?course_id=${id}`;
+
+ const formData = new FormData();
+ formData.append('title', value.title);
+ formData.append('description', value.description);
+ if (value.image instanceof File) {
+ formData.append('image', value.image);
+ }
+ formData.append('video_url', value.video_url);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers,
+ body: formData
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при обновлении курса', err);
+ return [];
+ }
+};
+
+// Themes
+
+export const fetchCourseInfo = async (token:AuthBaseType, id:AuthBaseType) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/courses/show?course_id=${id}`;
+
+ const headers: HeadersInit = token
+ ? {
+ Authorization: `Bearer ${token}`
+ }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при получении темы', err);
+ return [];
+ }
+};
+
+export const addThemes = async (token:string | null, id:number, value:OnlyTitle) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/lessons/store?course_id=${id}&title=${value}`;
+ console.log(value);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ const formData = new FormData();
+ formData.append('title', value);
+
+ try {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers,
+ body: formData
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при добавлении темы', err);
+ return [];
+ }
+};
+
+export const fetchThemes = async (token:string | null, id:number) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/lessons?course_id=${id}`;
+
+ const headers: HeadersInit = token
+ ? {
+ Authorization: `Bearer ${token}`
+ }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при получении темы', err);
+ return [];
+ }
+};
+
+export const updateTheme = async (token: string | null, course_id:number | null, theme_id: number, value:CourseCreateType) => {
+ console.log(value);
+
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/lessons/update?course_id=${course_id}&title=${value}&lesson_id=${theme_id}`;
+
+ const formData = new FormData();
+ formData.append('title', value.title);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers,
+ body: formData
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при обновлении темы', err);
+ return [];
+ }
+};
+
+export const deleteTheme = async (token:string | null, id:number) => {
+ url = process.env.NEXT_PUBLIC_BASE_URL + `/v1/teacher/lessons/delete?lesson_id=${id}`;
+ console.log(id);
+
+ const headers: HeadersInit = token
+ ? { Authorization: `Bearer ${token}` }
+ : {};
+
+ try {
+ const res = await fetch(url, {
+ method: 'DELETE',
+ headers
+ });
+
+ const data = await res.json();
+ return data;
+ } catch (err) {
+ console.log('Ошибка при удалении темы', err);
+ return [];
+ }
+};
\ No newline at end of file
diff --git a/styles/layout/_button.scss b/styles/layout/_button.scss
new file mode 100644
index 00000000..980c20d2
--- /dev/null
+++ b/styles/layout/_button.scss
@@ -0,0 +1,67 @@
+button {
+ outline: 0;
+ border: none;
+
+ &:focus {
+ outline: 0;
+ border: 0;
+ }
+}
+
+.default-btn {
+ text-align: center;
+ color: var(--whiteColor);
+ // font-size: var(--fontSize);
+ font-weight: 600;
+ 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;
+}
+
+.p-button{
+ background-color: var(--mainColor);
+ padding: 7px 14px;
+ font-weight: bold;
+}
+
+@media screen and (max-width: '640px') {
+ .p-button {
+ padding: 5px 10px;
+ }
+}
+
+.reject-button {
+ background-color: transparent;
+ color: var(--bodyColor);
+}
\ No newline at end of file
diff --git a/styles/layout/_topbar.scss b/styles/layout/_topbar.scss
index 79402366..d6a02350 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;
@@ -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;
+ // height: 2.5rem;
+ // margin-right: .5rem;
}
&:focus {
@@ -63,7 +63,7 @@
}
.layout-menu-button {
- margin-left: 2rem;
+ // margin-left: 2rem;
}
.layout-topbar-menu-button {
@@ -81,7 +81,7 @@
display: flex;
.layout-topbar-button {
- margin-left: 1rem;
+ // margin-left: 1rem;
}
}
}
@@ -91,35 +91,35 @@
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/styles/layout/_typography.scss b/styles/layout/_typography.scss
index b9a0c8ff..6278de2f 100644
--- a/styles/layout/_typography.scss
+++ b/styles/layout/_typography.scss
@@ -3,37 +3,13 @@ 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;
}
}
-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/styles/layout/layout.scss b/styles/layout/layout.scss
index fef2ed48..0b5314a9 100644
--- a/styles/layout/layout.scss
+++ b/styles/layout/layout.scss
@@ -8,4 +8,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
diff --git a/types/authBaseType.tsx b/types/authBaseType.tsx
new file mode 100644
index 00000000..2aab9c9e
--- /dev/null
+++ b/types/authBaseType.tsx
@@ -0,0 +1,4 @@
+export interface AuthBaseType {
+ token: string | null;
+ id: number;
+}
\ No newline at end of file
diff --git a/types/courseCreateType.tsx b/types/courseCreateType.tsx
new file mode 100644
index 00000000..3be660c4
--- /dev/null
+++ b/types/courseCreateType.tsx
@@ -0,0 +1,6 @@
+export interface CourseCreateType {
+ title: string;
+ description: string;
+ video_url: string;
+ image?: string | File;
+}
\ No newline at end of file
diff --git a/types/courseType.tsx b/types/courseType.tsx
new file mode 100644
index 00000000..7b339e63
--- /dev/null
+++ b/types/courseType.tsx
@@ -0,0 +1,10 @@
+export interface CourseType {
+ created_at: string;
+ description: string;
+ id: number;
+ image: string;
+ status: boolean;
+ title: string;
+ user_id: number;
+ video_url: string;
+}
diff --git a/types/layout.d.ts b/types/layout.d.ts
index fe94e601..fd7dbba4 100644
--- a/types/layout.d.ts
+++ b/types/layout.d.ts
@@ -2,6 +2,8 @@ import React, { ReactElement, Dispatch, SetStateAction, HTMLAttributeAnchorTarge
import { NextPage } from 'next';
import { Demo } from './demo';
import { Toast } from 'primereact/toast';
+import { User } from './user';
+import { MessageType } from './messageType';
/* Breadcrumb Types */
export interface AppBreadcrumbProps {
@@ -45,6 +47,14 @@ export interface LayoutContextProps {
setLayoutState: Dispatch>;
onMenuToggle: () => void;
showProfileSidebar: () => void;
+ user: User | null;
+ setUser: React.Dispatch>;
+ globalLoading: boolean;
+ setGlobalLoading: React.Dispatch>;
+ message: MessageType;
+ setMessage: React.Dispatch>;
+ // message: { state: boolean; value: MessageType };
+ // setMessage: React.Dispatch>;
}
export interface MenuContextProps {
diff --git a/types/login.tsx b/types/login.tsx
new file mode 100644
index 00000000..2cae126b
--- /dev/null
+++ b/types/login.tsx
@@ -0,0 +1,4 @@
+export interface LoginType {
+ email: string;
+ password: string;
+}
diff --git a/types/messageType.tsx b/types/messageType.tsx
new file mode 100644
index 00000000..589dbb8c
--- /dev/null
+++ b/types/messageType.tsx
@@ -0,0 +1,8 @@
+export interface MessageType {
+ state: boolean;
+ value: {
+ severity?:string;
+ summary?:string;
+ detail?:string;
+ }
+}
\ No newline at end of file
diff --git a/types/user.tsx b/types/user.tsx
new file mode 100644
index 00000000..442e50e9
--- /dev/null
+++ b/types/user.tsx
@@ -0,0 +1,12 @@
+export interface User {
+ birth_date: null;
+ email: string;
+ father_name: string;
+ id: number;
+ is_student: boolean;
+ is_working: boolean;
+ last_name: string;
+ name: string;
+ phone: string;
+ pin: null;
+}
diff --git a/utils/auth.tsx b/utils/auth.tsx
new file mode 100644
index 00000000..8ec683b5
--- /dev/null
+++ b/utils/auth.tsx
@@ -0,0 +1,28 @@
+'use client';
+
+export function getToken(name:string) {
+ if (typeof document === 'undefined') {
+ return null;
+ }
+
+ const cookies = document.cookie ? document.cookie.split("; ") : [];
+ for (let cookie of cookies) {
+ const [key, value] = cookie.split("=");
+ if (key === name) return decodeURIComponent(value);
+ }
+ return null;
+};
+
+export function isTokenExpired() {
+ const testToken = getToken('access_token');
+
+ try {
+ if (!testToken) throw new Error("Токен отсутствует");
+
+ const { exp } = JSON.parse(atob(testToken.split(".")[1]));
+ return exp - Math.floor(Date.now() / 1000) <= 300;
+ } catch (error) {
+ console.log("Ошибка при разборе токена:", error);
+ return true; // В случае ошибки считаем, что истёк
+ }
+}
\ No newline at end of file
diff --git a/utils/getConfirmOptions.tsx b/utils/getConfirmOptions.tsx
new file mode 100644
index 00000000..f4cf42f7
--- /dev/null
+++ b/utils/getConfirmOptions.tsx
@@ -0,0 +1,11 @@
+export const getConfirmOptions = (id: number, handleDeleteCourse, ) => ({
+ message: 'Сиз чын эле өчүрүүнү каалайсызбы?',
+ header: 'Өчүрүү',
+ icon: 'pi pi-info-circle',
+ defaultFocus: 'reject',
+ acceptClassName: 'p-button-danger',
+ acceptLabel: 'Өчүрүү',
+ rejectLabel: 'Артка',
+ rejectClassName: 'p-button-secondary reject-button',
+ accept: () => handleDeleteCourse(id)
+});
diff --git a/utils/getRedactor.tsx b/utils/getRedactor.tsx
new file mode 100644
index 00000000..c58848fd
--- /dev/null
+++ b/utils/getRedactor.tsx
@@ -0,0 +1,18 @@
+import { confirmDialog } from 'primereact/confirmdialog';
+
+export const getRedactor = (rowData: any, handlers ) => [
+ {
+ label: '',
+ icon: 'pi pi-pencil',
+ command: () => {
+ handlers.onEdit(rowData)
+ }
+ },
+ {
+ label: '',
+ icon: 'pi pi-trash',
+ command: () => {
+ confirmDialog(handlers.getConfirmOptions(rowData.id, handlers.onDelete ));
+ }
+ }
+];
diff --git a/utils/logout.tsx b/utils/logout.tsx
new file mode 100644
index 00000000..38d88fbf
--- /dev/null
+++ b/utils/logout.tsx
@@ -0,0 +1,14 @@
+'use client';
+
+export const logout = ({setGlobalLoading, setUser}) => {
+ console.log('logout');
+ setGlobalLoading(true);
+
+ setTimeout(() => {
+ setGlobalLoading(false);
+ }, 1000);
+
+ setUser(null);
+ localStorage.removeItem('userVisit');
+ document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;';
+};