[FEAT]: dynamic show places and users list
This commit is contained in:
parent
143e3513da
commit
c0de160c59
@ -68,9 +68,11 @@
|
|||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"usePrettierrc": true,
|
"usePrettierrc": true,
|
||||||
"singleQuote": true
|
"jsxSingleQuote": true,
|
||||||
},
|
"singleQuote": true,
|
||||||
{}
|
"endOfLine": "auto"
|
||||||
|
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"jest/valid-title": "off",
|
"jest/valid-title": "off",
|
||||||
"react/button-has-type": "off",
|
"react/button-has-type": "off",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
type Places = {
|
type Places = {
|
||||||
placeType: string;
|
placeType: string;
|
||||||
name: string;
|
name: string;
|
||||||
qr: null;
|
qr: null | string;
|
||||||
id: string;
|
id: string;
|
||||||
parentId: string | null;
|
parentId: string | null;
|
||||||
};
|
};
|
||||||
|
@ -16,8 +16,7 @@ const getPlacesAdapter = (): IGetPlacesPort & getPlacesAdapterReturnType => {
|
|||||||
// make the httpHandler
|
// make the httpHandler
|
||||||
const httpProvider = new HTTPPovider();
|
const httpProvider = new HTTPPovider();
|
||||||
|
|
||||||
const httpHandler = async () =>
|
const httpHandler = async () => httpProvider.request<GetPlacesResponse>(options);
|
||||||
httpProvider.request<GetPlacesResponse>(options);
|
|
||||||
|
|
||||||
// return the method
|
// return the method
|
||||||
return {
|
return {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export default abstract class StateManagementProvider {
|
export default abstract class StateManagementProvider {
|
||||||
abstract useGetQuery<DataType>(
|
abstract useGetQuery<DataType>(
|
||||||
key: string,
|
key: string,
|
||||||
httpHandler: () => Promise<DataType>
|
httpHandler: () => Promise<DataType>,
|
||||||
): { data: DataType | undefined; isLoading: boolean; error?: string };
|
): { data: DataType | undefined; isLoading: boolean; error?: string };
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export default class StateManagementService implements StateManagementProvider {
|
|||||||
|
|
||||||
useGetQuery<DataType>(
|
useGetQuery<DataType>(
|
||||||
key: string,
|
key: string,
|
||||||
httpHandler: () => Promise<DataType>
|
httpHandler: () => Promise<DataType>,
|
||||||
): {
|
): {
|
||||||
data: DataType | undefined;
|
data: DataType | undefined;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
@ -4,7 +4,7 @@ import StateManagementProvider from './stateManagementProvider';
|
|||||||
export default class SwrBoundary implements StateManagementProvider {
|
export default class SwrBoundary implements StateManagementProvider {
|
||||||
useGetQuery<DataType>(
|
useGetQuery<DataType>(
|
||||||
key: string,
|
key: string,
|
||||||
httpHandler: () => Promise<DataType>
|
httpHandler: () => Promise<DataType>,
|
||||||
): {
|
): {
|
||||||
data: DataType | undefined;
|
data: DataType | undefined;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
@ -7,5 +7,11 @@ interface IPageTitleProps {
|
|||||||
|
|
||||||
export default function PageTitle(props: IPageTitleProps) {
|
export default function PageTitle(props: IPageTitleProps) {
|
||||||
const { title, className } = props;
|
const { title, className } = props;
|
||||||
return <div className={`w-full shadow-sm shadow-txt-light font-semibold ${className}`}>{title}</div>;
|
return (
|
||||||
|
<div
|
||||||
|
className={`w-full shadow-sm shadow-txt-light font-semibold ${className}`}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ export const staticMessages = {
|
|||||||
place_id: 'Place id',
|
place_id: 'Place id',
|
||||||
title: 'title',
|
title: 'title',
|
||||||
status: 'Status',
|
status: 'Status',
|
||||||
|
placeType: 'Place Type',
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
qrCode: 'qrCode',
|
qrCode: 'qrCode',
|
||||||
createUser: 'Create user',
|
createUser: 'Create user',
|
||||||
|
@ -9,5 +9,11 @@ export default function TableRow(props: ITableRowInfra) {
|
|||||||
|
|
||||||
const { isRowSelected } = useTableRowVM({ selectedRowId, rowId });
|
const { isRowSelected } = useTableRowVM({ selectedRowId, rowId });
|
||||||
|
|
||||||
return <TableRowView isSelected={isRowSelected} rowData={rowData} setSelectedRowId={setSelectedRowId} />;
|
return (
|
||||||
|
<TableRowView
|
||||||
|
isSelected={isRowSelected}
|
||||||
|
rowData={rowData}
|
||||||
|
setSelectedRowId={setSelectedRowId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export interface ITableRowInfra {
|
export interface ITableRowInfra {
|
||||||
selectedRowId: string;
|
selectedRowId: string;
|
||||||
rowData: {
|
rowData: {
|
||||||
rowItemsTitle: string[];
|
rowItemsTitle: (string | null)[];
|
||||||
rowId: string;
|
rowId: string;
|
||||||
};
|
};
|
||||||
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
@ -6,7 +6,14 @@ export default function TableRowView(props: ITableRowProps) {
|
|||||||
const { isSelected, setSelectedRowId, rowData } = props;
|
const { isSelected, setSelectedRowId, rowData } = props;
|
||||||
const { rowId, rowItemsTitle } = rowData;
|
const { rowId, rowItemsTitle } = rowData;
|
||||||
const columns = rowItemsTitle.map((rowItemTitle, index) => {
|
const columns = rowItemsTitle.map((rowItemTitle, index) => {
|
||||||
return <RowItem key={rowItemTitle} hasCheckbox={index === 0} isSelected={isSelected} title={rowItemTitle} />;
|
return (
|
||||||
|
<RowItem
|
||||||
|
key={rowItemTitle}
|
||||||
|
hasCheckbox={index === 0}
|
||||||
|
isSelected={isSelected}
|
||||||
|
title={rowItemTitle}
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <tr onClick={() => setSelectedRowId(rowId)}>{columns}</tr>;
|
return <tr onClick={() => setSelectedRowId(rowId)}>{columns}</tr>;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export interface ITableRowProps {
|
export interface ITableRowProps {
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
rowData: {
|
rowData: {
|
||||||
rowItemsTitle: string[];
|
rowItemsTitle: (string | null)[];
|
||||||
rowId: string;
|
rowId: string;
|
||||||
};
|
};
|
||||||
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface IRowItemProp {
|
interface IRowItemProp {
|
||||||
title: string;
|
title: string | null;
|
||||||
hasCheckbox: boolean;
|
hasCheckbox: boolean;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
}
|
}
|
||||||
@ -17,7 +17,11 @@ export default function RowItem(props: IRowItemProp) {
|
|||||||
isSelected ? 'opacity-100' : 'opacity-0'
|
isSelected ? 'opacity-100' : 'opacity-0'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span className={`${isSelected ? 'visible' : 'hidden'} transition-all`}>✓</span>
|
<span
|
||||||
|
className={`${isSelected ? 'visible' : 'hidden'} transition-all`}
|
||||||
|
>
|
||||||
|
✓
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{title}
|
{title}
|
||||||
|
@ -1,39 +1,19 @@
|
|||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
||||||
import Loading from '~/driven/utils/components/loading/Loading';
|
import Loading from '~/driven/utils/components/loading/Loading';
|
||||||
|
import Places from '~/business-logic/core/places/common/entity/placeEntity';
|
||||||
import TableRow from '../../common/table-row';
|
import TableRow from '../../common/table-row';
|
||||||
import { IPlacesListProps } from './protocols';
|
import { IPlacesListProps } from './protocols';
|
||||||
|
|
||||||
export default function UsersListView(props: IPlacesListProps) {
|
export default function UsersListView(props: IPlacesListProps) {
|
||||||
const { selectedRowId, setSelectedRowId, placesList } = props;
|
const { selectedRowId, setSelectedRowId, placesList } = props;
|
||||||
console.log(placesList.data);
|
|
||||||
const rows = () => {
|
|
||||||
const placesdata = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
place_id: '6440020b89366fdcaf15a8c2',
|
|
||||||
title: 'flat demoplace ',
|
|
||||||
status: 'demo',
|
|
||||||
address: 'demoplace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
place_id: '6440020b89366fdcaf15asdfa',
|
|
||||||
title: 'flat demoplace second ',
|
|
||||||
status: 'demo second',
|
|
||||||
address: 'demoplace second',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return placesdata.map((places) => {
|
const rows = useMemo(() => {
|
||||||
|
if (!placesList.data) return null;
|
||||||
|
|
||||||
|
return placesList.data.getData().map((places) => {
|
||||||
const rowData = {
|
const rowData = {
|
||||||
rowItemsTitle: [
|
rowItemsTitle: [places.name, places.placeType, places.qr],
|
||||||
places.id,
|
|
||||||
places.title,
|
|
||||||
places.status,
|
|
||||||
places.address,
|
|
||||||
'',
|
|
||||||
],
|
|
||||||
rowId: places.id,
|
rowId: places.id,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@ -45,27 +25,36 @@ export default function UsersListView(props: IPlacesListProps) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
}, [placesList]);
|
||||||
|
|
||||||
if (placesList.isLoading)
|
if (placesList.isLoading)
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center">
|
<div className='flex justify-center items-center'>
|
||||||
<Loading />
|
<Loading />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
const tableTitles: Pick<Places, 'name' | 'placeType' | 'qr'> = {
|
||||||
|
name: staticMessages.global.title,
|
||||||
|
placeType: staticMessages.global.placeType,
|
||||||
|
qr: staticMessages.global.qrCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
const titles = Object.keys(tableTitles).map((titleKey) => {
|
||||||
|
const key = titleKey as keyof typeof tableTitles;
|
||||||
|
|
||||||
|
const title = tableTitles[key];
|
||||||
|
return (
|
||||||
|
<th key={key} className='py-3'>
|
||||||
|
{title}
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<table className="table-auto rounded-md w-full text-sm">
|
<table className='table-auto rounded-md w-full text-sm h-fit'>
|
||||||
<thead className="text-txt-medium font-bold">
|
<thead className='text-txt-medium font-bold'>
|
||||||
<tr>
|
<tr>{titles}</tr>
|
||||||
<th className="py-3">{staticMessages.global.place_id}</th>
|
|
||||||
<th className="py-3">{staticMessages.global.title}</th>
|
|
||||||
<th className="py-3">{staticMessages.global.status}</th>
|
|
||||||
<th className="py-3">{staticMessages.global.address}</th>
|
|
||||||
<th className="py-3">{staticMessages.global.qrCode}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{rows()}</tbody>
|
<tbody>{rows}</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from 'react';
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
||||||
|
import Users from '~/business-logic/core/users/common/entity/entity';
|
||||||
|
import Loading from '~/driven/utils/components/loading/Loading';
|
||||||
import TableRow from '../../common/table-row';
|
import TableRow from '../../common/table-row';
|
||||||
import { IUserListProps } from './protocols';
|
import { IUserListProps } from './protocols';
|
||||||
|
|
||||||
export default function UsersListView(props: IUserListProps) {
|
export default function UsersListView(props: IUserListProps) {
|
||||||
const { selectedRowId, setSelectedRowId, usersList } = props;
|
const { selectedRowId, setSelectedRowId, usersList } = props;
|
||||||
console.log(usersList.data);
|
const rows = useMemo(() => {
|
||||||
const rows = () => {
|
if (!usersList.data) return null;
|
||||||
const userdata = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
firstname: 'behnam',
|
|
||||||
lastname: 'rahimpour',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
firstname: 'Salar',
|
|
||||||
lastname: 'Sali',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return userdata.map((user) => {
|
return usersList.data.getData().map((user) => {
|
||||||
const rowData = {
|
const rowData = {
|
||||||
rowItemsTitle: [user.firstname, user.lastname],
|
rowItemsTitle: [user.firstname, user.lastname],
|
||||||
rowId: user.id,
|
rowId: user.accountId,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
@ -34,17 +25,36 @@ export default function UsersListView(props: IUserListProps) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
}, [usersList]);
|
||||||
|
const tableTitles: Pick<Users, 'firstname' | 'lastname'> = {
|
||||||
|
firstname: staticMessages.global.fistname,
|
||||||
|
lastname: staticMessages.global.lastname,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const titles = Object.keys(tableTitles).map((titleKey) => {
|
||||||
|
const key = titleKey as keyof typeof tableTitles;
|
||||||
|
|
||||||
|
const title = tableTitles[key];
|
||||||
|
return (
|
||||||
|
<th key={key} className='py-3'>
|
||||||
|
{title}
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (usersList.isLoading)
|
||||||
|
return (
|
||||||
|
<div className='flex justify-center items-center'>
|
||||||
|
<Loading />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<table className="table-auto rounded-md w-full text-sm">
|
<table className='table-auto rounded-md w-full text-sm h-fit'>
|
||||||
<thead className="text-txt-medium font-bold">
|
<thead className='text-txt-medium font-bold'>
|
||||||
<tr>
|
<tr>{titles}</tr>
|
||||||
<th className="py-3">{staticMessages.global.fistname}</th>
|
|
||||||
<th className="py-3">{staticMessages.global.lastname}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{rows()}</tbody>
|
<tbody>{rows}</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,9 @@ export default function Sidebar() {
|
|||||||
key={key}
|
key={key}
|
||||||
to={routesData[key].path}
|
to={routesData[key].path}
|
||||||
className={`flex text-white mb-6 text-sm w-full py-2 pl-2 rounded-lg ${
|
className={`flex text-white mb-6 text-sm w-full py-2 pl-2 rounded-lg ${
|
||||||
isCurrentPage.pathname === routesData[key].path ? 'bg-primary-300' : ''
|
isCurrentPage.pathname === routesData[key].path
|
||||||
|
? 'bg-primary-300'
|
||||||
|
: ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<img src={routesData[key].icon} alt='page icon' className='mr-2' />
|
<img src={routesData[key].icon} alt='page icon' className='mr-2' />
|
||||||
|
@ -6,7 +6,10 @@ import CreateUser from '~/driving/application/core/create-user';
|
|||||||
export default function CreateUserPage() {
|
export default function CreateUserPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageTitle className='px-4 py-5' title={staticMessages.global.createUser} />
|
<PageTitle
|
||||||
|
className='px-4 py-5'
|
||||||
|
title={staticMessages.global.createUser}
|
||||||
|
/>
|
||||||
<CreateUser />
|
<CreateUser />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -11,7 +11,11 @@ export default function index() {
|
|||||||
<PageTitle className='px-4 py-5' title={staticMessages.global.users} />
|
<PageTitle className='px-4 py-5' title={staticMessages.global.users} />
|
||||||
<div className='container mx-auto px-4'>
|
<div className='container mx-auto px-4'>
|
||||||
<div className='w-full flex flex-row-reverse items-center py-2'>
|
<div className='w-full flex flex-row-reverse items-center py-2'>
|
||||||
<PrimaryButton className='text-sm' title={staticMessages.global.submit} onClick={() => null} />
|
<PrimaryButton
|
||||||
|
className='text-sm'
|
||||||
|
title={staticMessages.global.submit}
|
||||||
|
onClick={() => null}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='md:grid-cols-2 gap-x-4 grid grid-cols-1 mx-auto'>
|
<div className='md:grid-cols-2 gap-x-4 grid grid-cols-1 mx-auto'>
|
||||||
<UsersList />
|
<UsersList />
|
||||||
|
@ -4,7 +4,7 @@ import Sidebar from '~/driving/application/support/sidebar';
|
|||||||
|
|
||||||
export default function MainPageLayout() {
|
export default function MainPageLayout() {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-nowrap h-screen'>
|
<div className='flex flex-nowrap min-h-screen'>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<main className='dipal-panel w-full text-black bg-white h-fit'>
|
<main className='dipal-panel w-full text-black bg-white h-fit'>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user