feat: add normal auth

This commit is contained in:
Сюткина Дарья Александровна (4047910) 2024-02-08 02:28:24 +04:00
parent 9f225294c7
commit bdd382042c
42 changed files with 1037 additions and 387 deletions

View File

@ -68,7 +68,6 @@
},
"Notifications": {
"title": "Notifications",
"read": "Read",
"delete": "Delete"
},
"Sessions": {

View File

@ -1,10 +1,22 @@
import { AxiosResponse } from 'axios';
import { apiClient } from '../lib/apiClient';
export const getAuth = (login: string, password: string, locale: string ): Promise<AxiosResponse<{ jwtToken: string }>> => (
export const getAuth = (locale: string, data: { login: string, password: string }): Promise<AxiosResponse<{ jwtToken: string }>> => (
apiClient.post(
'/auth/login',
{ login, password },
data,
{
headers: {
'X-User-Language': locale
}
}
)
);
export const getRegister = (locale: string): Promise<AxiosResponse<{ jwtToken: string }>> => (
apiClient.post(
'/auth/register',
{},
{
headers: {
'X-User-Language': locale

15
src/actions/profile.ts Normal file
View File

@ -0,0 +1,15 @@
import { AxiosResponse } from 'axios';
import { apiClient } from '../lib/apiClient';
export const setPersonData = (person: { login: string, password: string, role: string }, locale: string, jwt: string): Promise<AxiosResponse> => (
apiClient.post(
'/home/applyperson1',
{ ...person },
{
headers: {
'X-User-Language': locale,
Authorization: `Bearer ${jwt}`
}
}
)
);

View File

@ -34,7 +34,7 @@ export default function Information() {
mentors and/or consultants of our application and/or website as well as other users of our services
and suppliers.
</div>
<h3 className="title-h3">What Personal Date We Collect About You?</h3>
<h3 className="title-h3">What Personal Data We Collect About You?</h3>
<div className="base-text">
We may collect, use, store and transfer different kinds of personal data about you which we have grouped
together as follows:<br />

View File

@ -0,0 +1,61 @@
import React, { ReactNode } from 'react';
import { Metadata } from 'next';
import { useTranslations } from 'next-intl';
import { AccountMenu } from '../../../../components/Account';
type AccountInnerLayoutProps = {
children: ReactNode;
params: Record<string, string>;
};
export const metadata: Metadata = {
title: 'Bbuddy User Account'
};
export function generateStaticParams({
params: { locale },
}: { params: { locale: string } }) {
const result: { locale: string, userId: string }[] = [];
const users = [{ userId: '1' }, { userId: '2' }];
users.forEach(({ userId }) => {
result.push({ locale, userId });
});
return result;
}
const ROUTES = ['sessions', 'notifications', 'support', 'information', 'settings', 'messages', 'work-with-us'];
const COUNTS: Record<string, number> = {
sessions: 12,
notifications: 5,
messages: 113
};
export default function AccountInnerLayout({ children }: AccountInnerLayoutProps) {
const t = useTranslations('Account');
const getMenuConfig = () => ROUTES.map((path) => ({
path,
title: t(`menu.${path}`),
count: COUNTS[path] || undefined
}));
return (
<div className="page-account">
<div className="b-inner">
<div className="row">
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
<AccountMenu menu={getMenuConfig()} />
</div>
<div className="col-xl-9 col-lg-8 ">
<div className="page-account__inner">
{children}
</div>
</div>
</div>
</div>
</div>
);
};

View File

@ -1,28 +1,28 @@
import React from 'react';
import { useTranslations } from 'next-intl';
import { Link } from '../../../../../navigation';
import { Link } from '../../../../../../navigation';
export function generateStaticParams({
params: { locale, userId },
}: { params: { locale: string, userId: string } }) {
const result: { locale: string, userId: string, textId: string }[] = [];
params: { locale },
}: { params: { locale: string } }) {
const result: { locale: string, textId: string }[] = [];
const chats = [{ textId: '1' }, { textId: '2' }, { textId: '3' }];
chats.forEach(({ textId }) => {
result.push({ locale, userId, textId });
result.push({ locale, textId });
});
return result;
}
export default function Message({ params }: { params: { userId: string, textId: string } }) {
export default function Message({ params }: { params: { textId: string } }) {
const t = useTranslations('Account.Messages');
return (
<>
<ol className="breadcrumb">
<li className="breadcrumb-item">
<Link href={`/${params.userId}/messages` as any}>
<Link href={'/account/messages' as any}>
{t('title')}
</Link>
</li>

View File

@ -1,14 +1,15 @@
import React from 'react';
import React, { Suspense } from 'react';
import type { Metadata } from 'next';
import { useTranslations } from 'next-intl';
import { Link } from '../../../../navigation';
import { Link } from '../../../../../navigation';
import { CustomInput } from '../../../../../components/view';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Messages',
description: 'Bbuddy desc messages'
};
export default function Messages({ params }: { params: { userId: string } }) {
export default function Messages() {
const t = useTranslations('Account.Messages');
return (
@ -16,10 +17,13 @@ export default function Messages({ params }: { params: { userId: string } }) {
<ol className="breadcrumb">
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
</ol>
<Suspense>
<CustomInput placeholder="Name" />
</Suspense>
<div className="messages-session">
<Link
className="card-profile"
href={`/${params.userId}/messages/1` as any}
href={'1' as any}
>
<div className="card-profile__header">
<div className="card-profile__header__portrait">
@ -41,7 +45,7 @@ export default function Messages({ params }: { params: { userId: string } }) {
</Link>
<Link
className="card-profile"
href={`/${params.userId}/messages/2` as any}
href={'2' as any}
>
<div className="card-profile__header">
<div className="card-profile__header__portrait">
@ -60,7 +64,7 @@ export default function Messages({ params }: { params: { userId: string } }) {
</Link>
<Link
className="card-profile"
href={`/${params.userId}/messages/3` as any}
href={'3' as any}
>
<div className="card-profile__header">
<div className="card-profile__header__portrait">

View File

@ -23,7 +23,6 @@ export default function Notifications() {
</div>
<div className="b-notifications__date">25 may 2022</div>
<div className="b-notifications__inner">
<a href="#" className="b-notifications__read">{t('read')}</a>
<a href="#" className="b-notifications__delete">{t('delete')}</a>
</div>
</div>
@ -34,7 +33,6 @@ export default function Notifications() {
</div>
<div className="b-notifications__date">25 may 2022</div>
<div className="b-notifications__inner">
<a href="#" className="b-notifications__read">{t('read')}</a>
<a href="#" className="b-notifications__delete">{t('delete')}</a>
</div>
</div>
@ -45,7 +43,6 @@ export default function Notifications() {
</div>
<div className="b-notifications__date">25 may 2022</div>
<div className="b-notifications__inner">
<a href="#" className="b-notifications__read">{t('read')}</a>
<a href="#" className="b-notifications__delete">{t('delete')}</a>
</div>
</div>

View File

@ -0,0 +1,27 @@
import React, { Suspense } from 'react';
import type { Metadata } from 'next';
import { useTranslations } from 'next-intl';
import { SessionsTabs } from '../../../../../components/Account';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Sessions',
description: 'Bbuddy desc sessions'
};
export default function Sessions() {
const t = useTranslations('Account.Sessions');
return (
<Suspense fallback={<p>Loading...</p>}>
<SessionsTabs
intlConfig={{
upcoming: t('upcoming-sessions'),
requested: t('sessions-requested'),
recent: t('recent-sessions'),
selectTopicLabel: t('topic'),
dateLabel: t('day-start')
}}
/>
</Suspense>
);
}

View File

@ -1,6 +1,6 @@
import React from 'react';
import { useTranslations } from 'next-intl';
import { Link } from '../../../../../navigation';
import { Link } from '../../../../../../navigation';
export default function ChangePassword({ params }: { params: { userId: string } }) {
const t = useTranslations('Account.Settings');

View File

@ -1,7 +1,8 @@
import React from 'react';
import React, {Suspense} from 'react';
import type { Metadata } from 'next';
import { useTranslations } from 'next-intl';
import {Link} from "../../../../navigation";
import { Link } from '../../../../../navigation';
import { CustomInput } from '../../../../../components/view';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Profile Settings',
@ -25,19 +26,19 @@ export default function Settings({ params }: { params: { userId: string } }) {
<div className="user-avatar__text">{t('photo-desc')}</div>
</div>
<div className="form-field">
<input type="text" placeholder={t('name')} className="base-input" id="" value="" />
<CustomInput placeholder={t('name')} />
</div>
<div className="form-field">
<input type="text" placeholder={t('surname')} className="base-input" id="" value="" />
<CustomInput placeholder={t('surname')} />
</div>
<div className="form-field date">
<input className="base-input " type="text" placeholder={t('birthday')} id="" value="" />
<CustomInput placeholder={t('birthday')} />
</div>
<div className="form-field">
<input type="email" placeholder={t('email')} className="base-input" id="" value="" />
<CustomInput type="email" placeholder={t('email')} />
</div>
<div className="form-link">
<Link href={`/${params.userId}/settings/change-password` as any}>
<Link href={'change-password' as any}>
{t('change-password')}
</Link>
</div>

View File

@ -1,6 +1,6 @@
import React from 'react';
import type { Metadata } from 'next';
import {useTranslations} from "next-intl";
import { useTranslations } from 'next-intl';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Help & Support',

View File

@ -0,0 +1,94 @@
import React from 'react';
import { Link } from '../../../../../../../navigation';
import { CustomSelect } from '../../../../../../../components/view';
export default function AddOffer() {
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">
<Link href={'/account/work-with-us/coaching' as any}>
Coaching
</Link>
</li>
<li className="breadcrumb-item active" aria-current="page">Add Offer</li>
</ol>
<h2 className="title-h2">Select Topic</h2>
<form className="form-offer" action="">
<div className="form-field ">
<input type="text" placeholder="Search" className="base-input" id="" value="" />
</div>
<h3 className="title-h3">Life coaching</h3>
<div className="b-filter">
<div className="b-filter__inner">
<div className="b-filter__item">
<div className="b-filter__title">Work-life Balance</div>
<label className="base-switcher">
<input className="base-switcher__input" type="checkbox" />
<span className="base-switcher__line" />
<span className="base-switcher__circle" />
</label>
</div>
<div className="b-filter__item">
<div className="b-filter__title">Strategic Session</div>
<label className="base-switcher">
<input className="base-switcher__input" type="checkbox" />
<span className="base-switcher__line" />
<span className="base-switcher__circle" />
</label>
</div>
<div className="b-filter__item">
<div className="b-filter__title">Personal Growth
</div>
<label className="base-switcher">
<input className="base-switcher__input" type="checkbox" />
<span className="base-switcher__line" />
<span className="base-switcher__circle" />
</label>
</div>
<div className="b-filter__item">
<div className="b-filter__title">Executive Coaching</div>
<label className="base-switcher">
<input className="base-switcher__input" type="checkbox" />
<span className="base-switcher__line" />
<span className="base-switcher__circle" />
</label>
</div>
<div className="b-filter__item">
<div className="b-filter__title">Career Planning</div>
<label className="base-switcher">
<input className="base-switcher__input" type="checkbox" />
<span className="base-switcher__line" />
<span className="base-switcher__circle" />
</label>
</div>
</div>
</div>
<h3 className="title-h3">Business coaching</h3>
<h2 className="title-h2">Offer Details</h2>
<div className="form-field">
<CustomSelect label="Session Language" />
</div>
<div className="form-field">
<input type="text" placeholder="Title" className="base-input" id="" value="" />
</div>
<div className="form-field">
<textarea className="base-textarea" name="" id="" placeholder="Description" />
</div>
<div className="form-field">
<CustomSelect label="Session Duration" />
</div>
<div className="form-field">
<input className="base-input " type="text" placeholder="Session cost in euro" id="" value="" />
</div>
<button className="btn-apply">Save</button>
</form>
</>
);
}

View File

@ -0,0 +1,131 @@
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>
</>
);
}

View File

@ -0,0 +1,55 @@
import React from 'react';
import { Link } from '../../../../../../navigation';
import { CustomSelect } from '../../../../../../components/view';
export default function NewTopic() {
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">New Topic</li>
</ol>
<h2 className="title-h2">
Schedule
</h2>
<form action="">
<div className="schedule">
<div className="schedule__inner">
<div className="timezone">
<div className="timezone__title">Your timezone: +06:00</div>
<div className="timezone__utc">
<CustomSelect label="UTC" />
</div>
</div>
<h3 className="title-h3">Fill up your weekly schedule</h3>
<div className="">место для календаря на неделю...</div>
<h3 className="title-h3">Work time</h3>
<div className="schedule__wrap">
<CustomSelect label="Start at" />
<CustomSelect label="Finish at" />
<div className="btn-delete" />
</div>
<button className="btn-add">Add Working Hours</button>
</div>
<div className="separator" />
<div className="schedule__inner">
<h2 className="title-h2">Specialisation</h2>
<CustomSelect label="I'm best in" />
</div>
<div className="b-info">
<div className="image-info">
<img className="" src="/images/info.png" alt=""/>
</div>
<div className="b-info__title">
Select your specialisation to proceed
</div>
</div>
</div>
</form>
</>
);
}

View File

@ -1,6 +1,6 @@
import React from 'react';
import type { Metadata } from 'next';
import { useTranslations } from "next-intl";
import { useTranslations } from 'next-intl';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Work with us',

View File

@ -1,64 +1,18 @@
import React, { ReactNode } from 'react';
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { AccountMenu } from '../../../components/Account';
'use client';
type AccountLayoutProps = {
children: ReactNode;
params: Record<string, string>;
};
import { ReactNode, useEffect } from 'react';
import { redirect, notFound } from 'next/navigation';
import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AUTH_TOKEN_KEY } from '../../../constants/common';
export const metadata: Metadata = {
title: 'Bbuddy User Account'
};
export default function AccountLayout({ children }: { children: ReactNode }) {
const [token] = useLocalStorage(AUTH_TOKEN_KEY, '');
export function generateStaticParams({
params: { locale },
}: { params: { locale: string } }) {
const result: { locale: string, userId: string }[] = [];
const users = [{ userId: '1' }, { userId: '2' }];
users.forEach(({ userId }) => {
result.push({ locale, userId });
});
return result;
useEffect(() => {
if(!token){
notFound();
}
}, []);
const ROUTES = ['sessions', 'notifications', 'support', 'information', 'settings', 'messages', 'work-with-us'];
const COUNTS: Record<string, number> = {
sessions: 12,
notifications: 5,
messages: 113
};
export default function AccountLayout({ children, params }: AccountLayoutProps) {
if (!params?.userId || isNaN(Number(params?.userId))) notFound();
const t = useTranslations('Account');
const getMenuConfig = () => ROUTES.map((path) => ({
path,
title: t(`menu.${path}`),
count: COUNTS[path] || undefined
}));
return (
<div className="page-account">
<div className="b-inner">
<div className="row">
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
<AccountMenu userId={params.userId} menu={getMenuConfig()} />
</div>
<div className="col-xl-9 col-lg-8 ">
<div className="page-account__inner">
{children}
</div>
</div>
</div>
</div>
</div>
);
return children;
};

View File

@ -1,12 +1,12 @@
import { redirect, notFound } from 'next/navigation';
// import { checkAuthToken } from '../../../utils/storage/auth';
'use client';
export default function AccountMainPage() {
// if (checkAuthToken()) {
// redirect('/sessions');
// } else {
// notFound();
// }
import React from 'react';
import { redirect } from 'next/navigation';
import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AUTH_TOKEN_KEY } from '../../../constants/common';
redirect('/sessions');
export default function Account() {
const [token] = useLocalStorage(AUTH_TOKEN_KEY, '');
return token ? redirect('sessions') : null;
};

View File

@ -1,25 +0,0 @@
import React from 'react';
import type { Metadata } from 'next';
import { useTranslations } from 'next-intl';
import { SessionsTabs } from '../../../../components/Account';
export const metadata: Metadata = {
title: 'Bbuddy - Account - Sessions',
description: 'Bbuddy desc sessions'
};
export default function Sessions() {
const t = useTranslations('Account.Sessions');
return (
<SessionsTabs
intlConfig={{
upcoming: t('upcoming-sessions'),
requested: t('sessions-requested'),
recent: t('recent-sessions'),
selectTopicLabel: t('topic'),
dateLabel: t('day-start')
}}
/>
);
}

View File

@ -1,18 +1,39 @@
'use client';
import React from 'react';
import { useSelectedLayoutSegment } from 'next/navigation';
import styled from 'styled-components';
import { Button } from 'antd';
import { useSelectedLayoutSegment, usePathname } from 'next/navigation';
import { Link } from '../../navigation';
import { AUTH_TOKEN_KEY } from '../../constants/common';
import { deleteStorageKey } from '../../hooks/useLocalStorage';
export const AccountMenu = ({ userId, menu }: { userId: string, menu: { path: string, title: string, count?: number }[] }) => {
const Logout = styled(Button)`
width: 100%;
height: 49px !important;
color: #D93E5C !important;
font-style: normal;
font-weight: 600 !important;
padding: 0 !important;
font-size: 1.125rem !important;
text-align: left !important;
`;
export const AccountMenu = ({ menu }: { menu: { path: string, title: string, count?: number }[] }) => {
const selectedLayoutSegment = useSelectedLayoutSegment();
const pathname = selectedLayoutSegment || '';
const paths = usePathname();
const onLogout = () => {
deleteStorageKey(AUTH_TOKEN_KEY);
window?.location?.replace(`/${paths.split('/')[1]}/`);
};
return (
<ul className="list-sidebar">
{menu.map(({ path, title, count }) => (
<li key={path} className="list-sidebar__item">
<Link href={`/${userId}/${path}` as any} className={path === pathname ? 'active' : ''}>
<Link href={`/account/${path}` as any} className={path === pathname ? 'active' : ''}>
{title}
{count ? (
<span className="count">{count}</span>
@ -21,7 +42,12 @@ export const AccountMenu = ({ userId, menu }: { userId: string, menu: { path: st
</li>
))}
<li className="list-sidebar__item">
<a href="#" className="">Log Out</a>
<Logout
type="link"
onClick={onLogout}
>
Log Out
</Logout>
</li>
</ul>
)

View File

@ -1,19 +1,35 @@
'use client';
import React from 'react';
import { Tabs } from 'antd';
import React, { useCallback, useState } from 'react';
import styled from 'styled-components';
import { CustomSelect } from '../view';
const Tab = styled.div``;
export const SessionsTabs = ({ intlConfig }: { intlConfig: Record<string, string> }) => {
const [activeTab, setActiveTab] = useState<number>(0);
const [sort, setSort] = useState<string>();
const onChangeSort = useCallback((value: string) => {
setSort(value);
}, [sort]);
const getChildren = () => (
<>
<div className="filter-session">
<div className="filter-session__item filter-session__item--type">
<select name="" id="">
<option value="">1</option>
<option value="">2</option>
</select>
<div className="filter-session__item">
<CustomSelect
label="Topic"
value={sort}
onChange={onChangeSort}
options={[
{ value: 'topic1', label: 'Topic 1' },
{ value: 'topic2', label: 'Topic 2' },
{ value: 'topic3', label: 'Topic 3' },
{ value: 'topic4', label: 'Topic 4' }
]}
/>
</div>
</div>
<div className="list-session">
<div className="card-profile">
@ -72,39 +88,48 @@ export const SessionsTabs = ({ intlConfig }: { intlConfig: Record<string, string
{
key: 'upcoming',
label: (
<div className="tabs-session__item active">
<>
{intlConfig?.upcoming || 'Tab 1'}
<span className="count">3</span>
</div>
</>
),
children: getChildren()
},
{
key: 'requested',
label: (
<div className="tabs-session__item">
<>
{intlConfig?.requested || 'Tab 2'}
<span className="count">2</span>
</div>
</>
),
children: getChildren()
},
{
key: 'recent',
label: (
<div className="tabs-session__item">
<>
{intlConfig?.recent || 'Tab 3'}
</div>
</>
),
children: getChildren()
}
];
return (
<Tabs
defaultActiveKey="upcoming"
items={tabs}
renderTabBar={(props, DefaultTabBar) => (<DefaultTabBar {...props} className="tabs-session" />)}
/>
<>
<div className="tabs-session">
{tabs.map((tab, index) => (
<Tab
key={index}
className={`tabs-session__item ${index === activeTab ? 'active' : ''}`}
onClick={() => setActiveTab(index)}
>
{tab.label}
</Tab>
))}
</div>
{tabs[activeTab].children}
</>
);
};

View File

@ -47,7 +47,7 @@ export const ExpertsList = ({
} else {
setExperts(data);
}
}, []);
}, [searchParams]);
return experts ? (
<>

View File

@ -2,11 +2,11 @@
import React, { useCallback, useState } from 'react';
import { Button, List } from 'antd';
import { useSearchParams } from 'next/navigation';
import { Filter } from '../../types/experts';
import { SearchData, Tag } from '../../types/tags';
import { useSearchParams, usePathname } from 'next/navigation';
import { useRouter } from '../../navigation';
import { getObjectByFilter, getObjectByAdditionalFilter } from '../../utils/filter';
import { Filter, GeneralFilter } from '../../types/experts';
import { SearchData, Tag } from '../../types/tags';
import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter';
import { CustomSwitch, CustomSlider } from '../view';
type ExpertsFilterProps = {
@ -26,6 +26,7 @@ export const ExpertsFilter = ({
}: ExpertsFilterProps) => {
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
const [filter, setFilter] = useState<Filter | undefined>(getObjectByFilter(searchParams));
const onChangeTags = useCallback((id: number, checked: boolean) => {
@ -82,6 +83,14 @@ export const ExpertsFilter = ({
}, [filter, searchParams, searchData]);
const goToFilterPage = useCallback(() => {
// const newFilter: GeneralFilter = {
// ...filter,
// ...getObjectByAdditionalFilter(searchParams)
// };
// const search = getSearchParamsString(newFilter);
//
// router.push(search ? `${pathname}?${search}` : pathname, { scroll: false });
router.push({
pathname: basePath as any,
query: {

View File

@ -1,21 +1,19 @@
'use client';
import React, { FC, useState } from 'react';
import React, { Dispatch, FC, SetStateAction, useEffect } from 'react';
import { usePathname } from 'next/navigation';
import Image from 'next/image';
import Link from 'next/link';
import {Button, Modal as AntdModal, Form, notification} from 'antd';
import { Modal as AntdModal, Form } from 'antd';
import { CloseOutlined } from '@ant-design/icons';
import { styled } from 'styled-components';
import { CustomInput, CustomInputPassword } from '../view';
import { getAuth } from '../../actions/auth';
import { setAuthToken } from '../../utils/storage/auth';
import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent';
type AuthModalProps = {
open: boolean;
handleCancel: () => void;
mode: 'enter' | 'register' | 'reset' | 'finish';
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
updateToken: string | Dispatch<SetStateAction<string | undefined>> | undefined;
};
const Modal = styled(AntdModal)`
@ -37,84 +35,37 @@ const Modal = styled(AntdModal)`
}
`;
const FilledButton = styled(Button)`
background: #66A5AD !important;
font-size: 15px !important;
border-radius: 8px !important;
height: 54px !important;
box-shadow: 0px 2px 4px 0px rgba(102, 165, 173, 0.32) !important;
`;
const OutlinedButton = styled(Button)`
display: inline-flex !important;
justify-content: center;
align-items: center;
gap: 16px;
border-color: #66A5AD !important;
color: #66A5AD !important;
font-size: 15px !important;
border-radius: 8px !important;
height: 54px !important;
span {
margin-inline-end: 0 !important;
line-height: 15px !important;
}
`;
const LinkButton = styled(Button)`
color: #66A5AD !important;
font-size: 15px !important;
height: auto !important;
padding: 0 !important;
`;
export const AuthModal: FC<AuthModalProps> = ({
open,
handleCancel,
mode,
updateMode
updateMode,
updateToken
}) => {
const [form] = Form.useForm<{ login: string, password: string, confirmPassword: string }>();
const [isLoading, setIsLoading] = useState<boolean>(false);
const paths = usePathname().split('/');
const onAfterClose = () => {
form.resetFields();
};
const onSubmit = () => {
form.validateFields().then(() => {
const { login, password } = form.getFieldsValue();
setIsLoading(true);
getAuth(login, password, paths[1])
.then(({ data }) => {
if (data.jwtToken) {
setAuthToken(data.jwtToken);
handleCancel();
useEffect(() => {
if (form) {
form.resetFields();
}
})
.catch((error) => {
notification.error({
message: 'Error',
description: error?.response?.data?.errMessage
});
})
.finally(() => {
setIsLoading(false);
})
});
};
const onValidate = () => {
}, [mode]);
const onUpdateToken = (token: string) => {
if (updateToken && typeof updateToken !== 'string') {
updateToken(token);
}
};
return (
<Modal
open={open}
title={undefined}
onOk={onSubmit}
onOk={undefined}
onCancel={handleCancel}
afterClose={onAfterClose}
footer={false}
@ -126,124 +77,28 @@ export const AuthModal: FC<AuthModalProps> = ({
<img className="" src="/images/logo-auth.svg" alt=""/>
</div>
{mode === 'enter' && (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item name="login" rules={[{ required: true }]} noStyle>
<CustomInput
size="small"
placeholder="E-mail"
<EnterContent
form={form}
updateMode={updateMode}
locale={paths[1]}
handleCancel={handleCancel}
updateToken={onUpdateToken}
/>
</Form.Item>
<Form.Item name="password" rules={[{ required: true }]} noStyle>
<CustomInputPassword
size="small"
placeholder="Password"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
onClick={onSubmit}
loading={isLoading}
>
Enter
</FilledButton>
<OutlinedButton onClick={() => updateMode('register')}>Register</OutlinedButton>
<LinkButton
type="link"
onClick={() => updateMode('reset')}
>
Forgot password?
</LinkButton>
<span>or</span>
<OutlinedButton
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
>
Facebook account
</OutlinedButton>
<OutlinedButton
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
>
Apple account
</OutlinedButton>
<OutlinedButton
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
>
Google account
</OutlinedButton>
</>
)}
{mode === 'register' && (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item name="login" rules={[{ required: true }]} noStyle>
<CustomInput
size="small"
placeholder="E-mail"
<RegisterContent
form={form}
locale={paths[1]}
updateMode={updateMode}
updateToken={onUpdateToken}
handleCancel={handleCancel}
/>
</Form.Item>
<Form.Item name="password" rules={[{ required: true }]} noStyle>
<CustomInputPassword
size="small"
placeholder="Password"
/>
</Form.Item>
<Form.Item name="confirmPassword" rules={[{ required: true }]} noStyle>
<CustomInputPassword
size="small"
placeholder="Confirm password"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
>
Register
</FilledButton>
<OutlinedButton onClick={() => updateMode('enter')}>Enter</OutlinedButton>
</>
)}
{mode === 'reset' && (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item name="login" rules={[{ required: true }]} noStyle>
<CustomInput
size="small"
placeholder="E-mail"
/>
</Form.Item>
<Form.Item name="password" rules={[{ required: true }]} noStyle>
<CustomInputPassword
size="small"
placeholder="Password"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
>
Reset Password
</FilledButton>
<LinkButton
type="link"
>
Enter
</LinkButton>
</>
<ResetContent form={form} updateMode={updateMode} />
)}
{mode === 'finish' && (
<>
<div className="b-modal__auth__agreement">
A link to reset your password has been sent
<br />
to your email
</div>
<FilledButton
type="primary"
>
Enter Account
</FilledButton>
</>
<FinishContent />
)}
<div className="b-modal__auth__agreement">
I have read and agree with the terms of the

View File

@ -0,0 +1,116 @@
import React, { FC, useState } from 'react';
import { Form, FormInstance, notification } from 'antd';
import Image from 'next/image';
import { getAuth } from '../../../actions/auth';
import { CustomInput, CustomInputPassword, FilledButton, OutlinedButton, LinkButton } from '../../view';
type EnterProps = {
form: FormInstance;
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
locale: string;
handleCancel: () => void;
updateToken: (token: string) => void;
}
export const EnterContent: FC<EnterProps> = ({
form,
updateMode,
updateToken,
locale,
handleCancel
}) => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const onLogin = () => {
form.validateFields().then(() => {
const { login, password } = form.getFieldsValue();
setIsLoading(true);
getAuth(locale, { login, password })
.then(({ data }) => {
if (data.jwtToken) {
updateToken(data.jwtToken);
handleCancel();
}
})
.catch((error) => {
notification.error({
message: 'Error',
description: error?.response?.data?.errMessage
});
})
.finally(() => {
setIsLoading(false);
})
});
};
return (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item
name="login"
noStyle
rules={[
{
type: 'email',
message: 'The input is not valid E-mail'
},
{
required: true,
message: 'Please input your E-mail'
}
]}
>
<CustomInput
size="small"
placeholder="E-mail"
type="email"
/>
</Form.Item>
<Form.Item
name="password"
noStyle
rules={[{
required: true,
message: 'Please input your password'
}]}
>
<CustomInputPassword
size="small"
placeholder="Password"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
onClick={onLogin}
loading={isLoading}
>
Enter
</FilledButton>
<OutlinedButton onClick={() => updateMode('register')}>Register</OutlinedButton>
<LinkButton
type="link"
onClick={() => updateMode('reset')}
>
Forgot password?
</LinkButton>
<span>or</span>
<OutlinedButton
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
>
Facebook account
</OutlinedButton>
<OutlinedButton
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
>
Apple account
</OutlinedButton>
<OutlinedButton
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
>
Google account
</OutlinedButton>
</>
);
};

View File

@ -0,0 +1,17 @@
import React from 'react';
import { FilledButton } from '../../view';
export const FinishContent = () => (
<>
<div className="b-modal__auth__agreement">
A link to reset your password has been sent
<br />
to your email
</div>
<FilledButton
type="primary"
>
Enter Account
</FilledButton>
</>
);

View File

@ -0,0 +1,128 @@
import React, { FC, useState } from 'react';
import { Form, FormInstance, notification } from 'antd';
import { getRegister } from '../../../actions/auth';
import { setPersonData } from '../../../actions/profile';
import { CustomInput, CustomInputPassword, FilledButton, OutlinedButton } from '../../view';
type RegisterProps = {
form: FormInstance;
locale: string;
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
updateToken: (token: string) => void;
handleCancel: () => void;
};
export const RegisterContent: FC<RegisterProps> = ({
form,
updateMode,
locale,
updateToken,
handleCancel
}) => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const onRegister = () => {
form.validateFields().then(() => {
const { login, password } = form.getFieldsValue();
setIsLoading(true);
getRegister(locale)
.then(({ data }) => {
if (data.jwtToken) {
setPersonData( { login, password, role: 'client' }, locale, data.jwtToken)
.then(() => {
updateToken(data.jwtToken);
handleCancel();
})
.catch((error) => {
notification.error({
message: 'Error',
description: error?.response?.data?.errMessage
});
});
}
})
.catch((error) => {
notification.error({
message: 'Error',
description: error?.response?.data?.errMessage
});
})
.finally(() => {
setIsLoading(false);
})
});
};
return (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item
name="login"
noStyle
rules={[
{
type: 'email',
message: 'The input is not valid E-mail'
},
{
required: true,
message: 'Please input your E-mail'
}
]}
>
<CustomInput
size="small"
placeholder="E-mail"
type="email"
/>
</Form.Item>
<Form.Item
name="password"
noStyle
rules={[{
required: true,
message: 'Please input your password'
}]}
>
<CustomInputPassword
size="small"
placeholder="Password"
/>
</Form.Item>
<Form.Item
name="confirmPassword"
noStyle
dependencies={['password']}
hasFeedback
rules={[
{
required: true,
message: 'Please confirm your password',
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error('The new password that you entered do not match'));
},
}),
]}
>
<CustomInputPassword
size="small"
placeholder="Confirm password"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
onClick={onRegister}
loading={isLoading}
>
Register
</FilledButton>
<OutlinedButton onClick={() => updateMode('enter')}>Enter</OutlinedButton>
</>
);
};

View File

@ -0,0 +1,56 @@
import React, { FC } from 'react';
import { Form, FormInstance } from 'antd';
import { CustomInput, FilledButton, LinkButton } from '../../view';
type ResetProps = {
form: FormInstance;
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
}
export const ResetContent: FC<ResetProps> = ({
form,
updateMode
}) => {
const onResetPassword = () => {
console.log('reset');
};
return (
<>
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
<Form.Item
name="login"
noStyle
rules={[
{
type: 'email',
message: 'The input is not valid E-mail'
},
{
required: true,
message: 'Please input your E-mail'
}
]}
>
<CustomInput
size="small"
placeholder="E-mail"
type="email"
/>
</Form.Item>
</Form>
<FilledButton
type="primary"
onClick={onResetPassword}
>
Reset Password
</FilledButton>
<LinkButton
type="link"
onClick={() => updateMode('enter')}
>
Enter
</LinkButton>
</>
);
}

View File

@ -0,0 +1,4 @@
export * from './FinishContent';
export * from './ResetContent';
export * from './EnterContent';
export * from './RegisterContent'

View File

@ -4,9 +4,10 @@ import React, { FC, useState, useEffect } from 'react';
import { Button } from 'antd';
import { useSelectedLayoutSegment } from 'next/navigation';
import { styled } from 'styled-components';
import { AuthModal } from '../../Modals/AuthModal';
import { checkAuthToken } from '../../../utils/storage/auth';
import { Link } from '../../../navigation';
import { AUTH_TOKEN_KEY } from '../../../constants/common';
import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AuthModal } from '../../Modals/AuthModal';
type HeaderAuthLinksProps = {
enterTitle: string;
@ -35,6 +36,7 @@ export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
const [mode, setMode] = useState<'enter' | 'register' | 'reset' | 'finish'>('enter');
const selectedLayoutSegment = useSelectedLayoutSegment();
const pathname = selectedLayoutSegment || '';
const [token, setToken] = useLocalStorage(AUTH_TOKEN_KEY, '');
useEffect(() => {
if (!isOpenModal) {
@ -47,10 +49,10 @@ export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
setIsOpenModal(true);
};
return checkAuthToken()
return token
? (
<li>
<Link href={'/account' as any} className={pathname === 'account' ? 'active' : ''}>{accountTitle}</Link>
<Link href={'/account/sessions' as any} className={pathname === 'account' ? 'active' : ''}>{accountTitle}</Link>
</li>
)
: (
@ -79,6 +81,7 @@ export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
handleCancel={() => setIsOpenModal(false)}
mode={mode}
updateMode={setMode}
updateToken={setToken}
/>
</>
);

View File

@ -28,16 +28,12 @@ const Input = styled(AntdInput.Password)`
&.ant-input-status-error:not(.ant-input-disabled):not(.ant-input-borderless) {
border-color: #ff4d4f !important;
}
.ant-input-suffix {
opacity: .3;
}
`;
export const CustomInputPassword = (props: any) => (
<Input
iconRender={(visible) => (visible
? <EyeOutlined style={{ color: '#2C7873', fontSize: 20}} />
? <EyeOutlined style={{ color: '#2C7873', fontSize: 20, opacity: .3 }} />
: <EyeInvisibleOutlined style={{ color: '#2C7873', fontSize: 20 }} />
)}
{...props}

View File

@ -0,0 +1,17 @@
import React from 'react';
import { styled } from 'styled-components';
import { Button as AntdButton } from 'antd';
const Button = styled(AntdButton)`
background: #66A5AD !important;
font-size: 15px !important;
border-radius: 8px !important;
height: 54px !important;
box-shadow: 0px 2px 4px 0px rgba(102, 165, 173, 0.32) !important;
`;
export const FilledButton = (props: any) => (
<Button {...props}>
{props.children}
</Button>
);

View File

@ -0,0 +1,16 @@
import React from 'react';
import { styled } from 'styled-components';
import { Button as AntdButton } from 'antd';
const Button = styled(AntdButton)`
color: #66A5AD !important;
font-size: 15px !important;
height: auto !important;
padding: 0 !important;
`;
export const LinkButton = (props: any) => (
<Button {...props}>
{props.children}
</Button>
);

View File

@ -0,0 +1,26 @@
import React from 'react';
import { styled } from 'styled-components';
import { Button as AntdButton } from 'antd';
const Button = styled(AntdButton)`
display: inline-flex !important;
justify-content: center;
align-items: center;
gap: 16px;
border-color: #66A5AD !important;
color: #66A5AD !important;
font-size: 15px !important;
border-radius: 8px !important;
height: 54px !important;
span {
margin-inline-end: 0 !important;
line-height: 15px !important;
}
`;
export const OutlinedButton = (props: any) => (
<Button {...props}>
{props.children}
</Button>
);

View File

@ -9,3 +9,6 @@ export * from './CustomInputPassword';
export * from './CustomSelect';
export * from './CustomMultiSelect';
export * from './CustomSpin';
export * from './FilledButton';
export * from './OutlinedButton';
export * from './LinkButton';

View File

@ -0,0 +1,26 @@
import { useState, useEffect } from 'react';
function getStorageValue(key: string, defaultValue: any) {
if (typeof window !== 'undefined') {
const saved = localStorage.getItem(key);
return saved || defaultValue;
}
};
export function deleteStorageKey(key: string) {
if (typeof window !== 'undefined') {
localStorage.removeItem(key);
}
};
export const useLocalStorage = (key: string, defaultValue: any) => {
const [value, setValue] = useState(() => {
return getStorageValue(key, defaultValue);
});
useEffect(() => {
localStorage.setItem(key, value);
}, [key, value]);
return [value, setValue];
};

View File

@ -375,7 +375,7 @@ a {
padding: 8px 31px;
justify-content: center;
align-items: center;
color: $white;
color: $white !important;
@include rem(15);
font-style: normal;
font-weight: 400;
@ -526,7 +526,6 @@ a {
background: lightgray 50%;
box-shadow: 0 8px 16px 0 rgba(102, 165, 173, 0.32);
overflow: hidden;
margin-right: -16px;
img {
object-fit: cover;
@ -606,7 +605,7 @@ a {
a {
text-decoration: none;
color: #FF8A00;
color: #FF8A00 !important;
@include rem(15);
font-style: normal;
font-weight: 400;
@ -840,7 +839,7 @@ a {
justify-content: center;
a {
color: #003B46;
color: #003B46 !important;
@include rem(18);
font-style: normal;
font-weight: 600;

View File

@ -97,6 +97,7 @@ textarea {
display: flex;
gap: 16px;
align-items: center;
margin-bottom: 4px;
&__edit {
position: relative;

View File

@ -1,6 +1,9 @@
@import "_variables";
.b-header {
position: relative;
z-index: 2;
.b-inner {
display: flex;
justify-content: space-between;
@ -68,7 +71,7 @@
text-decoration: none;
&.active {
color: #003B46;
color: #003B46 !important;
}
}

View File

@ -269,16 +269,17 @@
border: 1px solid #003B46;
height: 40px;
padding: 8px 16px;
color: #003B46;
color: #003B46 !important;
@include rem(16);
font-style: normal;
font-weight: 700;
line-height: 133.333%;
text-decoration: none;
transition: all .2s ease;
&:hover,
&.active {
color: $white;
color: $white !important;
background-color: #003B46;
}
}
@ -753,7 +754,11 @@
border-bottom: none;
a {
color: #D93E5C;
color: #D93E5C !important;
&:before {
background-image: none;
}
}
}
}
@ -780,7 +785,7 @@
justify-content: space-between;
height: 49px;
gap: 8px;
color: #003B46;
color: #003B46 !important;
@include rem(18);
font-style: normal;
font-weight: 600;
@ -804,7 +809,7 @@
&.active {
color: #66A5AD;
color: #66A5AD !important;
padding-right: 0;
&:before {
@ -1016,17 +1021,8 @@
gap: 16px;
}
&__read {
color: #6FB98F;
@include rem(15);
font-style: normal;
font-weight: 500;
line-height: 150%;
text-decoration: none;
}
&__delete {
color: #D93E5C;
color: #D93E5C !important;
@include rem(15);
font-style: normal;
font-weight: 500;
@ -1046,9 +1042,11 @@
flex-direction: column;
gap: 16px;
margin-bottom: 16px;
padding: 12px 12px 0;
.card-profile {
cursor: pointer;
margin: 0 !important;
&__header {
gap: 8px;
@ -1135,7 +1133,8 @@
margin-bottom: 24px;
.card-profile {
border: none;
border: none !important;
&__header {
gap: 8px;
@ -1278,6 +1277,11 @@
font-weight: 300;
line-height: 116.667%;
}
&__utc {
margin-top: 8px;
width: 150px;
}
}
.schedule {
@ -1318,9 +1322,9 @@
cursor: pointer;
border-radius: 8px;
border: 1px solid #D93E5C;
display: flex;
width: 54px;
height: 54px;
padding: 0 27px;
background-image: url(/images/close.svg);
background-position: 50%;
background-repeat: no-repeat;

View File

@ -1,5 +1,5 @@
import { SearchData } from '../types/tags';
import { AdditionalFilter, Filter } from '../types/experts';
import { AdditionalFilter, Filter, GeneralFilter } from '../types/experts';
export const getDefaultFilter = (searchData: SearchData | null): Filter => {
const themesTagIds = searchData?.themesGroups?.reduce<number[]>((result, { tags }) => {
@ -101,3 +101,21 @@ export const getObjectByAdditionalFilter = (searchParams?: any): AdditionalFilte
return additionalFilter;
};
export const getSearchParamsString = (filter: GeneralFilter): string => {
const searchParams = new URLSearchParams();
Object.entries(filter).forEach(([key, value]) => {
if (value) {
if (Array.isArray(value)) {
value.forEach((val) => {
searchParams.append(key, `${val}`);
});
} else {
searchParams.set(key, `${value}`);
}
}
})
return searchParams.toString();
};

View File

@ -1,23 +0,0 @@
'use client';
import { AUTH_TOKEN_KEY } from '../../constants/common';
export function checkAuthToken() {
return !!getAuthToken();
}
export function getAuthToken() {
return '';
}
// export function getAuthToken() {
// return localStorage.getItem(AUTH_TOKEN_KEY);
// }
//
// export function removeAuthToken() {
// localStorage.removeItem(AUTH_TOKEN_KEY);
// }
//
export function setAuthToken(token: string) {
// localStorage.setItem(AUTH_TOKEN_KEY, token);
}