Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ module.exports = {
open: true,
port: "3000",
historyApiFallback: true,
client: {
overlay: {
errors: false,
warnings: false,
runtimeErrors: false,
},
},
},
module: {
rules: require('./webpack.rules'),
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/agent.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import FRONTEND_ROUTES from '../common/constants/frontend-routes.constants';
import UserLoginStore from '../stores/user-login-store';

axios.defaults.baseURL = process.env.NODE_ENV === 'development'
? 'https://localhost:5001/api' : 'https://app-streetcode-webapi-eu-prop-001-gsbqfwc2fdh6hhaw.polandcentral-01.azurewebsites.net/api';
? 'https://localhost:7146/api' : 'https://app-streetcode-webapi-eu-prop-001-gsbqfwc2fdh6hhaw.polandcentral-01.azurewebsites.net/api';
Comment thread
shribakb1 marked this conversation as resolved.

axios.interceptors.response.use(
async (response) => response,
Expand Down
22 changes: 19 additions & 3 deletions src/app/api/user/user.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@ import Agent from '@api/agent.api';

import { API_ROUTES } from '@/app/common/constants/api-routes.constants';
import {
LogoutRequest,
RefreshTokenRequest, RefreshTokenResponce,
UserLoginRequest, UserLoginResponce,
UserRegisterRequest,
} from '@/models/user/user.model';

const UserApi = {
login: (loginParams:UserLoginRequest) => Agent.post<UserLoginResponce>(API_ROUTES.USERS.LOGIN, loginParams),
refreshToken: (token:RefreshTokenRequest) => Agent
.post<RefreshTokenResponce>(API_ROUTES.USERS.REFRESH_TOKEN, token),
register: (registerData: UserRegisterRequest) => Agent.post<UserLoginResponce>(
API_ROUTES.USERS.REGISTER,
registerData,
),
login: (loginParams: UserLoginRequest) => Agent.post<UserLoginResponce>(
API_ROUTES.USERS.LOGIN,
loginParams,
),
logout: (logoutData: LogoutRequest) => Agent.post<void>(
API_ROUTES.USERS.LOGOUT,
logoutData,
),
refreshToken: (token: RefreshTokenRequest) => Agent.post<RefreshTokenResponce>(
API_ROUTES.USERS.REFRESH_TOKEN,
token,
),
};

export default UserApi;
6 changes: 4 additions & 2 deletions src/app/common/constants/api-routes.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,10 @@ export const API_ROUTES = {
DELETE: 'coordinate/delete',
},
USERS: {
LOGIN: 'user/login',
REFRESH_TOKEN: 'user/refreshToken',
REGISTER: 'Users/Register',
LOGIN: 'Users/Login',
LOGOUT: 'Users/Logout',
REFRESH_TOKEN: 'Users/RefreshToken',
},
EMAIL: {
SEND: 'email/send',
Expand Down
2 changes: 2 additions & 0 deletions src/app/common/constants/frontend-routes.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const FRONTEND_ROUTES = {
PARTNERS: '/partners-page',
SUPPORT_US: '/support-us',
NEWS: '/news',
LOGIN: '/login',
SIGNUP: '/signup',
},
};

Expand Down
2 changes: 2 additions & 0 deletions src/app/layout/header/HeaderBlock.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useEventListener from '@hooks/external/useEventListener.hook';
import useOnClickOutside from '@hooks/stateful/useClickOutside.hook';
import useToggle from '@hooks/stateful/useToggle.hook';
import HeaderDrawer from '@layout/header/HeaderDrawer/HeaderDrawer.component';
import ProfileCircle from '@layout/header/ProfileCircle/ProfileCircle.component';
import HeaderSkeleton from '@layout/header/HeaderSkeleton/HeaderSkeleton.component';
import useMobx, { useModalContext } from '@stores/root-store';

Expand Down Expand Up @@ -86,6 +87,7 @@ const HeaderBlock = () => {
style={isPageDimmed ? { zIndex: '-1' } : undefined}
/>
)}
<ProfileCircle />
<HeaderDrawer />
<Button
type="primary"
Expand Down
2 changes: 1 addition & 1 deletion src/app/layout/header/HeaderBlock.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
@use "@sass/mixins/_utils.mixins.scss" as mut;
@use "@sass/mixins/_vendor.mixins.scss" as vnd;

$navbar-innerwidth: 500px;
$navbar-innerwidth: 600px;
$navbar-hidden-innerwidth: 400px;

.navBarContainer {
Expand Down
22 changes: 14 additions & 8 deletions src/app/layout/header/HeaderDrawer/HeaderDrawer.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import './HeaderDrawer.styles.scss';

import CancelBtn from '@images/utils/Cancel_btn_drawer_mobile.svg';

import { observer } from 'mobx-react-lite';
import { useEffect, useState } from 'react';
import { useMediaQuery } from 'react-responsive';
import { useLocation } from 'react-router-dom';
Expand All @@ -13,6 +14,7 @@ import { Drawer } from 'antd';

import FRONTEND_ROUTES from '@/app/common/constants/frontend-routes.constants';
import HeaderDrawerItem from '@/app/layout/header/HeaderDrawer/HeaderDrawerItem/HeaderDrawerItem.component';
import useMobx from '@/app/stores/root-store';

import SocialMediaLinks from './SocialMediaLinks/SocialMediaLinks.component';

Expand Down Expand Up @@ -47,6 +49,8 @@ const HeaderDrawer = () => {
const [options, setOptions] = useState(desktopOptions);
const [scalingCooficient, setScalingCooficient] = useState(scaleDesktop);
const location = useLocation();
const { userLoginStore } = useMobx();
const isLoggedIn = userLoginStore.isUserLoggedIn;

const isSmall = useMediaQuery({
query: '(max-width: 1024px)',
Expand Down Expand Up @@ -102,13 +106,15 @@ const HeaderDrawer = () => {
link={FRONTEND_ROUTES.OTHER_PAGES.CATALOG}
toggleState={toggle}
/>
<HeaderDrawerItem
id={3}
parentActive={active}
text="Адмін-панель"
link={FRONTEND_ROUTES.ADMIN.BASE}
toggleState={toggle}
/>
{isLoggedIn && (
<HeaderDrawerItem
id={3}
parentActive={active}
text="Адмін-панель"
link={FRONTEND_ROUTES.ADMIN.BASE}
toggleState={toggle}
/>
)}
<HeaderDrawerItem
id={4}
parentActive={active}
Expand Down Expand Up @@ -162,4 +168,4 @@ const HeaderDrawer = () => {
);
};

export default HeaderDrawer;
export default observer(HeaderDrawer);
50 changes: 50 additions & 0 deletions src/app/layout/header/ProfileCircle/ProfileCircle.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import './ProfileCircle.styles.scss';

import { LogoutOutlined, UserOutlined } from '@ant-design/icons';
import { Dropdown } from 'antd';
import type { MenuProps } from 'antd';
import { observer } from 'mobx-react-lite';
import { useNavigate } from 'react-router-dom';
import FRONTEND_ROUTES from '@constants/frontend-routes.constants';
import useMobx from '@stores/root-store';

const ProfileCircle = () => {
const navigate = useNavigate();
const { userLoginStore } = useMobx();

const handleLogout = async () => {
await userLoginStore.logout();
navigate(FRONTEND_ROUTES.BASE);
};

const menuItems: MenuProps['items'] = [
{
key: 'logout',
icon: <LogoutOutlined />,
label: 'Вийти',
onClick: handleLogout,
},
];

if (!userLoginStore.isUserLoggedIn) {
return (
<button
type="button"
className="loginButton"
onClick={() => navigate(FRONTEND_ROUTES.OTHER_PAGES.LOGIN)}
>
Вхід
</button>
);
}

return (
<Dropdown menu={{ items: menuItems }} trigger={['click']} placement="bottomRight">
<div className="profileCircle">
<UserOutlined className="profileIcon" />
</div>
</Dropdown>
);
};

export default observer(ProfileCircle);
65 changes: 65 additions & 0 deletions src/app/layout/header/ProfileCircle/ProfileCircle.styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@use "sass:color";
@use "@sass/mixins/_utils.mixins.scss" as mut;

.loginButton {
width: 77px;
height: 39px;
padding: 9px 20px;
border-radius: 10px;
border: 2px solid #DB3424;
background-color: transparent;
color: #DB3424;
font-size: 16px;
font-weight: 500;
cursor: pointer;
margin-right: 12px;
flex-shrink: 0;

&:hover {
background-color: #DB3424;
color: white;
}
}

.profileCircle {
@include mut.sized(40px, 40px);
@include mut.flex-centered();
@include mut.full-rounded(50%);

background-color: #F0F3F9;
margin-right: 30px;
cursor: pointer;
flex-shrink: 0;

.profileIcon {
font-size: 20px;
color: #8C8C8C;
display: flex;
align-items: center;
justify-content: center;
margin-left: 6px;
}

&:hover {
background-color: color.adjust(#F0F3F9, $lightness: -5%);
}
}

@media screen and (max-width: 1024px) {
.loginButton {
width: 65px;
height: 34px;
padding: 7px 14px;
font-size: 14px;
margin-right: 8px;
}

.profileCircle {
@include mut.sized(36px, 36px);
margin-right: px;

.profileIcon {
font-size: 18px;
}
}
}
23 changes: 23 additions & 0 deletions src/app/router/ProtectedRoute.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { observer } from 'mobx-react-lite';
import { Navigate, useLocation } from 'react-router-dom';

import FRONTEND_ROUTES from '@/app/common/constants/frontend-routes.constants';
import useMobx from '@/app/stores/root-store';

interface ProtectedRouteProps {
children: React.ReactNode;
}

const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => {
const { userLoginStore } = useMobx();
const location = useLocation();

if (!userLoginStore.isUserLoggedIn) {
// Redirect to login page, saving the attempted URL
return <Navigate to={FRONTEND_ROUTES.OTHER_PAGES.LOGIN} state={{ from: location }} replace />;
}

return <>{children}</>;
};

export default observer(ProtectedRoute);
15 changes: 10 additions & 5 deletions src/app/router/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,50 @@ import StreetcodeContent from '@streetcode/Streetcode.component';

import NotFound from '@/features/AdditionalPages/NotFoundPage/NotFound.component';
import PartnersPage from '@/features/AdditionalPages/PartnersPage/Partners.component';
import LoginPage from '@/features/AdditionalPages/LoginPage/LoginPage.component';
import SignupPage from '@/features/AdditionalPages/SignupPage/SignupPage.component';
import AdminPage from '@/features/AdminPage/AdminPage.component';
import Partners from '@/features/AdminPage/PartnersPage/Partners.component';
import TeamPage from '@/features/AdminPage/TeamPage/TeamPage.component';
import StreetcodeCatalog from '@/features/StreetcodeCatalogPage/StreetcodeCatalog.component';
import NewsPage from '@/features/AdditionalPages/NewsPage/News.component';
import ContactUs from '@/features/AdditionalPages/ContactUsPage/ContanctUs.component';
import SupportPage from '@/features/AdditionalPages/SupportUsPage/SupportUs.component';
import ProtectedRoute from './ProtectedRoute.component';



const router = createBrowserRouter(createRoutesFromElements(
<Route path="/" element={<App />}>
<Route
path={`${FRONTEND_ROUTES.ADMIN.BASE}`}
element={<AdminPage />}
element={<ProtectedRoute><AdminPage /></ProtectedRoute>}
/>
<Route
path={`${FRONTEND_ROUTES.ADMIN.BASE}/:id`}
element={<StreetcodeContent />}
element={<ProtectedRoute><StreetcodeContent /></ProtectedRoute>}
/>
<Route
path={FRONTEND_ROUTES.ADMIN.FOR_FANS}
element={<ForFansMainPage />}
element={<ProtectedRoute><ForFansMainPage /></ProtectedRoute>}
/>
<Route
path={FRONTEND_ROUTES.ADMIN.PARTNERS}
element={<Partners />}
element={<ProtectedRoute><Partners /></ProtectedRoute>}
/>
<Route path={FRONTEND_ROUTES.OTHER_PAGES.CATALOG} element={<StreetcodeCatalog />} />
<Route
path={FRONTEND_ROUTES.ADMIN.TEAM}
element={(
<TeamPage />
<ProtectedRoute><TeamPage /></ProtectedRoute>
)}
/>
<Route path="*" element={<NotFound />} />
<Route path={FRONTEND_ROUTES.OTHER_PAGES.PARTNERS} element={<PartnersPage />} />
<Route path={FRONTEND_ROUTES.OTHER_PAGES.CONTACT_US} element={<ContactUs />} />
<Route path={FRONTEND_ROUTES.OTHER_PAGES.SUPPORT_US} element={<SupportPage />} />
<Route path={FRONTEND_ROUTES.OTHER_PAGES.LOGIN} element={<LoginPage />} />
<Route path={FRONTEND_ROUTES.OTHER_PAGES.SIGNUP} element={<SignupPage />} />
<Route index path="/:id" element={<StreetcodeContent />} />
<Route index path={`${FRONTEND_ROUTES.OTHER_PAGES.NEWS}/:id`} element={<NewsPage />} />
</Route>,
Expand Down
Loading