From c2e29cbef36997b3f5ed08625f880debf779e0de Mon Sep 17 00:00:00 2001 From: SD Date: Tue, 21 May 2024 01:18:08 +0400 Subject: [PATCH] feat: add sessions page, add delete modal, refactoring --- package-lock.json | 18 +++ package.json | 1 + src/actions/profile.ts | 15 +- .../account/(account)/sessions/page.tsx | 6 +- src/components/Account/AccountMenu.tsx | 12 +- src/components/Account/index.ts | 2 +- .../Account/sessions/SessionDetails.tsx | 137 ++++++++++++++++ .../Account/{ => sessions}/SessionsTabs.tsx | 29 ++-- src/components/Account/sessions/index.tsx | 22 +++ src/components/Experts/ExpertsList.tsx | 5 +- src/components/Modals/AuthModal.tsx | 23 +-- src/components/Modals/DeleteAccountModal.tsx | 37 +++++ src/styles/_default.scss | 2 +- src/styles/_modal.scss | 24 +++ src/styles/_pages.scss | 4 +- src/styles/sessions/_details.scss | 149 ++++++++++++++++++ src/styles/sessions/style.scss | 1 + src/styles/style.scss | 2 + src/types/experts.ts | 2 +- src/types/sessions.ts | 107 ++++++++++++- src/utils/expert.ts | 3 + 21 files changed, 548 insertions(+), 53 deletions(-) create mode 100644 src/components/Account/sessions/SessionDetails.tsx rename src/components/Account/{ => sessions}/SessionsTabs.tsx (87%) create mode 100644 src/components/Account/sessions/index.tsx create mode 100644 src/components/Modals/DeleteAccountModal.tsx create mode 100644 src/styles/_modal.scss create mode 100644 src/styles/sessions/_details.scss create mode 100644 src/styles/sessions/style.scss create mode 100644 src/utils/expert.ts diff --git a/package-lock.json b/package-lock.json index cfa03e5..4cbe0fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@ant-design/cssinjs": "^1.18.1", "@ant-design/icons": "^5.2.6", "@ant-design/nextjs-registry": "^1.0.0", + "agora-rtc-react": "^2.1.0", "antd": "^5.12.1", "antd-img-crop": "^4.21.0", "axios": "^1.6.5", @@ -873,6 +874,17 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agora-rtc-react": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/agora-rtc-react/-/agora-rtc-react-2.1.0.tgz", + "integrity": "sha512-3FGteA7FG51oK5MusbYNgAcKZaAQK+4sbEz4F0DPzcpDxqNANpocJDqOsmXoUAj5yDBsBZelmagU3abd++6RGA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5947,6 +5959,12 @@ "dev": true, "requires": {} }, + "agora-rtc-react": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/agora-rtc-react/-/agora-rtc-react-2.1.0.tgz", + "integrity": "sha512-3FGteA7FG51oK5MusbYNgAcKZaAQK+4sbEz4F0DPzcpDxqNANpocJDqOsmXoUAj5yDBsBZelmagU3abd++6RGA==", + "requires": {} + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", diff --git a/package.json b/package.json index 35d2112..8998103 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@ant-design/cssinjs": "^1.18.1", "@ant-design/icons": "^5.2.6", "@ant-design/nextjs-registry": "^1.0.0", + "agora-rtc-react": "^2.1.0", "antd": "^5.12.1", "antd-img-crop": "^4.21.0", "axios": "^1.6.5", diff --git a/src/actions/profile.ts b/src/actions/profile.ts index 53462bf..a3a98de 100644 --- a/src/actions/profile.ts +++ b/src/actions/profile.ts @@ -60,7 +60,7 @@ export const getRequestedSessions = (locale: string, jwt: string): Promise> => ( apiClient.post( - '/home/historicalmeetings ', + '/home/historicalmeetings', { sessionType: 'session', ...(filter || {}) @@ -73,3 +73,16 @@ export const getRecentSessions = (locale: string, jwt: string, filter?: Sessions } ) ); + +export const getSessionDetails = (locale: string, jwt: string, id: number): Promise> => ( + apiClient.post( + '/home/session', + { id }, + { + headers: { + 'X-User-Language': locale, + Authorization: `Bearer ${jwt}` + } + } + ) +); diff --git a/src/app/[locale]/account/(account)/sessions/page.tsx b/src/app/[locale]/account/(account)/sessions/page.tsx index 6262afe..c3ac0e5 100644 --- a/src/app/[locale]/account/(account)/sessions/page.tsx +++ b/src/app/[locale]/account/(account)/sessions/page.tsx @@ -1,7 +1,7 @@ import React, { Suspense } from 'react'; import type { Metadata } from 'next'; import { useTranslations } from 'next-intl'; -import { SessionsTabs } from '../../../../../components/Account'; +import { SessionsAll } from '../../../../../components/Account'; export const metadata: Metadata = { title: 'Bbuddy - Account - Sessions', @@ -13,9 +13,7 @@ export default function Sessions({ params: { locale } }: { params: { locale: str return ( Loading...

}> - +
); } diff --git a/src/components/Account/AccountMenu.tsx b/src/components/Account/AccountMenu.tsx index 8624fcb..5e4899f 100644 --- a/src/components/Account/AccountMenu.tsx +++ b/src/components/Account/AccountMenu.tsx @@ -1,6 +1,6 @@ 'use client'; -import React from 'react'; +import React, { useState } from 'react'; import styled from 'styled-components'; import { Button } from 'antd'; import { useSelectedLayoutSegment, usePathname } from 'next/navigation'; @@ -8,6 +8,7 @@ import { Link } from '../../navigation'; import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common'; import { deleteStorageKey } from '../../hooks/useLocalStorage'; import { i18nText } from '../../i18nKeys'; +import { DeleteAccountModal } from '../Modals/DeleteAccountModal'; const Logout = styled(Button)` width: 100%; @@ -24,6 +25,7 @@ export const AccountMenu = ({ menu, locale }: { menu: { path: string, title: str const selectedLayoutSegment = useSelectedLayoutSegment(); const pathname = selectedLayoutSegment || ''; const paths = usePathname(); + const [showDeleteModal, setShowDeleteModal] = useState(false); const onLogout = () => { deleteStorageKey(AUTH_TOKEN_KEY); @@ -31,9 +33,7 @@ export const AccountMenu = ({ menu, locale }: { menu: { path: string, title: str window?.location?.replace(`/${paths.split('/')[1]}/`); }; - const onDeleteAccount = () => { - console.log('delete'); - }; + const onDeleteAccount = () => setShowDeleteModal(true); return (
    @@ -62,6 +62,10 @@ export const AccountMenu = ({ menu, locale }: { menu: { path: string, title: str > {i18nText('deleteAcc', locale)} + setShowDeleteModal(false)} + />
); diff --git a/src/components/Account/index.ts b/src/components/Account/index.ts index 435b58a..8f56865 100644 --- a/src/components/Account/index.ts +++ b/src/components/Account/index.ts @@ -1,5 +1,5 @@ 'use client' export { AccountMenu } from './AccountMenu'; -export { SessionsTabs } from './SessionsTabs'; export { ProfileSettings } from './ProfileSettings'; +export * from './sessions'; diff --git a/src/components/Account/sessions/SessionDetails.tsx b/src/components/Account/sessions/SessionDetails.tsx new file mode 100644 index 0000000..922c191 --- /dev/null +++ b/src/components/Account/sessions/SessionDetails.tsx @@ -0,0 +1,137 @@ +'use client' + +import React, { useCallback, useEffect, useState } from 'react'; +import { Tag } from 'antd'; +import { RightOutlined } from '@ant-design/icons'; +import Image from 'next/image'; +import dayjs from 'dayjs'; +import { Link } from '../../../navigation'; +import { i18nText } from '../../../i18nKeys'; +import { getDuration, getPrice } from '../../../utils/expert'; +import { Session } from '../../../types/sessions'; +import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../constants/common'; +import { getSessionDetails } from '../../../actions/profile'; +import { useLocalStorage } from '../../../hooks/useLocalStorage'; +import { Loader } from '../../view/Loader'; + +type SessionDetailsProps = { + locale: string; + sessionId: number; + goBack: () => void; +}; + +export const SessionDetails = ({ sessionId, locale, goBack }: SessionDetailsProps) => { + const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, ''); + const [userId] = useLocalStorage(AUTH_USER, ''); + const [loading, setLoading] = useState(false); + const [errorData, setErrorData] = useState(); + const [session, setSession] = useState(); + + const fetchData = useCallback(() => { + setLoading(true); + setErrorData(undefined); + setSession(undefined); + + getSessionDetails(locale, jwt, sessionId) + .then(({ data }) => { + console.log(data); + setSession(data); + }) + .catch((err) => { + setErrorData(err); + }) + .finally(() => { + setLoading(false); + }) + }, []); + + useEffect(() => { + fetchData(); + }, [sessionId]); + + const client = session?.clients?.length ? session?.clients[0] : null; + const current = +userId !== client?.id ? client : session?.coach; + 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; + + return ( + +
+
+ +
+
+
+ +
+
+ +
{`${current?.name} ${current?.surname || ''}`}
+ +
+
+ {/* current?.coachLanguages?.map((lang) => ( + {lang} + )) */} +
+
+ {/*
{current?.speciality}
*/} +
+ {getPrice(session?.cost)} / {getDuration(locale, session?.totalDuration)} +
+
+ {today + ? `${i18nText('today', locale)} ${startDate.format('HH:mm')} - ${endDate.format('HH:mm')}` + : `${startDate.format('D MMMM')} ${startDate.format('HH:mm')} - ${endDate.format('HH:mm')}`} +
+
+
+ {session?.themesTags?.slice(0, 2).map((skill) => {skill?.name})} + {session?.themesTags?.length > 2 + ? ( + + + {`+${session?.themesTags?.length - 2}`} + + + ) : null } +
+
+ {/*
{current?.specialityDesc}
+
{current?.description}
*/} + + {i18nText('details', locale)} + + +
+
+
+ + +
+
+
+
+ My Comments +
+ +
+
+ Sed tincidunt finibus eros nec feugiat. Nulla facilisi. Nunc maximus magna et egestas tincidunt. Integer lobortis laoreet neque at sodales. Aenean eget risus pharetra, efficitur dolor ut, commodo lacus. Sed vitae nunc odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et velit et dolor rutrum euismod a pretium est. +
+
+ Coach Comments +
+
+ Sed tincidunt finibus eros nec feugiat. Nulla facilisi. Nunc maximus magna et egestas tincidunt. Integer lobortis laoreet neque at sodales. Aenean eget risus pharetra, efficitur dolor ut, commodo lacus. Sed vitae nunc odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et velit et dolor rutrum euismod a pretium est. +
+
+
+
+ ); +}; diff --git a/src/components/Account/SessionsTabs.tsx b/src/components/Account/sessions/SessionsTabs.tsx similarity index 87% rename from src/components/Account/SessionsTabs.tsx rename to src/components/Account/sessions/SessionsTabs.tsx index 2132d27..97f40ec 100644 --- a/src/components/Account/SessionsTabs.tsx +++ b/src/components/Account/sessions/SessionsTabs.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState, MouseEvent } from 'react'; import { Empty, Space } from 'antd'; import dayjs from 'dayjs'; import 'dayjs/locale/ru'; @@ -9,14 +9,19 @@ import 'dayjs/locale/de'; import 'dayjs/locale/it'; import 'dayjs/locale/fr'; import 'dayjs/locale/es'; -import { Loader } from '../view/Loader'; -import { useLocalStorage } from '../../hooks/useLocalStorage'; -import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common'; -import { getRecentSessions, getRequestedSessions, getUpcomingSessions } from '../../actions/profile'; -import { Session, Sessions, SessionType } from '../../types/sessions'; -import { i18nText } from '../../i18nKeys'; +import { Loader } from '../../view/Loader'; +import { useLocalStorage } from '../../../hooks/useLocalStorage'; +import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../constants/common'; +import { getRecentSessions, getRequestedSessions, getUpcomingSessions } from '../../../actions/profile'; +import { Session, Sessions, SessionType } from '../../../types/sessions'; +import { i18nText } from '../../../i18nKeys'; -export const SessionsTabs = ({ locale }: { locale: string }) => { +type SessionsTabsProps = { + locale: string; + updateSession: (val: number) => void; +}; + +export const SessionsTabs = ({ locale, updateSession }: SessionsTabsProps) => { const [activeTab, setActiveTab] = useState(0); const [sort, setSort] = useState(); const [sessions, setSessions] = useState(); @@ -56,6 +61,12 @@ export const SessionsTabs = ({ locale }: { locale: string }) => { setSort(value); }, [sort]); + const onClickSession = (event: MouseEvent, id: number) => { + event.stopPropagation(); + event.preventDefault(); + updateSession(id); + }; + const getChildren = (list?: Session[]) => ( <> {/*
@@ -82,7 +93,7 @@ export const SessionsTabs = ({ locale }: { locale: string }) => { const today = dayjs().format('YYYY-MM-DD') === startDate.format('YYYY-MM-DD'); return ( -
+
) => onClickSession(e, id)}>
diff --git a/src/components/Account/sessions/index.tsx b/src/components/Account/sessions/index.tsx new file mode 100644 index 0000000..264be30 --- /dev/null +++ b/src/components/Account/sessions/index.tsx @@ -0,0 +1,22 @@ +'use client' + +import React, { useState } from 'react'; +import { SessionDetails } from './SessionDetails'; +import { SessionsTabs } from './SessionsTabs'; + +export const SessionsAll = ({ locale }: { locale: string }) => { + const [customSession, setCustomSession] = useState(); + + return customSession ? ( + setCustomSession(undefined)} + /> + ) : ( + + ); +}; diff --git a/src/components/Experts/ExpertsList.tsx b/src/components/Experts/ExpertsList.tsx index 59df305..a1f6054 100644 --- a/src/components/Experts/ExpertsList.tsx +++ b/src/components/Experts/ExpertsList.tsx @@ -9,6 +9,7 @@ import Image from 'next/image'; import { Link, useRouter } from '../../navigation'; import { ExpertsData, Filter, GeneralFilter } from '../../types/experts'; import { getObjectByFilter, getObjectByAdditionalFilter } from '../../utils/filter'; +import { getDuration, getPrice } from '../../utils/expert'; import { getExpertsList } from '../../actions/experts'; import { CustomPagination } from '../view/CustomPagination'; import { CustomSpin } from '../view/CustomSpin'; @@ -31,8 +32,6 @@ export const ExpertsList = ({ }: ExpertListProps) => { const searchParams = useSearchParams(); const router = useRouter(); - const getDuration = (value?: any): string => `${value || 0}${locale === 'ru' ? 'мин' : 'min'}`; - const getPrice = (value?: any): string => `${value || 0}€`; const [experts, setExperts] = useState(); const [loading, setLoading] = useState(true); @@ -102,7 +101,7 @@ export const ExpertsList = ({
{`${item.name} ${item?.surname || ''}`}
- {getPrice(item?.sessionCost)} / {getDuration(item?.sessionDuration)} + {getPrice(item?.sessionCost)} / {getDuration(locale, item?.sessionDuration)}
diff --git a/src/components/Modals/AuthModal.tsx b/src/components/Modals/AuthModal.tsx index b2fb836..b7758a0 100644 --- a/src/components/Modals/AuthModal.tsx +++ b/src/components/Modals/AuthModal.tsx @@ -3,9 +3,8 @@ import React, { Dispatch, FC, SetStateAction, useEffect } from 'react'; import { usePathname } from 'next/navigation'; import Link from 'next/link'; -import { Modal as AntdModal, Form } from 'antd'; +import { Modal, Form } from 'antd'; import { CloseOutlined } from '@ant-design/icons'; -import { styled } from 'styled-components'; import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent'; type AuthModalProps = { @@ -16,25 +15,6 @@ type AuthModalProps = { updateToken: string | Dispatch> | undefined; }; -const Modal = styled(AntdModal)` - .ant-modal-content { - border-radius: 24px !important; - } - - .ant-modal-close { - height: 64px !important; - width: 64px !important; - border-radius: 50% !important; - background: #fff !important; - top: -32px !important; - inset-inline-end: -32px !important; - - &:active, &:hover { - background: #fff !important; - } - } -`; - export const AuthModal: FC = ({ open, handleCancel, @@ -63,6 +43,7 @@ export const AuthModal: FC = ({ return ( void; +}; + +export const DeleteAccountModal: FC = ({ + open, + handleCancel +}) => ( + } + > +
+

+ To delete your BBUDDY account, please send an email requesting account deletion to the following email address: +

+ info@bbuddy.expert +

+ Upon receiving the request, we will delete all existing data associated with your account within 24 hours. +

+
+
+); diff --git a/src/styles/_default.scss b/src/styles/_default.scss index f97b78d..96f03bd 100644 --- a/src/styles/_default.scss +++ b/src/styles/_default.scss @@ -586,7 +586,6 @@ a { line-height: 160%; } -// .card-profile { display: flex !important; flex-direction: column; @@ -598,6 +597,7 @@ a { &.session { &__item { margin: 0 !important; + cursor: pointer; } } diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss new file mode 100644 index 0000000..7e551ed --- /dev/null +++ b/src/styles/_modal.scss @@ -0,0 +1,24 @@ +.b-modal { + .ant-modal-content { + border-radius: 24px !important; + } + + .ant-modal-close { + height: 64px !important; + width: 64px !important; + border-radius: 50% !important; + background: #fff !important; + top: -32px !important; + inset-inline-end: -32px !important; + + &:active, &:hover { + background: #fff !important; + } + } + + &__content { + p { + margin: 16px 0; + } + } +} diff --git a/src/styles/_pages.scss b/src/styles/_pages.scss index 22fd774..d3ffa48 100644 --- a/src/styles/_pages.scss +++ b/src/styles/_pages.scss @@ -767,9 +767,9 @@ display: inline-flex; align-items: center; justify-content: center; - padding: 6px 8px 4px 8px; + padding: 6px 8px 4px; border-radius: 16px; - background: #66A5AD; + background: #FFBD00; color: $white; @include rem(12); font-style: normal; diff --git a/src/styles/sessions/_details.scss b/src/styles/sessions/_details.scss new file mode 100644 index 0000000..39e043b --- /dev/null +++ b/src/styles/sessions/_details.scss @@ -0,0 +1,149 @@ +.card-detail { + display: flex; + flex-direction: column; + gap: 16px; + + &__expert { + border-block-end: 1px solid #C4DFE6; + display: flex; + gap: 16px; + padding: 0 0 16px; + } + + &__portrait { + width: 140px; + height: 140px; + border-radius: 16px; + border: 2px solid #FFF; + background: lightgray 50%; + box-shadow: 0 8px 16px 0 rgba(102, 165, 173, 0.32); + overflow: hidden; + } + + &__inner { + display: flex; + flex-direction: column; + gap: 8px; + flex: 1 0 0; + } + + &__actions { + display: flex; + gap: 16px; + justify-content: flex-start; + } + + &__comments { + display: flex; + flex-direction: column; + gap: 16px; + + &_header { + display: flex; + justify-content: space-between; + align-items: center; + } + + &_title { + color: #6FB98F; + @include rem(18); + font-weight: 600; + line-height: 150%; + } + + &_item { + padding: 16px; + background: #E4F5FA; + border-radius: 0 16px 16px 16px; + color: #66A5AD; + @include rem(13); + font-weight: 500; + line-height: 133.333%; + } + } + + &__header { + display: flex; + padding-bottom: 8px; + align-items: center !important; + gap: 16px; + align-self: stretch; + margin-block-end: 0 !important; + + img { + object-fit: cover; + width: 100%; + height: 100%; + display: block; + border-radius: 16px; + } + + &__name { + overflow: hidden; + color: #003B46; + text-overflow: ellipsis; + white-space: nowrap; + @include rem(18); + font-style: normal; + font-weight: 600; + line-height: 133.333%; + } + + &__price { + color: #6FB98F; + @include rem(15); + font-style: normal; + font-weight: 600; + line-height: 120%; + + span { + color: #B7B7B7; + } + } + } + + &__title { + color: #003B46; + @include rem(18); + font-style: normal; + font-weight: 600; + line-height: 133.333%; + } + + &__subtitle { + color: #003B46; + @include rem(15); + font-style: normal; + font-weight: 600; + line-height: 120%; + } + + &__desc { + color: #66A5AD; + @include rem(13); + font-style: normal; + font-weight: 500; + line-height: 123.077%; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } + + &__footer { + display: flex; + justify-content: flex-end; + align-items: center; + + a { + text-decoration: none; + color: #FF8A00 !important; + @include rem(15); + font-style: normal; + font-weight: 400; + line-height: 160%; + display: inline-flex; + align-items: center; + } + } +} diff --git a/src/styles/sessions/style.scss b/src/styles/sessions/style.scss new file mode 100644 index 0000000..34589d5 --- /dev/null +++ b/src/styles/sessions/style.scss @@ -0,0 +1 @@ +@import "_details.scss"; diff --git a/src/styles/style.scss b/src/styles/style.scss index 4f1303e..d00dbd2 100644 --- a/src/styles/style.scss +++ b/src/styles/style.scss @@ -14,8 +14,10 @@ @import "_form.scss"; @import "_message.scss"; @import "_auth-modal.scss"; +@import "_modal.scss"; @import "./view/style.scss"; +@import "./sessions/style.scss"; diff --git a/src/types/experts.ts b/src/types/experts.ts index 20a7417..160db87 100644 --- a/src/types/experts.ts +++ b/src/types/experts.ts @@ -1,4 +1,4 @@ -import {Tag, ThemeGroups} from './tags'; +import { Tag, ThemeGroups } from './tags'; export type GeneralFilter = Filter & AdditionalFilter; diff --git a/src/types/sessions.ts b/src/types/sessions.ts index 9400c13..f6c507e 100644 --- a/src/types/sessions.ts +++ b/src/types/sessions.ts @@ -1,4 +1,6 @@ -type User = { +import { Language } from './tags'; + +type PublicUser = { id: number; login?: string; name?: string; @@ -6,6 +8,88 @@ type User = { faceImageUrl?: string; }; +// type User = { +// "id": 0, +// "login": "string", +// "password": "string", +// "role": "coach", +// "name": "string", +// "surname": "string", +// "phone": "string", +// "faceImageId": 0, +// "createdAtUtc": "2024-05-15T14:26:19.310Z", +// "practiceHours": 0, +// "supervisionPerYearId": 0, +// "sessionDuration": 0, +// "sessionCost": 0, +// "adminRoles": "admin", +// "isCoachApproved": true, +// "isBanned": true, +// "faceImage": { +// "id": 0, +// "userId": 0, +// "descriptor": "string", +// "fileType": "string", +// "contentLength": 0, +// "state": "active", +// "createdAtUtc": "2024-05-15T14:26:19.310Z", +// "unusedSinceUtc": "2024-05-15T14:26:19.310Z" +// }, +// "coachRating": 0, +// "isTestMode": true, +// "beneficiaryName": "string", +// "beneficiaryIban": "string", +// "beneficiaryBicOrSwift": "string", +// "userThemesTags": [ +// { +// "userId": 0, +// "themesTagId": 0, +// "themesTag": { +// "id": 0, +// "groupId": 0, +// "name": "string", +// "isActive": true, +// "userId": 0, +// "group": { +// "id": 0, +// "name": "string", +// "isActive": true, +// "userId": 0, +// "tags": [ +// "string" +// ], +// "multilangs": [ +// { +// "parentId": 0, +// "languageCode": "string", +// "name": "string" +// } +// ] +// }, +// "userThemesTags": [ +// "string" +// ], +// "multilangs": [ +// { +// "parentId": 0, +// "languageCode": "string", +// "name": "string" +// } +// ] +// }, +// "user": "string" +// } +// ], +// "languagesLinks": [ +// { +// "userId": 0, +// "languageId": 0, +// "user": "string", +// "language": Language +// } +// ] +// }; + type SessionTag = { id: number; groupId?: number; @@ -21,6 +105,15 @@ export type SessionsFilter = { endDate?: string; }; +export type SessionComment = { + id: number; + createdAtUtc: string; + comment?: string; + author?: PublicUser; + authorId?: number; + sessionId?: number; +}; + export type Session = { id: number; scheduledStartAtUtc?: string; @@ -37,11 +130,13 @@ export type Session = { description?: string; isNeedSupervisor?: boolean; supervisorComment?: string; - user?: User; - coach?: User; - supervisor?: User; - clients?: User[]; - themesTags?: SessionTag[] + user?: PublicUser; + coach?: PublicUser; + supervisor?: PublicUser; + clients?: PublicUser[]; + themesTags?: SessionTag[]; + coachComments?: SessionComment[]; + clientComments?: SessionComment[]; }; export enum SessionType { diff --git a/src/utils/expert.ts b/src/utils/expert.ts new file mode 100644 index 0000000..dd43b97 --- /dev/null +++ b/src/utils/expert.ts @@ -0,0 +1,3 @@ +export const getDuration = (locale: string, value?: any): string => `${value || 0}${locale === 'ru' ? 'мин' : 'min'}`; + +export const getPrice = (value?: any): string => `${value || 0}€`;