mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 13:38:51 +00:00
Merge pull request #13 from Nez27/feat/load-data-from-api
Load data from api to user 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,11 @@ 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';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
type TUserModal = { user: TUser };
|
type TUserModal = { user: TUser };
|
||||||
|
|
||||||
@@ -50,30 +54,48 @@ const UserRow = ({ user }: TUserModal) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const UserTable = () => {
|
const UserTable = () => {
|
||||||
return sampleData.length ? (
|
const { data, isPending, errorMsg } = useFetch('users');
|
||||||
<Direction>
|
const [users, setUsers] = useState<TUser[]>([]);
|
||||||
<StyledOperationTable>
|
|
||||||
<p>Sort / Filter / Search table</p>
|
|
||||||
</StyledOperationTable>
|
|
||||||
|
|
||||||
<Menus>
|
useEffect(() => {
|
||||||
<Table columns="10% 30% 20% 20% 10% 5%">
|
if (data) {
|
||||||
<Table.Header>
|
setUsers(data);
|
||||||
<div>Id</div>
|
}
|
||||||
<div>Name</div>
|
|
||||||
<div>Identified Code</div>
|
if (errorMsg) {
|
||||||
<div>Phone</div>
|
console.error(errorMsg);
|
||||||
<div>Room</div>
|
}
|
||||||
</Table.Header>
|
}, [data, errorMsg]);
|
||||||
<Table.Body<TUser>
|
|
||||||
data={sampleData}
|
return (
|
||||||
render={(user: TUser) => <UserRow user={user} key={user.id} />}
|
<>
|
||||||
/>
|
{isPending && <Spinner />}
|
||||||
</Table>
|
{users.length ? (
|
||||||
</Menus>
|
<Direction>
|
||||||
</Direction>
|
<StyledOperationTable>
|
||||||
) : (
|
<p>Sort / Search table</p>
|
||||||
<Message>No data to show here!</Message>
|
</StyledOperationTable>
|
||||||
|
|
||||||
|
<Menus>
|
||||||
|
<Table columns="10% 30% 20% 20% 10% 5%">
|
||||||
|
<Table.Header>
|
||||||
|
<div>Id</div>
|
||||||
|
<div>Name</div>
|
||||||
|
<div>Identified Code</div>
|
||||||
|
<div>Phone</div>
|
||||||
|
<div>Room</div>
|
||||||
|
</Table.Header>
|
||||||
|
<Table.Body<TUser>
|
||||||
|
data={users}
|
||||||
|
render={(user: TUser) => <UserRow user={user} key={user.id} />}
|
||||||
|
/>
|
||||||
|
</Table>
|
||||||
|
</Menus>
|
||||||
|
</Direction>
|
||||||
|
) : (
|
||||||
|
<Message>No data to show here!</Message>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user