Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { callsApiConfig, CallsQueryKey } from 'common.api';
import { useFetching } from 'common.config';
import { AxiosError } from 'axios';

export interface Participant {
user_id: number;
display_name: string;
}

export const useGetParticipantsByStudent = (classroom_id: string, disabled?: boolean) => {
const { data, isError, isLoading, ...rest } = useFetching({
const { data, isError, isLoading, error, ...rest } = useFetching({
apiConfig: {
method: callsApiConfig[CallsQueryKey.GetParticipantsStudent].method,
getUrl: () => callsApiConfig[CallsQueryKey.GetParticipantsStudent].getUrl(classroom_id),
Expand All @@ -19,8 +20,13 @@ export const useGetParticipantsByStudent = (classroom_id: string, disabled?: boo
queryKey: [CallsQueryKey.GetParticipantsStudent, classroom_id],
});

// Проверяем, является ли ошибка 409 (комната не активна)
const isConferenceNotActive =
isError && error instanceof AxiosError && error.response?.status === 409;

return {
participants: data as Participant[] | undefined,
isConferenceNotActive, // true если комната не активна (409)
isError,
isLoading,
...rest,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { callsApiConfig, CallsQueryKey } from 'common.api';
import { useFetching } from 'common.config';
import { AxiosError } from 'axios';

export interface Participant {
user_id: number;
display_name: string;
}

export const useGetParticipantsByTutor = (classroom_id: string, disabled?: boolean) => {
const { data, isError, isLoading, ...rest } = useFetching({
const { data, isError, isLoading, error, ...rest } = useFetching({
apiConfig: {
method: callsApiConfig[CallsQueryKey.GetParticipantsTutor].method,
getUrl: () => callsApiConfig[CallsQueryKey.GetParticipantsTutor].getUrl(classroom_id),
Expand All @@ -19,8 +20,13 @@ export const useGetParticipantsByTutor = (classroom_id: string, disabled?: boole
queryKey: [CallsQueryKey.GetParticipantsTutor, classroom_id],
});

// Проверяем, является ли ошибка 409 (комната не активна)
const isConferenceNotActive =
isError && error instanceof AxiosError && error.response?.status === 409;

return {
participants: data as Participant[] | undefined,
isConferenceNotActive, // true если комната не активна (409)
isError,
isLoading,
...rest,
Expand Down
38 changes: 36 additions & 2 deletions packages/pages.main/src/ui/components/Classrooms/Classroom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { Button } from '@xipkg/button';
import { Arrow, Conference } from '@xipkg/icons';
import { Tooltip, TooltipContent, TooltipTrigger } from '@xipkg/tooltip';
import { Avatar, AvatarFallback, AvatarImage } from '@xipkg/avatar';
import { useCurrentUser, useUserByRole } from 'common.services';
import {
useCurrentUser,
useUserByRole,
useGetParticipantsByTutor,
useGetParticipantsByStudent,
} from 'common.services';
import { SubjectBadge } from './SubjectBadge';

type UserAvatarPropsT = {
Expand Down Expand Up @@ -49,6 +54,28 @@ export const Classroom = ({ classroom, isLoading }: ClassroomProps) => {
const { data: user } = useCurrentUser();
const isTutor = user?.default_layout === 'tutor';

// Получаем участников конференции в зависимости от роли
// Логика определения активной конференции:
// - 409 ошибка = комната НЕ активна (была пустая >5 минут)
// - [] (пустой массив) = комната АКТИВНА, но пустая (репетитор начал, но еще не присоединился)
// - [участники] = комната активна, есть участники
// - undefined (при загрузке или других ошибках) = состояние неизвестно, кнопка disabled
const { participants: participantsStudent, isConferenceNotActive: isConferenceNotActiveStudent } =
useGetParticipantsByStudent(classroom.id.toString(), isTutor);

const { participants: participantsTutor, isConferenceNotActive: isConferenceNotActiveTutor } =
useGetParticipantsByTutor(classroom.id.toString(), !isTutor);

const participants = isTutor ? participantsTutor : participantsStudent;
const isConferenceNotActive = isTutor ? isConferenceNotActiveTutor : isConferenceNotActiveStudent;

// Конференция активна, если:
// 1. Нет ошибки 409 (комната активна)
// 2. И participants определен и является массивом (пустой [] или с участниками)
// При загрузке или других ошибках participants = undefined, поэтому isConferenceActive = false
const isConferenceActive =
!isConferenceNotActive && participants !== undefined && Array.isArray(participants);

const handleClick = () => {
// Сохраняем параметр call при переходе в кабинет
const filteredSearch = search.call ? { call: search.call } : {};
Expand All @@ -69,6 +96,12 @@ export const Classroom = ({ classroom, isLoading }: ClassroomProps) => {
window.location.href = url;
};

const getButtonText = () => {
if (isConferenceActive) return 'Присоединиться';
else if (isTutor) return 'Начать занятие';
else return 'Присоединиться';
};

return (
<div className="border-gray-30 relative flex min-h-[170px] max-w-[420px] min-w-[320px] flex-col items-start justify-start gap-1 rounded-2xl border bg-transparent p-4">
<Tooltip delayDuration={1000}>
Expand Down Expand Up @@ -116,8 +149,9 @@ export const Classroom = ({ classroom, isLoading }: ClassroomProps) => {
variant="secondary"
className="group mt-auto w-full"
onClick={handleStartLesson}
disabled={!isTutor && !isConferenceActive}
>
{isTutor ? 'Начать занятие' : 'Присоединиться'}{' '}
{getButtonText()}
<Conference className="group-hover:fill-gray-0 fill-brand-100 ml-2" />
</Button>
</div>
Expand Down
Loading
Loading