You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
11 KiB
392 lines
11 KiB
import React, { useMemo } from "react"; |
|
|
|
import "./index.scss"; |
|
|
|
import { |
|
useTable, |
|
useSortBy, |
|
useGlobalFilter, |
|
useFilters, |
|
usePagination, |
|
useRowSelect, |
|
useColumnOrder, |
|
useExpanded, |
|
} from "react-table"; |
|
|
|
import { COLUMNS } from "./columns"; |
|
import { GlobalFilter } from "./GlobalFilter"; |
|
|
|
import { Pagination } from "./Pagination"; |
|
import { GoToPage } from "./GoToPage"; |
|
import { Settings } from "./Settings"; |
|
|
|
import { Checkbox } from "./Checkbox"; |
|
import MOCK_DATA from "./MOCK_DATA.json"; |
|
|
|
// This is a custom filter UI for selecting |
|
// a unique option from a list |
|
export function SelectColumnFilter({ |
|
column: { filterValue, setFilter, preFilteredRows, id, render }, |
|
}) { |
|
const options = React.useMemo(() => { |
|
const options = new Set(); |
|
preFilteredRows.forEach((row) => { |
|
options.add(row.values[id]); |
|
}); |
|
return [...options.values()]; |
|
}, [id, preFilteredRows]); |
|
|
|
// Render a multi-select box |
|
return ( |
|
<label className="flex gap-x-2 items-baseline"> |
|
<span className="text-gray-700">{render("Header")}: </span> |
|
<select |
|
className="rounded-md border-gray-300 shadow-sm text-xs focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" |
|
name={id} |
|
id={id} |
|
value={filterValue} |
|
onChange={(e) => { |
|
setFilter(e.target.value || undefined); |
|
}} |
|
> |
|
<option className="text-xs" value=""> |
|
همه |
|
</option> |
|
{options.map((option, i) => ( |
|
<option key={i} value={option} className="text-xs"> |
|
{(() => { |
|
if (option === 1) { |
|
return "وضعیت عادی"; |
|
} else if (option === 2) { |
|
return "اعلان سطح هشدار"; |
|
} else if (option === 3) { |
|
return "بررسی و پیگیری"; |
|
} else if (option === 4) { |
|
return "وضعیت بحرانی"; |
|
} else { |
|
return " وضعیت پایدار"; |
|
} |
|
})()}{" "} |
|
</option> |
|
))} |
|
</select> |
|
</label> |
|
); |
|
} |
|
|
|
const BasicTable = ({ settingsIcon }) => { |
|
const columns = React.useMemo(() => COLUMNS, []); |
|
const data = useMemo(() => MOCK_DATA, []); |
|
|
|
// اگر بخواهیم ردیف های جدولمون یکی در میان زنگ پس زمینه اشون با هم فرق کند |
|
const isEven = (idx) => idx % 2 === 0; |
|
|
|
const { |
|
getTableProps, |
|
getTableBodyProps, |
|
headerGroups, |
|
footerGroups, |
|
rows, |
|
page, |
|
nextPage, |
|
previousPage, |
|
canNextPage, |
|
canPreviousPage, |
|
pageOptions, |
|
gotoPage, |
|
pageCount, |
|
setPageSize, |
|
prepareRow, |
|
allColumns, |
|
getToggleHideAllColumnsProps, |
|
setColumnOrder, |
|
selectedFlatRows, |
|
state, |
|
setGlobalFilter, |
|
resetResizing, |
|
} = useTable( |
|
{ |
|
columns, |
|
data, |
|
// initialState: { pageIndex: 2 } |
|
}, |
|
useColumnOrder, |
|
useFilters, |
|
useGlobalFilter, |
|
useSortBy, |
|
useExpanded, |
|
usePagination, |
|
useRowSelect, |
|
(hooks) => { |
|
hooks.visibleColumns.push((columns) => { |
|
return [ |
|
{ |
|
id: "selection", |
|
Header: ({ getToggleAllRowsSelectedProps }) => ( |
|
<Checkbox {...getToggleAllRowsSelectedProps()} /> |
|
), |
|
Cell: ({ row }) => ( |
|
<Checkbox {...row.getToggleRowSelectedProps()} /> |
|
), |
|
}, |
|
...columns, |
|
]; |
|
}); |
|
} |
|
); |
|
|
|
const changeOrder = () => { |
|
setColumnOrder([ |
|
"name", |
|
"order-number", |
|
"user-job", |
|
"order-level", |
|
"order-status", |
|
"order-price", |
|
]); |
|
}; |
|
|
|
const { globalFilter, pageIndex, pageSize } = state; |
|
// const firstPageRows = rows.slice(0, 10); |
|
return ( |
|
<> |
|
{/* filter */} |
|
{/* <div className="customeClass1"> |
|
{headerGroups.map((headerGroup) => |
|
headerGroup.headers.map((column) => |
|
column.Filter ? ( |
|
<div className="mt-2 sm:mt-0 customeClass2" key={column.id}> |
|
{column.render("Filter")} |
|
</div> |
|
) : null |
|
) |
|
)} |
|
</div> */} |
|
{/* toggle columns */} |
|
{/* <div> |
|
<div> |
|
<Checkbox {...getToggleHideAllColumnsProps()} /> Toggle All |
|
</div> |
|
{allColumns.map((column) => ( |
|
<div key={column.id}> |
|
<label> |
|
<input type="checkbox" {...column.getToggleHiddenProps()} /> |
|
{column.Header} |
|
</label> |
|
</div> |
|
))} |
|
</div> */} |
|
{/* Change Column Order */} |
|
{/* <button onClick={changeOrder}> Change Column Order </button> */} |
|
<div className="flex flex-row items-center justify-end"> |
|
{/* left box */} |
|
<div |
|
className="rounded-md p-2 flex flex-row items-center" |
|
style={{ backgroundColor: "#F1F6FF" }} |
|
> |
|
{/* search box */} |
|
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} /> |
|
{/* pagination */} |
|
<div |
|
className="flex flex-row items-center p-1 rounded" |
|
style={{ backgroundColor: "#F9FBFF" }} |
|
> |
|
{/* go to page */} |
|
<GoToPage |
|
pageIndex={pageIndex} |
|
gotoPage={gotoPage} |
|
pageOptions={pageOptions} |
|
/> |
|
{/* vertical line */} |
|
<div |
|
className={`w-0.5 h-4 mr-2`} |
|
style={{ backgroundColor: "#65A9FF" }} |
|
></div> |
|
{/* arrows */} |
|
<Pagination |
|
gotoPage={gotoPage} |
|
canPreviousPage={canPreviousPage} |
|
previousPage={previousPage} |
|
canNextPage={canNextPage} |
|
pageCount={pageCount} |
|
nextPage={nextPage} |
|
/> |
|
</div> |
|
{/* settings icon */} |
|
{settingsIcon && <Settings />} |
|
</div> |
|
</div> |
|
<table |
|
{...getTableProps()} |
|
className="min-w-full divide-y divide-gray-200" |
|
> |
|
<thead className="" style={{ backgroundColor: "#F3F8FF" }}> |
|
{headerGroups.map((headerGroup) => ( |
|
<tr {...headerGroup.getHeaderGroupProps()}> |
|
{headerGroup.headers.map((column) => ( |
|
<th |
|
{...column.getHeaderProps(column.getSortByToggleProps())} |
|
scope="col" |
|
className="cursor-pointer p-4 text-right text-sm font-medium" |
|
style={{ color: "#3287B9" }} |
|
> |
|
{column.render("Header")} |
|
<span> |
|
{column.isSorted |
|
? column.isSortedDesc |
|
? " 🔽" |
|
: " 🔼" |
|
: ""} |
|
</span> |
|
{/* <div>{column.canFilter ? column.render("Filter") : null}</div> */} |
|
</th> |
|
))} |
|
</tr> |
|
))} |
|
</thead> |
|
<tbody |
|
{...getTableBodyProps()} |
|
className="divide-y divide-gray-200 bg-white" |
|
> |
|
{page.map((row, idx) => { |
|
prepareRow(row); |
|
return ( |
|
<React.Fragment> |
|
<tr |
|
{...row.getRowProps()} |
|
// className={isEven(idx) ? "bg-gray-600" : "bg-white"} |
|
> |
|
{row.cells.map((cell) => { |
|
return ( |
|
<td |
|
{...cell.getCellProps()} |
|
className="p-4 whitespace-nowrap text-xs" |
|
role="cell" |
|
style={{ color: "#00253A" }} |
|
> |
|
{cell.render("Cell")} |
|
</td> |
|
); |
|
})} |
|
</tr> |
|
{row.isExpanded ? ( |
|
<tr> |
|
<td colSpan={headerGroups[0].headers.length}> |
|
{renderRowSubComponent({ rows: row.original })} |
|
{/* {renderRowSubComponent({ row: row.values })} */} |
|
</td> |
|
</tr> |
|
) : null} |
|
</React.Fragment> |
|
); |
|
})} |
|
</tbody> |
|
<tfoot |
|
className={`bg-blue-900 ${rows.length > 10 ? "w-full" : "hidden"}`} |
|
> |
|
{footerGroups.map((footerGroup) => ( |
|
<tr {...footerGroup.getFooterGroupProps()}> |
|
{footerGroup.headers.map((column) => ( |
|
<td |
|
{...column.getFooterProps} |
|
className="px-4 py-2 text-right text-xs" |
|
style={{ color: "#fff" }} |
|
> |
|
{column.render("Footer")} |
|
</td> |
|
))} |
|
</tr> |
|
))} |
|
</tfoot> |
|
</table> |
|
<pre> |
|
<code> |
|
{JSON.stringify( |
|
{ |
|
selectedFlatRows: selectedFlatRows.map((row) => row.original), |
|
}, |
|
null, |
|
2 |
|
)} |
|
</code> |
|
</pre> |
|
|
|
<div className="mt-3 "> |
|
{/* <span className="text-sm ml-4"> |
|
صفحه{" "} |
|
<strong className="text-indigo-500"> |
|
{pageIndex + 1} از {pageOptions.length} |
|
</strong> |
|
{""} |
|
</span> */} |
|
<span className="text-sm ml-4"> |
|
صفحه{" "} |
|
<strong className="text-indigo-500"> |
|
<input |
|
className="ml-1 text-xs p-1 rounded border-blue-400" |
|
type="number" |
|
defaultValue={pageIndex + 1} |
|
onChange={(e) => { |
|
const pageNumber = e.target.value |
|
? Number(e.target.value) - 1 |
|
: 0; |
|
gotoPage(pageNumber); |
|
}} |
|
style={{ width: "50px" }} |
|
/>{" "} |
|
از {pageOptions.length} |
|
</strong> |
|
{""} |
|
</span> |
|
|
|
<select |
|
className="text-white text-sm rounded cursor-pointer" |
|
style={{ |
|
backgroundColor: "#65A9FF", |
|
borderColor: "#65A9FF", |
|
}} |
|
value={pageSize} |
|
onChange={(e) => setPageSize(Number(e.target.value))} |
|
> |
|
{[7, 10, 25, 50].map((pageSize) => ( |
|
<option |
|
key={pageSize} |
|
value={pageSize} |
|
className=" text-sm" |
|
style={{ |
|
direction: "ltr", |
|
textAlign: "right", |
|
}} |
|
> |
|
نمایش {pageSize} |
|
</option> |
|
))} |
|
</select> |
|
</div> |
|
</> |
|
); |
|
}; |
|
|
|
function renderRowSubComponent({ rows }) { |
|
const persian = { |
|
weight: "وزن", |
|
pageNumber: "تعداد صفحات", |
|
pageType: "نوع کاغذ", |
|
bookNumber: "شماره شابک", |
|
publisher: "انتشارات", |
|
author: "نویسنده", |
|
bookType: "قطع", |
|
publishedYear: "سال انتشار", |
|
}; |
|
return ( |
|
<div className="flex flex-row items-center bg-indigo-100 border-r-4 border-blue-600 p-2"> |
|
مبلغ: {rows.history} |
|
<button className="bg-blue-400">ویرایش</button> |
|
</div> |
|
); |
|
} |
|
export default BasicTable; |
|
|
|
BasicTable.defaultProps = { |
|
settingsIcon: true, |
|
};
|
|
|