diff --git a/src/actions/experts.ts b/src/actions/experts.ts index 9450e58..3b7cd51 100644 --- a/src/actions/experts.ts +++ b/src/actions/experts.ts @@ -1,6 +1,5 @@ import { apiRequest } from './helpers'; -import { apiClient } from '../lib/apiClient'; -import {GeneralFilter, ExpertsData, ExpertDetails, ExpertScheduler, ExpertSchedulerSession} from '../types/experts'; +import { GeneralFilter, ExpertsData, ExpertDetails, ExpertScheduler, ExpertSchedulerSession, SignupSessionData } from '../types/experts'; export const getExpertsList = (locale: string, filter?: GeneralFilter): Promise => apiRequest({ url: '/home/coachsearch1', @@ -16,32 +15,17 @@ export const getExpertById = (id: string, locale: string): Promise { - const response = await apiClient.post( - '/home/sessionsignupdata', - { id: expertId }, - { - headers: { - 'X-User-Language': locale, - Authorization: `Bearer ${jwt}` - } - } - ); +export const getSchedulerByExpertId = (id: string, locale: string): Promise => apiRequest({ + url: '/home/sessionsignupdata', + method: 'post', + data: { id }, + locale +}); - return response.data as ExpertScheduler || null; -}; - -export const getSchedulerSession = async (data: { coachId: number, tagId: number, startAtUtc: string, clientComment: string }, locale: string, jwt: string) => { - const response = await apiClient.post( - '/home/sessionsignupsubmit', - data, - { - headers: { - 'X-User-Language': locale, - Authorization: `Bearer ${jwt}` - } - } - ); - - return response.data as ExpertSchedulerSession || null; -}; +export const getSchedulerSession = (data: SignupSessionData, locale: string, token: string): Promise => apiRequest({ + url: '/home/sessionsignupsubmit', + method: 'post', + data, + locale, + token +}); diff --git a/src/app/[locale]/experts/[expertId]/page.tsx b/src/app/[locale]/experts/[expertId]/page.tsx index 42a7b8f..40058c8 100644 --- a/src/app/[locale]/experts/[expertId]/page.tsx +++ b/src/app/[locale]/experts/[expertId]/page.tsx @@ -6,13 +6,11 @@ import { getExpertById, getExpertsList } from '../../../../actions/experts'; import { ExpertCard, ExpertCertificate, - ExpertInformation, ExpertPractice } from '../../../../components/Experts/ExpertDetails'; import { Details } from '../../../../types/education'; import { BackButton } from '../../../../components/view/BackButton'; import { i18nText } from '../../../../i18nKeys'; -import {SchedulerModal} from "../../../../components/Modals/SchedulerModal"; export const metadata: Metadata = { title: 'Bbuddy - Experts item', @@ -84,7 +82,6 @@ export default async function ExpertItem({ params: { expertId = '', locale } }: -

{i18nText('expertBackground', locale)}

diff --git a/src/components/ExpertProfile/ExpertProfile.tsx b/src/components/ExpertProfile/ExpertProfile.tsx index c7e1e71..eb7b78f 100644 --- a/src/components/ExpertProfile/ExpertProfile.tsx +++ b/src/components/ExpertProfile/ExpertProfile.tsx @@ -1,7 +1,7 @@ 'use client' import React, { useState } from 'react'; -import {Alert, message} from 'antd'; +import { Alert, message } from 'antd'; import Image from 'next/image'; import { i18nText } from '../../i18nKeys'; import { ExpertData, PayInfo, ProfileData } from '../../types/profile'; diff --git a/src/components/Experts/ExpertDetails.tsx b/src/components/Experts/ExpertDetails.tsx index d6fafef..842d538 100644 --- a/src/components/Experts/ExpertDetails.tsx +++ b/src/components/Experts/ExpertDetails.tsx @@ -1,8 +1,8 @@ 'use client'; -import React, {FC, useEffect, useState} from 'react'; +import React, { FC, useState } from 'react'; import Image from 'next/image'; -import { Tag, Image as AntdImage, Space } from 'antd'; +import { Tag, Image as AntdImage, Space, Button } from 'antd'; import { ZoomInOutlined, ZoomOutOutlined, StarFilled } from '@ant-design/icons'; import { ExpertScheduler } from '../../types/experts'; import { ExpertDetails, Practice, ThemeGroup } from '../../types/experts'; @@ -15,7 +15,7 @@ import {getSchedulerByExpertId} from "../../actions/experts"; import {useLocalStorage} from "../../hooks/useLocalStorage"; import {AUTH_TOKEN_KEY} from "../../constants/common"; import dayjs from "dayjs"; -import {SchedulerModal} from "../Modals/SchedulerModal"; +import {ScheduleModal} from "../Modals/ScheduleModal"; type ExpertDetailsProps = { expert: ExpertDetails; @@ -33,65 +33,47 @@ export const ExpertCard: FC = ({ expert, locale, expertId }) const { publicCoachDetails } = expert || {}; const [showSchedulerModal, setShowSchedulerModal] = useState(false); const [mode, setMode] = useState<'data' | 'time' | 'pay' | 'finish'>('data'); - const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0 } } = expert || {}; - - const onSchedulerHandle = async () => { - console.log('sessionCost', sessionCost); - setMode('data'); - setShowSchedulerModal(true) - // отмаппим. - } - - return ( -

-
-
- -
-
-

{`${publicCoachDetails?.name} ${publicCoachDetails?.surname || ''}`}

-
- {`${publicCoachDetails?.practiceHours} ${i18nText('practiceHours', locale)}`} - | - {`${publicCoachDetails?.supervisionPerYearId} ${i18nText('supervisionCount', locale)}`} -
-
- } disabled /> - {`4/5 (${i18nText('outOf', locale)} 345)`} -
-
-
- - setShowSchedulerModal(false)} - updateMode={setMode} - mode={mode} - expertId={expertId as string} - locale={locale as string} - sessionCost={sessionCost} - /> -
- ); -}; - -export const ExpertInformation: FC = ({ expert, locale }) => { const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0, coachLanguages = [] } } = expert || {}; const isRus = locale === Locale.ru; + const onSchedulerHandle = () => { + setMode('data'); + setShowSchedulerModal(true) + }; + return ( <> +
+
+
+ +
+
+

{`${publicCoachDetails?.name} ${publicCoachDetails?.surname || ''}`}

+
+ {`${publicCoachDetails?.practiceHours} ${i18nText('practiceHours', locale)}`} + | + {`${publicCoachDetails?.supervisionPerYearId} ${i18nText('supervisionCount', locale)}`} +
+
+ } disabled /> + {`4/5 (${i18nText('outOf', locale)} 345)`} +
+
+
+
+ + {/* + + + Video + + */} +
+
{/*

{}

*/}
@@ -117,11 +99,20 @@ export const ExpertInformation: FC = ({ expert, locale }) => {tags?.map((skill) => {skill?.name})}
- console.log('schedule')}>{i18nText('signUp', locale)} + {i18nText('signUp', locale)}
{`${sessionCost}€`} / {`${sessionDuration}${isRus ? 'мин' : 'min'}`}
+ setShowSchedulerModal(false)} + updateMode={setMode} + mode={mode} + expertId={expertId as string} + locale={locale as string} + sessionCost={sessionCost} + /> ); }; diff --git a/src/components/Modals/ScheduleModal.tsx b/src/components/Modals/ScheduleModal.tsx new file mode 100644 index 0000000..b9d31bd --- /dev/null +++ b/src/components/Modals/ScheduleModal.tsx @@ -0,0 +1,274 @@ +'use client'; + +import React, { FC, useEffect, useState } from 'react'; +import classNames from 'classnames'; +import { Modal, Menu, Calendar, Radio, Button, Input, message } from 'antd'; +import type { CalendarProps, RadioChangeEvent, MenuProps } from 'antd'; +import { ArrowLeftOutlined } from '@ant-design/icons'; +import { CloseOutlined } from '@ant-design/icons'; +import locale_ru from 'antd/lib/calendar/locale/ru_RU'; +import locale_en from 'antd/lib/calendar/locale/en_GB'; +import locale_de from 'antd/lib/calendar/locale/de_DE'; +import locale_it from 'antd/lib/calendar/locale/it_IT'; +import locale_es from 'antd/lib/calendar/locale/es_ES'; +import locale_fr from 'antd/lib/calendar/locale/fr_FR'; +import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent'; +import dayjs, { Dayjs } from 'dayjs'; +import 'dayjs/locale/ru'; +import 'dayjs/locale/en'; +import 'dayjs/locale/de'; +import 'dayjs/locale/it'; +import 'dayjs/locale/fr'; +import 'dayjs/locale/es'; +import { ExpertScheduler, SignupSessionData } from "../../types/experts"; +import { Tag } from "../../types/tags"; +import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { AUTH_TOKEN_KEY } from "../../constants/common"; +import { getSchedulerByExpertId, getSchedulerSession } from "../../actions/experts"; +import { ElementsForm } from "../stripe/ElementsForm"; +import { i18nText } from '../../i18nKeys'; +import { CustomSelect } from '../../components/view/CustomSelect'; + +type ScheduleModalProps = { + open: boolean; + handleCancel: () => void; + mode: 'data' | 'time' | 'pay' | 'finish'; + updateMode: (mode: 'data' | 'time' | 'pay' | 'finish') => void; + sessionCost: number; + expertId: string; + locale: string; +}; + +type MenuItem = Required['items'][number]; + +const getLocale = (locale: string) => { + if (locale) { + switch (locale) { + case 'ru': + return locale_ru; + case 'de': + return locale_de; + case 'fr': + return locale_fr; + case 'it': + return locale_it; + case 'es': + return locale_es; + default: + return locale_en; + }; + } + + return locale_en; +}; + +const getCalendarMenu = (start: Dayjs): MenuItem[] => Array.from({ length: 3 }) + .map((_: unknown, index: number) => { + const date = index ? start.add(index, 'M') : start.clone(); + return { + label: {date.format('MMMM')}, + key: date.format('YYYY-MM-DD') + } + }); + +export const ScheduleModal: FC = ({ + open, + handleCancel, + mode, + updateMode, + sessionCost, + locale, + expertId, +}) => { + const [selectDate, setSelectDate] = useState(dayjs()); + const [dates, setDates] = useState(); + const [tags, setTags] = useState(); + const [sessionData, setSesssionData] = useState({ coachId: +expertId }); + const [sessionId, setSessionId] = useState(-1); + const [rawScheduler, setRawScheduler] = useState(null); + const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, ''); + const [isPayLoading, setIsPayLoading] = useState(false); + + dayjs.locale(locale); + + useEffect(()=> { + if (open) { + getSchedulerByExpertId(expertId as string, locale as string) + .then((data) => { + setRawScheduler(data); + }) + .catch((err) => { + console.log(err); + }); + } + }, [open]); + + useEffect(() => { + const map = {} as any + rawScheduler?.availableSlots.forEach((el) => { + const key = dayjs(el.startTime).format('YYYY-MM-DD'); + if (!map[key]){ + map[key] = [] + } + map[key].push(el); + }) + setDates(map); + setTags(rawScheduler?.tags) + }, [rawScheduler]); + + const onPanelChange = (value: Dayjs) => setSelectDate(value); + + const onDateChange: CalendarProps['onSelect'] = (value, selectInfo) => { + if (selectInfo.source === 'date') { + setSelectDate(value); + updateMode('time'); + } + }; + + const disabledDate = (currentDate: Dayjs) => !dates || !dates[currentDate.format('YYYY-MM-DD')]; + + const onChangeTimeSlot = (e: RadioChangeEvent) => setSesssionData({ ...sessionData, startAtUtc: e.target.value.startTime }); + + const onChangeTag = (tagId: number) => setSesssionData({ ...sessionData, tagId }); + + const singupSession = () => { + console.log(sessionData); + if (sessionData?.startAtUtc && sessionData?.tagId) { + if (jwt) { + setIsPayLoading(true); + getSchedulerSession(sessionData, locale, jwt) + .then((session) => { + console.log(session); + // тут должна быть проверка все ли с регистрацией сессии + setSessionId(+session?.sessionId); + updateMode('pay'); + }) + .catch((err) => { + console.log(err); + message.error('Не удалось провести оплату') + }) + .finally(() => { + setIsPayLoading(false); + }) + } else { + + } + } + } + + const cellRender: CalendarProps['fullCellRender'] = (date, info) => { + const isWeekend = date.day() === 6 || date.day() === 0; + return React.cloneElement(info.originNode, { + ...info.originNode.props, + className: classNames('b-calendar-cell', { + ['b-calendar-cell__select']: selectDate.isSame(date, 'date'), + ['b-calendar-cell__today']: date.isSame(dayjs(), 'date'), + ['b-calendar-cell__weekend']: isWeekend, + }), + children: ( +
+ + {date.get('date')} + +
+ ), + }); + }; + + return ( + } + > + {mode === 'data' && ( + { + const start = dayjs().startOf('M'); + const [activeMonth, setActiveMonth] = useState(start.format('YYYY-MM-DD')); + + const onClick: MenuProps['onClick'] = (e) => { + setActiveMonth(e.key); + onChange(dayjs(e.key)); + }; + + return ( + + ); + }} + /> + )} + {mode === 'time' && ( +
+
+ +
+
+ {tags && ( + ({ value: id, label: name }))} + onChange={onChangeTag} + /> + )} +
+
+ + {dates[selectDate.format('YYYY-MM-DD')].map((el) => { + return ({dayjs(el.startTime).format('HH:mm')} - {dayjs(el.endTime).format('HH:mm')}) + })} + +
+
+ setSesssionData({ ...sessionData, clientComment: e.target.value })} + /> +
+ +
+ )} + {mode === 'pay' && ( + + )} + + ); +}; diff --git a/src/components/Modals/SchedulerModal.tsx b/src/components/Modals/SchedulerModal.tsx deleted file mode 100644 index 77d6c82..0000000 --- a/src/components/Modals/SchedulerModal.tsx +++ /dev/null @@ -1,290 +0,0 @@ -'use client'; - -import React, {Dispatch, FC, SetStateAction, useEffect, useState} from 'react'; -import { usePathname } from 'next/navigation'; -import classNames from 'classnames'; -import Link from 'next/link'; -import {Modal, Form, Calendar, Radio } from 'antd'; -import type { CalendarProps, RadioChangeEvent } from 'antd'; -import { CloseOutlined } from '@ant-design/icons'; -import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent'; -import dayjs, { Dayjs } from 'dayjs'; -import {ExpertDetails, ExpertScheduler, Tags} from "../../types/experts"; -import { createStyles } from 'antd-style'; -import {useLocalStorage} from "../../hooks/useLocalStorage"; -import {AUTH_TOKEN_KEY} from "../../constants/common"; -import {getSchedulerByExpertId, getSchedulerSession} from "../../actions/experts"; -import {ElementsForm} from "../stripe/ElementsForm"; - -type SchedulerModalProps = { - open: boolean; - handleCancel: () => void; - mode: 'data' | 'time' | 'pay' | 'finish'; - updateMode: (mode: 'data' | 'time' | 'pay' | 'finish') => void; - sessionCost: number; - expertId: string; - locale: string; -}; - -const useStyle = createStyles(({ token, css, cx }) => { - const lunar = css` - color: ${token.colorTextTertiary}; - font-size: ${token.fontSizeSM}px; - `; - return { - wrapper: css` - width: 450px; - border: 1px solid ${token.colorBorderSecondary}; - border-radius: ${token.borderRadiusOuter}; - padding: 5px; - `, - dateCell: css` - position: relative; - &:before { - content: ''; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - margin: auto; - max-width: 40px; - max-height: 40px; - background: transparent; - transition: background 300ms; - border-radius: ${token.borderRadiusOuter}px; - border: 1px solid transparent; - box-sizing: border-box; - } - &:hover:before { - background: rgba(0, 0, 0, 0.04); - } - `, - today: css` - &:before { - border: 1px solid ${token.colorPrimary}; - } - `, - text: css` - position: relative; - z-index: 1; - `, - lunar, - current: css` - color: ${token.colorTextLightSolid}; - &:before { - background: ${token.colorPrimary}; - } - &:hover:before { - background: ${token.colorPrimary}; - opacity: 0.8; - } - .${cx(lunar)} { - color: ${token.colorTextLightSolid}; - opacity: 0.9; - } - `, - monthCell: css` - width: 120px; - color: ${token.colorTextBase}; - border-radius: ${token.borderRadiusOuter}px; - padding: 5px 0; - &:hover { - background: rgba(0, 0, 0, 0.04); - } - `, - monthCellCurrent: css` - color: ${token.colorTextLightSolid}; - background: ${token.colorPrimary}; - &:hover { - background: ${token.colorPrimary}; - opacity: 0.8; - } - `, - weekend: css` - color: ${token.colorError}; - &.gray { - opacity: 0.4; - } - `, - }; -}); - -export const SchedulerModal: FC = ({ - open, - handleCancel, - mode, - updateMode, - sessionCost, - locale, - expertId, -}) => { - const { styles } = useStyle({ test: true }); - const [selectDate, setSelectDate] = React.useState(dayjs()); - const [dates, setDates] = React.useState(); - const [tags, setTags] = React.useState([]); - const [tag, setTag] = React.useState(-1); - const [slot, setSlot] = React.useState(''); - const [sessionId, setSessionId] = React.useState(-1); - const [rawScheduler, setRawScheduler] = useState(null); - const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, ''); - - useEffect( ()=> { - async function loadScheduler(){ - const rawScheduler = await getSchedulerByExpertId(expertId as string, locale as string, jwt) - setRawScheduler(rawScheduler) - } - if (open) { - loadScheduler() - } - }, [open]) - - useEffect(() => { - const map = {} as any - rawScheduler?.availableSlots.forEach((el)=>{ - const key = dayjs(el.startTime).format('YYYY-MM-DD'); - if (!map[key]){ - map[key] = [] - } - map[key].push(el) - - }) - console.log(rawScheduler, map) - setDates(map) - setTags(rawScheduler?.tags) - }, [rawScheduler]); - - const onPanelChange = (value: Dayjs, mode: CalendarProps['mode']) => { - console.log(value.format('YYYY-MM-DD'), mode); - }; - - const onDateChange: CalendarProps['onSelect'] = (value, selectInfo) => { - if (selectInfo.source === 'date') { - setSelectDate(value); - updateMode('time') - } - }; - - const disabledDate = (currentDate: Dayjs) => { - return !dates || !dates[currentDate.format('YYYY-MM-DD')] - } - - const handleTimeslot = (e: RadioChangeEvent) => { - setSlot(e.target.value.startTime) - console.log('radio checked', e.target.value); - }; - - const handleTag = (e: RadioChangeEvent) => { - setTag(e.target.value) - console.log('tag radio checked', e.target.value); - }; - - const handleSingupSession = async () => { - const data = {coachId: expertId, tagId: tag, startAtUtc: slot, clientComment:''} - console.log(data) - const session = await getSchedulerSession({coachId: expertId, tagId: tag, startAtUtc: slot, clientComment:''}, locale, jwt) - console.log(session); - // тут должна быть проверка все ли с регистрацией сессии - setSessionId(session?.sessionId) - updateMode('pay') - } - - const currentDay = dayjs() - - const cellRender: CalendarProps['fullCellRender'] = (date, info) => { - const isWeekend = date.day() === 6 || date.day() === 0; - return React.cloneElement(info.originNode, { - ...info.originNode.props, - className: classNames(styles.dateCell, { - [styles.current]: selectDate.isSame(date, 'date'), - [styles.today]: date.isSame(dayjs(), 'date'), - }), - children: ( -
- - {date.get('date')} - -
- ), - }); - } - - - return ( - } - > -
- {tags && ( - - {tags?.map((tag)=>( - {tag.name} - ) - )} - - ) - } -
- {mode === 'data' && ( - { - const start = 0; - const end = 12; - const monthOptions = []; - - let current = currentDay.clone(); - const localeData = value.locale(); - const months = []; - - for(let i=0; i<6; i++){ - const m = current.clone() - months.push(m); - current = current.add(1,'month') - } - return (<> - {months.map((m, i)=>( - - ))} - ) - }} - - /> - )} - {mode === 'time' && ( - <> -
- -
- - - {dates[selectDate.format('YYYY-MM-DD')].map( (el) => { - return ({dayjs(el.startTime).format('hh-mm')} - {dayjs(el.endTime).format('hh-mm')}) - })} - - - - )} - {mode === 'pay' && ( - - )} -
- ); -}; diff --git a/src/i18nKeys/de.ts b/src/i18nKeys/de.ts index 3a2f8c0..cc1bc64 100644 --- a/src/i18nKeys/de.ts +++ b/src/i18nKeys/de.ts @@ -42,7 +42,7 @@ export default { addComment: 'Neuen Kommentar hinzufügen', commentPlaceholder: 'Ihr Kommentar', clientComments: 'Kundenkommentare', - coachComments: 'Trainerkommentare' + coachComments: 'Expertenkommentare' }, room: { upcoming: 'Zukünftige Räume', @@ -110,9 +110,9 @@ export default { seminars: 'Seminare', courses: 'Kurse', mba: 'MBA-Information', - aboutCoach: 'Über Coach', + aboutCoach: 'Über den Experten', education: 'Bildung', - coaching: 'Coaching', + coaching: 'Expertenprofil', experiences: 'Praktische Erfahrung', payInfo: 'Zahlungsdaten', sessionDuration: 'Sitzungsdauer', @@ -146,6 +146,8 @@ export default { saturday: 'Sa', addNew: 'Neu hinzufügen', mExperiences: 'Führungserfahrung', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'Die E-Mail-Adresse ist ungültig', emptyEmail: 'Bitte geben Sie Ihre E-Mail ein', diff --git a/src/i18nKeys/en.ts b/src/i18nKeys/en.ts index 4be1bc4..c74544a 100644 --- a/src/i18nKeys/en.ts +++ b/src/i18nKeys/en.ts @@ -42,7 +42,7 @@ export default { addComment: 'Add new', commentPlaceholder: 'Your comment', clientComments: 'Client Comments', - coachComments: 'Coach Comments' + coachComments: 'Expert Comments' }, room: { upcoming: 'Upcoming Rooms', @@ -109,10 +109,10 @@ export default { seminars: 'Seminars', courses: 'Courses', mba: 'MBA Information', - aboutCoach: 'About Coach', + aboutCoach: 'About Expert', skillsInfo: 'Skills Info', education: 'Education', - coaching: 'Coaching', + coaching: 'Expert profile', experiences: 'Practical experience', payInfo: 'Payment Info', sessionDuration: 'Session duration', @@ -146,6 +146,8 @@ export default { saturday: 'Sa', addNew: 'Add New', mExperiences: 'Managerial Experience', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'The email address is not valid', emptyEmail: 'Please enter your E-mail', diff --git a/src/i18nKeys/es.ts b/src/i18nKeys/es.ts index f869ff2..b81773e 100644 --- a/src/i18nKeys/es.ts +++ b/src/i18nKeys/es.ts @@ -42,7 +42,7 @@ export default { addComment: 'Añadir nuevo comentario', commentPlaceholder: 'Tu comentario', clientComments: 'Comentarios del cliente', - coachComments: 'Comentarios del entrenador' + coachComments: 'Comentarios del experto' }, room: { upcoming: 'Próximas salas', @@ -110,9 +110,9 @@ export default { seminars: 'Seminarios', courses: 'Cursos', mba: 'Información sobre máster en ADE (MBA)', - aboutCoach: 'Sobre el coach', + aboutCoach: 'Acerca del experto', education: 'Educación', - coaching: 'Coaching', + coaching: 'Perfil del experto', experiences: 'Experiencia práctica', payInfo: 'Información de pago', sessionDuration: 'Duración de la sesión', @@ -146,6 +146,8 @@ export default { saturday: 'S', addNew: 'Añadir nuevo', mExperiences: 'Experiencia de dirección', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'La dirección de correo electrónico no es válida', emptyEmail: 'Introduce tu correo electrónico', diff --git a/src/i18nKeys/fr.ts b/src/i18nKeys/fr.ts index 6bad2ed..21bc050 100644 --- a/src/i18nKeys/fr.ts +++ b/src/i18nKeys/fr.ts @@ -42,7 +42,7 @@ export default { addComment: 'Ajouter un nouveau commentaire', commentPlaceholder: 'Votre commentaire', clientComments: 'Commentaires du client', - coachComments: 'Commentaires du coach' + coachComments: 'Commentaires de l\'expert' }, room: { upcoming: 'Salles futures', @@ -110,9 +110,9 @@ export default { seminars: 'Séminaires', courses: 'Cours', mba: 'Infos Maîtrise en gestion', - aboutCoach: 'À propos du coach', + aboutCoach: 'À propos de l\'expert', education: 'Éducation', - coaching: 'Coaching', + coaching: 'Profil de l\'expert', experiences: 'Expérience pratique', payInfo: 'Infos sur le paiement', sessionDuration: 'Durée de la session', @@ -146,6 +146,8 @@ export default { saturday: 'Sa', addNew: 'Ajouter un nouveau', mExperiences: 'Expérience en gestion', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'L\'adresse e-mail n\'est pas valide', emptyEmail: 'Veuillez saisir votre e-mail', diff --git a/src/i18nKeys/it.ts b/src/i18nKeys/it.ts index 81a7d39..06215a2 100644 --- a/src/i18nKeys/it.ts +++ b/src/i18nKeys/it.ts @@ -42,7 +42,7 @@ export default { addComment: 'Aggiungi nuovo commento', commentPlaceholder: 'Il tuo commento', clientComments: 'Commenti del cliente', - coachComments: 'Commenti dell\'allenatore' + coachComments: 'Commenti dell\'esperto' }, room: { upcoming: 'Prossime sale', @@ -110,9 +110,9 @@ export default { seminars: 'Seminari', courses: 'Corsi', mba: 'Info sull\'MBA', - aboutCoach: 'Informazioni sul coach', + aboutCoach: 'Informazioni sull\'esperto', education: 'Istruzione', - coaching: 'Coaching', + coaching: 'Profilo dell\'esperto', experiences: 'Esperienza pratica', payInfo: 'Info pagamento', sessionDuration: 'Durata della sessione', @@ -146,6 +146,8 @@ export default { saturday: 'Sa', addNew: 'Aggiungi nuovo', mExperiences: 'Esperienza manageriale', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'L\'indirizzo e-mail non è valido', emptyEmail: 'Inserisci l\'e-mail', diff --git a/src/i18nKeys/ru.ts b/src/i18nKeys/ru.ts index b7db7b9..4d7c128 100644 --- a/src/i18nKeys/ru.ts +++ b/src/i18nKeys/ru.ts @@ -42,7 +42,7 @@ export default { addComment: 'Добавить новый', commentPlaceholder: 'Ваш комментарий', clientComments: 'Комментарии клиента', - coachComments: 'Комментарии коуча' + coachComments: 'Комментарии эксперта' }, room: { upcoming: 'Предстоящие комнаты', @@ -111,9 +111,9 @@ export default { courses: 'Курсы', mba: 'Информация о MBA', experiences: 'Практический опыт', - aboutCoach: 'О коуче', + aboutCoach: 'Информация об эксперте', education: 'Образование', - coaching: 'Коучинг', + coaching: 'Профиль эксперта', payInfo: 'Платежная информация', sessionDuration: 'Продолжительность сессии', experienceHours: 'Общее количество часов практического опыта', @@ -146,6 +146,8 @@ export default { saturday: 'Сб', addNew: 'Добавить', mExperiences: 'Управленческий опыт', + pay: 'Pay', + sessionWishes: 'Write your wishes about the session', errors: { invalidEmail: 'Адрес электронной почты недействителен', emptyEmail: 'Пожалуйста, введите ваш E-mail', diff --git a/src/styles/view/_calendar.scss b/src/styles/view/_calendar.scss new file mode 100644 index 0000000..fe04d1e --- /dev/null +++ b/src/styles/view/_calendar.scss @@ -0,0 +1,62 @@ +.b-calendar { + padding: 44px 40px !important; + + &-month { + text-transform: capitalize; + } + + &-header { + justify-content: center; + border-bottom: none !important; + } + + &-cell { + span { + color: #66A5AD; + } + + &__weekend { + span { + color: #FFBD00; + } + } + } + + .ant-picker-body { + margin-bottom: -42px !important; + } + + .ant-picker-panel { + border-top: none !important; + margin-top: 12px; + } + + .ant-picker-cell { + opacity: 0 !important; + + &-disabled { + &::before { + background: transparent !important; + } + + span { + color: rgba(0, 0, 0, 0.25) !important; + } + } + + &.ant-picker-cell-in-view { + opacity: 1 !important; + background: transparent !important; + } + + } + + th, td { + vertical-align: middle !important; + height: 40px !important; + } + + th { + color: #66A5AD !important; + } +} \ No newline at end of file diff --git a/src/styles/view/_schedule.scss b/src/styles/view/_schedule.scss new file mode 100644 index 0000000..5c8f75c --- /dev/null +++ b/src/styles/view/_schedule.scss @@ -0,0 +1,26 @@ +.b-schedule { + &-time { + padding: 44px 40px; + display: flex; + flex-direction: column; + gap: 24px; + + .b-button-link-big { + font-size: 24px; + line-height: 32px; + color: #6FB98F !important; + font-family: var(--font-comfortaa); + padding: 0 !important; + border: none !important; + text-transform: capitalize; + } + } + + &-radio-list { + .ant-radio-group { + display: flex; + flex-direction: column; + gap: 12px; + } + } +} \ No newline at end of file diff --git a/src/styles/view/style.scss b/src/styles/view/style.scss index b626bbd..569d2c4 100644 --- a/src/styles/view/style.scss +++ b/src/styles/view/style.scss @@ -9,3 +9,5 @@ @import "_practice.scss"; @import "_collapse.scss"; @import "_timepicker.scss"; +@import "_calendar.scss"; +@import "_schedule.scss"; diff --git a/src/types/experts.ts b/src/types/experts.ts index 27fe753..c79322b 100644 --- a/src/types/experts.ts +++ b/src/types/experts.ts @@ -71,28 +71,23 @@ export type ExpertDetails = { associationLevels?: AssociationLevel[]; }; -export type Tags = { - id: number, - groupId: number, - name: string, - couchCount: number, - group: { - id: number, - name: string, - tags: string[]; - } -} - export type Slot = { startTime: string; endTime: string; } export type ExpertScheduler = { - tags: Tags[], + tags: Tag[], availableSlots: Slot[]; } export type ExpertSchedulerSession = { sessionId: string -} \ No newline at end of file +}; + +export type SignupSessionData = { + coachId: number, + tagId?: number, + startAtUtc?: string, + clientComment?: string +}; \ No newline at end of file