initial commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import { FC } from "react";
|
||||
import { NewDateTimeFormatter } from "../../../../../../_digifi/lib/NewDateTimeFormatter";
|
||||
|
||||
type Props = {
|
||||
added?: string;
|
||||
};
|
||||
|
||||
const AddedCell: FC<Props> = ({ added }) => (
|
||||
<div className="badge badge-light fw-bolder">
|
||||
{NewDateTimeFormatter(added)}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { AddedCell };
|
||||
@@ -0,0 +1,11 @@
|
||||
import {FC} from 'react'
|
||||
|
||||
type Props = {
|
||||
agent?: string
|
||||
}
|
||||
|
||||
const AgentCell: FC<Props> = ({agent}) => (
|
||||
<> {agent && <div className='badge badge-light-success fw-bolder'>{agent}</div>}</>
|
||||
)
|
||||
|
||||
export {AgentCell}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {FC} from 'react'
|
||||
import {ColumnInstance} from 'react-table'
|
||||
import {User} from '../../core/_models'
|
||||
|
||||
type Props = {
|
||||
column: ColumnInstance<User>
|
||||
}
|
||||
|
||||
const CustomHeaderColumn: FC<Props> = ({column}) => (
|
||||
<>
|
||||
{column.Header && typeof column.Header === 'string' ? <th {...column.getHeaderProps()}>{column.render('Header')}</th> : column.render('Header')}
|
||||
</>
|
||||
)
|
||||
|
||||
export {CustomHeaderColumn}
|
||||
@@ -0,0 +1,25 @@
|
||||
import clsx from 'clsx'
|
||||
import {FC} from 'react'
|
||||
import {Row} from 'react-table'
|
||||
import {User} from '../../core/_models'
|
||||
|
||||
type Props = {
|
||||
row: Row<User>
|
||||
}
|
||||
|
||||
const CustomRow: FC<Props> = ({row}) => (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map((cell) => {
|
||||
return (
|
||||
<td
|
||||
{...cell.getCellProps()}
|
||||
className={clsx({'text-end min-w-100px': cell.column.id === 'actions'})}
|
||||
>
|
||||
{cell.render('Cell')}
|
||||
</td>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
|
||||
export {CustomRow}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { FC, useEffect } from "react";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { MenuComponent } from "../../../../../../_digifi/assets/ts/components";
|
||||
import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers";
|
||||
import { useListView } from "../../core/ListViewProvider";
|
||||
import { useQueryResponse } from "../../core/QueryResponseProvider";
|
||||
import { deleteUser } from "../../core/_requests";
|
||||
|
||||
type Props = {
|
||||
id: ID;
|
||||
};
|
||||
|
||||
const UserActionsCell: FC<Props> = ({ id }) => {
|
||||
const { setItemIdForUpdate } = useListView();
|
||||
const { query } = useQueryResponse();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
useEffect(() => {
|
||||
MenuComponent.reinitialization();
|
||||
}, []);
|
||||
|
||||
const openEditModal = () => {
|
||||
setItemIdForUpdate(id);
|
||||
};
|
||||
|
||||
const deleteItem = useMutation(() => deleteUser(id), {
|
||||
// 💡 response of the mutation is passed to onSuccess
|
||||
onSuccess: () => {
|
||||
// ✅ update detail view directly
|
||||
queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<a
|
||||
href="#"
|
||||
className="btn btn-light btn-active-light-primary btn-sm"
|
||||
data-kt-menu-trigger="click"
|
||||
data-kt-menu-placement="bottom-end"
|
||||
>
|
||||
Actions
|
||||
<KTIcon iconName="down" className="fs-5 m-0" />
|
||||
</a>
|
||||
{/* begin::Menu */}
|
||||
<div
|
||||
className="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-600 menu-state-bg-light-primary fw-bold fs-7 w-125px py-4"
|
||||
data-kt-menu="true"
|
||||
>
|
||||
{/* begin::Menu item */}
|
||||
<div className="menu-item px-3">
|
||||
<a className="menu-link px-3" onClick={openEditModal}>
|
||||
Edit
|
||||
</a>
|
||||
</div>
|
||||
{/* end::Menu item */}
|
||||
|
||||
{/* begin::Menu item */}
|
||||
<div className="menu-item px-3">
|
||||
<a
|
||||
className="menu-link px-3"
|
||||
data-kt-users-table-filter="delete_row"
|
||||
onClick={async () => await deleteItem.mutateAsync()}
|
||||
>
|
||||
Delete
|
||||
</a>
|
||||
</div>
|
||||
{/* end::Menu item */}
|
||||
</div>
|
||||
{/* end::Menu */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { UserActionsCell };
|
||||
@@ -0,0 +1,61 @@
|
||||
import clsx from "clsx";
|
||||
import { FC, PropsWithChildren, useMemo } from "react";
|
||||
import { HeaderProps } from "react-table";
|
||||
import { initialQueryState } from "../../../../../../_digifi/helpers";
|
||||
import { useQueryRequest } from "../../core/QueryRequestProvider";
|
||||
import { User } from "../../core/_models";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
title?: string;
|
||||
tableProps: PropsWithChildren<HeaderProps<User>>;
|
||||
};
|
||||
const UserCustomHeader: FC<Props> = ({ className, title, tableProps }) => {
|
||||
const id = tableProps.column.id;
|
||||
const { state, updateState } = useQueryRequest();
|
||||
|
||||
const isSelectedForSorting = useMemo(() => {
|
||||
return state.sort && state.sort === id;
|
||||
}, [state, id]);
|
||||
const order: "asc" | "desc" | undefined = useMemo(() => state.order, [state]);
|
||||
|
||||
const sortColumn = () => {
|
||||
// avoid sorting for these columns
|
||||
if (id === "actions" || id === "selection") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSelectedForSorting) {
|
||||
// enable sort asc
|
||||
updateState({ sort: id, order: "asc", ...initialQueryState });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSelectedForSorting && order !== undefined) {
|
||||
if (order === "asc") {
|
||||
// enable sort desc
|
||||
updateState({ sort: id, order: "desc", ...initialQueryState });
|
||||
return;
|
||||
}
|
||||
|
||||
// disable sort
|
||||
updateState({ sort: undefined, order: undefined, ...initialQueryState });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<th
|
||||
{...tableProps.column.getHeaderProps()}
|
||||
className={clsx(
|
||||
className,
|
||||
isSelectedForSorting && order !== undefined && `table-sort-${order}`
|
||||
)}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={sortColumn}
|
||||
>
|
||||
{title}
|
||||
</th>
|
||||
);
|
||||
};
|
||||
|
||||
export { UserCustomHeader };
|
||||
@@ -0,0 +1,46 @@
|
||||
import clsx from "clsx";
|
||||
import { FC } from "react";
|
||||
import { toAbsoluteUrl } from "../../../../../../_digifi/helpers";
|
||||
import { User } from "../../core/_models";
|
||||
|
||||
type Props = {
|
||||
user: User;
|
||||
};
|
||||
|
||||
const UserInfoCell: FC<Props> = ({ user }) => (
|
||||
<div className="d-flex align-items-center">
|
||||
{/* begin:: Avatar */}
|
||||
<div className="symbol symbol-circle symbol-50px overflow-hidden me-3">
|
||||
<a href="#">
|
||||
{user.avatar ? (
|
||||
<div className="symbol-label">
|
||||
<img
|
||||
src={toAbsoluteUrl(`media/${user.avatar}`)}
|
||||
alt={user.name}
|
||||
className="w-100"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={clsx(
|
||||
"symbol-label fs-3",
|
||||
`bg-light-${user.initials?.state}`,
|
||||
`text-${user.initials?.state}`
|
||||
)}
|
||||
>
|
||||
{user.firstname?.substring(0, 1).toUpperCase()}{" "}
|
||||
{user.lastname?.substring(0, 1).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
<div className="d-flex flex-column">
|
||||
<a href="#" className="text-gray-800 text-hover-primary mb-1">
|
||||
{user.firstname} {user.lastname}
|
||||
</a>
|
||||
<span>{user.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export { UserInfoCell };
|
||||
@@ -0,0 +1,11 @@
|
||||
import {FC} from 'react'
|
||||
|
||||
type Props = {
|
||||
payment_month?: string
|
||||
}
|
||||
|
||||
const PaymentMonthCell: FC<Props> = ({payment_month}) => (
|
||||
<div className='badge badge-light fw-bolder'>{payment_month}</div>
|
||||
)
|
||||
|
||||
export {PaymentMonthCell}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { FC, useMemo } from "react";
|
||||
import { ID } from "../../../../../../_digifi/helpers";
|
||||
import { useListView } from "../../core/ListViewProvider";
|
||||
|
||||
type Props = {
|
||||
id: ID;
|
||||
};
|
||||
|
||||
const UserSelectionCell: FC<Props> = ({ id }) => {
|
||||
const { selected, onSelect } = useListView();
|
||||
const isSelected = useMemo(() => selected.includes(id), [id, selected]);
|
||||
return (
|
||||
<div className="form-check form-check-custom form-check-solid">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
data-kt-check={isSelected}
|
||||
data-kt-check-target="#kt_table_users .form-check-input"
|
||||
checked={isSelected}
|
||||
onChange={() => onSelect(id)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { UserSelectionCell };
|
||||
@@ -0,0 +1,28 @@
|
||||
import {FC, PropsWithChildren} from 'react'
|
||||
import {HeaderProps} from 'react-table'
|
||||
import {useListView} from '../../core/ListViewProvider'
|
||||
import {User} from '../../core/_models'
|
||||
|
||||
type Props = {
|
||||
tableProps: PropsWithChildren<HeaderProps<User>>
|
||||
}
|
||||
|
||||
const UserSelectionHeader: FC<Props> = ({tableProps}) => {
|
||||
const {isAllSelected, onSelectAll} = useListView()
|
||||
return (
|
||||
<th {...tableProps.column.getHeaderProps()} className='w-10px pe-2'>
|
||||
<div className='form-check form-check-sm form-check-custom form-check-solid me-3'>
|
||||
<input
|
||||
className='form-check-input'
|
||||
type='checkbox'
|
||||
data-kt-check={isAllSelected}
|
||||
data-kt-check-target='#kt_table_users .form-check-input'
|
||||
checked={isAllSelected}
|
||||
onChange={onSelectAll}
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
)
|
||||
}
|
||||
|
||||
export {UserSelectionHeader}
|
||||
@@ -0,0 +1,57 @@
|
||||
import {Column} from 'react-table'
|
||||
import {UserInfoCell} from './UserInfoCell'
|
||||
import { PaymentMonthCell } from './UserLastLoginCell'
|
||||
import {AgentCell} from './AgentCell'
|
||||
import {UserActionsCell} from './UserActionsCell'
|
||||
import {UserSelectionCell} from './UserSelectionCell'
|
||||
import {UserCustomHeader} from './UserCustomHeader'
|
||||
import {UserSelectionHeader} from './UserSelectionHeader'
|
||||
import {User} from '../../core/_models'
|
||||
import { AddedCell } from './AddedCell'
|
||||
|
||||
const usersColumns: ReadonlyArray<Column<User>> = [
|
||||
{
|
||||
Header: (props) => <UserSelectionHeader tableProps={props} />,
|
||||
id: 'selection',
|
||||
Cell: ({...props}) => <UserSelectionCell id={props.data[props.row.index].uid} />,
|
||||
},
|
||||
{
|
||||
Header: (props) => <UserCustomHeader tableProps={props} title='Name' className='min-w-125px' />,
|
||||
id: 'firstname',
|
||||
Cell: ({...props}) => <UserInfoCell user={props.data[props.row.index]} />,
|
||||
},
|
||||
{
|
||||
Header: (props) => <UserCustomHeader tableProps={props} title='Amount' className='min-w-125px' />,
|
||||
accessor: 'loan_amount',
|
||||
},
|
||||
{
|
||||
Header: (props) => (
|
||||
<UserCustomHeader tableProps={props} title='Payment Terms' className='min-w-125px' />
|
||||
),
|
||||
id: 'payment_month',
|
||||
Cell: ({...props}) => <PaymentMonthCell payment_month={props.data[props.row.index].payment_month} />,
|
||||
},
|
||||
{
|
||||
Header: (props) => (
|
||||
<UserCustomHeader tableProps={props} title='Agent' className='min-w-125px' />
|
||||
),
|
||||
id: 'sales_agent',
|
||||
Cell: ({...props}) => <AgentCell agent={props.data[props.row.index].sales_agent} />,
|
||||
},
|
||||
{
|
||||
Header: (props) => (
|
||||
<UserCustomHeader tableProps={props} title='Added' className='min-w-125px' />
|
||||
),
|
||||
id: 'added',
|
||||
Cell: ({...props}) => <AddedCell added={props.data[props.row.index].added} />,
|
||||
},
|
||||
{
|
||||
Header: (props) => (
|
||||
<UserCustomHeader tableProps={props} title='Actions' className='text-end min-w-100px' />
|
||||
),
|
||||
id: 'actions',
|
||||
Cell: ({...props}) => <UserActionsCell id={props.data[props.row.index].uid} />,
|
||||
},
|
||||
]
|
||||
|
||||
export {usersColumns}
|
||||
Reference in New Issue
Block a user