Added loading icon when data is getting fetch for the username
This commit is contained in:
parent
4c9b1927e8
commit
2e9db61173
@ -37,6 +37,7 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-final-form": "^6.5.9",
|
"react-final-form": "^6.5.9",
|
||||||
"react-hook-form": "^7.38.0",
|
"react-hook-form": "^7.38.0",
|
||||||
|
"react-loading-icons": "^1.1.0",
|
||||||
"react-router-dom": "^6.4.2",
|
"react-router-dom": "^6.4.2",
|
||||||
"sass": "^1.55.0",
|
"sass": "^1.55.0",
|
||||||
"sass-loader": "^13.1.0",
|
"sass-loader": "^13.1.0",
|
||||||
|
@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
|
|
||||||
export const axiosInstance = axios.create({
|
export const axiosInstance = axios.create({
|
||||||
baseURL: "http://localhost:5276",
|
baseURL: "http://localhost:5276",
|
||||||
timeout: 1000,
|
timeout: 5000,
|
||||||
params : {
|
params : {
|
||||||
shopId: 10,
|
shopId: 10,
|
||||||
}
|
}
|
||||||
|
37
src/api/fetchCustomerInfo.ts
Normal file
37
src/api/fetchCustomerInfo.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { axiosInstance } from "./axiosInstance";
|
||||||
|
import { ApiToken, CustomerInfo } from "./types";
|
||||||
|
|
||||||
|
const API_TOKEN_NOT_FOUND_ERROR_CODE = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data of customer
|
||||||
|
*
|
||||||
|
* @param token The token, given from WOnD, of the customer
|
||||||
|
* @returns the data of the customer
|
||||||
|
*/
|
||||||
|
export async function fetchCustomerInfo(token: ApiToken, id: number): Promise<CustomerInfo> {
|
||||||
|
|
||||||
|
function timeout(ms: number) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
|
||||||
|
await timeout(3000);
|
||||||
|
|
||||||
|
const res = await axiosInstance.get("/getCustomer", {
|
||||||
|
params: { token, id }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.data.getCustomer.result == "ERROR"){
|
||||||
|
const code: number = res.data.getCustomer.errorCode;
|
||||||
|
// if (code == API_TOKEN_NOT_FOUND_ERROR_CODE)
|
||||||
|
// navigate('/')
|
||||||
|
const msg: string = res.data.getCustomer.message;
|
||||||
|
throw new Error(`Couldn't get user info\nError code: ${code}\nError message: ${msg}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const customerInfo: CustomerInfo = {
|
||||||
|
name: res.data.getCustomer.customer.description, // yes i know...
|
||||||
|
balance: res.data.getCustomer.customer.prepayBalanceCash
|
||||||
|
}
|
||||||
|
return customerInfo;
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
export * from "./isTokenValid";
|
export * from "./isTokenValid";
|
||||||
export * from "./login";
|
export * from "./login";
|
||||||
export * from "./getCustomerInfo";
|
export * from "./fetchCustomerInfo";
|
@ -1,11 +1,12 @@
|
|||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState, MouseEvent } from "react";
|
||||||
import "@scss/transactions.scss";
|
import "@scss/transactions.scss";
|
||||||
|
import { ThreeDots as LoadingIcon } from "react-loading-icons";
|
||||||
import Table from "@components/Transactions/Table"
|
import Table from "@components/Transactions/Table"
|
||||||
import userContext from "@ts/userContext"
|
import userContext from "@ts/userContext"
|
||||||
import AppBar from "@theme/modules/components/AppBar";
|
import AppBar from "@theme/modules/components/AppBar";
|
||||||
import Toolbar from "@theme/modules/components/Toolbar";
|
import Toolbar from "@theme/modules/components/Toolbar";
|
||||||
import Typography from "@theme/modules/components/Typography";
|
import Typography from "@theme/modules/components/Typography";
|
||||||
import { Box, Link, TextFieldProps, TextField } from "@mui/material";
|
import { Box, Link, TextFieldProps, TextField, Button } from "@mui/material";
|
||||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||||
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
|
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@ -16,7 +17,7 @@ import dayjs, { Dayjs } from 'dayjs';
|
|||||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||||
import { getValue } from "@mui/system";
|
import { getValue } from "@mui/system";
|
||||||
import { CustomerInfo } from "@api/types";
|
import { CustomerInfo } from "@api/types";
|
||||||
import { getCustomerInfo } from "@api";
|
import { useGetCustomerInfo } from "src/hooks/useGetCustomerInfo";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -43,17 +44,11 @@ const schema = yup
|
|||||||
|
|
||||||
export function Transactions() {
|
export function Transactions() {
|
||||||
const user = useContext(userContext);
|
const user = useContext(userContext);
|
||||||
const [customerInfo, setCustomerInfo] = useState<CustomerInfo>({name: "John Smith", balance: -1});
|
const { customerInfo, isLoading, getCustomerInfo } = useGetCustomerInfo();
|
||||||
|
|
||||||
async function fetchData() {
|
|
||||||
if (!user.token)
|
|
||||||
return;
|
|
||||||
const info = await getCustomerInfo(user.token, user.id);
|
|
||||||
setCustomerInfo(info);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
if (user.token)
|
||||||
|
getCustomerInfo(user.token, user.id);
|
||||||
}, [user.token])
|
}, [user.token])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -80,7 +75,7 @@ export function Transactions() {
|
|||||||
inputFormat: "DD/MM/YYYY",
|
inputFormat: "DD/MM/YYYY",
|
||||||
renderInput: (params: TextFieldProps) => <TextField {...params} />
|
renderInput: (params: TextFieldProps) => <TextField {...params} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const { ref: endDateRef, ...endDateRegisterProps } = register("endDate");
|
const { ref: endDateRef, ...endDateRegisterProps } = register("endDate");
|
||||||
|
|
||||||
const endDatePickerProps = {
|
const endDatePickerProps = {
|
||||||
@ -120,6 +115,10 @@ export function Transactions() {
|
|||||||
helperText: errors?.maxAmount?.message,
|
helperText: errors?.maxAmount?.message,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleRefreshButton(event: MouseEvent<HTMLElement>): void {
|
||||||
|
getCustomerInfo(user.token, user.id);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="tablePage">
|
<div id="tablePage">
|
||||||
<AppBar position="fixed" sx={{ background: "#28282a" }}>
|
<AppBar position="fixed" sx={{ background: "#28282a" }}>
|
||||||
@ -128,9 +127,13 @@ export function Transactions() {
|
|||||||
<Typography variant="h3" >
|
<Typography variant="h3" >
|
||||||
Transactions
|
Transactions
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Button sx={{marginLeft: 5}} variant="contained" onClick={handleRefreshButton}>
|
||||||
|
Refresh
|
||||||
|
</Button>
|
||||||
<Box className="box right">
|
<Box className="box right">
|
||||||
<Link variant="h6" className="link" href="/">
|
<Link variant="h6" className="link userName" href="/">
|
||||||
{customerInfo.name} (CHF {customerInfo.balance})
|
{isLoading ? <LoadingIcon height=".5em"/> : customerInfo.name}
|
||||||
|
{/* {customerInfo.name} (CHF {customerInfo.balancE}) */}
|
||||||
</Link>
|
</Link>
|
||||||
<AccountCircleIcon className="icon" />
|
<AccountCircleIcon className="icon" />
|
||||||
</Box>
|
</Box>
|
||||||
@ -141,18 +144,26 @@ export function Transactions() {
|
|||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
Filters
|
Filters
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="h6">
|
<Box className="box">
|
||||||
Dates
|
<Typography variant="h6">
|
||||||
</Typography>
|
Dates
|
||||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
</Typography>
|
||||||
<DesktopDatePicker {...startDatePickerProps} />
|
<Box className="inputs-box dates">
|
||||||
<DesktopDatePicker {...endDatePickerProps} />
|
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||||
</LocalizationProvider>
|
<DesktopDatePicker {...startDatePickerProps} />
|
||||||
<Typography variant="h6">
|
<DesktopDatePicker {...endDatePickerProps} />
|
||||||
Transactions
|
</LocalizationProvider>
|
||||||
</Typography>
|
</Box>
|
||||||
<TextField {...minAmountProps}></TextField>
|
</Box>
|
||||||
<TextField {...maxAmountProps}></TextField>
|
<Box className="box">
|
||||||
|
<Typography variant="h6">
|
||||||
|
Transactions
|
||||||
|
</Typography>
|
||||||
|
<Box className="inputs-box transactions">
|
||||||
|
<TextField {...minAmountProps}></TextField>
|
||||||
|
<TextField {...maxAmountProps}></TextField>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
</form>
|
</form>
|
||||||
</aside>
|
</aside>
|
||||||
<main>
|
<main>
|
||||||
|
17
src/hooks/useGetCustomerInfo.ts
Normal file
17
src/hooks/useGetCustomerInfo.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { fetchCustomerInfo } from "@api";
|
||||||
|
import { ApiToken, CustomerInfo } from "@api/types";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function useGetCustomerInfo() {
|
||||||
|
const [customerInfo, setCustomerInfo] = useState<CustomerInfo>({ name: "John Smith", balance: -1 });
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(true); // this should be false, but at least the "Loading..." text appears when the page is loading
|
||||||
|
|
||||||
|
const getCustomerInfo = (token: ApiToken, id: number) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
fetchCustomerInfo(token, id)
|
||||||
|
.then(setCustomerInfo)
|
||||||
|
.then(() => setIsLoading(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isLoading, customerInfo, getCustomerInfo };
|
||||||
|
}
|
@ -40,6 +40,7 @@ body.transactions {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
|
text-align: right;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
@ -73,7 +74,9 @@ body.transactions {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
}
|
}
|
||||||
.amount, .total{
|
|
||||||
|
.amount,
|
||||||
|
.total {
|
||||||
min-width: 6em;
|
min-width: 6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +125,7 @@ body.transactions {
|
|||||||
header {
|
header {
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
|
||||||
.box.left {
|
.box.left {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -131,6 +135,7 @@ body.transactions {
|
|||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
|
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
form {
|
form {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
@ -142,16 +147,19 @@ body.transactions {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputs-box {
|
.box {
|
||||||
// background: red;
|
flex-grow: 1;
|
||||||
width: 50vw;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
|
|
||||||
.input {
|
.inputs-box {
|
||||||
// background: blue;
|
// background: red;
|
||||||
width: 10em;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
// background: blue;
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user