Skip to content

Commit

Permalink
Connect frontend with backend using access token
Browse files Browse the repository at this point in the history
  • Loading branch information
xeroxis-xs committed Jun 3, 2024
1 parent e16c295 commit 8a15819
Show file tree
Hide file tree
Showing 18 changed files with 547 additions and 242 deletions.
43 changes: 36 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@mui/x-date-pickers": "6.19.6",
"@phosphor-icons/react": "2.0.15",
"apexcharts": "3.46.0",
"axios": "^1.7.2",
"dayjs": "1.11.10",
"next": "14.1.3",
"react": "18.2.0",
Expand Down
46 changes: 46 additions & 0 deletions src/api/api-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import axios from 'axios';
// import { getToken } from '@/app/msal/msal';
// import { logger } from '@/lib/default-logger';
// import { type WooclapUser } from '@/types/wooclap-user';


const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
})

api.interceptors.request.use(
async (config) => {
const token = localStorage.getItem('access-token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
async () => {
return Promise.reject(new Error('Failed to set access-token for API request.'));
}
)

export default api;

// export async function getWooclapUser(): Promise<WooclapUser> {
// try {
// const response = await api.get<WooclapUser>("/api/WooclapUsers/")
// return response.data;
// } catch (error) {
// logger.error('API request failed.', error);
// throw error;
// }
// };
//
// export const fetchWooclapUserData = async (): Promise<WooclapUser> => {
// api
// .get('/api/WooclapUsers/')
// .then((response) => {
// response.data
// })
// .then((data) => {
// return data;
// }
// }

7 changes: 7 additions & 0 deletions src/app/dashboard/wooclap/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Metadata } from "next";
import Page from "./page"; // import your Demo's page
import { config } from "@/config";

export const metadata = { title: `Wooclap Users | Dashboard | ${config.site.name}` } satisfies Metadata;

export default Page;
89 changes: 89 additions & 0 deletions src/app/dashboard/wooclap/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use client"
import * as React from 'react';
import { useRouter } from 'next/navigation';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { Download as DownloadIcon } from '@phosphor-icons/react/dist/ssr/Download';
import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
import { Upload as UploadIcon } from '@phosphor-icons/react/dist/ssr/Upload';

import { WooclapUserFilters } from '@/components/dashboard/wooclap/wooclap-user-filters';
import { WooclapUserTable } from '@/components/dashboard/wooclap/wooclap-user-table';
import type { WooclapUser } from '@/types/wooclap-user';
import apiService from "@/api/api-service";
import { type AxiosResponse } from "axios";
import { logger } from '@/lib/default-logger'

function applyPagination(rows: WooclapUser[], page: number, rowsPerPage: number): WooclapUser[] {
return rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
}

export default function Page(): React.JSX.Element {
const router = useRouter();
const page = 0;
const rowsPerPage = 5;
const [wooclapUsers, setWooclapUsers] = React.useState<WooclapUser[]>([]);
const [paginatedWooclapUsers, setPaginatedWooclapUsers] = React.useState<WooclapUser[]>([]);

const getWooclapUser = async (): Promise<void> => {
try {
const response: AxiosResponse<WooclapUser[]> = await apiService.get<WooclapUser[]>('/api/WooclapUsers/');
const data: WooclapUser[] = response.data;
setWooclapUsers(data);
} catch (error: unknown) {
// if (axios.isAxiosError(error)) {
// logger.error(error.response?.data);
// // Handle specific axios errors here if necessary
// } else {
// logger.error(error);
// }
logger.error(error);
router.push('/errors/login-expired');
}
};

React.useEffect(() => {
const fetchData = async () => {
await getWooclapUser();
};

fetchData().catch((error: unknown) => {
logger.error('Failed to fetch data', error);
});
}, []);

React.useEffect(() => {
setPaginatedWooclapUsers(applyPagination(wooclapUsers, page, rowsPerPage));
}, [wooclapUsers]);

return (
<Stack spacing={3}>
<Stack direction="row" spacing={3}>
<Stack spacing={1} sx={{ flex: '1 1 auto' }}>
<Typography variant="h4">Wooclap Users</Typography>
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
<Button color="inherit" startIcon={<UploadIcon fontSize="var(--icon-fontSize-md)" />}>
Import
</Button>
<Button color="inherit" startIcon={<DownloadIcon fontSize="var(--icon-fontSize-md)" />}>
Export
</Button>
</Stack>
</Stack>
<div>
<Button startIcon={<PlusIcon fontSize="var(--icon-fontSize-md)" />} variant="contained">
Add
</Button>
</div>
</Stack>
<WooclapUserFilters />
<WooclapUserTable
count={paginatedWooclapUsers.length}
page={page}
rows={paginatedWooclapUsers}
rowsPerPage={rowsPerPage}
/>
</Stack>
);
}
47 changes: 47 additions & 0 deletions src/app/errors/login-expired/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as React from 'react';
import type { Metadata } from 'next';
import RouterLink from 'next/link';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { ArrowLeft as ArrowLeftIcon } from '@phosphor-icons/react/dist/ssr/ArrowLeft';
import { SignInButton } from '@/components/auth/sign-in-button';


import { config } from '@/config';
import { paths } from '@/paths';

export const metadata = { title: `Unauthorised | Errors | ${config.site.name}` } satisfies Metadata;

export default function LoginExpired(): React.JSX.Element {
return (
<Box component="main" sx={{ alignItems: 'center', display: 'flex', justifyContent: 'center', minHeight: '100%' }}>
<Stack spacing={3} sx={{ alignItems: 'center', maxWidth: 'md' }}>
<Box>
<Box
component="img"
alt="Under development"
src="/assets/error-404.png"
sx={{ display: 'inline-block', height: 'auto', maxWidth: '100%', width: '400px' }}
/>
</Box>
<Typography variant="h3" sx={{ textAlign: 'center' }}>
401: You are unauthorised to view this page or your login has expired.
</Typography>
<Typography color="text.secondary" variant="body1" sx={{ textAlign: 'center' }}>
Please try to login again.
</Typography>
<Button
component={RouterLink}
href={paths.auth.signIn}
startIcon={<ArrowLeftIcon fontSize="var(--icon-fontSize-md)" />}
variant="contained"
>
Back to Login
</Button>
{/*<SignInButton />*/}
</Stack>
</Box>
);
}
6 changes: 3 additions & 3 deletions src/app/msal/msal-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const msalConfig = {
},
};

export const API_SCOPE = "User.ReadBasic.All";
// export const API_SCOPE = "User.ReadBasic.All";

/**
* Scopes you add here will be prompted for user consent during sign-in.
Expand All @@ -26,11 +26,11 @@ export const API_SCOPE = "User.ReadBasic.All";
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
*/
export const loginRequest = {
scopes: [API_SCOPE]
scopes: ["api://778ca789-6293-4ad6-8bae-04fb1a9d9943/.default"]
};

export const userDataLoginRequest = {
scopes: [API_SCOPE]
scopes: ["User.Read"]
};
/**
* Add here the scopes to request when obtaining an access token for MS Graph API. For more information, see:
Expand Down
Loading

0 comments on commit 8a15819

Please sign in to comment.