FPSMS-frontend
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

287 satır
12 KiB

  1. "use client";
  2. import React, {useEffect, useState} from "react";
  3. import Paper from "@mui/material/Paper";
  4. import Table from "@mui/material/Table";
  5. import TableBody from "@mui/material/TableBody";
  6. import TableCell from "@mui/material/TableCell";
  7. import TableContainer from "@mui/material/TableContainer";
  8. import TableHead from "@mui/material/TableHead";
  9. import TablePagination from "@mui/material/TablePagination";
  10. import TableRow from "@mui/material/TableRow";
  11. import IconButton from "@mui/material/IconButton";
  12. import EditIcon from "@mui/icons-material/Edit";
  13. import SaveIcon from "@mui/icons-material/Save";
  14. import CancelIcon from "@mui/icons-material/Close";
  15. import DeleteIcon from "@mui/icons-material/Delete";
  16. import TextField from "@mui/material/TextField";
  17. import MultiSelect from "@/components/SearchBox/MultiSelect";
  18. import { Collapse } from "@mui/material";
  19. import TempInputGridForMockUp from "./TempInputGridForMockUp";
  20. import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
  21. import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
  22. export interface ResultWithId {
  23. id: string | number;
  24. }
  25. interface BaseColumn<T extends ResultWithId> {
  26. field: keyof T;
  27. label: string;
  28. type: string;
  29. options?: T[];
  30. renderCell?: (T) => void;
  31. }
  32. interface ColumnWithAction<T extends ResultWithId> extends BaseColumn<T> {
  33. onClick: (item: T) => void;
  34. buttonIcon: React.ReactNode;
  35. buttonColor?: "inherit" | "default" | "primary" | "secondary";
  36. }
  37. export type Column<T extends ResultWithId> =
  38. | BaseColumn<T>
  39. | ColumnWithAction<T>;
  40. interface Props<T extends ResultWithId> {
  41. items: T[],
  42. isMockUp?: Boolean,
  43. columns: Column<T>[],
  44. noWrapper?: boolean,
  45. setPagingController: (value: { pageNum: number; pageSize: number; totalCount: number, index?: number}) => void,
  46. pagingController: { pageNum: number; pageSize: number; totalCount: number },
  47. isAutoPaging: boolean
  48. }
  49. function EditableSearchResults<T extends ResultWithId>({
  50. index,
  51. items,
  52. isMockUp,
  53. columns,
  54. noWrapper,
  55. pagingController,
  56. setPagingController,
  57. isAutoPaging = true,
  58. isEdit = true,
  59. isHideButton = false,
  60. hasCollapse = false,
  61. }: Props<T>) {
  62. const [page, setPage] = useState(0);
  63. const [rowsPerPage, setRowsPerPage] = useState(10);
  64. const [editingRowId, setEditingRowId] = useState<number | null>(null);
  65. const [editedItems, setEditedItems] = useState<T[]>(items);
  66. console.log(items)
  67. useEffect(()=>{
  68. setEditedItems(items)
  69. },[items])
  70. const handleChangePage = (_event: unknown, newPage: number) => {
  71. setPage(newPage);
  72. setPagingController({ ...pagingController, pageNum: newPage + 1 }, (index ?? -1));
  73. };
  74. const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
  75. setRowsPerPage(+event.target.value);
  76. setPage(0);
  77. setPagingController({ ...pagingController, pageSize: +event.target.value, pageNum: 1 , index: index});
  78. };
  79. const handleEditClick = (id: number) => {
  80. setEditingRowId(id);
  81. };
  82. const handleSaveClick = (item: T) => {
  83. setEditingRowId(null);
  84. // Call API or any save logic here
  85. setEditedItems((prev) =>
  86. prev.map((row) => (row.id === item.id ? { ...row } : row))
  87. );
  88. };
  89. const handleInputChange = (id: number, field: keyof T, value: string | number[]) => {
  90. setEditedItems((prev) =>
  91. prev.map((item) =>
  92. item.id === id ? { ...item, [field]: value } : item
  93. )
  94. );
  95. };
  96. const handleDeleteClick = (id: number) => {
  97. // Implement delete logic here
  98. setEditedItems((prev) => prev.filter(item => item.id !== id));
  99. };
  100. useEffect(()=>{
  101. console.log("[debug] isEdit in table", isEdit)
  102. //TODO: switch all record to not in edit mode and save the changes
  103. if (!isEdit) {
  104. editedItems.forEach(item => {
  105. // Call save logic here
  106. console.log("Saving item:", item);
  107. // Reset editing state if needed
  108. });
  109. setEditingRowId(null);
  110. }
  111. },[isEdit])
  112. function Row(props: { row: T }) {
  113. const { row } = props;
  114. const [open, setOpen] = useState(false);
  115. console.log(row)
  116. return (
  117. <>
  118. <TableRow hover tabIndex={-1} key={row.id}>
  119. {
  120. !isHideButton && <TableCell>
  121. {(editingRowId === row.id) ? (
  122. <>
  123. <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}>
  124. <SaveIcon/>
  125. </IconButton>
  126. <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}>
  127. <CancelIcon/>
  128. </IconButton>
  129. {
  130. hasCollapse && <IconButton
  131. aria-label="expand row"
  132. size="small"
  133. onClick={() => setOpen(!open)}
  134. >
  135. {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
  136. </IconButton>
  137. }
  138. </>
  139. ) : (
  140. <>
  141. <IconButton disabled={!isEdit}
  142. onClick={() => handleEditClick(row.id as number)}>
  143. <EditIcon/>
  144. </IconButton>
  145. <IconButton disabled={!isEdit}
  146. onClick={() => handleDeleteClick(row.id as number)}>
  147. <DeleteIcon/>
  148. </IconButton>
  149. {
  150. hasCollapse && <IconButton
  151. aria-label="expand row"
  152. size="small"
  153. onClick={() => setOpen(!open)}
  154. >
  155. {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
  156. </IconButton>
  157. }
  158. </>
  159. )}
  160. </TableCell>
  161. }
  162. {columns.map((column, idx) => {
  163. console.log(column)
  164. const columnName = column.field;
  165. return (
  166. <TableCell key={`${columnName.toString()}-${idx}`}>
  167. {editingRowId === row.id ? (
  168. (() => {
  169. switch (column.type) {
  170. case 'input':
  171. console.log(column.type)
  172. return (
  173. <TextField
  174. hiddenLabel={true}
  175. fullWidth
  176. defaultValue={row[columnName] as string}
  177. onChange={(e) => handleInputChange(row.id as number, columnName, e.target.value)}
  178. />
  179. );
  180. case 'multi-select':
  181. return (
  182. <MultiSelect
  183. //label={column.label}
  184. options={column.options}
  185. selectedValues={[]}
  186. onChange={(selectedValues) => handleInputChange(row.id as number, columnName, selectedValues)}
  187. />
  188. );
  189. case 'read-only':
  190. return (
  191. <span>
  192. {row[columnName] as string}
  193. </span>
  194. );
  195. default:
  196. return null; // Handle any default case if needed
  197. }
  198. })()
  199. ) : (
  200. column.renderCell ?
  201. column.renderCell(row)
  202. :
  203. <span onDoubleClick={() => isEdit && handleEditClick(row.id as number)}>
  204. {row[columnName] as string}
  205. </span>
  206. )}
  207. </TableCell>
  208. );
  209. })}
  210. </TableRow>
  211. <TableRow>
  212. {
  213. hasCollapse &&
  214. <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
  215. <Collapse in={open} timeout="auto" unmountOnExit>
  216. <Table>
  217. <TableBody>
  218. <TableRow>
  219. <TableCell>
  220. <TempInputGridForMockUp
  221. stockInLine={row.lines as any[]}
  222. />
  223. </TableCell>
  224. </TableRow>
  225. </TableBody>
  226. </Table>
  227. </Collapse>
  228. </TableCell>
  229. }
  230. </TableRow>
  231. </>
  232. )
  233. }
  234. const table = (
  235. <>
  236. <TableContainer sx={{ maxHeight: 440 }}>
  237. <Table stickyHeader>
  238. <TableHead>
  239. <TableRow>
  240. {!isHideButton && <TableCell>Actions</TableCell>} {/* Action Column Header */}
  241. {columns.map((column, idx) => (
  242. <TableCell key={`${column.field.toString()}${idx}`}>
  243. {column.label}
  244. </TableCell>
  245. ))}
  246. </TableRow>
  247. </TableHead>
  248. <TableBody>
  249. {(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => (
  250. <Row key={item.id} row={item} />
  251. ))}
  252. </TableBody>
  253. </Table>
  254. </TableContainer>
  255. <TablePagination
  256. rowsPerPageOptions={[10, 25, 100]}
  257. component="div"
  258. count={pagingController.totalCount === 0 ? editedItems.length : pagingController.totalCount}
  259. rowsPerPage={rowsPerPage}
  260. page={page}
  261. onPageChange={handleChangePage}
  262. onRowsPerPageChange={handleChangeRowsPerPage}
  263. />
  264. </>
  265. );
  266. return noWrapper ? table : <Paper sx={{ overflow: "hidden" }}>{table}</Paper>;
  267. }
  268. export default EditableSearchResults;