Migrated to http instance

This commit is contained in:
2024-07-05 10:32:12 +08:00
parent 7b9afb27b8
commit ed9ebb5e29
11 changed files with 318 additions and 299 deletions

View File

@@ -16,16 +16,13 @@ function App() {
<Route element={<HomePage />} path="/" /> <Route element={<HomePage />} path="/" />
<Route element={<SignUpPage />} path="/signup" /> <Route element={<SignUpPage />} path="/signup" />
<Route element={<SignInPage />} path="/signin" /> <Route element={<SignInPage />} path="/signin" />
<Route element={<SpringboardPage />} path="/springboard/:accessToken" /> <Route element={<SpringboardPage />} path="/springboard" />
<Route <Route element={<ManageUserAccountPage />} path="/manage-account" />
element={<ManageUserAccountPage />}
path="/manage-account/:accessToken"
/>
<Route element={<CommunityPage />} path="/community" /> <Route element={<CommunityPage />} path="/community" />
<Route element={<CreatePostPage />} path="/createPost" /> <Route element={<CreatePostPage />} path="/createPost" />
<Route element={<EditPostPage/>} path="/editPost/:id" /> <Route element={<EditPostPage />} path="/editPost/:id" />
<Route element={<SchedulePage/>} path="/schedule"/> <Route element={<SchedulePage />} path="/schedule" />
</Routes> </Routes>
); );
} }

View File

@@ -38,7 +38,8 @@ export default function SignInModule() {
axios axios
.post(config.serverAddress + "/users/login", values) .post(config.serverAddress + "/users/login", values)
.then((response) => { .then((response) => {
navigate("/springboard/" + response.data.accessToken); localStorage.setItem("accessToken", response.data.accessToken);
navigate("/springboard/");
}) })
.catch((error) => { .catch((error) => {
popErrorToast(error); popErrorToast(error);

View File

@@ -1,12 +1,12 @@
import { Button, Checkbox, Link } from "@nextui-org/react"; import { Button, Checkbox, Link } from "@nextui-org/react";
import { Formik, Form, Field, ErrorMessage } from "formik"; import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup"; import * as Yup from "yup";
import axios from "axios";
import config from "../config"; import config from "../config";
import NextUIFormikInput from "./NextUIFormikInput"; import NextUIFormikInput from "./NextUIFormikInput";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { popErrorToast } from "../utilities"; import { popErrorToast } from "../utilities";
import { useState } from "react"; import { useState } from "react";
import instance from "../security/http";
const validationSchema = Yup.object({ const validationSchema = Yup.object({
firstName: Yup.string() firstName: Yup.string()
@@ -61,7 +61,7 @@ export default function SignUpModule() {
const handleSubmit = async (values: any) => { const handleSubmit = async (values: any) => {
try { try {
const response = await axios.post( const response = await instance.post(
config.serverAddress + "/users/register", config.serverAddress + "/users/register",
values values
); );

View File

@@ -1,4 +1,3 @@
import axios from "axios";
import * as Yup from "yup"; import * as Yup from "yup";
import config from "../config"; import config from "../config";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -19,26 +18,23 @@ import NextUIFormikInput from "./NextUIFormikInput";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import UserProfilePicture from "./UserProfilePicture"; import UserProfilePicture from "./UserProfilePicture";
import { popErrorToast } from "../utilities"; import { popErrorToast } from "../utilities";
import instance from "../security/http";
export default function UpdateAccountModule({ export default function UpdateAccountModule() {
accessToken,
}: {
accessToken: string;
}) {
const navigate = useNavigate(); const navigate = useNavigate();
let [userInformation, setUserInformation] = useState<any>(); let [userInformation, setUserInformation] = useState<any>();
const { isOpen, onOpen, onOpenChange } = useDisclosure(); const { isOpen, onOpen, onOpenChange } = useDisclosure();
useEffect(() => { useEffect(() => {
retrieveUserInformation(accessToken!) retrieveUserInformation()
.then((response) => { .then((response) => {
setUserInformation(response); setUserInformation(response);
}) })
.catch(() => { .catch(() => {
navigate("/springboard/" + accessToken); navigate("/springboard/");
}); });
}, [accessToken]); }, []);
const validationSchema = Yup.object({ const validationSchema = Yup.object({
firstName: Yup.string() firstName: Yup.string()
@@ -70,17 +66,12 @@ export default function UpdateAccountModule({
const handleSubmit = async (values: any) => { const handleSubmit = async (values: any) => {
try { try {
const response = await axios.put( const response = await instance.put(
`${config.serverAddress}/users/individual/${userInformation.id}`, `${config.serverAddress}/users/individual/${userInformation.id}`,
values, values
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
); );
console.log("User updated successfully:", response.data); console.log("User updated successfully:", response.data);
navigate("/springboard/" + accessToken); navigate("/springboard/");
} catch (error) { } catch (error) {
popErrorToast(error); popErrorToast(error);
} }
@@ -103,16 +94,8 @@ export default function UpdateAccountModule({
}; };
const archiveAccount = () => { const archiveAccount = () => {
axios instance
.put( .put(config.serverAddress + "/users/archive/" + userInformation.id)
config.serverAddress + "/users/archive/" + userInformation.id,
null,
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
.then(() => { .then(() => {
navigate("/signin"); navigate("/signin");
}) })
@@ -143,7 +126,7 @@ export default function UpdateAccountModule({
<Button <Button
variant="light" variant="light"
onPress={() => { onPress={() => {
navigate("/springboard/" + accessToken); navigate("/springboard/");
}} }}
> >
Cancel Cancel
@@ -200,7 +183,6 @@ export default function UpdateAccountModule({
<div> <div>
<UserProfilePicture <UserProfilePicture
userId={userInformation.id} userId={userInformation.id}
token={accessToken}
editable={true} editable={true}
/> />
</div> </div>

View File

@@ -1,39 +1,27 @@
import axios from "axios";
import React, { useRef, useState } from "react"; import React, { useRef, useState } from "react";
import config from "../config"; import config from "../config";
import { Button, Image } from "@nextui-org/react"; import { Button, Image } from "@nextui-org/react";
import { popErrorToast } from "../utilities"; import { popErrorToast } from "../utilities";
import instance from "../security/http";
export default function UserProfilePicture({ export default function UserProfilePicture({
userId, userId,
token,
editable, editable,
}: { }: {
userId: string; userId: string;
token: string;
editable: boolean; editable: boolean;
}) { }) {
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const uploadProfileImage = async ( const uploadProfileImage = async (userId: string, file: File) => {
userId: string,
file: File,
token: string
) => {
const formData = new FormData(); const formData = new FormData();
formData.append("image", file); formData.append("image", file);
try { try {
const response = await axios.put( const response = await instance.put(
`${config.serverAddress}/users/profile-image/${userId}`, `${config.serverAddress}/users/profile-image/${userId}`,
formData, formData
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
}
); );
return response.data; return response.data;
} catch (error) { } catch (error) {
@@ -57,7 +45,7 @@ export default function UserProfilePicture({
const uploadAndHandleSubmit = async (file: File) => { const uploadAndHandleSubmit = async (file: File) => {
setLoading(true); setLoading(true);
try { try {
await uploadProfileImage(userId, file, token); await uploadProfileImage(userId, file);
} catch (error) { } catch (error) {
} finally { } finally {
setLoading(false); setLoading(false);

View File

@@ -1,146 +1,159 @@
import DefaultLayout from '../layouts/default'; import DefaultLayout from "../layouts/default";
import { Button, Link } from "@nextui-org/react"; import { Button, Link } from "@nextui-org/react";
import { Formik, Form } from "formik"; import { Formik, Form } from "formik";
import * as Yup from 'yup'; import * as Yup from "yup";
import axios from "axios"; import { useEffect, useState } from "react";
import { useEffect, useState } from 'react'; import { useParams } from "react-router-dom";
import { useParams } from 'react-router-dom'; import { useNavigate } from "react-router-dom";
import { useNavigate } from 'react-router-dom'; import NextUIFormikInput from "../components/NextUIFormikInput";
import NextUIFormikInput from '../components/NextUIFormikInput'; import NextUIFormikTextarea from "../components/NextUIFormikTextarea";
import NextUIFormikTextarea from '../components/NextUIFormikTextarea'; import config from "../config";
import config from '../config'; import instance from "../security/http";
const validationSchema = Yup.object({ const validationSchema = Yup.object({
title: Yup.string().trim() title: Yup.string()
.min(3, 'Title must be at least 3 characters') .trim()
.max(200, 'Title must be at most 200 characters') .min(3, "Title must be at least 3 characters")
.matches(/^[a-zA-Z0-9\s]+$/, "Title can only contain letters, numbers, and spaces") .max(200, "Title must be at most 200 characters")
.required('Title is required'), .matches(
content: Yup.string().trim() /^[a-zA-Z0-9\s]+$/,
.min(3, 'Content must be at least 3 characters') "Title can only contain letters, numbers, and spaces"
.max(500, 'Content must be at most 500 characters') )
.matches(/^[a-zA-Z0-9,\s!"'-]*$/, 'Only letters, numbers, commas, spaces, exclamation marks, quotations, and common symbols are allowed') .required("Title is required"),
.required('Content is required') content: Yup.string()
.trim()
.min(3, "Content must be at least 3 characters")
.max(500, "Content must be at most 500 characters")
.matches(
/^[a-zA-Z0-9,\s!"'-]*$/,
"Only letters, numbers, commas, spaces, exclamation marks, quotations, and common symbols are allowed"
)
.required("Content is required"),
}); });
function editPost() { function editPost() {
const { id } = useParams(); const { id } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
// const initialValues = { // const initialValues = {
// title: '', // title: '',
// content: '', // content: '',
// tags: '' // tags: ''
// }; // };
const [post, setPost] = useState({ const [post, setPost] = useState({
title: "", title: "",
content: "" content: "",
});
const [loading, setLoading] = useState(true);
useEffect(() => {
instance.get(config.serverAddress + `/post/${id}`).then((res) => {
setPost(res.data);
setLoading(false);
}); });
const [loading, setLoading] = useState(true); }, [id]);
useEffect(() => { const handleSubmit = async (
axios.get(config.serverAddress + `/post/${id}`).then((res) => { values: any,
setPost(res.data); { setSubmitting, resetForm, setFieldError }: any
setLoading(false); ) => {
}); try {
}, [id]); const response = await instance.put(
config.serverAddress + `/post/${id}`,
values
); // Assuming an API route
if (response.status === 200) {
console.log("Post updated successfully:", response.data);
resetForm(); // Clear form after successful submit
navigate("/community");
} else {
console.error("Error updating post:", response.statusText);
}
} catch (error: any) {
if (error.response && error.response.data && error.response.data.field) {
setFieldError(error.response.data.field, error.response.data.error);
} else {
console.error("Unexpected error:", error);
}
} finally {
setSubmitting(false);
}
};
const handleSubmit = async (values: any, { setSubmitting, resetForm , setFieldError }: any) => { return (
try { <DefaultLayout>
const response = await axios.put(config.serverAddress + `/post/${id}`, values); // Assuming an API route <section className="w-8/12 mx-auto">
if (response.status === 200) { <Link href="/community">
console.log('Post updated successfully:', response.data); <svg
resetForm(); // Clear form after successful submit xmlns="http://www.w3.org/2000/svg"
navigate("/community"); fill="none"
} else { viewBox="0 0 24 24"
console.error('Error updating post:', response.statusText); stroke-width="1.5"
} stroke="black"
} catch (error: any) { className="size-5"
if (error.response && error.response.data && error.response.data.field) { >
setFieldError(error.response.data.field, error.response.data.error); <path
} else { stroke-linecap="round"
console.error('Unexpected error:', error); stroke-linejoin="round"
} d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3"
} finally { />
setSubmitting(false); </svg>
} </Link>
}; </section>
<section className="w-8/12 mx-auto p-5 bg-red-100 border border-none rounded-2xl">
return ( {!loading && (
<DefaultLayout> <Formik
<section className="w-8/12 mx-auto"> initialValues={post}
<Link href="/community"> validationSchema={validationSchema}
<svg onSubmit={handleSubmit}
xmlns="http://www.w3.org/2000/svg" >
fill="none" {({ isValid, dirty, isSubmitting }) => (
viewBox="0 0 24 24" <Form className="flex flex-col gap-5">
stroke-width="1.5" <div>
stroke="black" <NextUIFormikInput
className="size-5"> label="Title"
name="title"
<path type="text"
stroke-linecap="round" placeholder="Enter your post title"
stroke-linejoin="round" labelPlacement="inside"
d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" /> />
</svg> </div>
</Link> <div className="text-sm">
</section> <p>Image</p>
<section className="w-8/12 mx-auto p-5 bg-red-100 border border-none rounded-2xl"> </div>
{ <div>
!loading && ( <NextUIFormikTextarea
<Formik label="Content"
initialValues={post} name="content"
validationSchema={validationSchema} placeholder="Write your post content here"
onSubmit={handleSubmit} />
> </div>
{({ isValid, dirty, isSubmitting }) => ( <div>
<Form className="flex flex-col gap-5"> <NextUIFormikInput
<div> label="Tags (Optional)"
<NextUIFormikInput name="tags"
label="Title" type="text"
name="title" placeholder="Enter tags"
type="text" labelPlacement="inside"
placeholder="Enter your post title" />
labelPlacement="inside" </div>
/> <div className="flex flex-row-reverse border">
</div> <Button
<div className="text-sm"> type="submit"
<p>Image</p> className="bg-red-color text-white text-xl w-1/6"
</div> disabled={!isValid || !dirty || isSubmitting}
<div> >
<NextUIFormikTextarea <p>Update</p>
label="Content" </Button>
name="content" </div>
placeholder="Write your post content here" </Form>
/> )}
</div> </Formik>
<div> )}
<NextUIFormikInput </section>
label="Tags (Optional)" </DefaultLayout>
name="tags" );
type="text"
placeholder="Enter tags"
labelPlacement="inside"
/>
</div>
<div className="flex flex-row-reverse border">
<Button
type="submit"
className="bg-red-color text-white text-xl w-1/6"
disabled={!isValid || !dirty || isSubmitting}
>
<p>Update</p>
</Button>
</div>
</Form>
)}
</Formik>
)
}
</section>
</DefaultLayout>
);
} }
export default editPost export default editPost;

View File

@@ -1,15 +1,19 @@
import { useParams } from "react-router-dom";
import DefaultLayout from "../layouts/default"; import DefaultLayout from "../layouts/default";
import UpdateAccountModule from "../components/UpdateAccountModule"; import UpdateAccountModule from "../components/UpdateAccountModule";
import { useNavigate } from "react-router-dom";
export default function ManageUserAccountPage() { export default function ManageUserAccountPage() {
let { accessToken } = useParams<string>(); // TODO: Replace AT from props with AT from localstorage const navigate = useNavigate();
let accessToken = localStorage.getItem("accessToken");
if (!accessToken) {
navigate("/signin");
}
return ( return (
<DefaultLayout> <DefaultLayout>
<div> <div>
<div className="p-8 flex flex-col gap-8"> <div className="p-8 flex flex-col gap-8">
<UpdateAccountModule accessToken={accessToken!} /> <UpdateAccountModule />
</div> </div>
</div> </div>
</DefaultLayout> </DefaultLayout>

View File

@@ -1,9 +1,17 @@
import { Card, CardBody, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react'; import {
Card,
CardBody,
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from "@nextui-org/react";
import DefaultLayout from "../layouts/default"; import DefaultLayout from "../layouts/default";
import { useEffect, useState } from 'react'; import { useEffect, useState } from "react";
import axios from 'axios'; import config from "../config";
import config from '../config'; import instance from "../security/http";
interface Schedule { interface Schedule {
id: number; id: number;
@@ -14,11 +22,11 @@ interface Schedule {
} }
export default function SchedulePage() { export default function SchedulePage() {
const [scheduleList, setScheduleList] = useState<Schedule[]>([]); const [scheduleList, setScheduleList] = useState<Schedule[]>([]);
useEffect(() => { useEffect(() => {
axios.get(config.serverAddress + '/schedule') instance
.get(config.serverAddress + "/schedule")
.then((res) => { .then((res) => {
const schedules = res.data.map((schedule: Schedule) => ({ const schedules = res.data.map((schedule: Schedule) => ({
...schedule, ...schedule,
@@ -27,83 +35,91 @@ export default function SchedulePage() {
setScheduleList(schedules); setScheduleList(schedules);
}) })
.catch((err) => { .catch((err) => {
console.error('Error fetching schedules:', err); console.error("Error fetching schedules:", err);
}); });
}, []); }, []);
return ( return (
<DefaultLayout> <DefaultLayout>
<section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10"> <section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10">
<h1>Karang Guni Schedule</h1> <h1>Karang Guni Schedule</h1>
<div className="flex flex-col gap-8"> <div className="flex flex-col gap-8">
<Table> <Table>
<TableHeader> <TableHeader>
<TableColumn>Date</TableColumn> <TableColumn>Date</TableColumn>
<TableColumn>Time</TableColumn> <TableColumn>Time</TableColumn>
<TableColumn>Location</TableColumn> <TableColumn>Location</TableColumn>
<TableColumn>Postal Code</TableColumn> <TableColumn>Postal Code</TableColumn>
<TableColumn>Status</TableColumn> <TableColumn>Status</TableColumn>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{scheduleList.map((schedule) => ( {scheduleList.map((schedule) => (
<TableRow key={schedule.id}> <TableRow key={schedule.id}>
<TableCell>{((schedule.dateTime as unknown) as Date).toLocaleDateString()}</TableCell> <TableCell>
<TableCell>{((schedule.dateTime as unknown) as Date).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</TableCell> {(
<TableCell>{schedule.location}</TableCell> schedule.dateTime as unknown as Date
<TableCell>{schedule.postalCode}</TableCell> ).toLocaleDateString()}
<TableCell>{schedule.status}</TableCell> </TableCell>
</TableRow> <TableCell>
))} {(schedule.dateTime as unknown as Date).toLocaleTimeString(
</TableBody> [],
</Table> { hour: "2-digit", minute: "2-digit" }
<div> )}
</TableCell>
<TableCell>{schedule.location}</TableCell>
<TableCell>{schedule.postalCode}</TableCell>
<TableCell>{schedule.status}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<div>
<div>
<div className="flex flex-row gap-20 ">
<div> <div>
<div className="flex flex-row gap-20 "> <Card>
<div> <CardBody>
<Card> <p className="text-lg">Paper</p>
<CardBody> <p className="text-xl">$0.05 to 0.20/KG</p>
<p className="text-lg">Paper</p> <ul>
<p className="text-xl">$0.05 to 0.20/KG</p> <li>Cardboard ($0.20/kg)</li>
<ul> <li>Newspaper and B&W ($0.11/kg)</li>
<li>Cardboard ($0.20/kg)</li> <li>Mix paper ($0.05/kg)</li>
<li>Newspaper and B&W ($0.11/kg)</li> </ul>
<li>Mix paper ($0.05/kg)</li> </CardBody>
</ul> </Card>
</CardBody> </div>
</Card> <div>
</div> <Card>
<div> <CardBody>
<Card> <p className="text-lg">Paper</p>
<CardBody> <p className="text-xl">$0.05 to 0.20/KG</p>
<p className="text-lg">Paper</p> <ul>
<p className="text-xl">$0.05 to 0.20/KG</p> <li>Cardboard ($0.20/kg)</li>
<ul> <li>Newspaper and B&W ($0.11/kg)</li>
<li>Cardboard ($0.20/kg)</li> <li>Mix paper ($0.05/kg)</li>
<li>Newspaper and B&W ($0.11/kg)</li> </ul>
<li>Mix paper ($0.05/kg)</li> </CardBody>
</ul> </Card>
</CardBody> </div>
</Card> <div>
</div> <Card>
<div> <CardBody>
<Card> <p className="text-lg">Paper</p>
<CardBody> <p className="text-xl">$0.05 to 0.20/KG</p>
<p className="text-lg">Paper</p> <ul>
<p className="text-xl">$0.05 to 0.20/KG</p> <li>Cardboard ($0.20/kg)</li>
<ul> <li>Newspaper and B&W ($0.11/kg)</li>
<li>Cardboard ($0.20/kg)</li> <li>Mix paper ($0.05/kg)</li>
<li>Newspaper and B&W ($0.11/kg)</li> </ul>
<li>Mix paper ($0.05/kg)</li> </CardBody>
</ul> </Card>
</CardBody>
</Card>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
</section> </div>
</DefaultLayout> </section>
); </DefaultLayout>
} );
}

View File

@@ -1,4 +1,4 @@
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import DefaultLayout from "../layouts/default"; import DefaultLayout from "../layouts/default";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Button, Card, Link } from "@nextui-org/react"; import { Button, Card, Link } from "@nextui-org/react";
@@ -9,13 +9,15 @@ import { retrieveUserInformation } from "../security/users";
import UserProfilePicture from "../components/UserProfilePicture"; import UserProfilePicture from "../components/UserProfilePicture";
export default function SpringboardPage() { export default function SpringboardPage() {
let { accessToken } = useParams<string>(); // TODO: Replace AT from props with AT from localstorage const navigate = useNavigate();
let accessToken = localStorage.getItem("accessToken");
if (!accessToken) {
navigate("/signin");
}
let [userInformation, setUserInformation] = useState<any>(); let [userInformation, setUserInformation] = useState<any>();
let [accountUnavailable, setAccountUnavaliable] = useState(false); let [accountUnavailable, setAccountUnavaliable] = useState(false);
let timeOfDay = getTimeOfDay(); let timeOfDay = getTimeOfDay();
const navigate = useNavigate();
let greeting = ""; let greeting = "";
if (timeOfDay === 0) { if (timeOfDay === 0) {
greeting = "Good morning"; greeting = "Good morning";
@@ -26,11 +28,11 @@ export default function SpringboardPage() {
} }
useEffect(() => { useEffect(() => {
retrieveUserInformation(accessToken!) retrieveUserInformation()
.then((response) => { .then((response) => {
setUserInformation(response); setUserInformation(response);
}) })
.catch((error) => { .catch((_) => {
setAccountUnavaliable(true); setAccountUnavaliable(true);
}); });
return; return;
@@ -60,7 +62,7 @@ export default function SpringboardPage() {
</div> </div>
} }
onPress={() => { onPress={() => {
navigate("/manage-account/" + accessToken); navigate("/manage-account/");
}} }}
> >
Manage your account Manage your account
@@ -68,7 +70,6 @@ export default function SpringboardPage() {
</div> </div>
<UserProfilePicture <UserProfilePicture
userId={userInformation.id} userId={userInformation.id}
token={accessToken!}
editable={false} editable={false}
/> />
</div> </div>
@@ -77,25 +78,21 @@ export default function SpringboardPage() {
title="Community Forums" title="Community Forums"
subtitle="Be involved in discussions among your neighbourhood" subtitle="Be involved in discussions among your neighbourhood"
linkToPage="" linkToPage=""
></SpringboardButton> ></SpringboardButton>
<SpringboardButton <SpringboardButton
title="Events" title="Events"
subtitle="Participate in exciting upcoming events around Singapore" subtitle="Participate in exciting upcoming events around Singapore"
linkToPage="" linkToPage=""
></SpringboardButton> ></SpringboardButton>
<SpringboardButton <SpringboardButton
title="Home Bill Contest" title="Home Bill Contest"
subtitle="Save resources, win vouchers!" subtitle="Save resources, win vouchers!"
linkToPage="" linkToPage=""
></SpringboardButton> ></SpringboardButton>
<SpringboardButton <SpringboardButton
title="Karang Guni Scheduling" title="Karang Guni Scheduling"
subtitle="Arrange doorstep sales for your old gears with Karang Guni" subtitle="Arrange doorstep sales for your old gears with Karang Guni"
linkToPage="/schedule" linkToPage="/schedule"
></SpringboardButton> ></SpringboardButton>
</div> </div>
<div className="w-full h-[600px] bg-red-500"></div> <div className="w-full h-[600px] bg-red-500"></div>

View File

@@ -0,0 +1,29 @@
import axios from "axios";
import config from "../config";
const instance = axios.create({
baseURL: config.serverAddress,
});
// Add a request interceptor
instance.interceptors.request.use(
function (config) {
console.log("yessss");
// Do something before request is sent
let accessToken = localStorage.getItem("accessToken");
if (accessToken) {
config.headers["Authorization"] = `Bearer ${accessToken}`;
}
if (config.data && config.data.user) {
delete config.data.user;
}
return config;
},
function (error) {
// Do something with request error
localStorage.clear();
return Promise.reject(error);
}
);
export default instance;

View File

@@ -1,20 +1,12 @@
import axios, { AxiosError } from "axios"; import { AxiosError } from "axios";
import config from "../config"; import config from "../config";
import instance from "./http";
export async function retrieveUserInformation(accessToken: string) { export async function retrieveUserInformation() {
try { try {
let userId = await axios.get(`${config.serverAddress}/users/auth`, { let userId = await instance.get(`${config.serverAddress}/users/auth`);
headers: { let userInformation = await instance.get(
Authorization: `Bearer ${accessToken}`, `${config.serverAddress}/users/individual/${userId.data.id}`
},
});
let userInformation = await axios.get(
`${config.serverAddress}/users/individual/${userId.data.id}`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
); );
return userInformation.data; return userInformation.data;
} catch (error) { } catch (error) {