mirror of
https://github.com/lemeow125/Borrowing-TrackerFrontend.git
synced 2024-11-17 06:19:27 +08:00
Add user info page and add equipment status to pdf preview
This commit is contained in:
parent
c80908d8f1
commit
3850a61403
8 changed files with 262 additions and 3 deletions
11
src/App.tsx
11
src/App.tsx
|
@ -23,6 +23,7 @@ import TransactionPage from "./Pages/TransactionPage/TransactionPage";
|
||||||
import EquipmentInstanceTallyPage from "./Pages/EquipmentTallyPage/EquipmentTallyPage";
|
import EquipmentInstanceTallyPage from "./Pages/EquipmentTallyPage/EquipmentTallyPage";
|
||||||
import TransactionReportPage from "./Pages/TransactionReportPage/TransactionReportPage";
|
import TransactionReportPage from "./Pages/TransactionReportPage/TransactionReportPage";
|
||||||
import ManageEquipmentPage from "./Pages/ManageEquipmentPage/ManageEquipmentPage";
|
import ManageEquipmentPage from "./Pages/ManageEquipmentPage/ManageEquipmentPage";
|
||||||
|
import UserInfoPage from "./Pages/UserInfoPage/UserInfoPage";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
const router = createHashRouter([
|
const router = createHashRouter([
|
||||||
|
@ -184,6 +185,16 @@ const router = createHashRouter([
|
||||||
),
|
),
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/view/user/",
|
||||||
|
element: (
|
||||||
|
<>
|
||||||
|
<Revalidator />
|
||||||
|
<UserInfoPage />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
errorElement: <ErrorPage />,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
TransactionType,
|
TransactionType,
|
||||||
ClearanceType,
|
ClearanceType,
|
||||||
TransactionCreateType,
|
TransactionCreateType,
|
||||||
|
PatchUserType,
|
||||||
} from "../Types/Types";
|
} from "../Types/Types";
|
||||||
|
|
||||||
const debug = false;
|
const debug = false;
|
||||||
|
@ -148,6 +149,19 @@ export async function UserAPI() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function UserUpdateAPI(user: PatchUserType) {
|
||||||
|
const config = await GetConfig();
|
||||||
|
return instance
|
||||||
|
.patch("api/v1/accounts/users/me/", user, config)
|
||||||
|
.then((response) => {
|
||||||
|
return [true, response.data as UserType];
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("Error updating user info");
|
||||||
|
return [false, ParseError(error)];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function ActivationAPI(activation: ActivationType) {
|
export function ActivationAPI(activation: ActivationType) {
|
||||||
return instance
|
return instance
|
||||||
.post("api/v1/accounts/users/activation/", activation)
|
.post("api/v1/accounts/users/activation/", activation)
|
||||||
|
|
|
@ -39,7 +39,7 @@ export default function Drawer() {
|
||||||
backgroundColor: colors.header_color,
|
backgroundColor: colors.header_color,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={styles.flex_row}>
|
<div style={styles.flex_row} onClick={() => navigate("/view/user")}>
|
||||||
<AccountCircleIcon
|
<AccountCircleIcon
|
||||||
style={{
|
style={{
|
||||||
width: "48px",
|
width: "48px",
|
||||||
|
|
|
@ -26,6 +26,7 @@ export default function RegisterModal() {
|
||||||
username: "",
|
username: "",
|
||||||
email: "",
|
email: "",
|
||||||
course: "",
|
course: "",
|
||||||
|
section: "",
|
||||||
password: "",
|
password: "",
|
||||||
confirm_password: "",
|
confirm_password: "",
|
||||||
});
|
});
|
||||||
|
@ -166,6 +167,17 @@ export default function RegisterModal() {
|
||||||
</div>
|
</div>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<TextField
|
||||||
|
id="outlined-helperText"
|
||||||
|
label="Section"
|
||||||
|
style={styles.input_form}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setUser({ ...user, section: e.target.value });
|
||||||
|
setError("");
|
||||||
|
}}
|
||||||
|
value={user.username}
|
||||||
|
placeholder={"Enter current section"}
|
||||||
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-helperText"
|
id="outlined-helperText"
|
||||||
label="Username"
|
label="Username"
|
||||||
|
@ -268,6 +280,7 @@ export default function RegisterModal() {
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
confirm_password: "",
|
confirm_password: "",
|
||||||
|
section: "",
|
||||||
course: "",
|
course: "",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -268,6 +268,7 @@ export default function TransactionPDF(props: props) {
|
||||||
</Text>
|
</Text>
|
||||||
{props.transaction.equipments.map((equipment) => (
|
{props.transaction.equipments.map((equipment) => (
|
||||||
<Text
|
<Text
|
||||||
|
key={equipment.id}
|
||||||
style={{
|
style={{
|
||||||
color: colors.form_dark,
|
color: colors.form_dark,
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
|
@ -278,7 +279,7 @@ export default function TransactionPDF(props: props) {
|
||||||
padding: 3,
|
padding: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{` - ${equipment.name} (ID:${equipment.id})`}
|
{` - ${equipment.name} (ID:${equipment.id}) (${equipment.status})`}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
{/* total Equipment */}
|
{/* total Equipment */}
|
||||||
|
|
|
@ -107,6 +107,15 @@ export type UserType = {
|
||||||
last_name: string;
|
last_name: string;
|
||||||
is_teacher: boolean;
|
is_teacher: boolean;
|
||||||
is_technician: boolean;
|
is_technician: boolean;
|
||||||
|
course: string;
|
||||||
|
section: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PatchUserType = {
|
||||||
|
first_name?: string;
|
||||||
|
last_name?: string;
|
||||||
|
course?: string;
|
||||||
|
section?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TransactionType = {
|
export type TransactionType = {
|
||||||
|
|
|
@ -29,7 +29,6 @@ export default function Dashboard() {
|
||||||
>
|
>
|
||||||
<StudentDashboard />
|
<StudentDashboard />
|
||||||
<StudentTransactionListView />
|
<StudentTransactionListView />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</RestrictedComponent>
|
</RestrictedComponent>
|
||||||
<RestrictedComponent allow_only={"Teacher"}>
|
<RestrictedComponent allow_only={"Teacher"}>
|
||||||
|
|
212
src/Pages/UserInfoPage/UserInfoPage.tsx
Normal file
212
src/Pages/UserInfoPage/UserInfoPage.tsx
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
import Header from "../../Components/Header/Header";
|
||||||
|
import styles from "../../styles";
|
||||||
|
import RestrictedComponent from "../../Components/RestrictedComponent/RestrictedComponent";
|
||||||
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { UserAPI, UserUpdateAPI } from "../../Components/API/API";
|
||||||
|
import CircularProgress from "@mui/material/CircularProgress/CircularProgress";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import {
|
||||||
|
FormControlLabel,
|
||||||
|
FormLabel,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
TextField,
|
||||||
|
} from "@mui/material";
|
||||||
|
export default function UserInfoPage() {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const User = useQuery({ queryKey: ["user"], queryFn: UserAPI });
|
||||||
|
const [user, setUser] = useState({
|
||||||
|
first_name: "",
|
||||||
|
last_name: "",
|
||||||
|
username: "",
|
||||||
|
email: "",
|
||||||
|
course: "",
|
||||||
|
section: "",
|
||||||
|
});
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
const data = await UserUpdateAPI(user);
|
||||||
|
if (data[0] != true) {
|
||||||
|
setError(JSON.stringify(data[1]));
|
||||||
|
return Promise.reject(new Error(JSON.stringify(data[1])));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: (data) => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["user"],
|
||||||
|
});
|
||||||
|
setError("Updated successfully");
|
||||||
|
toast(`User info updated successfuly`, {
|
||||||
|
position: "top-right",
|
||||||
|
autoClose: 2000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
theme: "light",
|
||||||
|
});
|
||||||
|
if (data && User.data) {
|
||||||
|
setUser({
|
||||||
|
first_name: User.data.first_name,
|
||||||
|
last_name: User.data.last_name,
|
||||||
|
username: User.data.username,
|
||||||
|
email: User.data.email,
|
||||||
|
course: User.data.course,
|
||||||
|
section: User.data.section,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
useEffect(() => {
|
||||||
|
if (User.data) {
|
||||||
|
setUser(User.data);
|
||||||
|
}
|
||||||
|
}, [User.data]);
|
||||||
|
|
||||||
|
if (User.isLoading) {
|
||||||
|
return (
|
||||||
|
<div style={styles.background}>
|
||||||
|
<Header label={"Transactions"} />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...styles.flex_column,
|
||||||
|
...{
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingTop: "64px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress style={{ height: "128px", width: "128px" }} />
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
...styles.text_dark,
|
||||||
|
...styles.text_L,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Loading
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div style={styles.background}>
|
||||||
|
<Header label={"Dashboard"} />
|
||||||
|
<div style={{ position: "relative", zIndex: 999, marginTop: 80 }}>
|
||||||
|
<TextField
|
||||||
|
id="outlined-helperText"
|
||||||
|
label="First Name"
|
||||||
|
style={styles.input_form}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setUser({ ...user, first_name: e.target.value });
|
||||||
|
setError("");
|
||||||
|
}}
|
||||||
|
value={user.first_name}
|
||||||
|
placeholder={"Enter your first name"}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
id="outlined-helperText"
|
||||||
|
label="Last Name"
|
||||||
|
style={styles.input_form}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
setUser({ ...user, last_name: e.target.value })
|
||||||
|
}
|
||||||
|
value={user.last_name}
|
||||||
|
placeholder={"Enter your last name"}
|
||||||
|
/>
|
||||||
|
<p>{JSON.stringify(User.data)}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<RestrictedComponent allow_only={"Student"}>
|
||||||
|
<FormLabel style={styles.text_dark} id="status-selection">
|
||||||
|
Course
|
||||||
|
</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
aria-labelledby="demo-radio-buttons-group-label"
|
||||||
|
value={user.course}
|
||||||
|
defaultValue="BS Chemistry"
|
||||||
|
name="radio-buttons-group"
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setUser({ ...user, course: e.target.value });
|
||||||
|
setError("");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...styles.flex_column,
|
||||||
|
...{
|
||||||
|
overflowY: "scroll",
|
||||||
|
maxHeight: "128px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
value="BS Chemistry"
|
||||||
|
control={<Radio />}
|
||||||
|
label="BS Chemistry"
|
||||||
|
style={styles.text_dark}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value="BS Food Technology"
|
||||||
|
control={<Radio />}
|
||||||
|
label="BS Food Technology"
|
||||||
|
style={styles.text_dark}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value="BS Applied Physics"
|
||||||
|
control={<Radio />}
|
||||||
|
label="BS Applied Physics"
|
||||||
|
style={styles.text_dark}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value="BS Environmental Science"
|
||||||
|
control={<Radio />}
|
||||||
|
label="BS Environmental Science"
|
||||||
|
style={styles.text_dark}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</RadioGroup>
|
||||||
|
<TextField
|
||||||
|
id="outlined-helperText"
|
||||||
|
label="Section"
|
||||||
|
style={styles.input_form}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setUser({ ...user, section: e.target.value });
|
||||||
|
setError("");
|
||||||
|
}}
|
||||||
|
value={user.username}
|
||||||
|
placeholder={"Enter current section"}
|
||||||
|
/>
|
||||||
|
</RestrictedComponent>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
...styles.text_dark_red,
|
||||||
|
...styles.text_S,
|
||||||
|
flex: 1,
|
||||||
|
textAlign: "center",
|
||||||
|
marginLeft: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => mutation.mutate()}
|
||||||
|
style={{
|
||||||
|
borderRadius: 16,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
background: "#FBB217",
|
||||||
|
height: "40px",
|
||||||
|
width: "20vw",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in a new issue