소스 검색

[editable table] add editable search result

create_edit_user
jason.lam 3 달 전
부모
커밋
be01443bee
2개의 변경된 파일221개의 추가작업 그리고 20개의 파일을 삭제
  1. +24
    -20
      src/components/RoughScheduleSetting/RoughScheduleSetting.tsx
  2. +197
    -0
      src/components/SearchResults/EditableSearchResults.tsx

+ 24
- 20
src/components/RoughScheduleSetting/RoughScheduleSetting.tsx 파일 보기

@@ -12,7 +12,8 @@ import axios from "axios";
import {BASE_API_URL, NEXT_PUBLIC_API_URL} from "@/config/api";
import { useTranslation } from "react-i18next";
import axiosInstance from "@/app/(main)/axios/axiosInstance";
import Qs from 'qs'; // Make sure to import Qs
import Qs from 'qs';
import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs

type Props = {
items: ItemsResult[];
@@ -77,12 +78,12 @@ const RSSOverview: React.FC<Props> = ({ items }) => {
[t, items]
);

const onDetailClick = useCallback(
(item: ItemsResult) => {
router.push(`/settings/items/edit?id=${item.id}`);
},
[router]
);
// const onDetailClick = useCallback(
// (item: ItemsResult) => {
// router.push(`/settings/items/edit?id=${item.id}`);
// },
// [router]
// );

const onDeleteClick = useCallback(
(item: ItemsResult) => {},
@@ -91,26 +92,29 @@ const RSSOverview: React.FC<Props> = ({ items }) => {

const columns = useMemo<Column<ItemsResult>[]>(
() => [
{
name: "id",
label: t("Details"),
onClick: onDetailClick,
buttonIcon: <EditNote />,
},
// {
// name: "id",
// label: t("Details"),
// onClick: ()=>{},
// buttonIcon: <EditNote />,
// },
{
name: "fgName",
label: "Finished Goods Name",
type: 'input',
},
{
name: "excludeDate",
label: t("Exclude Date"),
type: 'multi-select',
options: dayOptions,
},
{
name: "action",
label: t(""),
buttonIcon: <GridDeleteIcon />,
onClick: onDeleteClick,
},
// {
// name: "action",
// label: t(""),
// buttonIcon: <GridDeleteIcon />,
// onClick: onDeleteClick,
// },
],
[filteredItems]
);
@@ -171,7 +175,7 @@ const RSSOverview: React.FC<Props> = ({ items }) => {
}}
onReset={onReset}
/>
<SearchResults<ItemsResult>
<EditableSearchResults<ItemsResult>
items={filteredItems}
columns={columns}
setPagingController={setPagingController}


+ 197
- 0
src/components/SearchResults/EditableSearchResults.tsx 파일 보기

@@ -0,0 +1,197 @@
"use client";

import React, {useEffect, useState} from "react";
import Paper from "@mui/material/Paper";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import IconButton from "@mui/material/IconButton";
import EditIcon from "@mui/icons-material/Edit";
import SaveIcon from "@mui/icons-material/Save";
import CancelIcon from "@mui/icons-material/Close";
import DeleteIcon from "@mui/icons-material/Delete";
import TextField from "@mui/material/TextField";
import MultiSelect from "@/components/SearchBox/MultiSelect";

export interface ResultWithId {
id: string | number;
}

interface BaseColumn<T extends ResultWithId> {
name: keyof T;
label: string;
type: string;
options: T[];
}

interface ColumnWithAction<T extends ResultWithId> extends BaseColumn<T> {
onClick: (item: T) => void;
buttonIcon: React.ReactNode;
buttonColor?: "inherit" | "default" | "primary" | "secondary";
}

export type Column<T extends ResultWithId> =
| BaseColumn<T>
| ColumnWithAction<T>;

interface Props<T extends ResultWithId> {
items: T[],
columns: Column<T>[],
noWrapper?: boolean,
setPagingController: (value: { pageNum: number; pageSize: number; totalCount: number }) => void,
pagingController: { pageNum: number; pageSize: number; totalCount: number },
isAutoPaging: boolean
}

function EditableSearchResults<T extends ResultWithId>({
items,
columns,
noWrapper,
pagingController,
setPagingController,
isAutoPaging = true,
}: Props<T>) {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [editingRowId, setEditingRowId] = useState<number | null>(null);
const [editedItems, setEditedItems] = useState<T[]>(items);

useEffect(()=>{
setEditedItems(items)
},[items])
const handleChangePage = (_event: unknown, newPage: number) => {
setPage(newPage);
setPagingController({ ...pagingController, pageNum: newPage + 1 });
};

const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
setRowsPerPage(+event.target.value);
setPage(0);
setPagingController({ ...pagingController, pageSize: +event.target.value, pageNum: 1 });
};

const handleEditClick = (id: number) => {
setEditingRowId(id);
};

const handleSaveClick = (item: T) => {
setEditingRowId(null);
// Call API or any save logic here
setEditedItems((prev) =>
prev.map((row) => (row.id === item.id ? { ...row } : row))
);
};

const handleInputChange = (id: number, field: keyof T, value: string | number[]) => {
setEditedItems((prev) =>
prev.map((item) =>
item.id === id ? { ...item, [field]: value } : item
)
);
};

const handleDeleteClick = (id: number) => {
// Implement delete logic here
setEditedItems((prev) => prev.filter(item => item.id !== id));
};

const table = (
<>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader>
<TableHead>
<TableRow>
<TableCell>Actions</TableCell> {/* Action Column Header */}
{columns.map((column, idx) => (
<TableCell key={`${column.name.toString()}${idx}`}>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => (
<TableRow hover tabIndex={-1} key={item.id}>
<TableCell>
{editingRowId === item.id ? (
<>
<IconButton onClick={() => handleSaveClick(item)}>
<SaveIcon />
</IconButton>
<IconButton onClick={() => setEditingRowId(null)}>
<CancelIcon />
</IconButton>
</>
) : (
<>
<IconButton onClick={() => handleEditClick(item.id as number)}>
<EditIcon />
</IconButton>
<IconButton onClick={() => handleDeleteClick(item.id as number)}>
<DeleteIcon />
</IconButton>
</>
)}
</TableCell>
{columns.map((column, idx) => {
const columnName = column.name;

return (
<TableCell key={`${columnName.toString()}-${idx}`}>
{editingRowId === item.id ? (
(() => {
switch (column.type) {
case 'input':
return (
<TextField
fullWidth
defaultValue={item[columnName] as string}
onChange={(e) => handleInputChange(item.id as number, columnName, e.target.value)}
/>
);
case 'multi-select':
return (
<MultiSelect
//label={column.label}
options={column.options}
selectedValues={[]}
onChange={(selectedValues) => handleInputChange(item.id as number, columnName, selectedValues)}
/>
);
default:
return null; // Handle any default case if needed
}
})()
) : (
<span onDoubleClick={() => handleEditClick(item.id as number)}>
{item[columnName] as string}
</span>
)}
</TableCell>
);
})}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={pagingController.totalCount === 0 ? editedItems.length : pagingController.totalCount}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</>
);

return noWrapper ? table : <Paper sx={{ overflow: "hidden" }}>{table}</Paper>;
}

export default EditableSearchResults;

불러오는 중...
취소
저장