302 lines
15 KiB
TypeScript
302 lines
15 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState } from 'react';
|
|
import { Button, Empty, notification, Tag } from 'antd';
|
|
import { LeftOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons';
|
|
import Image from 'next/image';
|
|
import dayjs from 'dayjs';
|
|
import { Link, useRouter } from '../../../navigation';
|
|
import { i18nText } from '../../../i18nKeys';
|
|
import { getDuration, getPrice } from '../../../utils/expert';
|
|
import { PublicUser, Session, SessionState, SessionType } from '../../../types/sessions';
|
|
import { AUTH_TOKEN_KEY } from '../../../constants/common';
|
|
import { approveRequestedSession, finishSession } from '../../../actions/sessions';
|
|
import { useLocalStorage } from '../../../hooks/useLocalStorage';
|
|
import { DeclineSessionModal } from '../../Modals/DeclineSessionModal';
|
|
import { AddCommentModal } from '../../Modals/AddCommentModal';
|
|
|
|
type SessionDetailsContentProps = {
|
|
locale: string;
|
|
session: Session;
|
|
activeType: SessionType;
|
|
startSession: () => void;
|
|
refresh: () => void;
|
|
isCoach: boolean;
|
|
};
|
|
|
|
export const SessionDetailsContent = ({ session, locale, activeType, startSession, refresh, isCoach }: SessionDetailsContentProps) => {
|
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
|
const [approveLoading, setApproveLoading] = useState<boolean>(false);
|
|
const [finishLoading, setFinishLoading] = useState<boolean>(false);
|
|
const [openDeclineModal, setOpenDeclineModal] = useState<boolean>(false);
|
|
const [openAddCommentModal, setOpenAddCommentModal] = useState<boolean>(false);
|
|
const router = useRouter();
|
|
|
|
const goBack = () => router.push(`/account/sessions/${activeType}`);
|
|
|
|
const onApproveSession = () => {
|
|
if (activeType === SessionType.REQUESTED) {
|
|
setApproveLoading(true);
|
|
approveRequestedSession(locale, jwt, session.id)
|
|
.then(() => {
|
|
goBack();
|
|
})
|
|
.catch((err) => {
|
|
notification.error({
|
|
message: i18nText('errors.approvingSession', locale),
|
|
description: err?.response?.data?.errMessage
|
|
});
|
|
})
|
|
.finally(() => {
|
|
setApproveLoading(false);
|
|
});
|
|
} else {
|
|
startSession();
|
|
}
|
|
};
|
|
|
|
const onFinishSession = () => {
|
|
if (isCoach) {
|
|
setFinishLoading(true);
|
|
finishSession(locale, jwt, session.id)
|
|
.then(() => {
|
|
goBack();
|
|
})
|
|
.catch((err) => {
|
|
notification.error({
|
|
message: i18nText('errors.finishingSession', locale),
|
|
description: err?.response?.data?.errMessage
|
|
});
|
|
})
|
|
.finally(() => {
|
|
setFinishLoading(false);
|
|
})
|
|
}
|
|
};
|
|
|
|
const startDate = session?.scheduledStartAtUtc ? dayjs(session?.scheduledStartAtUtc).locale(locale) : null;
|
|
const endDate = session?.scheduledEndAtUtc ? dayjs(session?.scheduledEndAtUtc).locale(locale) : null;
|
|
const today = startDate ? dayjs().format('YYYY-MM-DD') === startDate.format('YYYY-MM-DD') : false;
|
|
|
|
const CoachCard = (coach?: PublicUser) => coach ? (
|
|
<div className="card-detail__expert">
|
|
<div className="card-detail__portrait">
|
|
<Image src={coach?.faceImageUrl || '/images/person.png'} width={140} height={140} alt="" />
|
|
</div>
|
|
<div className="card-detail__inner">
|
|
<Link href={`/experts/${coach?.id}` as any} target="_blank">
|
|
<div className="card-detail__name">{`${coach?.name} ${coach?.surname || ''}`}</div>
|
|
</Link>
|
|
{/* <div className="card-detail__info">
|
|
<div className="card-profile__subtitle">{coach?.specialityDesc}</div>
|
|
<div className="card-detail__lang">
|
|
{coach?.coachLanguages?.map((lang) => (
|
|
<Tag key={lang} className="skills__list__item">{lang}</Tag>
|
|
))}
|
|
</div>
|
|
</div> */}
|
|
<div className="card-detail__cost">
|
|
{getPrice(session?.cost)} <span>/ {getDuration(locale, session?.totalDuration)}</span>
|
|
</div>
|
|
<div className={`card-detail__date${today ? ' chosen': ''}${activeType === SessionType.RECENT ? ' history' : ''}`}>
|
|
{today
|
|
? `${i18nText('today', locale)} ${startDate?.format('HH:mm')} - ${endDate?.format('HH:mm')}`
|
|
: `${startDate?.format('D MMMM')} ${startDate?.format('HH:mm')} - ${endDate?.format('HH:mm')}`}
|
|
</div>
|
|
<div className="card-detail__skills">
|
|
<div className="skills__list">
|
|
{session?.themesTags?.slice(0, 2).map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
|
{session?.themesTags?.length > 2
|
|
? (
|
|
<Tag className="skills__list__more">
|
|
<Link href={`/experts/${coach?.id}` as any} target="_blank">
|
|
{`+${session?.themesTags?.length - 2}`}
|
|
</Link>
|
|
</Tag>
|
|
) : null }
|
|
</div>
|
|
</div>
|
|
{/* <div className="card-profile__desc">{coach?.description}</div> */}
|
|
<Link href={`/experts/${coach?.id}` as any} target="_blank" className="card-detail__more">
|
|
{i18nText('details', locale)}
|
|
<RightOutlined style={{ fontSize: '10px', padding: '0 7px' }}/>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
) : null;
|
|
|
|
const StudentCard = (student?: PublicUser | null) => student ? (
|
|
<div className="card-detail__expert">
|
|
<div className="card-detail__portrait">
|
|
<Image src={student?.faceImageUrl || '/images/person.png'} width={140} height={140} alt="" />
|
|
</div>
|
|
<div className="card-detail__inner">
|
|
<div className="card-detail__name">{`${student?.name} ${student?.surname || ''}`}</div>
|
|
<div className={`card-detail__date${today ? ' chosen': ''}${activeType === SessionType.RECENT ? ' history' : ''}`}>
|
|
{today
|
|
? `${i18nText('today', locale)} ${startDate?.format('HH:mm')} - ${endDate?.format('HH:mm')}`
|
|
: `${startDate?.format('D MMMM')} ${startDate?.format('HH:mm')} - ${endDate?.format('HH:mm')}`}
|
|
</div>
|
|
<div className="card-detail__skills">
|
|
<div className="skills__list">
|
|
<Tag className="skills__list__item">{session?.themesTagName}</Tag>
|
|
</div>
|
|
</div>
|
|
{/* <div className="card-profile__desc">{student?.description}</div> */}
|
|
{activeType === SessionType.REQUESTED && session?.clientComment && (
|
|
<div className="card-detail__comments">
|
|
<div className="card-detail__comments_item">
|
|
{session.clientComment}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : null;
|
|
|
|
const client = session?.clients?.length ? session?.clients[0] : null;
|
|
const Current = isCoach ? StudentCard(client) : CoachCard(session?.coach);
|
|
|
|
return (
|
|
<div className="card-detail">
|
|
<div>
|
|
<Button
|
|
className="card-detail__back"
|
|
type="link"
|
|
icon={<LeftOutlined />}
|
|
onClick={goBack}
|
|
>
|
|
{i18nText('back', locale)}
|
|
</Button>
|
|
</div>
|
|
{Current}
|
|
{(activeType === SessionType.UPCOMING || activeType === SessionType.REQUESTED) &&
|
|
(session?.state === SessionState.CREATED || session?.state === SessionState.PAID
|
|
|| session?.state === SessionState.COACH_APPROVED || session?.state === SessionState.STARTED) && (
|
|
<div className="card-detail__actions">
|
|
<Button
|
|
className="card-detail__apply"
|
|
onClick={onApproveSession}
|
|
loading={approveLoading}
|
|
disabled={finishLoading}
|
|
>
|
|
{activeType === SessionType.UPCOMING
|
|
? (session?.state === SessionState.STARTED ? i18nText('session.join', locale) : i18nText('session.start', locale))
|
|
: i18nText('session.confirm', locale)}
|
|
</Button>
|
|
{session?.state === SessionState.STARTED && isCoach && (
|
|
<Button
|
|
className="card-detail__decline"
|
|
onClick={onFinishSession}
|
|
loading={finishLoading}
|
|
>
|
|
{i18nText('session.finish', locale)}
|
|
</Button>
|
|
)}
|
|
{session?.id && session?.state !== SessionState.STARTED && (
|
|
<>
|
|
<Button
|
|
className="card-detail__decline"
|
|
onClick={() => setOpenDeclineModal(true)}
|
|
disabled={approveLoading}
|
|
>
|
|
{i18nText('session.decline', locale)}
|
|
</Button>
|
|
<DeclineSessionModal
|
|
open={openDeclineModal}
|
|
handleCancel={() => setOpenDeclineModal(false)}
|
|
activeType={activeType}
|
|
locale={locale}
|
|
sessionId={session.id}
|
|
success={goBack}
|
|
/>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
{activeType !== SessionType.REQUESTED && (
|
|
<>
|
|
{activeType === SessionType.RECENT && (
|
|
<>
|
|
<div className="card-detail__name">{i18nText('courseInfo', locale)}</div>
|
|
<div className="card-detail__inner">
|
|
{/* <div className="card-detail__info">
|
|
<div className="card-profile__subtitle">{current?.specialityDesc}</div>
|
|
<div className="card-detail__lang">
|
|
{current?.coachLanguages?.map((lang) => (
|
|
<Tag key={lang} className="skills__list__item">{lang}</Tag>
|
|
))}
|
|
</div>
|
|
</div> */}
|
|
<div className="card-detail__cost">
|
|
{getPrice(session?.cost)} <span>/ {getDuration(locale, session?.totalDuration)}</span>
|
|
</div>
|
|
<div className="card-detail__skills">
|
|
<div className="skills__list">
|
|
{session?.themesTags?.slice(0, 2).map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
|
{session?.themesTags?.length > 2
|
|
? (
|
|
<Tag className="skills__list__more">
|
|
{`+${session?.themesTags?.length - 2}`}
|
|
</Tag>
|
|
) : null }
|
|
</div>
|
|
</div>
|
|
{/* <div className="card-profile__desc">{current?.description}</div> */}
|
|
</div>
|
|
</>
|
|
)}
|
|
<div className="card-detail__comments">
|
|
<div className="card-detail__comments_header">
|
|
<div className="card-detail__comments_title">
|
|
{session?.clientComments?.length === 0 && session?.coachComments?.length === 0
|
|
? i18nText('session.comments', locale)
|
|
: i18nText('session.myComments', locale)}
|
|
</div>
|
|
{activeType === SessionType.UPCOMING && (
|
|
<>
|
|
<Button
|
|
className="card-detail__comments_add"
|
|
type="link"
|
|
iconPosition="end"
|
|
icon={<PlusOutlined style={{ fontSize: 18 }} />}
|
|
onClick={() => setOpenAddCommentModal(true)}
|
|
>
|
|
{i18nText('session.addComment', locale)}
|
|
</Button>
|
|
<AddCommentModal
|
|
open={openAddCommentModal}
|
|
handleCancel={() => setOpenAddCommentModal(false)}
|
|
locale={locale}
|
|
sessionId={session.id}
|
|
refresh={refresh}
|
|
/>
|
|
</>
|
|
)}
|
|
</div>
|
|
{(session?.clientComments?.length > 0 || session?.coachComments?.length > 0) ? (
|
|
<>
|
|
{(isCoach ? session?.coachComments : session?.clientComments)?.map(({ id, comment }) => (
|
|
<div key={`my_${id}`} className="card-detail__comments_item">
|
|
{comment}
|
|
</div>
|
|
))}
|
|
{(isCoach ? session?.clientComments : session?.coachComments)?.length > 0 && (
|
|
<div className="card-detail__comments_title">
|
|
{isCoach ? 'Client Comments' : 'Coach Comments'}
|
|
</div>
|
|
)}
|
|
{(isCoach ? session?.clientComments : session?.coachComments)?.map(({ id , comment }) => (
|
|
<div key={`oth_${id}`} className="card-detail__comments_item">
|
|
{comment}
|
|
</div>
|
|
))}
|
|
</>
|
|
) : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|