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
12 changes: 3 additions & 9 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { memo, useEffect, useState, useMemo } from 'react';
import { Provider } from 'jotai';
import { memo, useEffect, useMemo } from 'react';
import { setupTokenRefresh } from './shared/utils/api-interceptor';
import { AppUnProtectedRoutes } from './modules/app/routes';
import { AppProtectedRoutes } from './modules/app/routes/auth-routes';
Expand All @@ -8,18 +7,13 @@ import { useAuth } from './shared/hooks/use-auth';

const App = memo(() => {
const { GlobalScrollbar } = useScrollbar();
const [cacheKey, setCacheKey] = useState<string>('');
const { token } = useAuth();
const isAuth = useMemo(() => !!token, [token]);

useEffect(() => {
setupTokenRefresh();
}, []);

useEffect(() => {
setCacheKey(Date.now().toString());
}, [isAuth]);

if (!isAuth) {
return (
<>
Expand All @@ -30,10 +24,10 @@ const App = memo(() => {
}

return (
<Provider key={cacheKey}>
<>
<GlobalScrollbar />
<AppProtectedRoutes />
</Provider>
</>
);
});

Expand Down
5 changes: 5 additions & 0 deletions client/src/infra/rest/apis/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { get, patch } from '../..';
import { ApiResponse } from '../../typings';
import { USER_DB_STATE } from '../../typings';
import {
getUserProfileResponse,
searchUserResponse,
Expand All @@ -18,6 +19,10 @@ export const userProfile = async (username: string) => {
);
};

export const getCurrentUser = async () => {
return get<undefined, ApiResponse<USER_DB_STATE>>(`/api/user/me`, true);
};

export const updateProfileImg = async (imageUrl: string) => {
return patch<{ url: string }, ApiResponse<{ profile_img: string }>>(
`/api/user/update-profile-img`,
Expand Down
19 changes: 11 additions & 8 deletions client/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'jotai';
import App from './App';
import createCache from '@emotion/cache';
import { CacheProvider } from '@emotion/react';
Expand All @@ -14,13 +15,15 @@ const cache = createCache({

createRoot(document.getElementById('root')!).render(
<StrictMode>
<CacheProvider value={cache}>
<MuiThemeProvider>
<BrowserRouter>
<A2ZNotifications />
<App />
</BrowserRouter>
</MuiThemeProvider>
</CacheProvider>
<Provider>
<CacheProvider value={cache}>
<MuiThemeProvider>
<BrowserRouter>
<A2ZNotifications />
<App />
</BrowserRouter>
</MuiThemeProvider>
</CacheProvider>
</Provider>
</StrictMode>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentType, LazyExoticComponent, Suspense } from 'react';
import Loader from '../../../../../shared/components/molecules/loader';
import { LOADING } from '../../constants';
import ProtectedPlaceholder from './protected';

export const ProtectedRoute = ({
component: LazyComponent,
hasAccess,
}: {
component: LazyExoticComponent<ComponentType<Record<string, unknown>>>;
hasAccess: boolean;
}) => {
if (hasAccess) {
return (
<Suspense fallback={<Loader size={32} secondary={LOADING} />}>
<LazyComponent />
</Suspense>
);
}

return <ProtectedPlaceholder />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { FC } from 'react';
import { Box, Typography, useTheme } from '@mui/material';
import { useCustomNavigate } from '../../../../../shared/hooks/use-custom-navigate';
import A2ZButton from '../../../../../shared/components/atoms/button';
import { ROUTES_V1 } from '../../constants/routes';

interface ProtectedPlaceholderProps {
onClick?: () => void;
heading?: string;
description?: string;
buttonText?: string;
showButton?: boolean;
}

const ProtectedPlaceholder: FC<ProtectedPlaceholderProps> = ({
heading = 'Access Denied',
description = 'You do not have access to this content.',
onClick,
buttonText = 'Go to Home',
showButton = true,
}) => {
const theme = useTheme();
const navigate = useCustomNavigate();

return (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
width: '100%',
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
p: { xs: 3, sm: '36px 72px' },
borderRadius: 2,
bgcolor:
theme.palette.mode === 'dark'
? 'background.paper'
: theme.palette.grey[50],
boxShadow: theme.shadows[2],
maxWidth: { xs: '90%', sm: 'auto' },
}}
>
<Typography
variant="h4"
component="h1"
sx={{
m: 0,
fontWeight: 600,
color: 'text.primary',
textAlign: 'center',
}}
>
{heading}
</Typography>
<Typography
variant="body1"
component="p"
sx={{
mt: 2,
color: 'text.secondary',
textAlign: 'center',
maxWidth: 400,
}}
>
{description}
</Typography>

{showButton && (
<A2ZButton
variant="contained"
sx={{
mt: 6,
px: 3,
py: 1.5,
fontSize: 16,
transition: 'all 0.2s ease-in-out',
bgcolor: 'primary.main',
color: 'primary.contrastText',
'&:hover': {
transform: 'scale(1.05)',
bgcolor: 'primary.dark',
},
}}
onClick={() => {
if (onClick) {
onClick();
} else {
navigate({ pathname: ROUTES_V1.HOME.replace('/*', '/') });
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string manipulation 'ROUTES_V1.HOME.replace('/', '/')' is fragile. ROUTES_V1.HOME is defined as '/v1/home' which doesn't contain '/', so this replace does nothing. If you intend to handle wildcard routes, verify that the route constant actually contains '/*' or remove this unnecessary replace call.

Suggested change
navigate({ pathname: ROUTES_V1.HOME.replace('/*', '/') });
navigate({ pathname: ROUTES_V1.HOME });

Copilot uses AI. Check for mistakes.
}
}}
>
{buttonText}
</A2ZButton>
)}
</Box>
</Box>
);
};

export default ProtectedPlaceholder;
4 changes: 2 additions & 2 deletions client/src/modules/app/routes/auth-routes/v1/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export default function getRoutesV1() {
}
/>,
<Route
key={ROUTES_V1.SETTINGS}
path={ROUTES_V1.SETTINGS}
key={`${ROUTES_V1.SETTINGS}/*`}
path={`${ROUTES_V1.SETTINGS}/*`}
element={
<Suspense fallback={<Loader size={32} secondary={LOADING} />}>
<SettingsPageLazyComponent />
Expand Down
1 change: 1 addition & 0 deletions client/src/modules/app/routes/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export enum ROUTES_V1 {
HOME = '/v1/home',
SETTINGS = '/v1/settings',
SETTINGS_PROFILE = '/profile',
}

export enum ROUTES_PAGE_V1 {
Expand Down
1 change: 0 additions & 1 deletion client/src/modules/edit-profile/constants/index.ts

This file was deleted.

90 changes: 0 additions & 90 deletions client/src/modules/edit-profile/hooks/index.ts

This file was deleted.

Loading