Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
52ac8f2
feat(19): Init AddLesson form
marina-bul Oct 9, 2025
e235b75
Merge branch 'main' into 19
marina-bul Oct 9, 2025
5fc3233
feat(19): Add date inputs and calendar block
marina-bul Oct 21, 2025
cb6bbb6
fix(19): Refactoring form component
marina-bul Oct 23, 2025
36e5f99
fix(19): Fix datepicker, schema and date components
marina-bul Nov 12, 2025
2f58b45
Merge branch 'main' into 19
marina-bul Nov 12, 2025
33daa6b
feat(19): Add mobile version
marina-bul Nov 18, 2025
7d92b66
fix(19): Small style fixes
marina-bul Nov 18, 2025
6bf2ed1
fix(19): Build fix
marina-bul Nov 18, 2025
ac5ecd4
feat(modules.navigation): redesign
unknownproperty Feb 19, 2026
0ea2009
feat(modules.navigation): update notifications
unknownproperty Feb 20, 2026
dfd207e
feat(modules.navigation): redesign main part first
unknownproperty Feb 20, 2026
7b198de
feat(modules.navigation): add Calendar to sidebar
unknownproperty Feb 20, 2026
72f5ec5
feat(modules.navigation): add Calendar to sidebar
unknownproperty Feb 20, 2026
834d4e6
Merge branch 'redesign' of https://github.com/xi-effect/xi.tutor into…
unknownproperty Feb 20, 2026
c0a018a
Merge branch 'redesign' of https://github.com/xi-effect/xi.tutor into 19
unknownproperty Feb 20, 2026
edfcac9
fix: regenerate pnpm-lock
unknownproperty Feb 20, 2026
8b77bb1
Merge pull request #78 from xi-effect/19
unknownproperty Feb 20, 2026
4a89aa1
feat(features.lesson.add): update lesson create mdal
unknownproperty Feb 20, 2026
dd9370f
fix(features.lesson.add): some improves
unknownproperty Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apps/xi.web/public/assets/brand/navigationlogo-small-dark-new.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions apps/xi.web/public/assets/brand/navigationlogo-small-dark.svg

This file was deleted.

11 changes: 11 additions & 0 deletions apps/xi.web/public/assets/brand/navigationlogo-small-light-new.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

1 change: 1 addition & 0 deletions apps/xi.web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@source "../../../packages/pages.email/src";
@source "../../../packages/pages.notes/src";
@source "../../../packages/pages.email-confirm/src";
@source "../../../packages/features.lesson.add/src";

@source "../../../node_modules/@xipkg";

Expand Down
4 changes: 2 additions & 2 deletions apps/xi.web/src/pages/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRootRouteWithContext, HeadContent, Outlet, redirect } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
// import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
import { AuthContextT } from 'common.auth';

interface MyRouterContext {
Expand Down Expand Up @@ -75,7 +75,7 @@ export const Route = createRootRouteWithContext<MyRouterContext>()({
<>
<HeadContent />
<Outlet />
<TanStackRouterDevtools />
{/* <TanStackRouterDevtools /> */}
</>
),
});
1 change: 1 addition & 0 deletions packages/common.ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export { LinkTanstack } from './src/LinkTanstack';
export { ErrorPage } from './src/ErrorPage';
export { Menu } from './src/Menu';
export { NetworkIndicator } from './src/NetworkIndicator';
export { SmallLogo } from './src/SmallLogo';
2 changes: 1 addition & 1 deletion packages/common.ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"@tanstack/react-router": "1.128.8",
"@xipkg/button": "4.1.0",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/link": "2.0.12",
"@xipkg/utils": "1.8.0",
"common.env": "*",
Expand Down
20 changes: 20 additions & 0 deletions packages/common.ui/src/SmallLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const SmallLogo = ({ width = 135, height = 16 }: { width?: number; height?: number }) => {
return (
<>
<img
src="/assets/brand/navigationlogo-small-light-new.svg"
alt="logo"
width={width}
height={height}
className="dark:hidden"
/>
<img
src="/assets/brand/navigationlogo-small-dark-new.svg"
alt="logo"
width={width}
height={height}
className="hidden dark:block"
/>
</>
);
};
2 changes: 1 addition & 1 deletion packages/features.avatar.editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"common.ui": "*",
"i18next": "24.2.2",
"react-i18next": "15.4.1",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/utils": "1.8.0",
"@xipkg/slider": "2.0.12",
"common.config": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/features.group.invite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"@tanstack/react-query": "^5.73.3",
"@tanstack/react-router": "^1.128.8",
"@xipkg/button": "4.1.0",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/input": "^2.2.9",
"@xipkg/modal": "^4.3.1",
"@xipkg/scrollarea": "^2.2.0",
"@xipkg/tooltip": "^2.1.0",
"@xipkg/userprofile": "^4.0.14",
"@xipkg/userprofile": "4.1.0",
"@xipkg/utils": "^1.8.0",
"common.api": "*",
"common.config": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/features.group.manage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"@tanstack/react-query": "^5.73.3",
"@tanstack/react-router": "^1.128.8",
"@xipkg/button": "4.1.0",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/input": "^2.2.9",
"@xipkg/modal": "^4.3.1",
"@xipkg/scrollarea": "^2.2.0",
"@xipkg/tooltip": "^2.1.0",
"@xipkg/userprofile": "^4.0.14",
"@xipkg/userprofile": "4.1.0",
"@xipkg/utils": "^1.8.0",
"common.api": "*",
"common.config": "*",
Expand Down
2 changes: 1 addition & 1 deletion packages/features.invites/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@xipkg/button": "4.1.0",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/modal": "^4.3.1",
"@xipkg/utils": "^1.8.0",
"common.env": "*",
Expand Down
2 changes: 1 addition & 1 deletion packages/features.invoice.card/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"common.api": "*",
"common.utils": "*",
"common.types": "*",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/button": "4.0.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/features.invoice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@tanstack/react-router": "1.120.11",
"@xipkg/button": "4.1.0",
"@xipkg/form": "4.2.1",
"@xipkg/icons": "^3.0.3",
"@xipkg/icons": "^3.0.4",
"@xipkg/input": "2.2.9",
"@xipkg/modal": "^4.3.1",
"@xipkg/select": "2.2.5",
Expand Down
3 changes: 3 additions & 0 deletions packages/features.lesson.add/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import config from 'common.eslint';

export default config;
1 change: 1 addition & 0 deletions packages/features.lesson.add/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AddingLessonModal } from './src';
56 changes: 56 additions & 0 deletions packages/features.lesson.add/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "features.lesson.add",
"version": "0.0.0",
"type": "module",
"exports": {
".": "./index.ts"
},
"license": "MIT",
"scripts": {
"dev": "tsc --watch",
"lint": "eslint \"**/*.{ts,tsx}\""
},
"dependencies": {
"@tanstack/react-router": "1.120.11",
"@tanstack/react-query": "^5.73.3",
"react-i18next": "15.4.1",
"sonner": "^1.4.0",
"common.services": "*",
"common.utils": "*",
"common.config": "*",
"common.api": "*",
"common.env": "*",
"common.types": "*",
"@xipkg/modal": "4.3.1",
"@xipkg/select": "2.2.5",
"@xipkg/utils": "1.8.0",
"@xipkg/form": "4.2.1",
"@xipkg/button": "4.1.0",
"@xipkg/input": "2.2.9",
"@xipkg/icons": "^3.0.4",
"@xipkg/datepicker": "2.2.0",
"@xipkg/inputmask": "2.0.12"
},
"devDependencies": {
"@eslint/js": "^9.19.0",
"common.typescript": "*",
"common.eslint": "*",
"@types/node": "^20.3.1",
"@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2",
"@xipkg/eslint": "3.2.0",
"@xipkg/tailwind": "0.8.1",
"@xipkg/typescript": "latest",
"eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
"typescript": "~5.7.2",
"typescript-eslint": "^8.22.0"
},
"peerDependencies": {
"react": "19"
},
"description": "adding lesson feature",
"author": "xi.effect"
}
2 changes: 2 additions & 0 deletions packages/features.lesson.add/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { useAddingForm } from './useAddingForm';
export { useConstants } from './useConstants';
62 changes: 62 additions & 0 deletions packages/features.lesson.add/src/hooks/useAddingForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useForm } from '@xipkg/form';
import { zodResolver } from '@hookform/resolvers/zod';
import { toast } from 'sonner';
import { formSchema, type FormData } from '../model/formSchema';
import { useFetchClassrooms } from 'common.services';

const DEFAULT_VALUES: FormData = {
title: '',
description: '',
studentId: '',
startTime: '09:00',
endTime: '10:00',
startDate: new Date(),
shouldRepeat: 'dont_repeat',
};

export const useAddingForm = () => {
const { data: classrooms, isLoading: isClassroomsLoading } = useFetchClassrooms();

const form = useForm<FormData>({
resolver: zodResolver(formSchema),
mode: 'onSubmit',
defaultValues: DEFAULT_VALUES,
});

const { control, handleSubmit, reset } = form;

const onSubmit = (data: FormData) => {
const classroom = classrooms?.find((c) => c.id === Number(data.studentId));
const studentIds = classroom?.kind === 'individual' ? [classroom.student_id] : [];

const payload = {
title: data.title,
description: data.description ?? '',
studentIds,
startTime: data.startTime,
endTime: data.endTime,
startDate: data.startDate,
shouldRepeat: data.shouldRepeat,
};

console.log('payload', payload);

// TODO: подключить API создания урока (common.api или модуль календаря)
// await createLesson(payload);
toast.success('Урок назначен');
};

const handleClearForm = () => {
reset(DEFAULT_VALUES);
};

return {
form,
control,
handleSubmit,
onSubmit,
handleClearForm,
classrooms: classrooms ?? [],
isClassroomsLoading,
};
};
24 changes: 24 additions & 0 deletions packages/features.lesson.add/src/hooks/useConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';

type RepeatVariant = {
value: string;
label: string;
};

export const useConstants = () => {
const { t } = useTranslation('calendar');

const repeatVariants: RepeatVariant[] = useMemo(() => {
return [
{ value: 'dont_repeat', label: t('repeat_settings.dont_repeat') },
{ value: 'every_day', label: t('repeat_settings.every_day') },
{ value: 'every_work_day', label: t('repeat_settings.every_work_day') },
{ value: 'every_week', label: t('repeat_settings.every_week') },
{ value: 'every_2_weeks', label: t('repeat_settings.every_2_weeks') },
{ value: 'every_month', label: t('repeat_settings.every_month') },
];
}, [t]);

return { repeatVariants };
};
3 changes: 3 additions & 0 deletions packages/features.lesson.add/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { AddingLessonModal } from './ui/AddingLessonModal';
export * from './hooks';
export * from './model';
48 changes: 48 additions & 0 deletions packages/features.lesson.add/src/model/formSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as z from 'zod';

const timeToMinutes = (time: string): number => {
const [hours, minutes] = time.split(':').map(Number);
return hours * 60 + minutes;
};

// Валидация времени
const timeValidation = z.string().refine((time) => {
const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
return timeRegex.test(time);
}, 'Неверный формат времени');

export const formSchema = z
.object({
title: z.string(),
description: z.string().optional(),
studentId: z.string().min(1, 'Выберите студента'),
startTime: timeValidation,
endTime: timeValidation,
startDate: z.date({ required_error: 'Укажите дату' }),
shouldRepeat: z
.enum([
'dont_repeat',
'every_day',
'every_work_day',
'every_week',
'every_2_weeks',
'every_month',
])
.default('dont_repeat'),
})
.refine(
(data) => {
if (data.startTime && data.endTime) {
const startMinutes = timeToMinutes(data.startTime);
const endMinutes = timeToMinutes(data.endTime);
return startMinutes <= endMinutes;
}
return true;
},
{
message: 'Время начала не может быть позже времени окончания',
path: ['startTime'],
},
);

export type FormData = z.infer<typeof formSchema>;
1 change: 1 addition & 0 deletions packages/features.lesson.add/src/model/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { formSchema, type FormData } from './formSchema';
Loading