mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 13:38:51 +00:00
Load data from api to the page
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": "123",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "231",
|
||||||
|
"name": "Phan Huu Loi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Ho Chi Minh"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "312",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "523",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "534",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "756",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "23",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "756",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "756",
|
||||||
|
"name": "Nezumi",
|
||||||
|
"identifiedCode": "123",
|
||||||
|
"phone": "0937425123",
|
||||||
|
"roomId": 246,
|
||||||
|
"address": "Da Nang"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import styled, { keyframes } from 'styled-components';
|
||||||
|
|
||||||
|
const rotate = keyframes`
|
||||||
|
to {
|
||||||
|
transform: rotate(1turn)
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Spinner = styled.div`
|
||||||
|
margin: 100px auto;
|
||||||
|
|
||||||
|
width: 80px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
background:
|
||||||
|
radial-gradient(farthest-side, var(--primary-color) 94%, #0000) top/10px
|
||||||
|
10px no-repeat,
|
||||||
|
conic-gradient(#0000 30%, var(--primary-color));
|
||||||
|
-webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 10px), #000 0);
|
||||||
|
mask: none;
|
||||||
|
animation: ${rotate} 1.5s infinite linear;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Spinner;
|
||||||
@@ -2,3 +2,4 @@ export const DASHBOARD: string = '/dashboard';
|
|||||||
export const USER: string = '/user';
|
export const USER: string = '/user';
|
||||||
export const ROOM: string = '/room';
|
export const ROOM: string = '/room';
|
||||||
export const OTHER_PATH: string = '*';
|
export const OTHER_PATH: string = '*';
|
||||||
|
export const BASE_URL: string = 'https://hotel-management-api.loiphan.com/';
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
import { TUser } from '../globals/types';
|
|
||||||
|
|
||||||
export const sampleData: TUser[] = [
|
|
||||||
{
|
|
||||||
id: '123',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '0937425123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '456',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '231',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '241',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '512',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '524',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '125',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '111',
|
|
||||||
name: 'Nezumi',
|
|
||||||
identifiedCode: '123',
|
|
||||||
phone: '123',
|
|
||||||
roomId: '246',
|
|
||||||
address: 'Da Nang',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
import { BASE_URL } from '../constants/path';
|
||||||
|
|
||||||
|
export const useFetch = (path: string) => {
|
||||||
|
const [data, setData] = useState(null);
|
||||||
|
const [isPending, setIsPending] = useState(false);
|
||||||
|
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
setIsPending(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(BASE_URL + path);
|
||||||
|
const json = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok)
|
||||||
|
throw new Error(
|
||||||
|
`Error code: ${response.status} \n Messages: ${response.statusText}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
setIsPending(false);
|
||||||
|
setData(json);
|
||||||
|
setErrorMsg(null);
|
||||||
|
} catch (error) {
|
||||||
|
setErrorMsg(`Could not fetch data.\n ${error}`);
|
||||||
|
setIsPending(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
}, [path]);
|
||||||
|
return { data, isPending, errorMsg };
|
||||||
|
};
|
||||||
@@ -11,7 +11,10 @@ import Message from '../../components/Message';
|
|||||||
import { TUser } from '../../globals/types';
|
import { TUser } from '../../globals/types';
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { sampleData } from '../../constants/sampleData';
|
import { useFetch } from '../../hooks/useFetch';
|
||||||
|
|
||||||
|
// Styled
|
||||||
|
import Spinner from '../../commons/styles/Spinner';
|
||||||
|
|
||||||
type TUserModal = { user: TUser };
|
type TUserModal = { user: TUser };
|
||||||
|
|
||||||
@@ -50,10 +53,19 @@ const UserRow = ({ user }: TUserModal) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const UserTable = () => {
|
const UserTable = () => {
|
||||||
return sampleData.length ? (
|
const { data, isPending, errorMsg } = useFetch('users');
|
||||||
|
let users: TUser[] = [];
|
||||||
|
|
||||||
|
if (data) users = data;
|
||||||
|
|
||||||
|
if (isPending) return <Spinner />;
|
||||||
|
|
||||||
|
if (errorMsg) console.error(errorMsg);
|
||||||
|
|
||||||
|
return users.length ? (
|
||||||
<Direction>
|
<Direction>
|
||||||
<StyledOperationTable>
|
<StyledOperationTable>
|
||||||
<p>Sort / Filter / Search table</p>
|
<p>Sort / Search table</p>
|
||||||
</StyledOperationTable>
|
</StyledOperationTable>
|
||||||
|
|
||||||
<Menus>
|
<Menus>
|
||||||
@@ -66,7 +78,7 @@ const UserTable = () => {
|
|||||||
<div>Room</div>
|
<div>Room</div>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
<Table.Body<TUser>
|
<Table.Body<TUser>
|
||||||
data={sampleData}
|
data={users}
|
||||||
render={(user: TUser) => <UserRow user={user} key={user.id} />}
|
render={(user: TUser) => <UserRow user={user} key={user.id} />}
|
||||||
/>
|
/>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
Reference in New Issue
Block a user