Merge remote-tracking branch 'origin/blog' into blog
This commit is contained in:
commit
dbb74b9ccd
|
@ -1,14 +1,18 @@
|
||||||
pipeline {
|
pipeline {
|
||||||
agent { label 'jenkins-nodejs-agent' }
|
agent { label 'jenkins-nodejs-agent' }
|
||||||
|
|
||||||
|
environment {
|
||||||
|
RELEASE = "latest"
|
||||||
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Build static content') {
|
stage('Build static content') {
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
docker build --progress=plain -t bbuddy/bbuddy_ui:latest .
|
#npm install
|
||||||
|
#npm run build
|
||||||
|
#pwd
|
||||||
|
#echo
|
||||||
|
docker build --progress=plain -t bbuddy/bbuddy_ui:${RELEASE} .
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +20,8 @@ pipeline {
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
sudo docker login https://harbor-wtkp3fsbv6.vertexa.devbay.tech/ -u 'robot$jenkins' -p 'ZrzsVIAeueW1p0alpAnPfM5CDtaRVVKz'
|
sudo docker login https://harbor-wtkp3fsbv6.vertexa.devbay.tech/ -u 'robot$jenkins' -p 'ZrzsVIAeueW1p0alpAnPfM5CDtaRVVKz'
|
||||||
sudo docker tag bbuddy/bbuddy_ui:latest harbor-wtkp3fsbv6.vertexa.devbay.tech/bbuddy/bbuddy_ui:latest
|
sudo docker tag bbuddy/bbuddy_ui:${RELEASE} harbor-wtkp3fsbv6.vertexa.devbay.tech/bbuddy/bbuddy_ui:${RELEASE}
|
||||||
sudo docker push harbor-wtkp3fsbv6.vertexa.devbay.tech/bbuddy/bbuddy_ui:latest
|
sudo docker push harbor-wtkp3fsbv6.vertexa.devbay.tech/bbuddy/bbuddy_ui:${RELEASE}
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
{
|
{
|
||||||
"Header": {
|
|
||||||
"registration": "Registration",
|
|
||||||
"enter": "Enter",
|
|
||||||
"account": "My Account",
|
|
||||||
"menu": {
|
|
||||||
"bb-client": "Start grow with BB",
|
|
||||||
"bb-expert": "Become BB Expert",
|
|
||||||
"blog": "Blog&News"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Main",
|
"title": "Bbuddy - Main",
|
||||||
"description": "Bbuddy desc",
|
"description": "Bbuddy desc",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Plattform für persönlichen und beruflichen Erfolg",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Erhalten Sie Beratungen von führenden Coaches und Mentoren auf BBuddy. Unsere Experten helfen Ihnen, sich zu entwickeln, zu lernen und Ihre persönlichen und beruflichen Ziele zu erreichen. Nutzen Sie unsere Web-Plattform und mobile App für professionelle Unterstützung und Wachstum.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Fachartikel & Projektneuigkeiten",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
"BbClient": {
|
"BbClient": {
|
||||||
|
@ -89,7 +79,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Experts": {
|
"Experts": {
|
||||||
"title": "Find a expert",
|
"title": "Einen Experten finden",
|
||||||
"filter": {
|
"filter": {
|
||||||
"price": "Price from {from}€ to {to}€",
|
"price": "Price from {from}€ to {to}€",
|
||||||
"duration": "Duration from {from}min to {to}min",
|
"duration": "Duration from {from}min to {to}min",
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Main",
|
"title": "Bbuddy - Main",
|
||||||
"description": "Bbuddy desc",
|
"description": "Bbuddy desc",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Platform for Personal and Career Success",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Receive consultations from leading coaches and mentors on BBuddy. Our experts will help you develop, learn, and achieve your personal and career goals. Use our web platform and mobile app for professional support and growth.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Professional Articles & Project News",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Experts": {
|
"Experts": {
|
||||||
"title": "Find a expert",
|
"title": "Find an expert",
|
||||||
"filter": {
|
"filter": {
|
||||||
"price": "Price from {from}€ to {to}€",
|
"price": "Price from {from}€ to {to}€",
|
||||||
"duration": "Duration from {from}min to {to}min",
|
"duration": "Duration from {from}min to {to}min",
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
{
|
{
|
||||||
"Header": {
|
|
||||||
"registration": "Registration",
|
|
||||||
"enter": "Enter",
|
|
||||||
"account": "My Account",
|
|
||||||
"menu": {
|
|
||||||
"bb-client": "Start grow with BB",
|
|
||||||
"bb-expert": "Become BB Expert",
|
|
||||||
"blog": "Blog&News"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Main",
|
"title": "Bbuddy - Main",
|
||||||
"description": "Bbuddy desc",
|
"description": "Bbuddy desc",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Plataforma para el éxito personal y profesional",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Reciba consultas de entrenadores y mentores líderes en BBuddy. Nuestros expertos le ayudarán a desarrollarse, aprender y alcanzar sus objetivos personales y profesionales. Utilice nuestra plataforma web y aplicación móvil para apoyo profesional y crecimiento.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Artículos profesionales y Noticias de proyectos",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
"BbClient": {
|
"BbClient": {
|
||||||
|
@ -89,7 +79,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Experts": {
|
"Experts": {
|
||||||
"title": "Find a expert",
|
"title": "Encontrar un experto",
|
||||||
"filter": {
|
"filter": {
|
||||||
"price": "Price from {from}€ to {to}€",
|
"price": "Price from {from}€ to {to}€",
|
||||||
"duration": "Duration from {from}min to {to}min",
|
"duration": "Duration from {from}min to {to}min",
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
{
|
{
|
||||||
"Header": {
|
|
||||||
"registration": "Registration",
|
|
||||||
"enter": "Enter",
|
|
||||||
"account": "My Account",
|
|
||||||
"menu": {
|
|
||||||
"bb-client": "Start grow with BB",
|
|
||||||
"bb-expert": "Become BB Expert",
|
|
||||||
"blog": "Blog&News"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Main",
|
"title": "Bbuddy - Main",
|
||||||
"description": "Bbuddy desc",
|
"description": "Bbuddy desc",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Plateforme pour le succès personnel et professionnel",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Recevez des consultations de coachs et mentors de premier plan sur BBuddy. Nos experts vous aideront à développer, apprendre et atteindre vos objectifs personnels et professionnels. Utilisez notre plateforme web et notre application mobile pour un soutien professionnel et une croissance.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Articles professionnels et actualités des projets",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
"BbClient": {
|
"BbClient": {
|
||||||
|
@ -89,7 +79,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Experts": {
|
"Experts": {
|
||||||
"title": "Find a expert",
|
"title": "Trouver un expert",
|
||||||
"filter": {
|
"filter": {
|
||||||
"price": "Price from {from}€ to {to}€",
|
"price": "Price from {from}€ to {to}€",
|
||||||
"duration": "Duration from {from}min to {to}min",
|
"duration": "Duration from {from}min to {to}min",
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
{
|
{
|
||||||
"Header": {
|
|
||||||
"registration": "Registration",
|
|
||||||
"enter": "Enter",
|
|
||||||
"account": "My Account",
|
|
||||||
"menu": {
|
|
||||||
"bb-client": "Start grow with BB",
|
|
||||||
"bb-expert": "Become BB Expert",
|
|
||||||
"blog": "Blog&News"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Main",
|
"title": "Bbuddy - Main",
|
||||||
"description": "Bbuddy desc",
|
"description": "Bbuddy desc",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Piattaforma per il successo personale e professionale",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Ricevi consulenze da coach e mentori leader su BBuddy. I nostri esperti ti aiuteranno a svilupparti, imparare e raggiungere i tuoi obiettivi personali e professionali. Usa la nostra piattaforma web e l'app mobile per supporto professionale e crescita.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Articoli professionali e novità sui progetti",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
"BbClient": {
|
"BbClient": {
|
||||||
|
@ -89,7 +79,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Experts": {
|
"Experts": {
|
||||||
"title": "Find a expert",
|
"title": "Trova un esperto",
|
||||||
"filter": {
|
"filter": {
|
||||||
"price": "Price from {from}€ to {to}€",
|
"price": "Price from {from}€ to {to}€",
|
||||||
"duration": "Duration from {from}min to {to}min",
|
"duration": "Duration from {from}min to {to}min",
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
{
|
{
|
||||||
"Header": {
|
|
||||||
"registration": "Регистрация",
|
|
||||||
"enter": "Вход",
|
|
||||||
"account": "Мой аккаунт",
|
|
||||||
"menu": {
|
|
||||||
"bb-client": "Начни вместе с BB",
|
|
||||||
"bb-expert": "Стань BB экспертом",
|
|
||||||
"blog": "Блог&Новости"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Main": {
|
"Main": {
|
||||||
"title": "Bbuddy - Главная",
|
"title": "Bbuddy - Главная",
|
||||||
"description": "Bbuddy описание",
|
"description": "Bbuddy описание",
|
||||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
"header": "BBuddy: Платформа для Личного и Карьерного Успеха",
|
||||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
"header-desc": "Получайте консультации от ведущих коучей и менторов в BBuddy. Наши эксперты помогут вам развиваться, обучаться и достигать личных и карьерных целей. Используйте нашу веб-платформу и мобильное приложение для получения профессиональной поддержки и роста.",
|
||||||
"news": "Professional Articles & Project News",
|
"news": "Профессиональные статьи и новости проекта",
|
||||||
"popular": "Popular Topics"
|
"popular": "Popular Topics"
|
||||||
},
|
},
|
||||||
"BbClient": {
|
"BbClient": {
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 4.2 KiB |
|
@ -1,26 +1,14 @@
|
||||||
import { AxiosResponse } from 'axios';
|
import { apiRequest } from './helpers';
|
||||||
import { apiClient } from '../lib/apiClient';
|
|
||||||
|
|
||||||
export const getAuth = (locale: string, data: { login: string, password: string }): Promise<AxiosResponse<{ jwtToken: string }>> => (
|
export const getAuth = (locale: string, data: { login: string, password: string }): Promise<{ jwtToken: string }> => apiRequest({
|
||||||
apiClient.post(
|
url: '/auth/login',
|
||||||
'/auth/login',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
{
|
locale
|
||||||
headers: {
|
});
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getRegister = (locale: string): Promise<AxiosResponse<{ jwtToken: string }>> => (
|
export const getRegister = (locale: string): Promise<{ jwtToken: string }> => apiRequest({
|
||||||
apiClient.post(
|
url: '/auth/register',
|
||||||
'/auth/register',
|
method: 'post',
|
||||||
{},
|
locale
|
||||||
{
|
});
|
||||||
headers: {
|
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,30 +1,16 @@
|
||||||
import { apiClient } from '../lib/apiClient';
|
|
||||||
import { GeneralFilter, ExpertsData, ExpertDetails } from '../types/experts';
|
import { GeneralFilter, ExpertsData, ExpertDetails } from '../types/experts';
|
||||||
|
import { apiRequest } from './helpers';
|
||||||
|
|
||||||
export const getExpertsList = async (locale: string, filter?: GeneralFilter) => {
|
export const getExpertsList = (locale: string, filter?: GeneralFilter): Promise<ExpertsData> => apiRequest({
|
||||||
const response = await apiClient.post(
|
url: '/home/coachsearch1',
|
||||||
'/home/coachsearch1',
|
method: 'post',
|
||||||
{ ...filter },
|
data: { ...filter },
|
||||||
{
|
locale
|
||||||
headers: {
|
});
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data as ExpertsData || null;
|
export const getExpertById = (id: string, locale: string): Promise<ExpertDetails> => apiRequest({
|
||||||
};
|
url: '/home/coachdetails',
|
||||||
|
method: 'post',
|
||||||
export const getExpertById = async (id: string, locale: string) => {
|
data: { id },
|
||||||
const response = await apiClient.post(
|
locale
|
||||||
'/home/coachdetails',
|
});
|
||||||
{ id },
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data as ExpertDetails || null;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
|
import { apiClient } from '../lib/apiClient';
|
||||||
|
|
||||||
|
type RequiredConfigParams<D = any> = Required<Pick<AxiosRequestConfig, 'url' | 'method'>> & Pick<AxiosRequestConfig<D>, 'data'>;
|
||||||
|
export type PageRequestConfig<D = any> = RequiredConfigParams<D> & Partial<Pick<AxiosRequestConfig, 'headers'>> & { locale?: string, token?: string };
|
||||||
|
|
||||||
|
export const apiRequest = async <T = any, K = any>(
|
||||||
|
baseParams: PageRequestConfig<T>,
|
||||||
|
): Promise<K> => {
|
||||||
|
try {
|
||||||
|
const config = {
|
||||||
|
url: baseParams.url,
|
||||||
|
method: baseParams.method,
|
||||||
|
data: baseParams?.data,
|
||||||
|
headers: {
|
||||||
|
'X-User-Language': baseParams?.locale || 'en',
|
||||||
|
'X-Referrer-Channel': 'site',
|
||||||
|
...(baseParams?.token ? { Authorization: `Bearer ${baseParams.token}` } : {}),
|
||||||
|
...(baseParams.headers || {})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const response: AxiosResponse<K> = await apiClient.request<any, AxiosResponse<K>, T>(config as AxiosRequestConfig<T>);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (err) {
|
||||||
|
// const {
|
||||||
|
// response: {
|
||||||
|
// status: responseCode = null,
|
||||||
|
// statusText = '',
|
||||||
|
// data: { message = '', status: errorKey = '' } = {},
|
||||||
|
// } = {},
|
||||||
|
// code: statusCode = '',
|
||||||
|
// } = err as AxiosError;
|
||||||
|
//
|
||||||
|
// throw new Error(
|
||||||
|
// JSON.stringify({
|
||||||
|
// statusCode,
|
||||||
|
// statusMessage: message || statusText,
|
||||||
|
// responseCode,
|
||||||
|
// errorKey,
|
||||||
|
// }),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,21 +1,20 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { Profile } from '../../types/profile';
|
import { ProfileData, ProfileRequest } from '../../types/profile';
|
||||||
import { getPersonalData } from '../profile';
|
import { getPersonalData, setPersonData } from '../profile';
|
||||||
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
||||||
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||||
|
|
||||||
export const useProfileSettings = (locale: string) => {
|
export const useProfileSettings = (locale: string) => {
|
||||||
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
||||||
const [profileSettings, setProfileSettings] = useState<Profile | undefined>();
|
const [profileSettings, setProfileSettings] = useState<ProfileData | undefined>();
|
||||||
const [fetchLoading, setFetchLoading] = useState<boolean>(false);
|
const [fetchLoading, setFetchLoading] = useState<boolean>(false);
|
||||||
const [saveLoading, setSaveLoading] = useState<boolean>(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchProfileSettings = () => {
|
||||||
if (jwt) {
|
if (jwt) {
|
||||||
getPersonalData(locale, jwt)
|
getPersonalData(locale, jwt)
|
||||||
.then(({ data }) => {
|
.then((data) => {
|
||||||
setProfileSettings(data);
|
setProfileSettings(data);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
@ -25,16 +24,14 @@ export const useProfileSettings = (locale: string) => {
|
||||||
setFetchLoading(false);
|
setFetchLoading(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
};
|
||||||
|
|
||||||
const save = useCallback(() => {
|
const save = useCallback((data: ProfileRequest) => setPersonData(data, locale, jwt), []);
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fetchLoading,
|
fetchLoading,
|
||||||
|
fetchProfileSettings,
|
||||||
save,
|
save,
|
||||||
saveLoading,
|
|
||||||
profileSettings
|
profileSettings
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,8 +18,8 @@ export const useSessionDetails = (locale: string, sessionId: number) => {
|
||||||
setSession(undefined);
|
setSession(undefined);
|
||||||
|
|
||||||
getSessionDetails(locale, jwt, sessionId)
|
getSessionDetails(locale, jwt, sessionId)
|
||||||
.then(({ data }) => {
|
.then((session) => {
|
||||||
setSession(data);
|
setSession(session);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setErrorData(err);
|
setErrorData(err);
|
||||||
|
|
|
@ -1,29 +1,103 @@
|
||||||
import { AxiosResponse } from 'axios';
|
import { PayInfo, Profile, ProfileRequest, ProfileData } from '../types/profile';
|
||||||
import { apiClient } from '../lib/apiClient';
|
import { ExpertsTags } from '../types/tags';
|
||||||
import { Profile } from '../types/profile';
|
import { EducationData, EducationDTO } from '../types/education';
|
||||||
|
import { PracticeData, PracticeDTO } from '../types/practice';
|
||||||
|
import { ScheduleDTO } from '../types/schedule';
|
||||||
|
import { apiRequest } from './helpers';
|
||||||
|
|
||||||
export const setPersonData = (person: { login: string, password: string, role: string, languagesLinks: any[] }, locale: string, jwt: string): Promise<AxiosResponse<{ userData: Profile }>> => (
|
export const getUserData = (locale: string, token: string): Promise<Profile> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/userdata',
|
||||||
'/home/applyperson1',
|
method: 'post',
|
||||||
{ ...person },
|
locale,
|
||||||
{
|
token
|
||||||
headers: {
|
});
|
||||||
'X-User-Language': locale,
|
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getPersonalData = (locale: string, jwt: string): Promise<AxiosResponse<Profile>> => (
|
export const getPersonalData = (locale: string, token: string): Promise<ProfileData> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/person1',
|
||||||
'/home/userdata',
|
method: 'post',
|
||||||
{},
|
locale,
|
||||||
{
|
token
|
||||||
headers: {
|
});
|
||||||
'X-User-Language': locale,
|
|
||||||
Authorization: `Bearer ${jwt}`
|
export const setPersonData = (data: ProfileRequest, locale: string, token: string): Promise<{ userData: Profile }> => apiRequest({
|
||||||
}
|
url: '/home/applyperson1',
|
||||||
}
|
method: 'post',
|
||||||
)
|
data,
|
||||||
);
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getEducation = (locale: string, token: string): Promise<EducationDTO> => apiRequest({
|
||||||
|
url: '/home/person2',
|
||||||
|
method: 'post',
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setEducation = (locale: string, token: string, data: EducationData): Promise<EducationData> => apiRequest({
|
||||||
|
url: '/home/applyperson2',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getTags = (locale: string, token: string): Promise<ExpertsTags> => apiRequest({
|
||||||
|
url: '/home/person3',
|
||||||
|
method: 'post',
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setTags = (locale: string, token: string, data: ExpertsTags): Promise<ExpertsTags> => apiRequest({
|
||||||
|
url: '/home/applyperson3',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getPractice = (locale: string, token: string): Promise<PracticeDTO> => apiRequest({
|
||||||
|
url: '/home/person4',
|
||||||
|
method: 'post',
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setPractice = (locale: string, token: string, data: PracticeData): Promise<PracticeDTO> => apiRequest({
|
||||||
|
url: '/home/applyperson4',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getSchedule = (locale: string, token: string): Promise<ScheduleDTO> => apiRequest({
|
||||||
|
url: '/home/person51',
|
||||||
|
method: 'post',
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setSchedule = (locale: string, token: string, data: ScheduleDTO): Promise<ScheduleDTO> => apiRequest({
|
||||||
|
url: '/home/applyperson51',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getPayData = (locale: string, token: string): Promise<{ person6Data?: PayInfo }> => apiRequest({
|
||||||
|
url: '/home/person6',
|
||||||
|
method: 'post',
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setPayData = (locale: string, token: string, data: PayInfo): Promise<PayInfo> => apiRequest({
|
||||||
|
url: '/home/applyperson6',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
|
@ -1,145 +1,93 @@
|
||||||
import { AxiosResponse } from 'axios';
|
|
||||||
import { apiClient } from '../lib/apiClient';
|
|
||||||
import { DeclineSessionData, Session, SessionsFilter, SessionCommentData } from '../types/sessions';
|
import { DeclineSessionData, Session, SessionsFilter, SessionCommentData } from '../types/sessions';
|
||||||
|
import { apiRequest } from './helpers';
|
||||||
|
|
||||||
export const getUpcomingSessions = (locale: string, jwt: string, filter?: SessionsFilter): Promise<AxiosResponse<Session[]>> => (
|
export const getUpcomingSessions = (locale: string, token: string, filter?: SessionsFilter): Promise<Session[]> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/upcomingsessionsall',
|
||||||
'/home/upcomingsessionsall',
|
method: 'post',
|
||||||
{
|
data: {
|
||||||
sessionType: 'session',
|
sessionType: 'session',
|
||||||
...(filter || {})
|
...(filter || {})
|
||||||
},
|
},
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getRequestedSessions = (locale: string, jwt: string): Promise<AxiosResponse<{ requestedSessions: Session[] }>> => (
|
export const getRequestedSessions = (locale: string, token: string): Promise<{ requestedSessions: Session[] }> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/coachhomedata',
|
||||||
'/home/coachhomedata',
|
method: 'post',
|
||||||
{},
|
locale,
|
||||||
{
|
token
|
||||||
headers: {
|
});
|
||||||
'X-User-Language': locale,
|
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getRecentSessions = (locale: string, jwt: string, filter?: SessionsFilter): Promise<AxiosResponse<Session[]>> => (
|
export const getRecentSessions = (locale: string, token: string, filter?: SessionsFilter): Promise<Session[]> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/historicalmeetings',
|
||||||
'/home/historicalmeetings',
|
method: 'post',
|
||||||
{
|
data: {
|
||||||
sessionType: 'session',
|
sessionType: 'session',
|
||||||
...(filter || {})
|
...(filter || {})
|
||||||
},
|
},
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getSessionDetails = (locale: string, jwt: string, id: number): Promise<AxiosResponse<Session>> => (
|
export const getSessionDetails = (locale: string, token: string, id: number): Promise<Session> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/session',
|
||||||
'/home/session',
|
method: 'post',
|
||||||
{ id },
|
data: { id },
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const approveRequestedSession = (locale: string, jwt: string, sessionId: number): Promise<AxiosResponse> => (
|
export const approveRequestedSession = (locale: string, token: string, sessionId: number): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/approverequestedsession',
|
||||||
'/home/approverequestedsession',
|
method: 'post',
|
||||||
{ sessionId },
|
data: { sessionId },
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const declineRequestedSession = (locale: string, jwt: string, { sessionId, reason }: DeclineSessionData): Promise<AxiosResponse> => (
|
export const declineRequestedSession = (locale: string, token: string, { sessionId, reason }: DeclineSessionData): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/declinerequestedsession',
|
||||||
'/home/declinerequestedsession',
|
method: 'post',
|
||||||
{
|
data: {
|
||||||
sessionId,
|
sessionId,
|
||||||
coachDeclineReason: reason
|
coachDeclineReason: reason
|
||||||
},
|
},
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const cancelUpcomingSession = (locale: string, jwt: string, { sessionId, reason }: DeclineSessionData): Promise<AxiosResponse> => (
|
export const cancelUpcomingSession = (locale: string, token: string, { sessionId, reason }: DeclineSessionData): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/cancelupcomingsession',
|
||||||
'/home/cancelupcomingsession',
|
method: 'post',
|
||||||
{
|
data: {
|
||||||
sessionId,
|
sessionId,
|
||||||
coachCancelReason: reason
|
coachCancelReason: reason
|
||||||
},
|
},
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const addSessionComment = (locale: string, jwt: string, data: SessionCommentData): Promise<AxiosResponse> => (
|
export const addSessionComment = (locale: string, token: string, data: SessionCommentData): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/session_comment',
|
||||||
'/home/session_comment',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const trackingStartSession = (locale: string, jwt: string, id: number): Promise<AxiosResponse> => (
|
export const trackingStartSession = (locale: string, token: string, id: number): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/sessiontracking',
|
||||||
'/home/sessiontracking',
|
method: 'post',
|
||||||
{ id },
|
data: { id },
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const finishSession = (locale: string, jwt: string, sessionId: number): Promise<AxiosResponse> => (
|
export const finishSession = (locale: string, token: string, sessionId: number): Promise<any> => apiRequest({
|
||||||
apiClient.post(
|
url: '/home/finishsession',
|
||||||
'/home/finishsession',
|
method: 'post',
|
||||||
{ sessionId },
|
data: { sessionId },
|
||||||
{
|
locale,
|
||||||
headers: {
|
token
|
||||||
'X-User-Language': locale,
|
});
|
||||||
Authorization: `Bearer ${jwt}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,29 +1,14 @@
|
||||||
import { apiClient } from '../lib/apiClient';
|
|
||||||
import { SearchData, Languages } from '../types/tags';
|
import { SearchData, Languages } from '../types/tags';
|
||||||
|
import { apiRequest } from './helpers';
|
||||||
|
|
||||||
export const getTagList = async (locale: string) => {
|
export const getTagList = (locale: string): Promise<SearchData> => apiRequest({
|
||||||
const response = await apiClient.post(
|
url: '/home/searchdata',
|
||||||
'/home/searchdata',
|
method: 'post',
|
||||||
{},
|
locale
|
||||||
{
|
});
|
||||||
headers: {
|
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data as SearchData || null;
|
export const getLanguages = (locale: string): Promise<Languages> => apiRequest({
|
||||||
};
|
url: '/home/languages',
|
||||||
|
method: 'get',
|
||||||
export const getLanguages = async (locale: string) => {
|
locale
|
||||||
const response = await apiClient.get(
|
});
|
||||||
'/home/languages',
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'X-User-Language': locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data as Languages || null;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ExpertDocument } from '../types/file';
|
||||||
|
import { apiRequest } from './helpers';
|
||||||
|
|
||||||
|
export const setUploadFile = (locale: string, token: string, data: any): Promise<ExpertDocument> => apiRequest({
|
||||||
|
url: '/home/uploadfile',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
locale,
|
||||||
|
token,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,10 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { unstable_setRequestLocale } from 'next-intl/server';
|
||||||
|
import { i18nText } from '../../../../i18nKeys';
|
||||||
|
|
||||||
|
export default function News({ params: { locale } }: { params: { locale: string }}) {
|
||||||
|
unstable_setRequestLocale(locale);
|
||||||
|
const t = useTranslations('Main');
|
||||||
|
|
||||||
export default function News() {
|
|
||||||
return (
|
return (
|
||||||
<div className="main-articles">
|
<div className="main-articles">
|
||||||
<div className="b-inner">
|
<div className="b-inner">
|
||||||
<h2 className="title-h2">Professional Articles & Project News</h2>
|
<h2 className="title-h2">{t('news')}</h2>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-lg-4 col-md-6 col-sm-6">
|
<div className="col-lg-4 col-md-6 col-sm-6">
|
||||||
<div className="b-article">
|
<div className="b-article">
|
||||||
|
@ -18,7 +24,7 @@ export default function News() {
|
||||||
performance from many angles, such as human resources management, IT, operations
|
performance from many angles, such as human resources management, IT, operations
|
||||||
management, risks etc.
|
management, risks etc.
|
||||||
</div>
|
</div>
|
||||||
<a href="#" className="b-article__link">Read more
|
<a href="#" className="b-article__link">{i18nText('readMore', locale)}
|
||||||
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +42,7 @@ export default function News() {
|
||||||
performance from many angles, such as human resources management, IT, operations
|
performance from many angles, such as human resources management, IT, operations
|
||||||
management, risks etc.
|
management, risks etc.
|
||||||
</div>
|
</div>
|
||||||
<a href="#" className="b-article__link">Read more
|
<a href="#" className="b-article__link">{i18nText('readMore', locale)}
|
||||||
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -54,7 +60,7 @@ export default function News() {
|
||||||
performance from many angles, such as human resources management, IT, operations
|
performance from many angles, such as human resources management, IT, operations
|
||||||
management, risks etc.
|
management, risks etc.
|
||||||
</div>
|
</div>
|
||||||
<a href="#" className="b-article__link">Read more
|
<a href="#" className="b-article__link">{i18nText('readMore', locale)}
|
||||||
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
<img className="" src="/images/chevron-forward.svg" alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,17 +12,15 @@ import React, { ReactNode } from 'react';
|
||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
|
|
||||||
export default function MainLayout({ children, news, directions, experts }: {
|
export default function MainLayout({ children, news, experts }: {
|
||||||
children: ReactNode,
|
children: ReactNode,
|
||||||
news: ReactNode,
|
news: ReactNode,
|
||||||
directions: ReactNode,
|
|
||||||
experts: ReactNode
|
experts: ReactNode
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{children}
|
{children}
|
||||||
{news}
|
{news}
|
||||||
{directions}
|
|
||||||
{experts}
|
{experts}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from '../../../../../../../navigation';
|
import { Link } from '../../../../../../navigation';
|
||||||
import { CustomSelect } from '../../../../../../../components/view/CustomSelect';
|
import { CustomSelect } from '../../../../../../components/view/CustomSelect';
|
||||||
|
|
||||||
export default function AddOffer() {
|
export default function AddOffer() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ol className="breadcrumb">
|
<ol className="breadcrumb">
|
||||||
<li className="breadcrumb-item">
|
<li className="breadcrumb-item">
|
||||||
<Link href={'/account/work-with-us' as any}>
|
<Link href={'/account/expert-profile' as any}>
|
||||||
Work With Us
|
Work With Us
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="breadcrumb-item">
|
<li className="breadcrumb-item">
|
||||||
<Link href={'/account/work-with-us/coaching' as any}>
|
<Link href={'/account/expert-profile/coaching' as any}>
|
||||||
Coaching
|
Coaching
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
|
@ -7,7 +7,7 @@ export default function NewTopic() {
|
||||||
<>
|
<>
|
||||||
<ol className="breadcrumb">
|
<ol className="breadcrumb">
|
||||||
<li className="breadcrumb-item">
|
<li className="breadcrumb-item">
|
||||||
<Link href={'/account/work-with-us' as any}>
|
<Link href={'/account/expert-profile' as any}>
|
||||||
Work With Us
|
Work With Us
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
|
@ -0,0 +1,66 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { message } from 'antd';
|
||||||
|
// import { unstable_setRequestLocale } from 'next-intl/server';
|
||||||
|
import { ExpertData } from '../../../../../types/profile';
|
||||||
|
import { AUTH_TOKEN_KEY } from '../../../../../constants/common';
|
||||||
|
import { useLocalStorage } from '../../../../../hooks/useLocalStorage';
|
||||||
|
import { getEducation, getPersonalData, getTags, getPractice, getSchedule, getPayData } from '../../../../../actions/profile';
|
||||||
|
import { ExpertProfile } from '../../../../../components/ExpertProfile';
|
||||||
|
import { Loader } from '../../../../../components/view/Loader';
|
||||||
|
|
||||||
|
export default function ExpertProfilePage({ params: { locale } }: { params: { locale: string } }) {
|
||||||
|
// unstable_setRequestLocale(locale);
|
||||||
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [data, setData] = useState<ExpertData | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (jwt) {
|
||||||
|
setLoading(true);
|
||||||
|
Promise.all([
|
||||||
|
getPersonalData(locale, jwt),
|
||||||
|
getEducation(locale, jwt),
|
||||||
|
getTags(locale, jwt),
|
||||||
|
getPractice(locale, jwt),
|
||||||
|
getSchedule(locale, jwt),
|
||||||
|
getPayData(locale, jwt)
|
||||||
|
])
|
||||||
|
.then(([person, education, tags, practice, schedule, payData]) => {
|
||||||
|
console.log('person', person);
|
||||||
|
console.log('education', education);
|
||||||
|
console.log('tags', tags);
|
||||||
|
console.log('practice', practice);
|
||||||
|
console.log('schedule', schedule);
|
||||||
|
console.log('payData', payData);
|
||||||
|
setData({
|
||||||
|
person,
|
||||||
|
education,
|
||||||
|
tags,
|
||||||
|
practice,
|
||||||
|
schedule,
|
||||||
|
payData
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('Не удалось загрузить данные эксперта');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [jwt]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Loader isLoading={loading}>
|
||||||
|
{data && (
|
||||||
|
<ExpertProfile
|
||||||
|
locale={locale}
|
||||||
|
data={data}
|
||||||
|
updateData={setData}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Loader>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,18 +1,10 @@
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import type { Metadata } from 'next';
|
|
||||||
import { unstable_setRequestLocale } from 'next-intl/server';
|
import { unstable_setRequestLocale } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
|
||||||
import { ProfileSettings } from '../../../../../components/Account';
|
import { ProfileSettings } from '../../../../../components/Account';
|
||||||
import { i18nText } from '../../../../../i18nKeys';
|
import { i18nText } from '../../../../../i18nKeys';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Bbuddy - Account - Profile Settings',
|
|
||||||
description: 'Bbuddy desc Profile settings'
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Settings({ params: { locale } }: { params: { locale: string } }) {
|
export default function Settings({ params: { locale } }: { params: { locale: string } }) {
|
||||||
unstable_setRequestLocale(locale);
|
unstable_setRequestLocale(locale);
|
||||||
const t = useTranslations('Account.Settings');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Link } from '../../../../../../navigation';
|
|
||||||
|
|
||||||
export default function Coaching() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ol className="breadcrumb">
|
|
||||||
<li className="breadcrumb-item">
|
|
||||||
<Link href={'/account/work-with-us' as any}>
|
|
||||||
Work With Us
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li className="breadcrumb-item active" aria-current="page">Coaching</li>
|
|
||||||
</ol>
|
|
||||||
<div className="coaching-info">
|
|
||||||
<div className="card-profile">
|
|
||||||
<div className="card-profile__header">
|
|
||||||
<div className="card-profile__header__portrait">
|
|
||||||
<img src="/images/person.png" className="" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="card-profile__header__inner">
|
|
||||||
<div className="card-profile__header__name">
|
|
||||||
David
|
|
||||||
</div>
|
|
||||||
<div className="card-profile__header__title">
|
|
||||||
12 Practice hours
|
|
||||||
</div>
|
|
||||||
<div className="card-profile__header__title ">
|
|
||||||
15 Supervision per year
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-info__wrap-btn">
|
|
||||||
<a href="#" className="btn-edit">Edit</a>
|
|
||||||
<a href="#" className="btn-apply">Add Offer</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
My Offers
|
|
||||||
</h2>
|
|
||||||
<div className="coaching-section__desc">
|
|
||||||
<div className="coaching-offer">
|
|
||||||
<div className="coaching-offer__header">
|
|
||||||
<div className="coaching-offer__title">
|
|
||||||
Senior Software Engineer
|
|
||||||
</div>
|
|
||||||
<div className="coaching-offer__wrap-btn">
|
|
||||||
<a href="#" className="link-edit">Edit</a>
|
|
||||||
<a href="#" className="link-remove">Remove</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-offer__price">
|
|
||||||
45$ <span>/ 45min</span>
|
|
||||||
</div>
|
|
||||||
<div className="skills__list">
|
|
||||||
<div className="skills__list__item">Engineering & Data</div>
|
|
||||||
<div className="skills__list__item">Engineering & Data</div>
|
|
||||||
<div className="skills__list__more">+6</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-offer__desc">
|
|
||||||
I have worked across a variety of organizations, lead teams, and delivered quality software
|
|
||||||
for 8 years. In that time I've worked as an independent consultant, at agencies as a team
|
|
||||||
lead, and as a senior engineer at Auth0. I also host a podcast
|
|
||||||
https://anchor.fm/work-in-programming where I break down how …
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
About Coach
|
|
||||||
</h2>
|
|
||||||
<div className="base-text">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
Education
|
|
||||||
</h2>
|
|
||||||
<div className="coaching-section__desc">
|
|
||||||
<h3 className="title-h3">Psychologist </h3>
|
|
||||||
<div className="base-text">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
|
||||||
</div>
|
|
||||||
<div className="sertific">
|
|
||||||
<img src="/images/sertific.png" className="" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
Professional Certification
|
|
||||||
</h2>
|
|
||||||
<div className="coaching-section__desc">
|
|
||||||
<div className="base-text">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
Trainings | Seminars | Courses
|
|
||||||
</h2>
|
|
||||||
<div className="coaching-section__desc">
|
|
||||||
<div className="base-text">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="coaching-section">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
MBA Information
|
|
||||||
</h2>
|
|
||||||
<div className="coaching-section__desc">
|
|
||||||
<div className="base-text">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import type { Metadata } from 'next';
|
|
||||||
import { unstable_setRequestLocale } from 'next-intl/server';
|
|
||||||
import { useTranslations } from 'next-intl';
|
|
||||||
import { i18nText } from '../../../../../i18nKeys';
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Bbuddy - Account - Work with us',
|
|
||||||
description: 'Bbuddy desc work with us'
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function WorkWithUs({ params: { locale } }: { params: { locale: string } }) {
|
|
||||||
unstable_setRequestLocale(locale);
|
|
||||||
const t = useTranslations('Account.WorkWithUs');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ol className="breadcrumb">
|
|
||||||
<li className="breadcrumb-item active" aria-current="page">{i18nText('accountMenu.work-with-us', locale)}</li>
|
|
||||||
</ol>
|
|
||||||
<div className="b-info">
|
|
||||||
<div className="image-info">
|
|
||||||
<img className="" src="/images/info.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="b-info__title">{i18nText('insertInfo', locale)}</div>
|
|
||||||
<button className="btn-apply">{i18nText('getStarted', locale)}</button>
|
|
||||||
<div className="base-text">{i18nText('changeUserData', locale)}</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
} from '../../../../components/Experts/ExpertDetails';
|
} from '../../../../components/Experts/ExpertDetails';
|
||||||
import { Details } from '../../../../types/experts';
|
import { Details } from '../../../../types/experts';
|
||||||
import { BackButton } from '../../../../components/view/BackButton';
|
import { BackButton } from '../../../../components/view/BackButton';
|
||||||
|
import { i18nText } from '../../../../i18nKeys';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Bbuddy - Experts item',
|
title: 'Bbuddy - Experts item',
|
||||||
|
@ -31,10 +32,11 @@ export async function generateStaticParams({
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function ExpertItem({ params: { expertId = '', locale} }: { params: { expertId: string, locale: string } }) {
|
export default async function ExpertItem({ params: { expertId = '', locale } }: { params: { expertId: string, locale: string } }) {
|
||||||
if (!expertId) notFound();
|
if (!expertId) notFound();
|
||||||
|
|
||||||
const expert = await getExpertById(expertId, locale);
|
const expert = await getExpertById(expertId, locale);
|
||||||
|
console.log(expert);
|
||||||
|
|
||||||
const getAssociationLevel = (accLevelId?: number) => {
|
const getAssociationLevel = (accLevelId?: number) => {
|
||||||
if (accLevelId) {
|
if (accLevelId) {
|
||||||
|
@ -75,16 +77,16 @@ export default async function ExpertItem({ params: { expertId = '', locale} }: {
|
||||||
<div className="b-inner">
|
<div className="b-inner">
|
||||||
<div className="b-page__back">
|
<div className="b-page__back">
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<BackButton className="btn-back">
|
<BackButton className="btn-back btn-back__auto">
|
||||||
<img src="/images/arrow-back.svg" className="" alt="" />
|
<img src="/images/arrow-back.svg" className="" alt="" />
|
||||||
Back to experts list
|
{i18nText('backToExperts', locale)}
|
||||||
</BackButton>
|
</BackButton>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
<ExpertCard expert={expert} />
|
<ExpertCard expert={expert} locale={locale} />
|
||||||
<ExpertInformation expert={expert} locale={locale} />
|
<ExpertInformation expert={expert} locale={locale} />
|
||||||
|
|
||||||
<h2 className="title-h2">Expert Background</h2>
|
<h2 className="title-h2">{i18nText('expertBackground', locale)}</h2>
|
||||||
<p className="base-text">
|
<p className="base-text">
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
@ -92,7 +94,7 @@ export default async function ExpertItem({ params: { expertId = '', locale} }: {
|
||||||
{expert?.publicCoachDetails?.educations && expert.publicCoachDetails.educations?.map(generateDescription)}
|
{expert?.publicCoachDetails?.educations && expert.publicCoachDetails.educations?.map(generateDescription)}
|
||||||
{expert?.publicCoachDetails?.certificates && expert.publicCoachDetails.certificates.length > 0 && (
|
{expert?.publicCoachDetails?.certificates && expert.publicCoachDetails.certificates.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="title-h3">Professional Certification</h3>
|
<h3 className="title-h3">{i18nText('profCertification', locale)}</h3>
|
||||||
{expert.publicCoachDetails.certificates?.map((cert) => (
|
{expert.publicCoachDetails.certificates?.map((cert) => (
|
||||||
<div key={cert.id}>
|
<div key={cert.id}>
|
||||||
<p className="base-text">
|
<p className="base-text">
|
||||||
|
@ -110,7 +112,7 @@ export default async function ExpertItem({ params: { expertId = '', locale} }: {
|
||||||
{expert?.publicCoachDetails?.trainings && expert.publicCoachDetails.trainings?.map(generateDescription)}
|
{expert?.publicCoachDetails?.trainings && expert.publicCoachDetails.trainings?.map(generateDescription)}
|
||||||
{expert?.publicCoachDetails?.mbas && expert.publicCoachDetails.mbas?.map(generateDescription)}
|
{expert?.publicCoachDetails?.mbas && expert.publicCoachDetails.mbas?.map(generateDescription)}
|
||||||
{expert?.publicCoachDetails?.experiences && expert.publicCoachDetails.experiences?.map(generateDescription)}
|
{expert?.publicCoachDetails?.experiences && expert.publicCoachDetails.experiences?.map(generateDescription)}
|
||||||
<ExpertPractice expert={expert} />
|
<ExpertPractice expert={expert} locale={locale} />
|
||||||
|
|
||||||
{/* <h2 className="title-h2">All Offers by this Expert</h2>
|
{/* <h2 className="title-h2">All Offers by this Expert</h2>
|
||||||
<div className="offers-list">
|
<div className="offers-list">
|
||||||
|
|
|
@ -6,4 +6,4 @@ export default function Loading() {
|
||||||
...loading
|
...loading
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { useSelectedLayoutSegment, usePathname } from 'next/navigation';
|
import { useSelectedLayoutSegment, usePathname } from 'next/navigation';
|
||||||
import { Link } from '../../navigation';
|
import { Link } from '../../navigation';
|
||||||
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common';
|
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common';
|
||||||
import { deleteStorageKey } from '../../hooks/useLocalStorage';
|
import { deleteStorageKey } from '../../hooks/useLocalStorage';
|
||||||
import { i18nText } from '../../i18nKeys';
|
import { i18nText } from '../../i18nKeys';
|
||||||
import { DeleteAccountModal } from '../Modals/DeleteAccountModal';
|
|
||||||
import { getMenuConfig } from '../../utils/account';
|
import { getMenuConfig } from '../../utils/account';
|
||||||
|
|
||||||
export const AccountMenu = ({ locale }: { locale: string }) => {
|
export const AccountMenu = ({ locale }: { locale: string }) => {
|
||||||
const selectedLayoutSegment = useSelectedLayoutSegment();
|
const selectedLayoutSegment = useSelectedLayoutSegment();
|
||||||
const pathname = selectedLayoutSegment || '';
|
const pathname = selectedLayoutSegment || '';
|
||||||
const paths = usePathname();
|
const paths = usePathname();
|
||||||
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
|
|
||||||
const menu: { path: string, title: string, count?: number }[] = getMenuConfig(locale);
|
const menu: { path: string, title: string, count?: number }[] = getMenuConfig(locale);
|
||||||
|
|
||||||
const onLogout = () => {
|
const onLogout = () => {
|
||||||
|
@ -23,8 +20,6 @@ export const AccountMenu = ({ locale }: { locale: string }) => {
|
||||||
window?.location?.replace(`/${paths.split('/')[1]}/`);
|
window?.location?.replace(`/${paths.split('/')[1]}/`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteAccount = () => setShowDeleteModal(true);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="list-sidebar">
|
<ul className="list-sidebar">
|
||||||
{menu.map(({ path, title, count }) => (
|
{menu.map(({ path, title, count }) => (
|
||||||
|
@ -46,19 +41,6 @@ export const AccountMenu = ({ locale }: { locale: string }) => {
|
||||||
{i18nText('logout', locale)}
|
{i18nText('logout', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
<li className="list-sidebar__item">
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
onClick={onDeleteAccount}
|
|
||||||
className="b-button__logout"
|
|
||||||
>
|
|
||||||
{i18nText('deleteAcc', locale)}
|
|
||||||
</Button>
|
|
||||||
<DeleteAccountModal
|
|
||||||
open={showDeleteModal}
|
|
||||||
handleCancel={() => setShowDeleteModal(false)}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,38 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { FC, useEffect, useState } from 'react';
|
import React, { FC, useEffect, useState } from 'react';
|
||||||
import { Form, Upload, Button } from 'antd';
|
import { Button, Form, message, Upload } from 'antd';
|
||||||
import type { UploadFile, UploadProps } from 'antd';
|
import type { GetProp, UploadFile, UploadProps } from 'antd';
|
||||||
import ImgCrop from 'antd-img-crop';
|
import ImgCrop from 'antd-img-crop';
|
||||||
import { CameraOutlined } from '@ant-design/icons';
|
import { CameraOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||||
import { Link } from '../../navigation';
|
import { useRouter } from '../../navigation';
|
||||||
import { CustomInput } from '../view/CustomInput';
|
|
||||||
import { Profile } from '../../types/profile';
|
|
||||||
import { useProfileSettings } from '../../actions/hooks/useProfileSettings';
|
|
||||||
import { i18nText } from '../../i18nKeys';
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
import { ProfileRequest } from '../../types/profile';
|
||||||
|
import { validateImage } from '../../utils/account';
|
||||||
|
import { useProfileSettings } from '../../actions/hooks/useProfileSettings';
|
||||||
|
import { CustomInput } from '../view/CustomInput';
|
||||||
|
import { OutlinedButton } from '../view/OutlinedButton';
|
||||||
|
import { FilledYellowButton } from '../view/FilledButton';
|
||||||
|
import { DeleteAccountModal } from '../Modals/DeleteAccountModal';
|
||||||
|
import { Loader } from '../view/Loader';
|
||||||
|
|
||||||
type ProfileSettingsProps = {
|
type ProfileSettingsProps = {
|
||||||
locale: string;
|
locale: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
||||||
|
|
||||||
export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
||||||
const [form] = Form.useForm<Profile>();
|
const [form] = Form.useForm<ProfileRequest>();
|
||||||
const { profileSettings } = useProfileSettings(locale);
|
const { profileSettings, fetchProfileSettings, save, fetchLoading } = useProfileSettings(locale);
|
||||||
|
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
|
||||||
|
const [saveLoading, setSaveLoading] = useState<boolean>(false);
|
||||||
|
const [photo, setPhoto] = useState<UploadFile | undefined>();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchProfileSettings()
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (profileSettings) {
|
if (profileSettings) {
|
||||||
|
@ -27,28 +40,64 @@ export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
||||||
}
|
}
|
||||||
}, [profileSettings]);
|
}, [profileSettings]);
|
||||||
|
|
||||||
const [fileList, setFileList] = useState<UploadFile[]>();
|
const onSaveProfile = () => {
|
||||||
|
form.validateFields()
|
||||||
const onChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
.then(({ login, surname, username }) => {
|
||||||
setFileList(newFileList);
|
const { phone, role, languagesLinks } = profileSettings;
|
||||||
|
const newProfile: ProfileRequest = {
|
||||||
|
phone,
|
||||||
|
role,
|
||||||
|
login,
|
||||||
|
surname,
|
||||||
|
username,
|
||||||
|
isPasswordKeepExisting: true,
|
||||||
|
isFaceImageKeepExisting: true,
|
||||||
|
languagesLinks: languagesLinks?.map(({ languageId }) => ({ languageId })) || []
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPreview = async (file: UploadFile) => {
|
// if (photo) {
|
||||||
// let src = file.url as string;
|
// console.log(photo);
|
||||||
// if (!src) {
|
// const formData = new FormData();
|
||||||
// src = await new Promise((resolve) => {
|
// formData.append('file', photo as FileType);
|
||||||
// const reader = new FileReader();
|
//
|
||||||
// reader.readAsDataURL(file.originFileObj as FileType);
|
// newProfile.faceImage = photo;
|
||||||
// reader.onload = () => resolve(reader.result as string);
|
// newProfile.isFaceImageKeepExisting = false;
|
||||||
// });
|
|
||||||
// }
|
// }
|
||||||
// const image = new Image();
|
|
||||||
// image.src = src;
|
console.log(newProfile);
|
||||||
// const imgWindow = window.open(src);
|
|
||||||
// imgWindow?.document.write(image.outerHTML);
|
setSaveLoading(true);
|
||||||
};
|
save(newProfile)
|
||||||
|
.then(() => {
|
||||||
|
fetchProfileSettings();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('Не удалось сохранить изменения');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSaveLoading(false);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeCrop = (file: UploadFile) => {
|
||||||
|
return validateImage(file, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeUpload = (file: UploadFile) => {
|
||||||
|
const isValid = validateImage(file);
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
setPhoto(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDeleteAccount = () => setShowDeleteModal(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Loader isLoading={fetchLoading} refresh={fetchProfileSettings}>
|
||||||
<Form form={form} className="form-settings">
|
<Form form={form} className="form-settings">
|
||||||
<div className="user-avatar">
|
<div className="user-avatar">
|
||||||
<div className="user-avatar__edit" style={profileSettings?.faceImageUrl ? { backgroundImage: `url(${profileSettings.faceImageUrl})` } : undefined}>
|
<div className="user-avatar__edit" style={profileSettings?.faceImageUrl ? { backgroundImage: `url(${profileSettings.faceImageUrl})` } : undefined}>
|
||||||
|
@ -57,18 +106,38 @@ export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="user-avatar__text">{i18nText('photoDesc', locale)}</div>
|
<div className="user-avatar__text">{i18nText('photoDesc', locale)}</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <ImgCrop rotationSlider>
|
<ImgCrop
|
||||||
<Upload
|
modalTitle="Редактировать"
|
||||||
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
|
modalOk="Сохранить"
|
||||||
fileList={fileList}
|
modalCancel="Отмена"
|
||||||
onChange={onChange}
|
beforeCrop={beforeCrop}
|
||||||
onPreview={onPreview}
|
|
||||||
>
|
>
|
||||||
|
<Upload
|
||||||
|
fileList={photo ? [photo] : profileSettings?.faceImageUrl ? [
|
||||||
|
{
|
||||||
|
uid: profileSettings.faceImageUrl,
|
||||||
|
name: profileSettings.faceImageUrl,
|
||||||
|
status: 'done',
|
||||||
|
url: profileSettings.faceImageUrl
|
||||||
|
}
|
||||||
|
] : undefined}
|
||||||
|
accept=".jpg,.jpeg,.png,.gif"
|
||||||
|
beforeUpload={beforeUpload}
|
||||||
|
multiple={false}
|
||||||
|
showUploadList={false}
|
||||||
|
>
|
||||||
|
{photo && <img height={100} width={100} src={URL.createObjectURL(photo)} />}
|
||||||
<Button icon={<CameraOutlined />}>Click to Upload</Button>
|
<Button icon={<CameraOutlined />}>Click to Upload</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
</ImgCrop> */}
|
</ImgCrop>
|
||||||
|
<div className="form-fieldset">
|
||||||
<div className="form-field">
|
<div className="form-field">
|
||||||
<Form.Item name="username">
|
<Form.Item name="username" rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Поле не должно быть пустым'
|
||||||
|
}
|
||||||
|
]}>
|
||||||
<CustomInput placeholder={i18nText('name', locale)} />
|
<CustomInput placeholder={i18nText('name', locale)} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,16 +152,39 @@ export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="form-field">
|
<div className="form-field">
|
||||||
<Form.Item name="login">
|
<Form.Item name="login" rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Поле не должно быть пустым'
|
||||||
|
}
|
||||||
|
]}>
|
||||||
<CustomInput type="email" placeholder="E-mail" />
|
<CustomInput type="email" placeholder="E-mail" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-link">
|
|
||||||
<Link href={'change-password' as any}>
|
|
||||||
{i18nText('changePass', locale)}
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
<button className="btn-apply">{i18nText('save', locale)}</button>
|
<div className="form-actions">
|
||||||
|
<FilledYellowButton
|
||||||
|
onClick={onSaveProfile}
|
||||||
|
loading={saveLoading}
|
||||||
|
>
|
||||||
|
{i18nText('save', locale)}
|
||||||
|
</FilledYellowButton>
|
||||||
|
<OutlinedButton onClick={() => router.push('change-password')}>
|
||||||
|
{i18nText('changePass', locale)}
|
||||||
|
</OutlinedButton>
|
||||||
|
<OutlinedButton
|
||||||
|
onClick={onDeleteAccount}
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
danger
|
||||||
|
>
|
||||||
|
{i18nText('deleteAcc', locale)}
|
||||||
|
</OutlinedButton>
|
||||||
|
</div>
|
||||||
|
<DeleteAccountModal
|
||||||
|
open={showDeleteModal}
|
||||||
|
handleCancel={() => setShowDeleteModal(false)}
|
||||||
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
|
</Loader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, {useState} from 'react';
|
import React, { useState } from 'react';
|
||||||
import {Button, Empty, notification, Tag} from 'antd';
|
import { Button, Empty, notification, Tag } from 'antd';
|
||||||
import {LeftOutlined, PlusOutlined, RightOutlined} from '@ant-design/icons';
|
import { LeftOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import {Link, useRouter} from '../../../navigation';
|
import { Link, useRouter } from '../../../navigation';
|
||||||
import {i18nText} from '../../../i18nKeys';
|
import { i18nText } from '../../../i18nKeys';
|
||||||
import {getDuration, getPrice} from '../../../utils/expert';
|
import { getDuration, getPrice } from '../../../utils/expert';
|
||||||
import {PublicUser, Session, SessionState, SessionType} from '../../../types/sessions';
|
import { PublicUser, Session, SessionState, SessionType } from '../../../types/sessions';
|
||||||
import {AUTH_TOKEN_KEY} from '../../../constants/common';
|
import { AUTH_TOKEN_KEY } from '../../../constants/common';
|
||||||
import {approveRequestedSession, finishSession} from '../../../actions/sessions';
|
import { approveRequestedSession, finishSession } from '../../../actions/sessions';
|
||||||
import {useLocalStorage} from '../../../hooks/useLocalStorage';
|
import { useLocalStorage } from '../../../hooks/useLocalStorage';
|
||||||
import {DeclineSessionModal} from '../../Modals/DeclineSessionModal';
|
import { DeclineSessionModal } from '../../Modals/DeclineSessionModal';
|
||||||
import {AddCommentModal} from '../../Modals/AddCommentModal';
|
import { AddCommentModal } from '../../Modals/AddCommentModal';
|
||||||
|
|
||||||
type SessionDetailsContentProps = {
|
type SessionDetailsContentProps = {
|
||||||
locale: string;
|
locale: string;
|
||||||
|
@ -43,7 +43,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: 'Error approve session',
|
message: i18nText('errors.approvingSession', locale),
|
||||||
description: err?.response?.data?.errMessage
|
description: err?.response?.data?.errMessage
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -64,7 +64,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: 'Error finish session',
|
message: i18nText('errors.finishingSession', locale),
|
||||||
description: err?.response?.data?.errMessage
|
description: err?.response?.data?.errMessage
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -166,7 +166,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
icon={<LeftOutlined />}
|
icon={<LeftOutlined />}
|
||||||
onClick={goBack}
|
onClick={goBack}
|
||||||
>
|
>
|
||||||
Back
|
{i18nText('back', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{Current}
|
{Current}
|
||||||
|
@ -181,8 +181,8 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
disabled={finishLoading}
|
disabled={finishLoading}
|
||||||
>
|
>
|
||||||
{activeType === SessionType.UPCOMING
|
{activeType === SessionType.UPCOMING
|
||||||
? (session?.state === SessionState.STARTED ? 'Join Session' : 'Start Session')
|
? (session?.state === SessionState.STARTED ? i18nText('session.join', locale) : i18nText('session.start', locale))
|
||||||
: 'Confirm Session'}
|
: i18nText('session.confirm', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
{session?.state === SessionState.STARTED && isCoach && (
|
{session?.state === SessionState.STARTED && isCoach && (
|
||||||
<Button
|
<Button
|
||||||
|
@ -190,7 +190,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
onClick={onFinishSession}
|
onClick={onFinishSession}
|
||||||
loading={finishLoading}
|
loading={finishLoading}
|
||||||
>
|
>
|
||||||
Finish Session
|
{i18nText('session.finish', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{session?.id && session?.state !== SessionState.STARTED && (
|
{session?.id && session?.state !== SessionState.STARTED && (
|
||||||
|
@ -200,7 +200,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
onClick={() => setOpenDeclineModal(true)}
|
onClick={() => setOpenDeclineModal(true)}
|
||||||
disabled={approveLoading}
|
disabled={approveLoading}
|
||||||
>
|
>
|
||||||
Decline Session
|
{i18nText('session.decline', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
<DeclineSessionModal
|
<DeclineSessionModal
|
||||||
open={openDeclineModal}
|
open={openDeclineModal}
|
||||||
|
@ -218,7 +218,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
<>
|
<>
|
||||||
{activeType === SessionType.RECENT && (
|
{activeType === SessionType.RECENT && (
|
||||||
<>
|
<>
|
||||||
<div className="card-detail__name">Course Info</div>
|
<div className="card-detail__name">{i18nText('courseInfo', locale)}</div>
|
||||||
<div className="card-detail__inner">
|
<div className="card-detail__inner">
|
||||||
{/* <div className="card-detail__info">
|
{/* <div className="card-detail__info">
|
||||||
<div className="card-profile__subtitle">{current?.specialityDesc}</div>
|
<div className="card-profile__subtitle">{current?.specialityDesc}</div>
|
||||||
|
@ -249,7 +249,9 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
<div className="card-detail__comments">
|
<div className="card-detail__comments">
|
||||||
<div className="card-detail__comments_header">
|
<div className="card-detail__comments_header">
|
||||||
<div className="card-detail__comments_title">
|
<div className="card-detail__comments_title">
|
||||||
{session?.clientComments?.length === 0 && session?.coachComments?.length === 0 ? 'Comments' : 'My Comments'}
|
{session?.clientComments?.length === 0 && session?.coachComments?.length === 0
|
||||||
|
? i18nText('session.comments', locale)
|
||||||
|
: i18nText('session.myComments', locale)}
|
||||||
</div>
|
</div>
|
||||||
{activeType === SessionType.UPCOMING && (
|
{activeType === SessionType.UPCOMING && (
|
||||||
<>
|
<>
|
||||||
|
@ -260,7 +262,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
icon={<PlusOutlined style={{ fontSize: 18 }} />}
|
icon={<PlusOutlined style={{ fontSize: 18 }} />}
|
||||||
onClick={() => setOpenAddCommentModal(true)}
|
onClick={() => setOpenAddCommentModal(true)}
|
||||||
>
|
>
|
||||||
Add new
|
{i18nText('session.addComment', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
<AddCommentModal
|
<AddCommentModal
|
||||||
open={openAddCommentModal}
|
open={openAddCommentModal}
|
||||||
|
@ -281,7 +283,7 @@ export const SessionDetailsContent = ({ session, locale, activeType, startSessio
|
||||||
))}
|
))}
|
||||||
{(isCoach ? session?.clientComments : session?.coachComments)?.length > 0 && (
|
{(isCoach ? session?.clientComments : session?.coachComments)?.length > 0 && (
|
||||||
<div className="card-detail__comments_title">
|
<div className="card-detail__comments_title">
|
||||||
{isCoach ? 'Client Comments' : 'Coach Comments'}
|
{isCoach ? i18nText('session.clientComments', locale) : i18nText('session.coachComments', locale)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(isCoach ? session?.clientComments : session?.coachComments)?.map(({ id , comment }) => (
|
{(isCoach ? session?.clientComments : session?.coachComments)?.map(({ id , comment }) => (
|
||||||
|
|
|
@ -42,9 +42,9 @@ export const SessionsTabs = ({ locale, activeTab }: SessionsTabsProps) => {
|
||||||
])
|
])
|
||||||
.then(([upcoming, requested, recent]) => {
|
.then(([upcoming, requested, recent]) => {
|
||||||
setSessions({
|
setSessions({
|
||||||
[SessionType.UPCOMING]: upcoming.data || [],
|
[SessionType.UPCOMING]: upcoming || [],
|
||||||
[SessionType.REQUESTED]: requested.data?.requestedSessions || [],
|
[SessionType.REQUESTED]: requested?.requestedSessions || [],
|
||||||
[SessionType.RECENT]: recent.data || []
|
[SessionType.RECENT]: recent || []
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
@ -115,7 +115,7 @@ export const SessionsTabs = ({ locale, activeTab }: SessionsTabsProps) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}) : (
|
}) : (
|
||||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={i18nText('noData', locale)} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
|
||||||
|
export const EmptyExpertProfile = ({ locale }: { locale: string }) => (
|
||||||
|
<>
|
||||||
|
<ol className="breadcrumb">
|
||||||
|
<li className="breadcrumb-item active" aria-current="page">{i18nText('accountMenu.expert-profile', locale)}</li>
|
||||||
|
</ol>
|
||||||
|
<div className="b-work">
|
||||||
|
<div className="image-info">
|
||||||
|
<img className="" src="/images/info.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<div className="b-work__description">
|
||||||
|
<div className="b-work__text">{i18nText('insertInfo', locale)}</div>
|
||||||
|
<div className="b-work__text">{i18nText('changeUserData', locale)}</div>
|
||||||
|
<button className="btn-apply">{i18nText('getStarted', locale)}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
|
@ -0,0 +1,98 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { message } from 'antd';
|
||||||
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
import { ExpertData } from '../../types/profile';
|
||||||
|
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||||
|
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
||||||
|
import { getTags } from '../../actions/profile';
|
||||||
|
import { Loader } from '../view/Loader';
|
||||||
|
import { LinkButton } from '../view/LinkButton';
|
||||||
|
import { ExpertTags } from './content/ExpertTags';
|
||||||
|
import { ExpertSchedule } from './content/ExpertSchedule';
|
||||||
|
import { ExpertPayData } from './content/ExpertPayData';
|
||||||
|
import { ExpertEducation } from './content/ExpertEducation';
|
||||||
|
|
||||||
|
type ExpertProfileProps = {
|
||||||
|
locale: string;
|
||||||
|
data: ExpertData;
|
||||||
|
updateData: (data: ExpertData) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExpertProfile = ({ locale, data, updateData }: ExpertProfileProps) => {
|
||||||
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
||||||
|
const [loading, setLoading] = useState<(keyof ExpertData)[]>([]);
|
||||||
|
|
||||||
|
const updateExpert = (key: keyof ExpertData) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'tags':
|
||||||
|
setLoading([key]);
|
||||||
|
getTags(locale, jwt)
|
||||||
|
.then((tags) => {
|
||||||
|
updateData({
|
||||||
|
...data,
|
||||||
|
tags
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => message.error('Не удалось обновить направления'))
|
||||||
|
.finally(() => setLoading([]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ol className="breadcrumb">
|
||||||
|
<li className="breadcrumb-item active" aria-current="page">{i18nText('coaching', locale)}</li>
|
||||||
|
</ol>
|
||||||
|
<div className="coaching-info">
|
||||||
|
<div className="coaching-profile">
|
||||||
|
<div className="coaching-profile__portrait">
|
||||||
|
<img src="/images/person.png" className="" alt="" />
|
||||||
|
</div>
|
||||||
|
<div className="coaching-profile__inner">
|
||||||
|
<div className="coaching-profile__name">
|
||||||
|
David
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-section__wrap">
|
||||||
|
<div className="coaching-section">
|
||||||
|
<div className="coaching-section__title">
|
||||||
|
<h2 className="title-h2">{i18nText('aboutCoach', locale)}</h2>
|
||||||
|
<h2 className="title-h2">person1 + person4</h2>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card-profile__header__title">
|
||||||
|
{`12 ${i18nText('practiceHours', locale)}`}
|
||||||
|
</div>
|
||||||
|
<div className="card-profile__header__title ">
|
||||||
|
{`15 ${i18nText('supervisionCount', locale)}`}
|
||||||
|
</div>
|
||||||
|
<div className="base-text">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Loader isLoading={loading.includes('tags')}>
|
||||||
|
<ExpertTags
|
||||||
|
locale={locale}
|
||||||
|
data={data?.tags}
|
||||||
|
updateExpert={updateExpert}
|
||||||
|
/>
|
||||||
|
</Loader>
|
||||||
|
<ExpertSchedule locale={locale} data={data?.schedule} />
|
||||||
|
<ExpertEducation locale={locale} data={data?.education} />
|
||||||
|
<ExpertPayData locale={locale} data={data?.payData?.person6Data} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
export const MyOffers = () => (
|
||||||
|
<div className="coaching-section">
|
||||||
|
<h2 className="title-h2">
|
||||||
|
My Offers
|
||||||
|
</h2>
|
||||||
|
<div className="coaching-section__desc">
|
||||||
|
<div className="coaching-offer">
|
||||||
|
<div className="coaching-offer__header">
|
||||||
|
<div className="coaching-offer__title">
|
||||||
|
Senior Software Engineer
|
||||||
|
</div>
|
||||||
|
<div className="coaching-offer__wrap-btn">
|
||||||
|
<a href="#" className="link-edit">Edit</a>
|
||||||
|
<a href="#" className="link-remove">Remove</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-offer__price">
|
||||||
|
45$ <span>/ 45min</span>
|
||||||
|
</div>
|
||||||
|
<div className="skills__list">
|
||||||
|
<div className="skills__list__item">Engineering & Data</div>
|
||||||
|
<div className="skills__list__item">Engineering & Data</div>
|
||||||
|
<div className="skills__list__more">+6</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-offer__desc">
|
||||||
|
I have worked across a variety of organizations, lead teams, and delivered quality software
|
||||||
|
for 8 years. In that time I've worked as an independent consultant, at agencies as a team
|
||||||
|
lead, and as a senior engineer at Auth0. I also host a podcast
|
||||||
|
https://anchor.fm/work-in-programming where I break down how …
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
|
import { EducationDTO } from '../../../types/education';
|
||||||
|
import { i18nText } from '../../../i18nKeys';
|
||||||
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
|
|
||||||
|
type ExpertEducationProps = {
|
||||||
|
locale: string;
|
||||||
|
data?: EducationDTO;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExpertEducation = ({ locale, data }: ExpertEducationProps) => {
|
||||||
|
return (
|
||||||
|
<div className="coaching-section__wrap">
|
||||||
|
<div className="coaching-section">
|
||||||
|
<div className="coaching-section__title">
|
||||||
|
<h2 className="title-h2">{i18nText('education', locale)}</h2>
|
||||||
|
<h2 className="title-h2">person2</h2>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-section__desc">
|
||||||
|
<h3 className="title-h3">Psychologist</h3>
|
||||||
|
<div className="base-text">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
</div>
|
||||||
|
<div className="sertific">
|
||||||
|
<img src="/images/sertific.png" className="" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-section">
|
||||||
|
<h2 className="title-h2">{i18nText('profCertification', locale)}</h2>
|
||||||
|
<div className="coaching-section__desc">
|
||||||
|
<div className="base-text">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-section">
|
||||||
|
<h2 className="title-h2">
|
||||||
|
{`${i18nText('trainings', locale)} | ${i18nText('seminars', locale)} | ${i18nText('courses', locale)}`}
|
||||||
|
</h2>
|
||||||
|
<div className="coaching-section__desc">
|
||||||
|
<div className="base-text">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="coaching-section">
|
||||||
|
<h2 className="title-h2">{i18nText('mba', locale)}</h2>
|
||||||
|
<div className="coaching-section__desc">
|
||||||
|
<div className="base-text">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||||
|
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
|
import { i18nText } from '../../../i18nKeys';
|
||||||
|
import { PayInfo } from '../../../types/profile';
|
||||||
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
|
|
||||||
|
type ExpertPayDataProps = {
|
||||||
|
locale: string;
|
||||||
|
data?: PayInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExpertPayData = ({ locale, data }: ExpertPayDataProps) => {
|
||||||
|
return (
|
||||||
|
<div className="coaching-section__wrap">
|
||||||
|
<div className="coaching-section">
|
||||||
|
<div className="coaching-section__title">
|
||||||
|
<h2 className="title-h2">Card data - person6</h2>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="base-text">
|
||||||
|
Card
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
|
import { ScheduleDTO } from '../../../types/schedule';
|
||||||
|
import { i18nText } from '../../../i18nKeys';
|
||||||
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
|
|
||||||
|
type ExpertScheduleProps = {
|
||||||
|
locale: string;
|
||||||
|
data?: ScheduleDTO;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExpertSchedule = ({ locale, data }: ExpertScheduleProps) => {
|
||||||
|
return (
|
||||||
|
<div className="coaching-section__wrap">
|
||||||
|
<div className="coaching-section">
|
||||||
|
<div className="coaching-section__title">
|
||||||
|
<h2 className="title-h2">Schedule - person51</h2>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="base-text">
|
||||||
|
Schedule
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Tag } from 'antd';
|
||||||
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
|
import { i18nText } from '../../../i18nKeys';
|
||||||
|
import { ExpertsTags } from '../../../types/tags';
|
||||||
|
import { ExpertData } from '../../../types/profile';
|
||||||
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
|
import { EditExpertTagsModal } from '../../Modals/EditExpertTagsModal';
|
||||||
|
|
||||||
|
type ExpertTagsProps = {
|
||||||
|
locale: string;
|
||||||
|
data?: ExpertsTags;
|
||||||
|
updateExpert: (key: keyof ExpertData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ExpertTags = ({ locale, data, updateExpert }: ExpertTagsProps) => {
|
||||||
|
const [showEdit, setShowEdit] = useState<boolean>(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="coaching-section__wrap">
|
||||||
|
<div className="coaching-section">
|
||||||
|
<div className="coaching-section__title">
|
||||||
|
<h2 className="title-h2">{i18nText('direction', locale)}</h2>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => setShowEdit(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="skills__list">
|
||||||
|
{data?.themesTags && data.themesTags?.length > 0 && data.themesTags
|
||||||
|
.filter(({ isActive, isSelected }) => isActive && isSelected)
|
||||||
|
.map(({ id, name }) => <Tag key={id} className="skills__list__item">{name}</Tag>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditExpertTagsModal
|
||||||
|
locale={locale}
|
||||||
|
open={showEdit}
|
||||||
|
data={data}
|
||||||
|
handleCancel={() => setShowEdit(false)}
|
||||||
|
refresh={() => updateExpert('tags')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
export * from './EmptyExpertProfile';
|
||||||
|
export * from './ExpertProfile';
|
||||||
|
export * from './MyOffers';
|
|
@ -7,13 +7,15 @@ import { ZoomInOutlined, ZoomOutOutlined, StarFilled } from '@ant-design/icons';
|
||||||
import { ExpertDetails, ExpertDocument } from '../../types/experts';
|
import { ExpertDetails, ExpertDocument } from '../../types/experts';
|
||||||
import { Locale } from '../../types/locale';
|
import { Locale } from '../../types/locale';
|
||||||
import { CustomRate } from '../view/CustomRate';
|
import { CustomRate } from '../view/CustomRate';
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
import { FilledYellowButton } from '../view/FilledButton';
|
||||||
|
|
||||||
type ExpertDetailsProps = {
|
type ExpertDetailsProps = {
|
||||||
expert: ExpertDetails;
|
expert: ExpertDetails;
|
||||||
locale?: string;
|
locale?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExpertCard: FC<ExpertDetailsProps> = ({ expert }) => {
|
export const ExpertCard: FC<ExpertDetailsProps> = ({ expert, locale }) => {
|
||||||
const { publicCoachDetails } = expert || {};
|
const { publicCoachDetails } = expert || {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -25,39 +27,43 @@ export const ExpertCard: FC<ExpertDetailsProps> = ({ expert }) => {
|
||||||
<div className="expert-card__inner">
|
<div className="expert-card__inner">
|
||||||
<h1 className="expert-card__title">{`${publicCoachDetails?.name} ${publicCoachDetails?.surname || ''}`}</h1>
|
<h1 className="expert-card__title">{`${publicCoachDetails?.name} ${publicCoachDetails?.surname || ''}`}</h1>
|
||||||
<div className="expert-card__info">
|
<div className="expert-card__info">
|
||||||
<span>{`${publicCoachDetails?.practiceHours} Practice hours`}</span>
|
<span>{`${publicCoachDetails?.practiceHours} ${i18nText('practiceHours', locale)}`}</span>
|
||||||
<i>|</i>
|
<i>|</i>
|
||||||
<span>{`${publicCoachDetails?.supervisionPerYearId} Supervision per year`}</span>
|
<span>{`${publicCoachDetails?.supervisionPerYearId} ${i18nText('supervisionCount', locale)}`}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="expert-card__rating">
|
<div className="expert-card__rating">
|
||||||
<CustomRate defaultValue={4} character={<StarFilled style={{ fontSize: 32 }} />} disabled />
|
<CustomRate defaultValue={4} character={<StarFilled style={{ fontSize: 32 }} />} disabled />
|
||||||
<span>4/5 (out of 345)</span>
|
<span>{`4/5 (${i18nText('outOf', locale)} 345)`}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="expert-card__wrap-btn">
|
<div className="expert-card__wrap-btn">
|
||||||
<a href="#" className="btn-apply">
|
<a href="#" className="btn-apply">
|
||||||
<img src="/images/calendar-outline.svg" className="" alt="" />
|
<img src="/images/calendar-outline.svg" className="" alt="" />
|
||||||
Schedule
|
{i18nText('schedule', locale)}
|
||||||
</a>
|
</a>
|
||||||
|
{/*
|
||||||
<a href="#" className="btn-video">
|
<a href="#" className="btn-video">
|
||||||
<img src="/images/videocam-outline.svg" className="" alt="" />
|
<img src="/images/videocam-outline.svg" className="" alt=""/>
|
||||||
Video
|
Video
|
||||||
</a>
|
</a>
|
||||||
|
*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExpertInformation: FC<ExpertDetailsProps> = ({ expert, locale }) => {
|
export const ExpertInformation: FC<ExpertDetailsProps> = ({ expert, locale }) => {
|
||||||
const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0 } } = expert || {};
|
const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0, coachLanguages = [] } } = expert || {};
|
||||||
const isRus = locale === Locale.ru;
|
const isRus = locale === Locale.ru;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2 className="title-h2">Current Offer</h2>
|
<div className="expert-info">
|
||||||
|
{/* <h2 className="title-h2">{}</h2> */}
|
||||||
<div className="skills__list">
|
<div className="skills__list">
|
||||||
{tags?.map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
{coachLanguages?.map((skill) => <Tag key={skill} className="skills__list__item">{skill}</Tag>)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="base-text">
|
<p className="base-text">
|
||||||
Hello, my name is Marcelo. I am a Senior UX Designer with more than 6 years of experience working
|
Hello, my name is Marcelo. I am a Senior UX Designer with more than 6 years of experience working
|
||||||
|
@ -74,10 +80,11 @@ export const ExpertInformation: FC<ExpertDetailsProps> = ({ expert, locale }) =>
|
||||||
|
|
||||||
Oh, and I also speak Spanish!
|
Oh, and I also speak Spanish!
|
||||||
</p>
|
</p>
|
||||||
|
<div className="skills__list">
|
||||||
|
{tags?.map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
||||||
|
</div>
|
||||||
<div className="wrap-btn-prise">
|
<div className="wrap-btn-prise">
|
||||||
<a href="#" className="btn-apply">
|
<FilledYellowButton onClick={() => console.log('schedule')}>{i18nText('signUp', locale)}</FilledYellowButton>
|
||||||
Sign Up Now
|
|
||||||
</a>
|
|
||||||
<div className="wrap-btn-prise__text">
|
<div className="wrap-btn-prise__text">
|
||||||
{`${sessionCost}€`} <span>/ {`${sessionDuration}${isRus ? 'мин' : 'min'}`}</span>
|
{`${sessionCost}€`} <span>/ {`${sessionDuration}${isRus ? 'мин' : 'min'}`}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,12 +93,12 @@ export const ExpertInformation: FC<ExpertDetailsProps> = ({ expert, locale }) =>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExpertPractice: FC<ExpertDetailsProps> = ({ expert }) => {
|
export const ExpertPractice: FC<ExpertDetailsProps> = ({ expert, locale }) => {
|
||||||
const { publicCoachDetails: { practiceCases = [], themesGroups = [] } } = expert || {};
|
const { publicCoachDetails: { practiceCases = [], themesGroups = [] } } = expert || {};
|
||||||
|
|
||||||
return practiceCases?.length > 0 ? (
|
return practiceCases?.length > 0 ? (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="title-h3">Successful Cases From Practice</h3>
|
<h3 className="title-h3">{i18nText('successfulCase', locale)}</h3>
|
||||||
{practiceCases?.map(({ id, description, themesGroupIds }) => {
|
{practiceCases?.map(({ id, description, themesGroupIds }) => {
|
||||||
const filtered = themesGroups?.filter(({ id }) => themesGroupIds?.includes(+id));
|
const filtered = themesGroups?.filter(({ id }) => themesGroupIds?.includes(+id));
|
||||||
|
|
||||||
|
@ -100,7 +107,7 @@ export const ExpertPractice: FC<ExpertDetailsProps> = ({ expert }) => {
|
||||||
{themesGroupIds && (
|
{themesGroupIds && (
|
||||||
<div className="skills__list">
|
<div className="skills__list">
|
||||||
{filtered?.map(({ id, name }) => (
|
{filtered?.map(({ id, name }) => (
|
||||||
<div key={id} className="skills__list__item">{name}</div>
|
<Tag key={id} className="skills__list__item">{name}</Tag>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -84,6 +84,7 @@ export const ExpertsList = ({
|
||||||
size="large"
|
size="large"
|
||||||
className="search-result"
|
className="search-result"
|
||||||
dataSource={experts.coaches}
|
dataSource={experts.coaches}
|
||||||
|
locale={{ emptyText: i18nText('notFound', locale) }}
|
||||||
renderItem={(item) => (
|
renderItem={(item) => (
|
||||||
<List.Item key={item?.id} className="card-profile">
|
<List.Item key={item?.id} className="card-profile">
|
||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
|
|
|
@ -179,7 +179,7 @@ export const ExpertsFilter = ({
|
||||||
|
|
||||||
return searchData?.themesGroups?.length ? searchData.themesGroups.map(({ id, name, tags }) => (
|
return searchData?.themesGroups?.length ? searchData.themesGroups.map(({ id, name, tags }) => (
|
||||||
<div key={id}>
|
<div key={id}>
|
||||||
<h3 className="title-h5">{name}</h3>
|
<h3 className="title-h4">{name}</h3>
|
||||||
{getList('themesTagIds', tags)}
|
{getList('themesTagIds', tags)}
|
||||||
</div>
|
</div>
|
||||||
)) : null;
|
)) : null;
|
||||||
|
@ -214,7 +214,7 @@ export const ExpertsFilter = ({
|
||||||
key: 'themesTagIds',
|
key: 'themesTagIds',
|
||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
<div className="b-filter__collapsed__title">Direction</div>
|
<div className="b-filter__collapsed__title">{i18nText('direction', locale)}</div>
|
||||||
{!openedTabs.includes('themesTagIds') && filter?.themesTagIds?.length > 0 && (
|
{!openedTabs.includes('themesTagIds') && filter?.themesTagIds?.length > 0 && (
|
||||||
<div className="b-filter__collapsed__desc">{getSelectedTags()}</div>
|
<div className="b-filter__collapsed__desc">{getSelectedTags()}</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -83,7 +83,7 @@ export const AddCommentModal: FC<AddCommentModalProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your comment'
|
message: i18nText('errors.emptyComment', locale)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -91,7 +91,7 @@ export const AddCommentModal: FC<AddCommentModalProps> = ({
|
||||||
className="b-textarea"
|
className="b-textarea"
|
||||||
rows={4}
|
rows={4}
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
placeholder="Your comment"
|
placeholder={i18nText('session.commentPlaceholder', locale)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -101,7 +101,7 @@ export const AddCommentModal: FC<AddCommentModalProps> = ({
|
||||||
onClick={onAddComment}
|
onClick={onAddComment}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
>
|
>
|
||||||
Send
|
{i18nText('send', locale)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Link from 'next/link';
|
||||||
import { Modal, Form } from 'antd';
|
import { Modal, Form } from 'antd';
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent';
|
import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent';
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
|
||||||
type AuthModalProps = {
|
type AuthModalProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -13,6 +14,7 @@ type AuthModalProps = {
|
||||||
mode: 'enter' | 'register' | 'reset' | 'finish';
|
mode: 'enter' | 'register' | 'reset' | 'finish';
|
||||||
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
|
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
|
||||||
updateToken: string | Dispatch<SetStateAction<string | undefined>> | undefined;
|
updateToken: string | Dispatch<SetStateAction<string | undefined>> | undefined;
|
||||||
|
locale: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AuthModal: FC<AuthModalProps> = ({
|
export const AuthModal: FC<AuthModalProps> = ({
|
||||||
|
@ -20,7 +22,8 @@ export const AuthModal: FC<AuthModalProps> = ({
|
||||||
handleCancel,
|
handleCancel,
|
||||||
mode,
|
mode,
|
||||||
updateMode,
|
updateMode,
|
||||||
updateToken
|
updateToken,
|
||||||
|
locale
|
||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm<{ login: string, password: string, confirmPassword: string }>();
|
const [form] = Form.useForm<{ login: string, password: string, confirmPassword: string }>();
|
||||||
const paths = usePathname().split('/');
|
const paths = usePathname().split('/');
|
||||||
|
@ -50,7 +53,7 @@ export const AuthModal: FC<AuthModalProps> = ({
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
afterClose={onAfterClose}
|
afterClose={onAfterClose}
|
||||||
footer={false}
|
footer={false}
|
||||||
width={498}
|
width={598}
|
||||||
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#000' }}/>}
|
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#000' }}/>}
|
||||||
>
|
>
|
||||||
<div className="b-modal__auth__content">
|
<div className="b-modal__auth__content">
|
||||||
|
@ -82,8 +85,8 @@ export const AuthModal: FC<AuthModalProps> = ({
|
||||||
<FinishContent locale={paths[1]} />
|
<FinishContent locale={paths[1]} />
|
||||||
)}
|
)}
|
||||||
<div className="b-modal__auth__agreement">
|
<div className="b-modal__auth__agreement">
|
||||||
I have read and agree with the terms of the
|
{`${i18nText('agreementText', locale)} `}
|
||||||
User Agreement, <Link href={'/docs/BBUDDY_privacy_policy_fin.docx' as any}>Privacy Policy</Link>
|
<Link href={'/docs/BBUDDY_privacy_policy_fin.docx' as any}>{i18nText('privacyPolicy', locale)}</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SessionType } from '../../types/sessions';
|
||||||
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||||
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
||||||
import { cancelUpcomingSession, declineRequestedSession } from '../../actions/sessions';
|
import { cancelUpcomingSession, declineRequestedSession } from '../../actions/sessions';
|
||||||
// import { i18nText } from '../../i18nKeys';
|
import { i18nText } from '../../i18nKeys';
|
||||||
import { FilledButton } from '../view/FilledButton';
|
import { FilledButton } from '../view/FilledButton';
|
||||||
|
|
||||||
type DeclineModalProps = {
|
type DeclineModalProps = {
|
||||||
|
@ -79,7 +79,7 @@ export const DeclineSessionModal: FC<DeclineModalProps> = ({
|
||||||
<img className="" src="/images/decline-sign.svg" alt=""/>
|
<img className="" src="/images/decline-sign.svg" alt=""/>
|
||||||
</div>
|
</div>
|
||||||
<div className="b-modal__decline__title">
|
<div className="b-modal__decline__title">
|
||||||
Enter a reason for cancelling the session
|
{i18nText('session.cancelReason', locale)}
|
||||||
</div>
|
</div>
|
||||||
<Form form={form} style={{ width: '100%' }}>
|
<Form form={form} style={{ width: '100%' }}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
@ -88,14 +88,14 @@ export const DeclineSessionModal: FC<DeclineModalProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input the reason'
|
message: i18nText('errors.emptyCancelReason', locale)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
className="b-textarea"
|
className="b-textarea"
|
||||||
rows={1}
|
rows={1}
|
||||||
placeholder="Describe the reason for the rejection"
|
placeholder={i18nText('session.reasonPlaceholder', locale)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -106,7 +106,7 @@ export const DeclineSessionModal: FC<DeclineModalProps> = ({
|
||||||
onClick={onDecline}
|
onClick={onDecline}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
>
|
>
|
||||||
Decline
|
{i18nText('decline', locale)}
|
||||||
</FilledButton>
|
</FilledButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, {FC, useCallback, useEffect, useState} from 'react';
|
||||||
|
import { Modal, Button, List, message } from 'antd';
|
||||||
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
||||||
|
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||||
|
import { ExpertsTags, Tag } from '../../types/tags';
|
||||||
|
import { CustomSwitch } from '../view/CustomSwitch';
|
||||||
|
import { setTags } from '../../actions/profile';
|
||||||
|
|
||||||
|
type EditExpertTagsModalProps = {
|
||||||
|
open: boolean;
|
||||||
|
handleCancel: () => void;
|
||||||
|
locale: string;
|
||||||
|
data?: ExpertsTags;
|
||||||
|
refresh: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EditExpertTagsModal: FC<EditExpertTagsModalProps> = ({
|
||||||
|
open,
|
||||||
|
handleCancel,
|
||||||
|
locale,
|
||||||
|
data,
|
||||||
|
refresh
|
||||||
|
}) => {
|
||||||
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [expertTags, setExpertTags] = useState<Tag[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setExpertTags(data?.themesTags || []);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const onSaveTags = () => {
|
||||||
|
setLoading(true);
|
||||||
|
setTags(locale, jwt, { themesGroups: data?.themesGroups, themesTags: expertTags })
|
||||||
|
.then(() => {
|
||||||
|
handleCancel();
|
||||||
|
refresh();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('Не удалось сохранить направления');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateTag = useCallback((id: number, isSelected: boolean) => {
|
||||||
|
setExpertTags(expertTags.map((tag) => {
|
||||||
|
if (tag.id === id) {
|
||||||
|
tag.isSelected = isSelected;
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}))
|
||||||
|
}, [expertTags, setExpertTags]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
className="b-modal"
|
||||||
|
open={open}
|
||||||
|
title={undefined}
|
||||||
|
onOk={undefined}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
footer={false}
|
||||||
|
width={498}
|
||||||
|
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#000' }}/>}
|
||||||
|
>
|
||||||
|
<div className="b-modal__expert__content">
|
||||||
|
<div className="b-modal__expert__title">{i18nText('direction', locale)}</div>
|
||||||
|
<div className="b-modal__expert__inner">
|
||||||
|
{data?.themesGroups && data.themesGroups.filter(({ isActive }) => isActive).map(({ id, name }) => (
|
||||||
|
<div key={`group_${id}`}>
|
||||||
|
<h3 className="title-h4">{name}</h3>
|
||||||
|
{expertTags?.length > 0 ? (
|
||||||
|
<div className="b-filter__inner">
|
||||||
|
<List
|
||||||
|
itemLayout="vertical"
|
||||||
|
size="small"
|
||||||
|
dataSource={expertTags.filter(({ isActive, groupId }) => (isActive && groupId == id)) || []}
|
||||||
|
split={false}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
renderItem={({ id, name, isSelected }) => (
|
||||||
|
<List.Item key={`tag_${id}`} style={{ padding: 0 }}>
|
||||||
|
<div className="b-filter__item">
|
||||||
|
<div className="b-filter__title">{name}</div>
|
||||||
|
<CustomSwitch
|
||||||
|
defaultChecked={isSelected || false}
|
||||||
|
onChange={(checked: boolean) => updateTag(id, checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : <div>No tags</div>}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="b-modal__expert__button">
|
||||||
|
<Button
|
||||||
|
className="card-detail__apply"
|
||||||
|
onClick={onSaveTags}
|
||||||
|
loading={loading}
|
||||||
|
>
|
||||||
|
{i18nText('save', locale)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
|
@ -37,10 +37,10 @@ export const EnterContent: FC<EnterProps> = ({
|
||||||
const { login, password } = form.getFieldsValue();
|
const { login, password } = form.getFieldsValue();
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
getAuth(locale, { login, password })
|
getAuth(locale, { login, password })
|
||||||
.then(({ data }) => {
|
.then((data) => {
|
||||||
if (data.jwtToken) {
|
if (data.jwtToken) {
|
||||||
getPersonalData(locale, data.jwtToken)
|
getPersonalData(locale, data.jwtToken)
|
||||||
.then(({ data: profile }) => {
|
.then((profile) => {
|
||||||
localStorage.setItem(AUTH_USER, JSON.stringify(profile));
|
localStorage.setItem(AUTH_USER, JSON.stringify(profile));
|
||||||
updateToken(data.jwtToken);
|
updateToken(data.jwtToken);
|
||||||
handleCancel();
|
handleCancel();
|
||||||
|
@ -110,11 +110,11 @@ export const EnterContent: FC<EnterProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
type: 'email',
|
type: 'email',
|
||||||
message: 'The input is not valid E-mail'
|
message: i18nText('errors.validEmail', locale)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your E-mail'
|
message: i18nText('error.emptyEmail', locale)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -129,7 +129,7 @@ export const EnterContent: FC<EnterProps> = ({
|
||||||
noStyle
|
noStyle
|
||||||
rules={[{
|
rules={[{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your password'
|
message: i18nText('errors.emptyPass', locale)
|
||||||
}]}
|
}]}
|
||||||
>
|
>
|
||||||
<CustomInputPassword
|
<CustomInputPassword
|
||||||
|
@ -152,26 +152,26 @@ export const EnterContent: FC<EnterProps> = ({
|
||||||
type="link"
|
type="link"
|
||||||
onClick={() => updateMode('reset')}
|
onClick={() => updateMode('reset')}
|
||||||
>
|
>
|
||||||
Forgot password?
|
{`${i18nText('forgotPass', locale)}?`}
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
<span>or</span>
|
<span>{i18nText('or', locale)}</span>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
||||||
onClick={() => onSocialEnter(Social.FACEBOOK)}
|
onClick={() => onSocialEnter(Social.FACEBOOK)}
|
||||||
>
|
>
|
||||||
Facebook account
|
{i18nText('facebook', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
||||||
onClick={() => onSocialEnter(Social.APPLE)}
|
onClick={() => onSocialEnter(Social.APPLE)}
|
||||||
>
|
>
|
||||||
Apple account
|
{i18nText('apple', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
||||||
onClick={() => onSocialEnter(Social.GOOGLE)}
|
onClick={() => onSocialEnter(Social.GOOGLE)}
|
||||||
>
|
>
|
||||||
Google account
|
{i18nText('google', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,14 +5,10 @@ import { i18nText } from '../../../i18nKeys';
|
||||||
export const FinishContent = ({ locale }: { locale: string }) => (
|
export const FinishContent = ({ locale }: { locale: string }) => (
|
||||||
<>
|
<>
|
||||||
<div className="b-modal__auth__agreement">
|
<div className="b-modal__auth__agreement">
|
||||||
A link to reset your password has been sent
|
{i18nText('resetPassText', locale)}
|
||||||
<br />
|
|
||||||
to your email
|
|
||||||
</div>
|
</div>
|
||||||
<FilledButton
|
<FilledButton type="primary">
|
||||||
type="primary"
|
{i18nText('enterAccount', locale)}
|
||||||
>
|
|
||||||
{i18nText('enter', locale)}
|
|
||||||
</FilledButton>
|
</FilledButton>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,10 +36,10 @@ export const RegisterContent: FC<RegisterProps> = ({
|
||||||
const { login, password } = form.getFieldsValue();
|
const { login, password } = form.getFieldsValue();
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
getRegister(locale)
|
getRegister(locale)
|
||||||
.then(({ data }) => {
|
.then((data) => {
|
||||||
if (data.jwtToken) {
|
if (data.jwtToken) {
|
||||||
setPersonData( { login, password, role: 'client', languagesLinks: [] }, locale, data.jwtToken)
|
setPersonData( { login, password, role: 'client', languagesLinks: [] }, locale, data.jwtToken)
|
||||||
.then(({ data: profile }) => {
|
.then((profile) => {
|
||||||
updateToken(data.jwtToken);
|
updateToken(data.jwtToken);
|
||||||
localStorage.setItem(AUTH_USER, JSON.stringify(profile.userData));
|
localStorage.setItem(AUTH_USER, JSON.stringify(profile.userData));
|
||||||
handleCancel();
|
handleCancel();
|
||||||
|
@ -115,11 +115,11 @@ export const RegisterContent: FC<RegisterProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
type: 'email',
|
type: 'email',
|
||||||
message: 'The input is not valid E-mail'
|
message: i18nText('errors.validEmail', locale)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your E-mail'
|
message: i18nText('error.emptyEmail', locale)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -134,7 +134,7 @@ export const RegisterContent: FC<RegisterProps> = ({
|
||||||
noStyle
|
noStyle
|
||||||
rules={[{
|
rules={[{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your password'
|
message: i18nText('errors.emptyPass', locale)
|
||||||
}]}
|
}]}
|
||||||
>
|
>
|
||||||
<CustomInputPassword
|
<CustomInputPassword
|
||||||
|
@ -150,14 +150,14 @@ export const RegisterContent: FC<RegisterProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please confirm your password',
|
message: i18nText('errors.confirmPass', locale),
|
||||||
},
|
},
|
||||||
({ getFieldValue }) => ({
|
({ getFieldValue }) => ({
|
||||||
validator(_, value) {
|
validator(_, value) {
|
||||||
if (!value || getFieldValue('password') === value) {
|
if (!value || getFieldValue('password') === value) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return Promise.reject(new Error('The new password that you entered do not match'));
|
return Promise.reject(new Error(i18nText('errors.notMatchPass', locale)));
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
|
@ -176,24 +176,24 @@ export const RegisterContent: FC<RegisterProps> = ({
|
||||||
{i18nText('registration', locale)}
|
{i18nText('registration', locale)}
|
||||||
</FilledButton>
|
</FilledButton>
|
||||||
<OutlinedButton onClick={() => updateMode('enter')}>{i18nText('enter', locale)}</OutlinedButton>
|
<OutlinedButton onClick={() => updateMode('enter')}>{i18nText('enter', locale)}</OutlinedButton>
|
||||||
<span>or</span>
|
<span>{i18nText('or', locale)}</span>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
||||||
onClick={() => onSocialRegister(Social.FACEBOOK)}
|
onClick={() => onSocialRegister(Social.FACEBOOK)}
|
||||||
>
|
>
|
||||||
Facebook account
|
{i18nText('facebook', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
||||||
onClick={() => onSocialRegister(Social.APPLE)}
|
onClick={() => onSocialRegister(Social.APPLE)}
|
||||||
>
|
>
|
||||||
Apple account
|
{i18nText('apple', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
<OutlinedButton
|
<OutlinedButton
|
||||||
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
||||||
onClick={() => onSocialRegister(Social.GOOGLE)}
|
onClick={() => onSocialRegister(Social.GOOGLE)}
|
||||||
>
|
>
|
||||||
Google account
|
{i18nText('google', locale)}
|
||||||
</OutlinedButton>
|
</OutlinedButton>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,11 +29,11 @@ export const ResetContent: FC<ResetProps> = ({
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
type: 'email',
|
type: 'email',
|
||||||
message: 'The input is not valid E-mail'
|
message: i18nText('errors.validEmail', locale)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your E-mail'
|
message: i18nText('error.emptyEmail', locale)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -48,7 +48,7 @@ export const ResetContent: FC<ResetProps> = ({
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={onResetPassword}
|
onClick={onResetPassword}
|
||||||
>
|
>
|
||||||
Reset Password
|
{i18nText('resetPass', locale)}
|
||||||
</FilledButton>
|
</FilledButton>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const GeneralTopSection = ({
|
||||||
mainImage
|
mainImage
|
||||||
}: GeneralTopSectionProps) => (
|
}: GeneralTopSectionProps) => (
|
||||||
<div className="main-top">
|
<div className="main-top">
|
||||||
<div className="b-inner">
|
<div className="b-inner b-main-desc">
|
||||||
<h1 className="title-h1">{title}</h1>
|
<h1 className="title-h1">{title}</h1>
|
||||||
<div className="main-top__wrap-text">
|
<div className="main-top__wrap-text">
|
||||||
{description && <p className="main-top__text">{description}</p>}
|
{description && <p className="main-top__text">{description}</p>}
|
||||||
|
|
|
@ -72,6 +72,7 @@ function HeaderAuthLinks ({
|
||||||
mode={mode}
|
mode={mode}
|
||||||
updateMode={setMode}
|
updateMode={setMode}
|
||||||
updateToken={setToken}
|
updateToken={setToken}
|
||||||
|
locale={locale}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,7 @@ export const HeaderMenu = ({
|
||||||
}: HeaderMenuProps) => {
|
}: HeaderMenuProps) => {
|
||||||
const selectedLayoutSegment = useSelectedLayoutSegment();
|
const selectedLayoutSegment = useSelectedLayoutSegment();
|
||||||
const pathname = selectedLayoutSegment || '';
|
const pathname = selectedLayoutSegment || '';
|
||||||
|
const url = pathname === '(main)' ? '' : pathname;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="b-header__nav">
|
<div className="b-header__nav">
|
||||||
|
@ -25,7 +26,7 @@ export const HeaderMenu = ({
|
||||||
<ul className="b-header__nav__list">
|
<ul className="b-header__nav__list">
|
||||||
{linkConfig.map(({ path, title }) => (
|
{linkConfig.map(({ path, title }) => (
|
||||||
<li key={path}>
|
<li key={path}>
|
||||||
<Link href={`/${path}` as any} className={pathname === path ? 'active' : ''}>{title}</Link>
|
<Link href={`/${path}` as any} className={path === url ? 'active' : ''}>{title}</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
<AuthLinks locale={locale} />
|
<AuthLinks locale={locale} />
|
||||||
|
|
|
@ -13,7 +13,7 @@ type HeaderProps = {
|
||||||
export const Header: FC<HeaderProps> = ({ locale }) => {
|
export const Header: FC<HeaderProps> = ({ locale }) => {
|
||||||
const routes: { path: string, title: string }[] = HEAD_ROUTES.map((item) => ({
|
const routes: { path: string, title: string }[] = HEAD_ROUTES.map((item) => ({
|
||||||
path: item,
|
path: item,
|
||||||
title: i18nText(`menu.${item}`, locale)
|
title: i18nText(item ? `menu.${item}` : 'menu.home', locale)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,3 +6,9 @@ export const FilledButton = (props: any) => (
|
||||||
{props.children}
|
{props.children}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const FilledYellowButton = (props: any) => (
|
||||||
|
<Button className="b-button__filled_yellow" {...props}>
|
||||||
|
{props.children}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
|
|
||||||
export const OutlinedButton = (props: any) => (
|
export const OutlinedButton = (props: any) => (
|
||||||
<Button className="b-button__outlined" {...props}>
|
<Button className={`b-button__outlined${props?.danger ? ' danger': ''}`} {...props}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export const HEAD_ROUTES = ['bb-client', 'bb-expert', 'blog'];
|
// export const HEAD_ROUTES = ['bb-client', 'bb-expert', 'blog'];
|
||||||
|
export const HEAD_ROUTES = ['', 'blog'];
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Benachrichtigung',
|
notifications: 'Benachrichtigung',
|
||||||
support: 'Hilfe & Support',
|
support: 'Hilfe & Support',
|
||||||
information: 'Rechtliche Informationen',
|
information: 'Rechtliche Informationen',
|
||||||
settings: 'Profileinstellungen',
|
settings: 'Kontoeinstellungen',
|
||||||
messages: 'Nachrichten',
|
messages: 'Nachrichten',
|
||||||
'work-with-us': 'Arbeite mit uns'
|
'expert-profile': 'Expertenprofil'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Mit BB wachsen',
|
'bb-client': 'Mit BB wachsen',
|
||||||
'bb-expert': 'Werde BB-Experte',
|
'bb-expert': 'Werde BB-Experte',
|
||||||
|
home: 'Startseite',
|
||||||
blog: 'Blog&News'
|
blog: 'Blog&News'
|
||||||
},
|
},
|
||||||
registration: 'Registrieren',
|
registration: 'Registrieren',
|
||||||
enter: 'Anmelden',
|
enter: 'Anmelden',
|
||||||
|
enterAccount: 'Konto anmelden',
|
||||||
account: 'Mein Konto',
|
account: 'Mein Konto',
|
||||||
logout: 'Abmelden',
|
logout: 'Abmelden',
|
||||||
|
decline: 'Ablehnen',
|
||||||
|
send: 'Senden',
|
||||||
deleteAcc: 'Konto löschen',
|
deleteAcc: 'Konto löschen',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'FAQ',
|
faq: 'FAQ',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Kommende Sitzungen',
|
upcoming: 'Kommende Sitzungen',
|
||||||
requested: 'Angefragte Sitzungen',
|
requested: 'Angefragte Sitzungen',
|
||||||
recent: 'Letzte Sitzungen'
|
recent: 'Letzte Sitzungen',
|
||||||
|
cancelReason: 'Gib einen Grund für die Absage der Sitzung ein',
|
||||||
|
reasonPlaceholder: 'Beschreibe den Grund für die Ablehnung',
|
||||||
|
decline: 'Sitzung ablehnen',
|
||||||
|
confirm: 'Sitzung bestätigen',
|
||||||
|
join: 'Sitzung beitreten',
|
||||||
|
start: 'Sitzung starten',
|
||||||
|
finish: 'Sitzung abschließen',
|
||||||
|
comments: 'Kommentare',
|
||||||
|
myComments: 'Meine Kommentare',
|
||||||
|
addComment: 'Neuen Kommentar hinzufügen',
|
||||||
|
commentPlaceholder: 'Ihr Kommentar',
|
||||||
|
clientComments: 'Kundenkommentare',
|
||||||
|
coachComments: 'Trainerkommentare'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Zukünftige Räume',
|
||||||
|
requested: 'Angeforderte Räume',
|
||||||
|
recent: 'Kürzliche Räume',
|
||||||
|
newRoom: 'Neuer Raum'
|
||||||
|
},
|
||||||
|
agreementText: 'Folgendes habe ich gelesen und erkläre mich damit einverstanden: Benutzervereinbarung,',
|
||||||
|
userAgreement: 'Benutzervereinbarung',
|
||||||
|
privacyPolicy: 'Datenschutzrichtlinie',
|
||||||
|
readMore: 'Mehr erfahren',
|
||||||
photoDesc: 'Füge ein echtes Foto hinzu, mit Gesicht wirkt es immer glaubwürdiger.',
|
photoDesc: 'Füge ein echtes Foto hinzu, mit Gesicht wirkt es immer glaubwürdiger.',
|
||||||
dayStart: 'Tagesbeginn',
|
dayStart: 'Tagesbeginn',
|
||||||
topic: 'Thema',
|
topic: 'Thema',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Altes Passwort',
|
oldPass: 'Altes Passwort',
|
||||||
newPass: 'Neues Passwort',
|
newPass: 'Neues Passwort',
|
||||||
confirmPass: 'Passwort bestätigen',
|
confirmPass: 'Passwort bestätigen',
|
||||||
|
forgotPass: 'Passwort vergessen',
|
||||||
|
resetPassText: 'Ein Link zum Zurücksetzen Ihres Passworts wurde an Ihre E-Mail gesendet',
|
||||||
|
or: 'oder',
|
||||||
|
facebook: 'Facebook-Konto',
|
||||||
|
apple: 'Apple-Konto',
|
||||||
|
google: 'Google-Konto',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Füge deine persönlichen Informationen ein, um deine Reise als BBuddy-Experte zu beginnen',
|
insertInfo: 'Füge deine persönlichen Informationen ein, um deine Reise als BBuddy-Experte zu beginnen',
|
||||||
changeUserData: 'Du kannst deine Angaben jederzeit ergänzen oder ändern\n',
|
changeUserData: 'Du kannst deine Angaben jederzeit ergänzen oder ändern\n',
|
||||||
|
@ -49,11 +82,46 @@ export default {
|
||||||
sortPriceDesc: 'Nach Preis absteigend',
|
sortPriceDesc: 'Nach Preis absteigend',
|
||||||
details: 'Details',
|
details: 'Details',
|
||||||
sessionLang: 'Sitzungssprache',
|
sessionLang: 'Sitzungssprache',
|
||||||
|
direction: 'Wegbeschreibung',
|
||||||
fromTo: 'von $ bis $',
|
fromTo: 'von $ bis $',
|
||||||
apply: 'Anwenden',
|
apply: 'Anwenden',
|
||||||
save: 'Speichern',
|
save: 'Speichern',
|
||||||
|
edit: 'Bearbeiten',
|
||||||
changePass: 'Passwort ändern',
|
changePass: 'Passwort ändern',
|
||||||
|
resetPass: 'Passwort zurücksetzen',
|
||||||
getStarted: 'Loslegen',
|
getStarted: 'Loslegen',
|
||||||
delete: 'Löschen',
|
delete: 'Löschen',
|
||||||
today: 'Heute'
|
today: 'Heute',
|
||||||
|
back: 'Zurück',
|
||||||
|
backToExperts: 'Zurück zur Expertenliste',
|
||||||
|
courseInfo: 'Kursinfo',
|
||||||
|
expertBackground: 'Expertenhintergrund',
|
||||||
|
profCertification: 'Professionelle Zertifizierung',
|
||||||
|
practiceHours: 'Praxisstunden',
|
||||||
|
supervisionCount: 'Supervision pro Jahr',
|
||||||
|
outOf: 'von',
|
||||||
|
schedule: 'Zeitplan',
|
||||||
|
successfulCase: 'Erfolgreiche Fälle aus der Praxis',
|
||||||
|
signUp: 'Jetzt anmelden',
|
||||||
|
noData: 'Keine Daten',
|
||||||
|
notFound: 'Nicht gefunden',
|
||||||
|
trainings: 'Trainings',
|
||||||
|
seminars: 'Seminare',
|
||||||
|
courses: 'Kurse',
|
||||||
|
mba: 'MBA-Information',
|
||||||
|
aboutCoach: 'Über Coach',
|
||||||
|
education: 'Bildung',
|
||||||
|
coaching: 'Coaching',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'Die E-Mail-Adresse ist ungültig',
|
||||||
|
emptyEmail: 'Bitte geben Sie Ihre E-Mail ein',
|
||||||
|
emptyPass: 'Bitte geben Sie Ihr Passwort ein',
|
||||||
|
confirmPass: 'Bitte bestätigen Sie Ihr Passwort',
|
||||||
|
notMatchPass: 'Die neuen Passwörter stimmen nicht überein',
|
||||||
|
emptyCancelReason: 'Bitte gib den Grund ein',
|
||||||
|
approvingSession: 'Fehler beim Genehmigen der Sitzung',
|
||||||
|
finishingSession: 'Fehler beim Beenden der Sitzung',
|
||||||
|
emptyComment: 'Bitte geben Sie Ihren Kommentar ein',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Notification',
|
notifications: 'Notification',
|
||||||
support: 'Help & Support',
|
support: 'Help & Support',
|
||||||
information: 'Legal Information',
|
information: 'Legal Information',
|
||||||
settings: 'Profile Settings',
|
settings: 'Account Settings',
|
||||||
messages: 'Messages',
|
messages: 'Messages',
|
||||||
'work-with-us': 'Work With Us'
|
'expert-profile': 'Expert profile'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Start grow with BB',
|
'bb-client': 'Start grow with BB',
|
||||||
'bb-expert': 'Become BB Expert',
|
'bb-expert': 'Become BB Expert',
|
||||||
|
home: 'Home',
|
||||||
blog: 'Blog&News'
|
blog: 'Blog&News'
|
||||||
},
|
},
|
||||||
registration: 'Registration',
|
registration: 'Registration',
|
||||||
enter: 'Enter',
|
enter: 'Enter',
|
||||||
|
enterAccount: 'Enter account',
|
||||||
account: 'My Account',
|
account: 'My Account',
|
||||||
logout: 'Log out',
|
logout: 'Log out',
|
||||||
|
decline: 'Decline',
|
||||||
|
send: 'Send',
|
||||||
deleteAcc: 'Delete account',
|
deleteAcc: 'Delete account',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'FAQ',
|
faq: 'FAQ',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Upcoming Sessions',
|
upcoming: 'Upcoming Sessions',
|
||||||
requested: 'Sessions Requested',
|
requested: 'Sessions Requested',
|
||||||
recent: 'Recent Sessions'
|
recent: 'Recent Sessions',
|
||||||
|
cancelReason: 'Enter a reason for cancelling the session',
|
||||||
|
reasonPlaceholder: 'Describe the reason for the rejection',
|
||||||
|
decline: 'Decline session',
|
||||||
|
confirm: 'Confirm session',
|
||||||
|
join: 'Join session',
|
||||||
|
start: 'Start session',
|
||||||
|
finish: 'Finish session',
|
||||||
|
comments: 'Comments',
|
||||||
|
myComments: 'My comments',
|
||||||
|
addComment: 'Add new',
|
||||||
|
commentPlaceholder: 'Your comment',
|
||||||
|
clientComments: 'Client Comments',
|
||||||
|
coachComments: 'Coach Comments'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Upcoming Rooms',
|
||||||
|
requested: 'Rooms Requested',
|
||||||
|
recent: 'Recent Rooms',
|
||||||
|
newRoom: 'New Room'
|
||||||
|
},
|
||||||
|
agreementText: 'I have read and agree with the terms of the User Agreement,',
|
||||||
|
userAgreement: 'User Agreement',
|
||||||
|
privacyPolicy: 'Privacy Policy',
|
||||||
|
readMore: 'Read more',
|
||||||
photoDesc: 'Add a real photo, as a person\'s face is always more credible.',
|
photoDesc: 'Add a real photo, as a person\'s face is always more credible.',
|
||||||
dayStart: 'Day start',
|
dayStart: 'Day start',
|
||||||
topic: 'Topic',
|
topic: 'Topic',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Old Password',
|
oldPass: 'Old Password',
|
||||||
newPass: 'New Password',
|
newPass: 'New Password',
|
||||||
confirmPass: 'Confirm Password',
|
confirmPass: 'Confirm Password',
|
||||||
|
forgotPass: 'Forgot password',
|
||||||
|
resetPassText: 'A link to reset your password has been sent to your email',
|
||||||
|
or: 'or',
|
||||||
|
facebook: 'Facebook account',
|
||||||
|
apple: 'Apple account',
|
||||||
|
google: 'Google account',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Insert your personal information to start your journey as a BBuddy Expert',
|
insertInfo: 'Insert your personal information to start your journey as a BBuddy Expert',
|
||||||
changeUserData: 'Your info can either be added or amended at anytime',
|
changeUserData: 'Your info can either be added or amended at anytime',
|
||||||
|
@ -49,11 +82,45 @@ export default {
|
||||||
sortPriceDesc: 'By price descending',
|
sortPriceDesc: 'By price descending',
|
||||||
details: 'Details',
|
details: 'Details',
|
||||||
sessionLang: 'Session Language',
|
sessionLang: 'Session Language',
|
||||||
|
direction: 'Direction',
|
||||||
fromTo: 'from $ to $',
|
fromTo: 'from $ to $',
|
||||||
apply: 'Apply',
|
apply: 'Apply',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
|
edit: 'Edit',
|
||||||
changePass: 'Change password',
|
changePass: 'Change password',
|
||||||
|
resetPass: 'Reset password',
|
||||||
getStarted: 'Get started',
|
getStarted: 'Get started',
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
today: 'Today'
|
today: 'Today',
|
||||||
|
back: 'Back',
|
||||||
|
backToExperts: 'Back to experts list',
|
||||||
|
courseInfo: 'Course Info',
|
||||||
|
expertBackground: 'Expert Background',
|
||||||
|
profCertification: 'Professional Certification',
|
||||||
|
practiceHours: 'Practice hours',
|
||||||
|
supervisionCount: 'Supervision per year',
|
||||||
|
outOf: 'out of',
|
||||||
|
schedule: 'Schedule',
|
||||||
|
successfulCase: 'Successful Cases From Practice',
|
||||||
|
signUp: 'Sign up now',
|
||||||
|
noData: 'No data',
|
||||||
|
notFound: 'Not found',
|
||||||
|
trainings: 'Trainings',
|
||||||
|
seminars: 'Seminars',
|
||||||
|
courses: 'Courses',
|
||||||
|
mba: 'MBA Information',
|
||||||
|
aboutCoach: 'About Coach',
|
||||||
|
education: 'Education',
|
||||||
|
coaching: 'Coaching',
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'The email address is not valid',
|
||||||
|
emptyEmail: 'Please enter your E-mail',
|
||||||
|
emptyPass: 'Please enter your password',
|
||||||
|
confirmPass: 'Please confirm your password',
|
||||||
|
notMatchPass: 'The new passwords you entered do not match',
|
||||||
|
emptyCancelReason: 'Please enter the reason',
|
||||||
|
approvingSession: 'Error approving session',
|
||||||
|
finishingSession: 'Error finishing session',
|
||||||
|
emptyComment: 'Please enter your comment',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Notificación',
|
notifications: 'Notificación',
|
||||||
support: 'Ayuda y asistencia',
|
support: 'Ayuda y asistencia',
|
||||||
information: 'Información jurídica',
|
information: 'Información jurídica',
|
||||||
settings: 'Ajustes del perfil',
|
settings: 'Ajustes de cuenta',
|
||||||
messages: 'Mensajes',
|
messages: 'Mensajes',
|
||||||
'work-with-us': 'Trabaja con nosotros'
|
'expert-profile': 'Perfil del experto'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Empieza a crecer con BB',
|
'bb-client': 'Empieza a crecer con BB',
|
||||||
'bb-expert': 'Conviértete en un experto en BB',
|
'bb-expert': 'Conviértete en un experto en BB',
|
||||||
|
home: 'Inicio',
|
||||||
blog: 'Blog y noticias'
|
blog: 'Blog y noticias'
|
||||||
},
|
},
|
||||||
registration: 'Registro',
|
registration: 'Registro',
|
||||||
enter: 'Entrar',
|
enter: 'Entrar',
|
||||||
|
enterAccount: 'Introducir cuenta',
|
||||||
account: 'Mi cuenta',
|
account: 'Mi cuenta',
|
||||||
logout: 'Cerrar sesión',
|
logout: 'Cerrar sesión',
|
||||||
|
decline: 'Rechazar',
|
||||||
|
send: 'Enviar',
|
||||||
deleteAcc: 'Eliminar cuenta',
|
deleteAcc: 'Eliminar cuenta',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'Preguntas frecuentes',
|
faq: 'Preguntas frecuentes',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Próximas sesiones',
|
upcoming: 'Próximas sesiones',
|
||||||
requested: 'Sesiones solicitadas',
|
requested: 'Sesiones solicitadas',
|
||||||
recent: 'Sesiones recientes'
|
recent: 'Sesiones recientes',
|
||||||
|
cancelReason: 'Introduce el motivo por el que has cancelado la sesión',
|
||||||
|
reasonPlaceholder: 'Describe el motivo del rechazo',
|
||||||
|
decline: 'Rechazar sesión',
|
||||||
|
confirm: 'Confirmar sesión',
|
||||||
|
join: 'Unirse a la sesión',
|
||||||
|
start: 'Iniciar sesión',
|
||||||
|
finish: 'Finalizar la sesión',
|
||||||
|
comments: 'Comentarios',
|
||||||
|
myComments: 'Mis comentarios',
|
||||||
|
addComment: 'Añadir nuevo comentario',
|
||||||
|
commentPlaceholder: 'Tu comentario',
|
||||||
|
clientComments: 'Comentarios del cliente',
|
||||||
|
coachComments: 'Comentarios del entrenador'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Próximas salas',
|
||||||
|
requested: 'Salas solicitadas',
|
||||||
|
recent: 'Salas recientes',
|
||||||
|
newRoom: 'Nueva sala'
|
||||||
|
},
|
||||||
|
agreementText: 'He leído y acepto las condiciones del Acuerdo de usuario,',
|
||||||
|
userAgreement: 'Acuerdo de usuario',
|
||||||
|
privacyPolicy: 'Política de privacidad',
|
||||||
|
readMore: 'Seguir leyendo',
|
||||||
photoDesc: 'Añade una foto real, ya que la cara de una persona siempre es más creíble.',
|
photoDesc: 'Añade una foto real, ya que la cara de una persona siempre es más creíble.',
|
||||||
dayStart: 'Inicio del día',
|
dayStart: 'Inicio del día',
|
||||||
topic: 'Tema',
|
topic: 'Tema',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Contraseña antigua',
|
oldPass: 'Contraseña antigua',
|
||||||
newPass: 'Nueva contraseña',
|
newPass: 'Nueva contraseña',
|
||||||
confirmPass: 'Confirmar contraseña',
|
confirmPass: 'Confirmar contraseña',
|
||||||
|
forgotPass: 'Se te ha olvidado la contraseña',
|
||||||
|
resetPassText: 'Se ha enviado un enlace para restablecer la contraseña a tu correo electrónico',
|
||||||
|
or: 'o',
|
||||||
|
facebook: 'Cuenta de Facebook',
|
||||||
|
apple: 'Cuenta de Apple',
|
||||||
|
google: 'Cuenta de Google',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Introduce tu información personal para comenzar tu viaje como experto en BBuddy',
|
insertInfo: 'Introduce tu información personal para comenzar tu viaje como experto en BBuddy',
|
||||||
changeUserData: 'Tus datos pueden añadirse o modificarse en cualquier momento',
|
changeUserData: 'Tus datos pueden añadirse o modificarse en cualquier momento',
|
||||||
|
@ -49,11 +82,46 @@ export default {
|
||||||
sortPriceDesc: 'Por precio descendiente',
|
sortPriceDesc: 'Por precio descendiente',
|
||||||
details: 'Detalles',
|
details: 'Detalles',
|
||||||
sessionLang: 'Idioma de la sesión',
|
sessionLang: 'Idioma de la sesión',
|
||||||
|
direction: 'Dirección',
|
||||||
fromTo: 'de $ a $',
|
fromTo: 'de $ a $',
|
||||||
apply: 'Solicitar',
|
apply: 'Solicitar',
|
||||||
save: 'Guardar',
|
save: 'Guardar',
|
||||||
|
edit: 'Editar',
|
||||||
changePass: 'Cambiar contraseña',
|
changePass: 'Cambiar contraseña',
|
||||||
|
resetPass: 'Restablecer contraseña',
|
||||||
getStarted: 'Empieza',
|
getStarted: 'Empieza',
|
||||||
delete: 'Eliminar',
|
delete: 'Eliminar',
|
||||||
today: 'Hoy día'
|
today: 'Hoy',
|
||||||
|
back: 'Volver',
|
||||||
|
backToExperts: 'Volver a la lista de expertos',
|
||||||
|
courseInfo: 'Información del curso',
|
||||||
|
expertBackground: 'Antecedentes del experto',
|
||||||
|
profCertification: 'Certificación profesional',
|
||||||
|
practiceHours: 'Horas de práctica',
|
||||||
|
supervisionCount: 'Supervisiones anuales',
|
||||||
|
outOf: 'de',
|
||||||
|
schedule: 'Horario',
|
||||||
|
successfulCase: 'Casos de éxito de la práctica',
|
||||||
|
signUp: 'Regístrate ahora',
|
||||||
|
noData: 'Sin datos',
|
||||||
|
notFound: 'No encontrado',
|
||||||
|
trainings: 'Formación',
|
||||||
|
seminars: 'Seminarios',
|
||||||
|
courses: 'Cursos',
|
||||||
|
mba: 'Información sobre máster en ADE (MBA)',
|
||||||
|
aboutCoach: 'Sobre el coach',
|
||||||
|
education: 'Educación',
|
||||||
|
coaching: 'Coaching',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'La dirección de correo electrónico no es válida',
|
||||||
|
emptyEmail: 'Introduce tu correo electrónico',
|
||||||
|
emptyPass: 'Introduce tu contraseña',
|
||||||
|
confirmPass: 'Confirma tu contraseña',
|
||||||
|
notMatchPass: 'Las nuevas contraseñas que has introducido no coinciden',
|
||||||
|
emptyCancelReason: 'Introduce el motivo',
|
||||||
|
approvingSession: 'Error al aprobar la sesión',
|
||||||
|
finishingSession: 'Error al finalizar la sesión',
|
||||||
|
emptyComment: 'Introduce tu comentario',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Notification',
|
notifications: 'Notification',
|
||||||
support: 'Aide et support',
|
support: 'Aide et support',
|
||||||
information: 'Informations légales',
|
information: 'Informations légales',
|
||||||
settings: 'Paramètres du profil',
|
settings: 'Paramètres du compte',
|
||||||
messages: 'Messages',
|
messages: 'Messages',
|
||||||
'work-with-us': 'Travaillez avec nous'
|
'expert-profile': 'Profil de l\'expert'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Commencez à vous développer avec BB',
|
'bb-client': 'Commencez à vous développer avec BB',
|
||||||
'bb-expert': 'Devenez Expert BB',
|
'bb-expert': 'Devenez Expert BB',
|
||||||
|
home: 'Accueil',
|
||||||
blog: 'Blog et actus'
|
blog: 'Blog et actus'
|
||||||
},
|
},
|
||||||
registration: 'Inscription',
|
registration: 'Inscription',
|
||||||
enter: 'Saisir',
|
enter: 'Saisir',
|
||||||
|
enterAccount: 'Saisir le compte',
|
||||||
account: 'Mon compte',
|
account: 'Mon compte',
|
||||||
logout: 'Déconnexion',
|
logout: 'Déconnexion',
|
||||||
|
decline: 'Refuser',
|
||||||
|
send: 'Envoyer',
|
||||||
deleteAcc: 'Supprimer le compte',
|
deleteAcc: 'Supprimer le compte',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'FAQ',
|
faq: 'FAQ',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Prochaines sessions',
|
upcoming: 'Prochaines sessions',
|
||||||
requested: 'Sessions demandées',
|
requested: 'Sessions demandées',
|
||||||
recent: 'Sessions récentes'
|
recent: 'Sessions récentes',
|
||||||
|
cancelReason: 'Saisissez une raison pour l\'annulation de la session',
|
||||||
|
reasonPlaceholder: 'Décrivez la raison du refus',
|
||||||
|
decline: 'Refuser la session',
|
||||||
|
confirm: 'Confirmer la session',
|
||||||
|
join: 'Rejoindre la session',
|
||||||
|
start: 'Commencer la session',
|
||||||
|
finish: 'Terminer la session',
|
||||||
|
comments: 'Commentaires',
|
||||||
|
myComments: 'Mes commentaires',
|
||||||
|
addComment: 'Ajouter un nouveau commentaire',
|
||||||
|
commentPlaceholder: 'Votre commentaire',
|
||||||
|
clientComments: 'Commentaires du client',
|
||||||
|
coachComments: 'Commentaires du coach'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Salles futures',
|
||||||
|
requested: 'Salles demandées',
|
||||||
|
recent: 'Salles récentes',
|
||||||
|
newRoom: 'Nouvelle salle'
|
||||||
|
},
|
||||||
|
agreementText: 'J\'ai lu et j\'accepte les dispositions de l\'Accord Utilisateur et de la',
|
||||||
|
userAgreement: '',
|
||||||
|
privacyPolicy: 'Politique de Confidentialité',
|
||||||
|
readMore: 'En savoir plus',
|
||||||
photoDesc: 'Ajoutez une photo réelle, le visage d\'une personne est toujours plus crédible.',
|
photoDesc: 'Ajoutez une photo réelle, le visage d\'une personne est toujours plus crédible.',
|
||||||
dayStart: 'Début de la journée',
|
dayStart: 'Début de la journée',
|
||||||
topic: 'Sujet',
|
topic: 'Sujet',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Ancien mot de passe',
|
oldPass: 'Ancien mot de passe',
|
||||||
newPass: 'Nouveau mot de passe',
|
newPass: 'Nouveau mot de passe',
|
||||||
confirmPass: 'Confirmer le mot de passe',
|
confirmPass: 'Confirmer le mot de passe',
|
||||||
|
forgotPass: 'Mot de passe oublié',
|
||||||
|
resetPassText: 'Un lien pour réinitialiser votre mot de passe a été envoyé à votre adresse e-mail',
|
||||||
|
or: 'ou',
|
||||||
|
facebook: 'Compte Facebook',
|
||||||
|
apple: 'Compte Apple',
|
||||||
|
google: 'Compte Google',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Insérez vos informations personnelles pour commencer votre voyage en tant qu\'expert BBuddy',
|
insertInfo: 'Insérez vos informations personnelles pour commencer votre voyage en tant qu\'expert BBuddy',
|
||||||
changeUserData: 'Vos informations peuvent être ajoutées ou modifiées à tout moment',
|
changeUserData: 'Vos informations peuvent être ajoutées ou modifiées à tout moment',
|
||||||
|
@ -49,11 +82,46 @@ export default {
|
||||||
sortPriceDesc: 'Par prix décroissant',
|
sortPriceDesc: 'Par prix décroissant',
|
||||||
details: 'Détails',
|
details: 'Détails',
|
||||||
sessionLang: 'Langue de la session',
|
sessionLang: 'Langue de la session',
|
||||||
|
direction: 'Direction',
|
||||||
fromTo: 'de $ à $',
|
fromTo: 'de $ à $',
|
||||||
apply: 'Appliquer',
|
apply: 'Appliquer',
|
||||||
save: 'Sauvegarder',
|
save: 'Sauvegarder',
|
||||||
|
edit: 'Modifier',
|
||||||
changePass: 'Modifier le mot de passe',
|
changePass: 'Modifier le mot de passe',
|
||||||
|
resetPass: 'Réinitialiser le mot de passe',
|
||||||
getStarted: 'Commencer',
|
getStarted: 'Commencer',
|
||||||
delete: 'Supprimer',
|
delete: 'Supprimer',
|
||||||
today: 'Ce jour'
|
today: 'Aujourd\'hui',
|
||||||
|
back: 'Retour',
|
||||||
|
backToExperts: 'Retour à la liste d\'experts',
|
||||||
|
courseInfo: 'Infos sur le cours',
|
||||||
|
expertBackground: 'Antécédents de l\'expert',
|
||||||
|
profCertification: 'Certification professionnelle',
|
||||||
|
practiceHours: 'Heures de pratique',
|
||||||
|
supervisionCount: 'Supervision par an',
|
||||||
|
outOf: 'sur',
|
||||||
|
schedule: 'Programme',
|
||||||
|
successfulCase: 'Cas réussis de la pratique',
|
||||||
|
signUp: 'Inscrivez-vous maintenant',
|
||||||
|
noData: 'Aucune donnée',
|
||||||
|
notFound: 'Non trouvé',
|
||||||
|
trainings: 'Formations',
|
||||||
|
seminars: 'Séminaires',
|
||||||
|
courses: 'Cours',
|
||||||
|
mba: 'Infos Maîtrise en gestion',
|
||||||
|
aboutCoach: 'À propos du coach',
|
||||||
|
education: 'Éducation',
|
||||||
|
coaching: 'Coaching',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'L\'adresse e-mail n\'est pas valide',
|
||||||
|
emptyEmail: 'Veuillez saisir votre e-mail',
|
||||||
|
emptyPass: 'Veuillez saisir votre mot de passe',
|
||||||
|
confirmPass: 'Veuillez confirmer votre mot de passe',
|
||||||
|
notMatchPass: 'Les nouveaux mots de passe que vous avez saisis ne sont pas identiques',
|
||||||
|
emptyCancelReason: 'Veuillez saisir la raison',
|
||||||
|
approvingSession: 'Erreur lors de l\'approbation de la session',
|
||||||
|
finishingSession: 'Erreur lors de la fin de la session',
|
||||||
|
emptyComment: 'Veuillez saisir votre commentaire',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Notifica',
|
notifications: 'Notifica',
|
||||||
support: 'Assistenza e supporto',
|
support: 'Assistenza e supporto',
|
||||||
information: 'Informazioni legali',
|
information: 'Informazioni legali',
|
||||||
settings: 'Impostazioni profilo',
|
settings: 'Impostazioni account',
|
||||||
messages: 'Messaggi',
|
messages: 'Messaggi',
|
||||||
'work-with-us': 'Lavora con noi'
|
'expert-profile': 'Profilo dell\'esperto'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Inizia a crescere con BB',
|
'bb-client': 'Inizia a crescere con BB',
|
||||||
'bb-expert': 'Diventa esperto BB',
|
'bb-expert': 'Diventa esperto BB',
|
||||||
|
home: 'Home',
|
||||||
blog: 'Blog&Notizie'
|
blog: 'Blog&Notizie'
|
||||||
},
|
},
|
||||||
registration: 'Registrazione',
|
registration: 'Registrazione',
|
||||||
enter: 'Inserisci',
|
enter: 'Inserisci',
|
||||||
|
enterAccount: 'Inserisci account',
|
||||||
account: 'Il mio account',
|
account: 'Il mio account',
|
||||||
logout: 'Disconnetti',
|
logout: 'Disconnetti',
|
||||||
|
decline: 'Rifiuta',
|
||||||
|
send: 'Invia',
|
||||||
deleteAcc: 'Elimina account',
|
deleteAcc: 'Elimina account',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'Domande frequenti',
|
faq: 'Domande frequenti',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Prossime sessioni',
|
upcoming: 'Prossime sessioni',
|
||||||
requested: 'Sessioni richieste',
|
requested: 'Sessioni richieste',
|
||||||
recent: 'Sessioni recenti'
|
recent: 'Sessioni recenti',
|
||||||
|
cancelReason: 'Inserisci un motivo per l\'annullamento della sessione',
|
||||||
|
reasonPlaceholder: 'Descrivi il motivo del rifiuto',
|
||||||
|
decline: 'Rifiuta sessione',
|
||||||
|
confirm: 'Conferma sessione',
|
||||||
|
join: 'Partecipa alla sessione',
|
||||||
|
start: 'Avvia sessione',
|
||||||
|
finish: 'Termina sessione',
|
||||||
|
comments: 'Commenti',
|
||||||
|
myComments: 'I miei commenti',
|
||||||
|
addComment: 'Aggiungi nuovo commento',
|
||||||
|
commentPlaceholder: 'Il tuo commento',
|
||||||
|
clientComments: 'Commenti del cliente',
|
||||||
|
coachComments: 'Commenti dell\'allenatore'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Prossime sale',
|
||||||
|
requested: 'Sale richieste',
|
||||||
|
recent: 'Sale recenti',
|
||||||
|
newRoom: 'Nuova sala'
|
||||||
|
},
|
||||||
|
agreementText: 'Ho letto e accetto i termini dell\'Accordo con l\'utente,',
|
||||||
|
userAgreement: '',
|
||||||
|
privacyPolicy: 'Informativa sulla privacy',
|
||||||
|
readMore: 'Leggi di più',
|
||||||
photoDesc: 'Aggiungi una foto vera: il volto di una persona è sempre più credibile.',
|
photoDesc: 'Aggiungi una foto vera: il volto di una persona è sempre più credibile.',
|
||||||
dayStart: 'Inizio del giorno',
|
dayStart: 'Inizio del giorno',
|
||||||
topic: 'Argomento',
|
topic: 'Argomento',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Vecchia password',
|
oldPass: 'Vecchia password',
|
||||||
newPass: 'Nuova password',
|
newPass: 'Nuova password',
|
||||||
confirmPass: 'Conferma password',
|
confirmPass: 'Conferma password',
|
||||||
|
forgotPass: 'Hai dimenticato la password',
|
||||||
|
resetPassText: 'Un link per reimpostare la password è stato inviato al tuo indirizzo e-mail',
|
||||||
|
or: 'o',
|
||||||
|
facebook: 'Account Facebook',
|
||||||
|
apple: 'Account Apple',
|
||||||
|
google: 'Account Google',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Inserisci i tuoi dati personali per iniziare il tuo viaggio come esperto BBuddy',
|
insertInfo: 'Inserisci i tuoi dati personali per iniziare il tuo viaggio come esperto BBuddy',
|
||||||
changeUserData: 'I tuoi dati possono essere aggiunti o modificati in qualsiasi momento',
|
changeUserData: 'I tuoi dati possono essere aggiunti o modificati in qualsiasi momento',
|
||||||
|
@ -49,11 +82,46 @@ export default {
|
||||||
sortPriceDesc: 'Per prezzo decrescente',
|
sortPriceDesc: 'Per prezzo decrescente',
|
||||||
details: 'Dettagli',
|
details: 'Dettagli',
|
||||||
sessionLang: 'Lingua sessione',
|
sessionLang: 'Lingua sessione',
|
||||||
|
direction: 'Direzione',
|
||||||
fromTo: 'da $ a $',
|
fromTo: 'da $ a $',
|
||||||
apply: 'Applica',
|
apply: 'Applica',
|
||||||
save: 'Salva',
|
save: 'Salva',
|
||||||
|
edit: 'Modifica',
|
||||||
changePass: 'Cambia password',
|
changePass: 'Cambia password',
|
||||||
|
resetPass: 'Reimposta password',
|
||||||
getStarted: 'Inizia',
|
getStarted: 'Inizia',
|
||||||
delete: 'Elimina',
|
delete: 'Elimina',
|
||||||
today: 'Oggi'
|
today: 'Oggi',
|
||||||
|
back: 'Indietro',
|
||||||
|
backToExperts: 'Torna all\'elenco degli esperti',
|
||||||
|
courseInfo: 'Informazioni sul corso',
|
||||||
|
expertBackground: 'Background esperto',
|
||||||
|
profCertification: 'Certificazione professionale',
|
||||||
|
practiceHours: 'Ore di pratica',
|
||||||
|
supervisionCount: 'Supervisioni per anno',
|
||||||
|
outOf: 'su',
|
||||||
|
schedule: 'Programma',
|
||||||
|
successfulCase: 'Casi di successo dalla pratica',
|
||||||
|
signUp: 'Iscriviti ora',
|
||||||
|
noData: 'Nessun dato',
|
||||||
|
notFound: 'Non trovato',
|
||||||
|
trainings: 'Training',
|
||||||
|
seminars: 'Seminari',
|
||||||
|
courses: 'Corsi',
|
||||||
|
mba: 'Info sull\'MBA',
|
||||||
|
aboutCoach: 'Informazioni sul coach',
|
||||||
|
education: 'Istruzione',
|
||||||
|
coaching: 'Coaching',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'L\'indirizzo e-mail non è valido',
|
||||||
|
emptyEmail: 'Inserisci l\'e-mail',
|
||||||
|
emptyPass: 'Inserisci la password',
|
||||||
|
confirmPass: 'Conferma la password',
|
||||||
|
notMatchPass: 'Le nuove password inserite non corrispondono',
|
||||||
|
emptyCancelReason: 'Inserisci il motivo',
|
||||||
|
approvingSession: 'Errore nell\'approvazione della sessione',
|
||||||
|
finishingSession: 'Errore durante la chiusura della sessione',
|
||||||
|
emptyComment: 'Inserisci il tuo commento',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,23 @@ export default {
|
||||||
notifications: 'Уведомления',
|
notifications: 'Уведомления',
|
||||||
support: 'Служба поддержки',
|
support: 'Служба поддержки',
|
||||||
information: 'Юридическая информация',
|
information: 'Юридическая информация',
|
||||||
settings: 'Настройки профиля',
|
settings: 'Настройки учетной записи',
|
||||||
messages: 'Сообщения',
|
messages: 'Сообщения',
|
||||||
'work-with-us': 'Сотрудничество'
|
'expert-profile': 'Профиль эксперта'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
'bb-client': 'Начните свой рост с BB',
|
'bb-client': 'Начните свой рост с BB',
|
||||||
'bb-expert': 'Станьте экспертом BB',
|
'bb-expert': 'Станьте экспертом BB',
|
||||||
|
home: 'Главная',
|
||||||
blog: 'Блог и новости'
|
blog: 'Блог и новости'
|
||||||
},
|
},
|
||||||
registration: 'Регистрация',
|
registration: 'Регистрация',
|
||||||
enter: 'Войти',
|
enter: 'Войти',
|
||||||
|
enterAccount: 'Войти в аккаунт',
|
||||||
account: 'Учетная запись',
|
account: 'Учетная запись',
|
||||||
logout: 'Выйти',
|
logout: 'Выйти',
|
||||||
|
decline: 'Отклонить',
|
||||||
|
send: 'Отправить',
|
||||||
deleteAcc: 'Удалить учетную запись',
|
deleteAcc: 'Удалить учетную запись',
|
||||||
footer: {
|
footer: {
|
||||||
faq: 'Частые вопросы',
|
faq: 'Частые вопросы',
|
||||||
|
@ -25,8 +29,31 @@ export default {
|
||||||
session: {
|
session: {
|
||||||
upcoming: 'Предстоящие сессии',
|
upcoming: 'Предстоящие сессии',
|
||||||
requested: 'Запрошенные сессии',
|
requested: 'Запрошенные сессии',
|
||||||
recent: 'Недавние сессии'
|
recent: 'Недавние сессии',
|
||||||
|
cancelReason: 'Введите причину отмены сессии',
|
||||||
|
reasonPlaceholder: 'Опишите причину отказа',
|
||||||
|
decline: 'Отклонить сессию',
|
||||||
|
confirm: 'Подтвердить сессию',
|
||||||
|
join: 'Присоединиться к сессии',
|
||||||
|
start: 'Начать сессию',
|
||||||
|
finish: 'Завершить сессию',
|
||||||
|
comments: 'Комментарии',
|
||||||
|
myComments: 'Мои комментарии',
|
||||||
|
addComment: 'Добавить новый',
|
||||||
|
commentPlaceholder: 'Ваш комментарий',
|
||||||
|
clientComments: 'Комментарии клиента',
|
||||||
|
coachComments: 'Комментарии коуча'
|
||||||
},
|
},
|
||||||
|
room: {
|
||||||
|
upcoming: 'Предстоящие комнаты',
|
||||||
|
requested: 'Запрошенные комнаты',
|
||||||
|
recent: 'Недавние комнаты',
|
||||||
|
newRoom: 'Новая комната'
|
||||||
|
},
|
||||||
|
agreementText: 'Я прочитал и согласен с условиями Пользовательского соглашения,',
|
||||||
|
userAgreement: 'Пользовательского соглашения',
|
||||||
|
privacyPolicy: 'Политикой конфиденциальности',
|
||||||
|
readMore: 'Читать дальше',
|
||||||
photoDesc: 'Добавьте реальную фотографию, ведь лицо человека всегда вызывает больше доверия.',
|
photoDesc: 'Добавьте реальную фотографию, ведь лицо человека всегда вызывает больше доверия.',
|
||||||
dayStart: 'День начала',
|
dayStart: 'День начала',
|
||||||
topic: 'Тема',
|
topic: 'Тема',
|
||||||
|
@ -37,6 +64,12 @@ export default {
|
||||||
oldPass: 'Старый пароль',
|
oldPass: 'Старый пароль',
|
||||||
newPass: 'Новый пароль',
|
newPass: 'Новый пароль',
|
||||||
confirmPass: 'Подтвердите пароль',
|
confirmPass: 'Подтвердите пароль',
|
||||||
|
forgotPass: 'Забыли пароль',
|
||||||
|
resetPassText: 'Ссылка для сброса пароля была отправлена на ваш E-mail',
|
||||||
|
or: 'или',
|
||||||
|
facebook: 'Аккаунт Facebook',
|
||||||
|
apple: 'Аккаунт Apple',
|
||||||
|
google: 'Аккаунт Google',
|
||||||
becomeExpert: '',
|
becomeExpert: '',
|
||||||
insertInfo: 'Введите личные данные и начните свой путь эксперта BBuddy',
|
insertInfo: 'Введите личные данные и начните свой путь эксперта BBuddy',
|
||||||
changeUserData: 'Добавить и изменить информацию о себе можно в любое время',
|
changeUserData: 'Добавить и изменить информацию о себе можно в любое время',
|
||||||
|
@ -49,11 +82,46 @@ export default {
|
||||||
sortPriceDesc: 'Цена по убыванию',
|
sortPriceDesc: 'Цена по убыванию',
|
||||||
details: 'Информация',
|
details: 'Информация',
|
||||||
sessionLang: 'Язык сессии',
|
sessionLang: 'Язык сессии',
|
||||||
|
direction: 'Направление',
|
||||||
fromTo: 'от $ до $',
|
fromTo: 'от $ до $',
|
||||||
apply: 'Применить',
|
apply: 'Применить',
|
||||||
save: 'Сохранить',
|
save: 'Сохранить',
|
||||||
|
edit: 'Редактировать',
|
||||||
changePass: 'Изменить пароль',
|
changePass: 'Изменить пароль',
|
||||||
|
resetPass: 'Сбросить пароль',
|
||||||
getStarted: 'Начать работу',
|
getStarted: 'Начать работу',
|
||||||
delete: 'Удалить',
|
delete: 'Удалить',
|
||||||
today: 'Сегодня'
|
today: 'Сегодня',
|
||||||
|
back: 'Назад',
|
||||||
|
backToExperts: 'Вернуться к списку экспертов',
|
||||||
|
courseInfo: 'Информация о курсе',
|
||||||
|
expertBackground: 'Профессиональный опыт эксперта',
|
||||||
|
profCertification: 'Профессиональная сертификация',
|
||||||
|
practiceHours: 'Часов практики',
|
||||||
|
supervisionCount: 'Часов супервизии в год',
|
||||||
|
outOf: 'из',
|
||||||
|
schedule: 'Расписание',
|
||||||
|
successfulCase: 'Успешные случаи из практики',
|
||||||
|
signUp: 'Записаться сейчас',
|
||||||
|
noData: 'Нет данных',
|
||||||
|
notFound: 'Не найдено',
|
||||||
|
trainings: 'Тренинги',
|
||||||
|
seminars: 'Семинары',
|
||||||
|
courses: 'Курсы',
|
||||||
|
mba: 'Информация о MBA',
|
||||||
|
aboutCoach: 'О коуче',
|
||||||
|
education: 'Образование',
|
||||||
|
coaching: 'Коучинг',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
invalidEmail: 'Адрес электронной почты недействителен',
|
||||||
|
emptyEmail: 'Пожалуйста, введите ваш E-mail',
|
||||||
|
emptyPass: 'Пожалуйста, введите ваш пароль',
|
||||||
|
confirmPass: 'Пожалуйста, подтвердите ваш пароль',
|
||||||
|
notMatchPass: 'Введенные новые пароли не совпадают',
|
||||||
|
emptyCancelReason: 'Пожалуйста, введите причину',
|
||||||
|
approvingSession: 'Ошибка при подтверждении сессии',
|
||||||
|
finishingSession: 'Ошибка при завершении сессии',
|
||||||
|
emptyComment: 'Пожалуйста, введите ваш комментарий',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,10 @@ export const onSuccessRequestCallback = (config: InternalAxiosRequestConfig) =>
|
||||||
// if (IS_DEV && !newConfig.headers.Authorization && getAuthToken()) {
|
// if (IS_DEV && !newConfig.headers.Authorization && getAuthToken()) {
|
||||||
// newConfig.headers.Authorization = `Bearer ${getAuthToken()}`;
|
// newConfig.headers.Authorization = `Bearer ${getAuthToken()}`;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
if (!newConfig.headers['Content-Type']) {
|
||||||
newConfig.headers['Content-Type'] = 'application/json';
|
newConfig.headers['Content-Type'] = 'application/json';
|
||||||
|
}
|
||||||
|
|
||||||
return newConfig;
|
return newConfig;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,21 @@ body{
|
||||||
--font: var(--font-comfortaa), -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
--font: var(--font-comfortaa), -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
font-family: var(--font);
|
font-family: var(--font);
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
& * {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: #C4DFE6;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #2C7873;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*::selection {
|
*::selection {
|
||||||
|
@ -70,11 +85,11 @@ a {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
@include rem(30);
|
@include rem(28);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@include rem(42);
|
@include rem(40);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +324,14 @@ a {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-h4 {
|
||||||
|
color: #003B46;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.title-h3 {
|
.title-h3 {
|
||||||
color: #003B46;
|
color: #003B46;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
@ -561,6 +584,10 @@ a {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 160%;
|
line-height: 160%;
|
||||||
|
|
||||||
|
&__auto {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-video {
|
.btn-video {
|
||||||
|
@ -762,6 +789,8 @@ a {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-bottom: 42px;
|
||||||
|
top: 24px;
|
||||||
|
|
||||||
&__avatar {
|
&__avatar {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
|
@ -815,8 +844,8 @@ a {
|
||||||
color: $white;
|
color: $white;
|
||||||
@include rem(13);
|
@include rem(13);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 300;
|
||||||
line-height: 123.077%;
|
line-height: 120%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
@ -831,6 +860,7 @@ a {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -853,7 +883,7 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
padding: 38px 24px 38px 24px;
|
padding: 24px;
|
||||||
flex-flow: nowrap;
|
flex-flow: nowrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
|
@ -861,7 +891,7 @@ a {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
height: 220px;
|
height: 220px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 24px;
|
top: -18px;
|
||||||
left: 24px;
|
left: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,7 +933,7 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
&__info {
|
&__info {
|
||||||
@include rem(18);
|
@include rem(15);
|
||||||
flex-flow: nowrap;
|
flex-flow: nowrap;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
i {
|
i {
|
||||||
|
@ -922,6 +952,17 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expert-info {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 24px;
|
||||||
|
|
||||||
|
.skills__list {
|
||||||
|
align-self: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.base-text {
|
.base-text {
|
||||||
color: #66A5AD;
|
color: #66A5AD;
|
||||||
@include rem(13);
|
@include rem(13);
|
||||||
|
@ -964,7 +1005,7 @@ a {
|
||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
|
|
||||||
.breadcrumb-item {
|
.breadcrumb-item {
|
||||||
color: #6FB98F;
|
color: #003B46;
|
||||||
@include rem(18);
|
@include rem(18);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
@ -985,14 +1026,6 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.breadcrumb-item {
|
|
||||||
@include rem(24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-fieldset {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.ant-form-item {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
&.base-input {
|
&.base-input {
|
||||||
height: 54px;
|
height: 54px;
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
max-height: 570px;
|
max-height: 570px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
.b-main-desc {
|
||||||
|
min-height: 440px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
max-height: 600px;
|
max-height: 600px;
|
||||||
}
|
}
|
||||||
|
@ -110,16 +118,12 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
position: relative;
|
||||||
@media (min-width: 768px) {
|
z-index: 1;
|
||||||
padding-top: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
max-width: 690px;
|
max-width: 690px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-top: 70px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +152,11 @@
|
||||||
line-height: 133.333%;
|
line-height: 133.333%;
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
@include rem(16);
|
@include rem(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@include rem(24);
|
@include rem(18);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1249px) {
|
@media (max-width: 1249px) {
|
||||||
|
@ -166,13 +170,14 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-bottom: 24px;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
|
@ -321,16 +326,17 @@
|
||||||
.main-articles {
|
.main-articles {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #DFF5FB;
|
background: #DFF5FB;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 94px;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-image: url(/images/wave-top.svg);
|
background-image: url(/images/wave-top.svg);
|
||||||
background-position: center;
|
background-position: center;
|
||||||
height: 86px;
|
height: 80px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: -86px;
|
top: -80px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-size: 893px 87px;
|
background-size: 893px 87px;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,55 @@
|
||||||
padding: 44px 40px;
|
padding: 44px 40px;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__expert {
|
||||||
|
&__title {
|
||||||
|
color: #003B46;
|
||||||
|
@include rem(20);
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 133.333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__inner {
|
||||||
|
height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-right: 20px;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
.title-h4 {
|
||||||
|
color: #003B46;
|
||||||
|
@include rem(16);
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 150%;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-modal-mask {
|
.ant-modal-mask {
|
||||||
|
|
|
@ -7,12 +7,8 @@
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expert-card {
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-h2 {
|
.title-h2 {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
padding-top: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-h3 {
|
.title-h3 {
|
||||||
|
@ -29,6 +25,9 @@
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
border-bottom: 1px solid #C4DFE6;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
&__text {
|
&__text {
|
||||||
color: #6FB98F;
|
color: #6FB98F;
|
||||||
|
@ -80,14 +79,6 @@
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-h2 {
|
|
||||||
padding-top: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expert-card {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-list {
|
.offers-list {
|
||||||
margin-bottom: 72px;
|
margin-bottom: 72px;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +86,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.b-news {
|
.b-news {
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: 24px;
|
padding-top: 24px;
|
||||||
|
@ -749,6 +739,11 @@
|
||||||
&__item {
|
&__item {
|
||||||
border-bottom: 1px solid #C4DFE6;
|
border-bottom: 1px solid #C4DFE6;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 8px 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
padding: 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
@ -783,13 +778,11 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 49px;
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
color: #003B46 !important;
|
@include rem(15);
|
||||||
@include rem(18);
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 133.333%;
|
line-height: 160%;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding-right: 32px;
|
padding-right: 32px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -809,7 +802,7 @@
|
||||||
|
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: #66A5AD !important;
|
color: #003B46 !important;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -831,16 +824,16 @@
|
||||||
|
|
||||||
&__item {
|
&__item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 48px;
|
height: 40px;
|
||||||
padding-bottom: 16px;
|
padding: 8px 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: #66A5AD;
|
color: #66A5AD;
|
||||||
@include rem(24);
|
@include rem(18);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 500;
|
||||||
line-height: 133.333%;
|
line-height: 133.333%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: calc(33.33333333% - 8px);
|
width: calc(33.33333333% - 8px);
|
||||||
|
@ -865,12 +858,12 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 8px;
|
height: 4px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: #6FB98F;
|
color: #2C7873;
|
||||||
&:before{
|
&:before{
|
||||||
background: #2C7873;
|
background: #2C7873;
|
||||||
}
|
}
|
||||||
|
@ -1113,6 +1106,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.b-work {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
color: #2C7873;
|
||||||
|
@include rem(16);
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-apply {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.image-info {
|
.image-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -1122,15 +1140,13 @@
|
||||||
height: 146px;
|
height: 146px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.coaching-info {
|
.coaching-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 24px;
|
gap: 16px;
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.card-profile {
|
.card-profile {
|
||||||
border: none !important;
|
border: none !important;
|
||||||
|
@ -1154,9 +1170,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
flex-flow: nowrap;
|
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
&__wrap-btn {
|
&__wrap-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
@ -1165,8 +1178,66 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.coaching-profile {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
&__portrait {
|
||||||
|
width: 86px;
|
||||||
|
height: 86px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 2px solid #FFF;
|
||||||
|
background: lightgray 50%;
|
||||||
|
box-shadow: 0 8px 16px 0 rgba(102, 165, 173, 0.32);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__inner {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
color: #003B46;
|
||||||
|
@include rem(18);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 150%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.coaching-section {
|
.coaching-section {
|
||||||
margin-bottom: 24px;
|
&__wrap {
|
||||||
|
border-top: 1px solid #C4DFE6;
|
||||||
|
padding-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
.b-button__link {
|
||||||
|
height: 24px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-h2 {
|
||||||
|
color: #003B46;
|
||||||
|
@include rem(18);
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.base-text {
|
.base-text {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
|
@ -6,6 +6,17 @@
|
||||||
height: 54px !important;
|
height: 54px !important;
|
||||||
box-shadow: 0px 2px 4px 0px rgba(102, 165, 173, 0.32) !important;
|
box-shadow: 0px 2px 4px 0px rgba(102, 165, 173, 0.32) !important;
|
||||||
|
|
||||||
|
&_yellow {
|
||||||
|
background: #FFBD00 !important;
|
||||||
|
border-color: #FFBD00 !important;
|
||||||
|
color: #003B46 !important;
|
||||||
|
font-size: 15px !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
height: 54px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
padding: 4px 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.danger {
|
&.danger {
|
||||||
background: #D93E5C !important;
|
background: #D93E5C !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
@ -30,6 +41,11 @@
|
||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
height: 54px !important;
|
height: 54px !important;
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
border-color: #D93E5C !important;
|
||||||
|
color: #D93E5C !important;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
margin-inline-end: 0 !important;
|
margin-inline-end: 0 !important;
|
||||||
line-height: 15px !important;
|
line-height: 15px !important;
|
||||||
|
@ -38,12 +54,12 @@
|
||||||
|
|
||||||
&__logout {
|
&__logout {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 49px !important;
|
height: 24px !important;
|
||||||
color: #D93E5C !important;
|
color: #D93E5C !important;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600 !important;
|
font-weight: 600 !important;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
font-size: 1.125rem !important;
|
font-size: 15px !important;
|
||||||
justify-content: flex-start !important;
|
justify-content: flex-start !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
|
|
||||||
&:focus, &:hover {
|
&:focus, &:hover {
|
||||||
&::after {
|
&::after {
|
||||||
box-shadow: 0 0 0 12px rgba(102, 165, 173, .2) !important;
|
outline: none !important;
|
||||||
|
box-shadow: 0 0 0 8px rgba(102, 165, 173, .2) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { ExpertDocument } from './file';
|
||||||
|
|
||||||
|
export type Details = {
|
||||||
|
id: number;
|
||||||
|
userId?:number;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
document?: ExpertDocument;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Certificate = {
|
||||||
|
id: number;
|
||||||
|
userId?: number;
|
||||||
|
associationLevelId?: number;
|
||||||
|
document?: ExpertDocument;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Experience = {
|
||||||
|
id: number,
|
||||||
|
userId?: number,
|
||||||
|
title?: string,
|
||||||
|
description?: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Association = {
|
||||||
|
id: number;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AssociationLevel = Association & { associationId?: number };
|
||||||
|
|
||||||
|
export type EducationData = {
|
||||||
|
certificates?: Certificate[],
|
||||||
|
educations?: Details[],
|
||||||
|
trainings?: Details[],
|
||||||
|
mbas?: Details[],
|
||||||
|
experiences?: Experience[]
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface EducationDTO {
|
||||||
|
person2Data?: EducationData,
|
||||||
|
associations?: Association[],
|
||||||
|
associationLevels?: AssociationLevel[]
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import { Tag, ThemeGroups } from './tags';
|
import { Tag, ThemeGroups } from './tags';
|
||||||
|
import { Association, AssociationLevel, EducationData } from './education';
|
||||||
|
|
||||||
export type GeneralFilter = Filter & AdditionalFilter;
|
export type GeneralFilter = Filter & AdditionalFilter;
|
||||||
|
|
||||||
|
@ -19,34 +20,6 @@ export type AdditionalFilter = {
|
||||||
coachSort?: string;
|
coachSort?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type File = {
|
|
||||||
id: number;
|
|
||||||
fileType: string;
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ExpertDocument {
|
|
||||||
fileName: string;
|
|
||||||
original?: File;
|
|
||||||
preview?: File;
|
|
||||||
fullSize?: File;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Details = {
|
|
||||||
id: number;
|
|
||||||
userId?:number;
|
|
||||||
title?: string;
|
|
||||||
description?: string;
|
|
||||||
document?: ExpertDocument;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Certificate = {
|
|
||||||
id: number;
|
|
||||||
userId?: number;
|
|
||||||
associationLevelId?: number;
|
|
||||||
document?: ExpertDocument;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Practice = {
|
export type Practice = {
|
||||||
id: number;
|
id: number;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
@ -61,16 +34,6 @@ export type ThemeGroup = {
|
||||||
canDeleted?: boolean;
|
canDeleted?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Association = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AssociationLevel = {
|
|
||||||
id: number;
|
|
||||||
associationId: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ExpertItem {
|
export interface ExpertItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -98,14 +61,9 @@ export type ExpertsData = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExpertDetails = {
|
export type ExpertDetails = {
|
||||||
publicCoachDetails: ExpertItem & {
|
publicCoachDetails: ExpertItem & EducationData & {
|
||||||
practiceHours?: number;
|
practiceHours?: number;
|
||||||
supervisionPerYearId?: number;
|
supervisionPerYearId?: number;
|
||||||
educations?: Details[];
|
|
||||||
certificates?: Certificate[];
|
|
||||||
trainings?: Details[];
|
|
||||||
mbas?: Details[];
|
|
||||||
experiences?: Details[];
|
|
||||||
practiceCases?: Practice[];
|
practiceCases?: Practice[];
|
||||||
themesGroups?: ThemeGroup[];
|
themesGroups?: ThemeGroup[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
export type File = {
|
||||||
|
id: number;
|
||||||
|
fileType: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ExpertDocument {
|
||||||
|
fileName: string;
|
||||||
|
original?: File;
|
||||||
|
preview?: File;
|
||||||
|
fullSize?: File;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ExpertsThemesGroups } from './tags';
|
||||||
|
|
||||||
|
export type Supervision = {
|
||||||
|
id: number,
|
||||||
|
name: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PracticeCase = {
|
||||||
|
id: number,
|
||||||
|
userId?: number,
|
||||||
|
description?: string,
|
||||||
|
themesGroupIds?: number[]
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PracticeData = {
|
||||||
|
practiceHours?: number,
|
||||||
|
supervisionPerYearId?: number,
|
||||||
|
sessionDuration?: number,
|
||||||
|
sessionCost?: number,
|
||||||
|
practiceCases?: PracticeCase[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PracticeDTO {
|
||||||
|
person4Data: PracticeData & {
|
||||||
|
themesGroups?: ExpertsThemesGroups[],
|
||||||
|
supervisionPerYears?: Supervision[],
|
||||||
|
sessionCosts?: number[]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
export type Profile = {
|
import { UploadFile } from 'antd';
|
||||||
id: number;
|
import {EducationDTO} from "./education";
|
||||||
|
import {ExpertsTags} from "./tags";
|
||||||
|
import {PracticeDTO} from "./practice";
|
||||||
|
import {ScheduleDTO} from "./schedule";
|
||||||
|
|
||||||
|
export type ProfileData = {
|
||||||
username?: string;
|
username?: string;
|
||||||
surname?: string;
|
surname?: string;
|
||||||
fillProgress?: string;
|
fillProgress?: string;
|
||||||
|
@ -9,4 +14,35 @@ export type Profile = {
|
||||||
hasPassword?: boolean;
|
hasPassword?: boolean;
|
||||||
hasExternalLogin?: boolean;
|
hasExternalLogin?: boolean;
|
||||||
isTestMode?: boolean;
|
isTestMode?: boolean;
|
||||||
|
phone?: string;
|
||||||
|
languagesLinks?: { language: { id: number, code: string, nativeSpelling: string }, languageId: number }[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Profile = ProfileData & { id: number };
|
||||||
|
|
||||||
|
export type ProfileRequest = {
|
||||||
|
login?: string;
|
||||||
|
password?: string;
|
||||||
|
isPasswordKeepExisting?: boolean;
|
||||||
|
languagesLinks?: { languageId: number }[];
|
||||||
|
username?: string;
|
||||||
|
surname?: string;
|
||||||
|
faceImage?: UploadFile;
|
||||||
|
isFaceImageKeepExisting?: boolean;
|
||||||
|
phone?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PayInfo = {
|
||||||
|
beneficiaryName?: string,
|
||||||
|
iban?: string,
|
||||||
|
bicOrSwift?: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ExpertData {
|
||||||
|
person?: ProfileData,
|
||||||
|
education?: EducationDTO,
|
||||||
|
tags?: ExpertsTags,
|
||||||
|
practice?: PracticeDTO,
|
||||||
|
schedule?: ScheduleDTO,
|
||||||
|
payData?: { person6Data?: PayInfo },
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export type WorkingTime = {
|
||||||
|
startDayOfWeekUtc?: string,
|
||||||
|
startTimeUtc?: number,
|
||||||
|
endDayOfWeekUtc?: string,
|
||||||
|
endTimeUtc?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScheduleDTO {
|
||||||
|
workingTimes?: WorkingTime[]
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ export type Tag = {
|
||||||
name: string
|
name: string
|
||||||
couchCount?: number;
|
couchCount?: number;
|
||||||
group?: string | null;
|
group?: string | null;
|
||||||
|
isActive?: boolean,
|
||||||
|
isSelected?: boolean,
|
||||||
|
canDeleted?: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ThemeGroups = {
|
export type ThemeGroups = {
|
||||||
|
@ -27,3 +30,15 @@ export type Language = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Languages = Language[];
|
export type Languages = Language[];
|
||||||
|
|
||||||
|
export type ExpertsThemesGroups = {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
isActive?: boolean,
|
||||||
|
canDeleted?: boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ExpertsTags {
|
||||||
|
themesGroups?: ExpertsThemesGroups[],
|
||||||
|
themesTags?: Tag[]
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { message } from 'antd';
|
||||||
|
import type { UploadFile } from 'antd';
|
||||||
import { i18nText } from '../i18nKeys';
|
import { i18nText } from '../i18nKeys';
|
||||||
|
|
||||||
const ROUTES = ['sessions', 'notifications', 'support', 'information', 'settings', 'messages', 'work-with-us'];
|
const ROUTES = ['sessions', 'notifications', 'support', 'information', 'settings', 'messages', 'expert-profile'];
|
||||||
const COUNTS: Record<string, number> = {
|
const COUNTS: Record<string, number> = {
|
||||||
sessions: 12,
|
sessions: 12,
|
||||||
notifications: 5,
|
notifications: 5,
|
||||||
|
@ -12,3 +14,17 @@ export const getMenuConfig = (locale: string) => ROUTES.map((path) => ({
|
||||||
title: i18nText(`accountMenu.${path}`, locale),
|
title: i18nText(`accountMenu.${path}`, locale),
|
||||||
count: COUNTS[path] || undefined
|
count: COUNTS[path] || undefined
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const validateImage = (file: UploadFile, showMessage?: boolean): boolean => {
|
||||||
|
const isImage = file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif';
|
||||||
|
if (!isImage && showMessage) {
|
||||||
|
message.error('You can only upload JPG/PNG file');
|
||||||
|
}
|
||||||
|
|
||||||
|
const isLt5M = file.size / 1024 / 1024 <= 5;
|
||||||
|
if (!isLt5M && showMessage) {
|
||||||
|
message.error('Image must smaller than 5MB');
|
||||||
|
}
|
||||||
|
|
||||||
|
return isImage && isLt5M;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue