Browse Source

Review Modal dynamic data load from API

master
Sourya Banerjee 6 months ago
parent
commit
d17a2811da
7 changed files with 181 additions and 85 deletions
  1. +10
    -0
      package-lock.json
  2. +1
    -0
      package.json
  3. +3
    -32
      src/app/(dashboard)/review/page.tsx
  4. +88
    -0
      src/components/reviewModal/ReviewModal.tsx
  5. +30
    -23
      src/components/reviewModal/components/reviewModalContent/ReviewModalContent.tsx
  6. +44
    -30
      src/components/table/TanStackTable.tsx
  7. +5
    -0
      yarn.lock

+ 10
- 0
package-lock.json View File

@ -16,6 +16,7 @@
"@mui/material-nextjs": "^5.16.6", "@mui/material-nextjs": "^5.16.6",
"@tanstack/react-table": "^8.20.1", "@tanstack/react-table": "^8.20.1",
"axios": "^1.7.3", "axios": "^1.7.3",
"moment": "^2.30.1",
"next": "14.2.5", "next": "14.2.5",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
@ -3842,6 +3843,15 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",


+ 1
- 0
package.json View File

@ -17,6 +17,7 @@
"@mui/material-nextjs": "^5.16.6", "@mui/material-nextjs": "^5.16.6",
"@tanstack/react-table": "^8.20.1", "@tanstack/react-table": "^8.20.1",
"axios": "^1.7.3", "axios": "^1.7.3",
"moment": "^2.30.1",
"next": "14.2.5", "next": "14.2.5",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",


+ 3
- 32
src/app/(dashboard)/review/page.tsx View File

@ -4,8 +4,9 @@ import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Modal from "@mui/material/Modal"; import Modal from "@mui/material/Modal";
import Stack from "@mui/material/Stack"; import Stack from "@mui/material/Stack";
import ReviewModalContent from "./reviewModalContent/ReviewModalContent";
import ReviewModalContent from "../../../components/reviewModal/components/reviewModalContent/ReviewModalContent";
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
import TanStackTable from "@/components/table/TanStackTable";
const style = { const style = {
position: "absolute" as "absolute", position: "absolute" as "absolute",
top: "50%", top: "50%",
@ -34,37 +35,7 @@ const labels: { [index: string]: string } = {
}; };
const HomePage = () => { const HomePage = () => {
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<Box>
<Button onClick={handleOpen}>Open modal</Button>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<Typography
variant="h5"
sx={{ lineHeight: 1, marginBlockEnd: "20px" }}
>
Reviews
</Typography>
<Stack
spacing={2}
direction={"column"}
sx={{ maxHeight: "350px", overflow: "auto" }}
>
<ReviewModalContent />
<ReviewModalContent />
</Stack>
</Box>
</Modal>
</Box>
);
return <Box>{/* <Button onClick={handleOpen}>Open modal</Button> */}</Box>;
}; };
export default HomePage; export default HomePage;

+ 88
- 0
src/components/reviewModal/ReviewModal.tsx View File

@ -0,0 +1,88 @@
"use client";
import Box from "@mui/material/Box";
import Modal from "@mui/material/Modal";
import Stack from "@mui/material/Stack";
import ReviewModalContent from "./components/reviewModalContent/ReviewModalContent";
import { Typography } from "@mui/material";
const style = {
position: "absolute" as "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "90%",
maxWidth: 400,
bgcolor: "background.paper",
border: "none",
boxShadow: 24,
borderRadius: 4,
paddingInline: 2,
paddingBlock: 4,
};
const labels: { [index: string]: string } = {
0.5: "Useless",
1: "Useless+",
1.5: "Poor",
2: "Poor+",
2.5: "Ok",
3: "Ok+",
3.5: "Good",
4: "Good+",
4.5: "Excellent",
5: "Excellent+",
};
interface ReviewModalProps {
open: boolean;
handleClose: () => void;
reviewModalData: ReviewModalData[];
}
export interface ReviewModalData {
reviewerName: string;
reviewerEmail: string;
date: string;
comment: string;
rating: number;
}
const ReviewModal = ({
open,
handleClose,
reviewModalData,
}: ReviewModalProps) => {
console.log("reviewModalData", reviewModalData);
return (
<Box>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<Typography
variant="h5"
sx={{ lineHeight: 1, marginBlockEnd: "20px" }}
>
Reviews
</Typography>
<Stack
spacing={2}
direction={"column"}
sx={{ maxHeight: "350px", overflow: "auto" }}
>
{reviewModalData.map((review: ReviewModalData, index: number) => (
<ReviewModalContent key={index} data={review} />
))}
</Stack>
</Box>
</Modal>
</Box>
);
};
export default ReviewModal;

src/app/(dashboard)/review/reviewModalContent/ReviewModalContent.tsx → src/components/reviewModal/components/reviewModalContent/ReviewModalContent.tsx View File

@ -3,11 +3,16 @@ import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import Rating from "@mui/material/Rating"; import Rating from "@mui/material/Rating";
import StarIcon from "@mui/icons-material/Star"; import StarIcon from "@mui/icons-material/Star";
import { Avatar } from "@mui/material";
import moment from "moment";
import { ReviewModalData } from "../../ReviewModal";
const ReviewModalContent = () => {
const [value, setValue] = React.useState<number | null>(2);
const [hover, setHover] = React.useState(-1);
interface ReviewModalContentProps {
data: ReviewModalData;
}
const ReviewModalContent = ({ data }: ReviewModalContentProps) => {
// const [value, setValue] = React.useState<number | null>(data?.rating);
// const [hover, setHover] = React.useState(-1);
return ( return (
<> <>
<Box <Box
@ -33,10 +38,10 @@ const ReviewModalContent = () => {
}} }}
> >
<Typography variant="body1" sx={{ m: 0, lineHeight: 1 }}> <Typography variant="body1" sx={{ m: 0, lineHeight: 1 }}>
Amit Roy
{data?.reviewerName}
</Typography> </Typography>
<Typography variant="caption" sx={{ m: 0 }}> <Typography variant="caption" sx={{ m: 0 }}>
amit.roy@sentientgeeks.com
{data?.reviewerEmail}
</Typography> </Typography>
</Box> </Box>
<Box <Box
@ -49,34 +54,36 @@ const ReviewModalContent = () => {
> >
<Rating <Rating
name="hover-feedback" name="hover-feedback"
value={value}
value={data?.rating}
size="small" size="small"
precision={0.5} precision={0.5}
onChange={(event, newValue) => {
setValue(newValue);
}}
onChangeActive={(event, newHover) => {
setHover(newHover);
}}
readOnly
// onChange={(event, newValue) => {
// setValue(newValue);
// }}
// onChangeActive={(event, newHover) => {
// setHover(newHover);
// }}
emptyIcon={ emptyIcon={
<StarIcon style={{ opacity: 0.55 }} fontSize="inherit" /> <StarIcon style={{ opacity: 0.55 }} fontSize="inherit" />
} }
/> />
<Typography
variant="caption"
display="block"
gutterBottom
sx={{ textAlign: "center", m: 0 }}
>
April 17, 03:30PM
</Typography>
{data?.date && (
<Typography
variant="caption"
display="block"
gutterBottom
sx={{ textAlign: "center", m: 0 }}
>
{moment(data?.date).format("MMMM D, hh:mmA")}
</Typography>
)}
</Box> </Box>
</Box> </Box>
</Box> </Box>
<Typography variant="body2" id="modal-modal-description" sx={{ mt: 2 }}> <Typography variant="body2" id="modal-modal-description" sx={{ mt: 2 }}>
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Temporibus
Dolorem."
{data?.comment}
</Typography> </Typography>
</Box> </Box>
</> </>

+ 44
- 30
src/components/table/TanStackTable.tsx View File

@ -8,9 +8,14 @@ import {
import styles from "./TanStackTable.module.scss"; import styles from "./TanStackTable.module.scss";
import axios from "axios"; import axios from "axios";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ReviewModal from "../reviewModal/ReviewModal";
const TanStackTable = () => { const TanStackTable = () => {
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [open, setOpen] = useState(false);
const [reviewModalData, setReviewModalData] = useState([]);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const columns: any = [ const columns: any = [
{ {
header: "ID", header: "ID",
@ -67,7 +72,9 @@ const TanStackTable = () => {
]; ];
const handleButtonClick = (rowData: any) => { const handleButtonClick = (rowData: any) => {
console.log("Button clicked for row:", rowData?.reviews);
setReviewModalData(rowData?.reviews);
handleOpen();
// console.log("Button clicked for row:", rowData?.reviews);
}; };
const table = useReactTable({ const table = useReactTable({
@ -85,35 +92,42 @@ const TanStackTable = () => {
}, []); }, []);
return ( return (
<div className="w3-container">
<table className="w3-table-all">
<thead>
{table.getHeaderGroups().map((headerGroup: any) => (
<tr key={headerGroup?.id}>
{headerGroup.headers.map((header: any) => (
<th key={header?.id}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row: any) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell: any) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<>
<div className="w3-container">
<table className="w3-table-all">
<thead>
{table.getHeaderGroups().map((headerGroup: any) => (
<tr key={headerGroup?.id}>
{headerGroup.headers.map((header: any) => (
<th key={header?.id}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row: any) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell: any) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<ReviewModal
open={open}
handleClose={handleClose}
reviewModalData={reviewModalData}
/>
</>
); );
}; };


+ 5
- 0
yarn.lock View File

@ -2176,6 +2176,11 @@ minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
moment@^2.30.1:
version "2.30.1"
resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
ms@^2.1.1, ms@2.1.2: ms@^2.1.1, ms@2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"


Loading…
Cancel
Save