This repository has been archived by the owner on Dec 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #49 from Cassianky/client-angely-surveys
[Admin] [Client] Surveys and Reviews
- Loading branch information
Showing
36 changed files
with
3,286 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import React from "react"; | ||
|
||
import styled from "@emotion/styled"; | ||
import { useTheme } from "@emotion/react"; | ||
import { Badge, CircularProgress, Tabs, Tab, Typography } from "@mui/material"; | ||
import { useEffect, useState } from "react"; | ||
import { | ||
useActivityStore, | ||
useAdminSurveyResponseStore, | ||
useBookingStore, | ||
useSnackbarStore, | ||
} from "../../zustand/GlobalStore"; | ||
import MainBodyContainer from "../common/MainBodyContainer"; | ||
|
||
import ReviewActivityTable from "./ReviewActivityTable"; | ||
function ActivityReviews() { | ||
const theme = useTheme(); | ||
|
||
const { openSnackbar } = useSnackbarStore(); | ||
const { activities, getActivity, isLoading, pendingApprovalActivities } = | ||
useActivityStore(); | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
await getActivity(); | ||
}; | ||
fetchData(); | ||
}, [getActivity]); | ||
|
||
if (isLoading) { | ||
return <CircularProgress />; | ||
} | ||
return ( | ||
<MainBodyContainer | ||
hasBackButton={false} | ||
breadcrumbNames={[]} | ||
breadcrumbLinks={[]} | ||
currentBreadcrumbName={"Manage Reviews"} | ||
> | ||
<Typography | ||
fontSize={25} | ||
fontWeight={700} | ||
noWrap | ||
component="div" | ||
color={theme.palette.primary.main} | ||
> | ||
Manage Reviews | ||
</Typography> | ||
{activities && <ReviewActivityTable activities={activities} />} | ||
</MainBodyContainer> | ||
); | ||
} | ||
|
||
export default ActivityReviews; |
68 changes: 68 additions & 0 deletions
68
admin-frontend/src/components/review/ManageReviewsForActivity.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React from "react"; | ||
|
||
import { useTheme } from "@emotion/react"; | ||
import { CircularProgress, Typography } from "@mui/material"; | ||
import { useEffect } from "react"; | ||
import { useParams } from "react-router-dom"; | ||
import { | ||
useActivityStore, | ||
useReviewStore, | ||
useSnackbarStore | ||
} from "../../zustand/GlobalStore"; | ||
import MainBodyContainer from "../common/MainBodyContainer"; | ||
|
||
import ManageReviewsForActivityTable from "./ManageReviewsForActivityTable"; | ||
|
||
function ManageReviewsForActivity() { | ||
const theme = useTheme(); | ||
const { activityId } = useParams(); | ||
|
||
const { openSnackbar } = useSnackbarStore(); | ||
const { activities, getActivity, isLoading, pendingApprovalActivities } = | ||
useActivityStore(); | ||
|
||
const { reviews, activity, getReviewsForActivity, toggleReviewVisibility } = | ||
useReviewStore(); | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
await getReviewsForActivity(activityId); | ||
}; | ||
fetchData(); | ||
}, [getActivity]); | ||
console.log(reviews); | ||
|
||
const handleToggle = async (reviewId) => { | ||
try { | ||
await toggleReviewVisibility(reviewId); | ||
console.log("after handle toggle", reviews) | ||
} catch (error) { | ||
console.error(error); | ||
openSnackbar("An error occurred", "error"); | ||
} | ||
}; | ||
if (isLoading) { | ||
return <CircularProgress />; | ||
} | ||
return ( | ||
<MainBodyContainer | ||
hasBackButton={true} | ||
breadcrumbNames={["Manage Reviews"]} | ||
breadcrumbLinks={["/reviews"]} | ||
currentBreadcrumbName={`For ${activity?.title || "Loading"}`} | ||
> | ||
<Typography | ||
fontSize={25} | ||
fontWeight={700} | ||
noWrap | ||
component="div" | ||
color={theme.palette.primary.main} | ||
> | ||
Manage Reviews For {activity?.title} | ||
</Typography> | ||
{reviews && <ManageReviewsForActivityTable reviews={reviews} handleToggle={handleToggle} />} | ||
</MainBodyContainer> | ||
); | ||
} | ||
|
||
export default ManageReviewsForActivity; |
170 changes: 170 additions & 0 deletions
170
admin-frontend/src/components/review/ManageReviewsForActivityTable.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import { | ||
Dialog, | ||
DialogContent, | ||
Rating, | ||
Stack, | ||
Switch, | ||
Typography, | ||
} from "@mui/material"; | ||
|
||
import Box from "@mui/material/Box"; | ||
import { DataGrid, GridToolbarFilterButton } from "@mui/x-data-grid"; | ||
import PropTypes from "prop-types"; | ||
import React, { useEffect, useState } from "react"; | ||
|
||
const ManageReviewsForActivityTable = ({ reviews, handleToggle }) => { | ||
const [currentTabRows, setCurrentTabRows] = useState(reviews); | ||
const [selectedReview, setSelectedReview] = useState(null); | ||
|
||
useEffect(() => { | ||
setCurrentTabRows(reviews); | ||
}, [reviews]); | ||
|
||
const columns = [ | ||
{ | ||
field: "rating", | ||
headerName: "Rating", | ||
flex: 1, | ||
renderCell: (params) => { | ||
const ratingValue = params.value; | ||
return ( | ||
<Stack | ||
direction="row" | ||
spacing={1} | ||
justifyContent="center" | ||
alignItems="center" | ||
> | ||
<Rating name="read-only" value={ratingValue} readOnly /> | ||
<div>{ratingValue}</div> | ||
</Stack> | ||
); | ||
}, | ||
}, | ||
{ | ||
field: "comment", | ||
headerName: "Client Comment", | ||
flex: 1, | ||
}, | ||
{ | ||
field: "client", | ||
headerName: "By Client", | ||
flex: 1, | ||
renderCell: (params) => { | ||
return params.row.client.name; | ||
}, | ||
}, | ||
{ | ||
field: "date", | ||
headerName: "Date Submitted", | ||
flex: 1, | ||
renderCell: (params) => { | ||
const date = new Date(params.value); | ||
const formattedDate = date.toLocaleDateString(undefined, { | ||
year: "2-digit", | ||
month: "2-digit", | ||
day: "2-digit", | ||
}); | ||
const formattedTime = date.toLocaleTimeString(undefined, { | ||
hour: "numeric", | ||
minute: "numeric", | ||
hour12: true, | ||
}); | ||
return ( | ||
<div style={{ display: "flex" }}> | ||
<Typography color="#9F91CC" fontSize={"0.875rem"}> | ||
Submitted on | ||
<span style={{ color: "black" }}> | ||
{formattedDate} at {formattedTime} | ||
</span> | ||
</Typography> | ||
</div> | ||
); | ||
}, | ||
}, | ||
{ | ||
field: "actions", | ||
type: "actions", | ||
flex: 1, | ||
headerName: "Shown", | ||
renderCell: (params) => { | ||
const isChecked = !params.row.hidden; | ||
return ( | ||
<div | ||
style={{ | ||
display: "flex", | ||
paddingTop: 3, | ||
paddingBottom: 3, | ||
alignItems: "center", | ||
}} | ||
> | ||
<Switch | ||
color="primary" | ||
checked={isChecked} | ||
onChange={() => handleToggle(params.row._id)} | ||
/> | ||
</div> | ||
); | ||
}, | ||
}, | ||
]; | ||
|
||
const handleRowClick = (params) => { | ||
setSelectedReview(params.row); | ||
}; | ||
|
||
const handleClose = () => { | ||
setSelectedReview(null); | ||
}; | ||
|
||
return ( | ||
<Box> | ||
<div style={{ height: 500, width: "99%" }}> | ||
<DataGrid | ||
initialState={{ | ||
pagination: { | ||
paginationModel: { pageSize: 25, page: 0 }, | ||
}, | ||
}} | ||
getRowId={(row) => row._id} | ||
rows={currentTabRows} | ||
columns={columns} | ||
slots={{ | ||
toolbar: GridToolbarFilterButton, | ||
}} | ||
disableRowSelectionOnClick | ||
getRowHeight={() => "auto"} | ||
onRowClick={handleRowClick} | ||
sx={{ | ||
borderRadius: "10px", | ||
boxShadow: "4px 4px 0px 0px rgb(159 145 204 / 40%)", | ||
border: "none", | ||
backgroundColor: "white", | ||
"& .MuiDataGrid-cell:hover": { | ||
cursor: "pointer", | ||
}, | ||
}} | ||
/> | ||
</div> | ||
<Dialog open={selectedReview !== null} onClose={handleClose} fullWidth> | ||
<DialogContent> | ||
{selectedReview && ( | ||
<div> | ||
<Typography variant="h6">Rating:</Typography> | ||
<Rating name="read-only" value={selectedReview.rating} readOnly /> | ||
<Typography variant="h6">Comment:</Typography> | ||
<Typography>{selectedReview.comment}</Typography> | ||
<Typography variant="h6">By:</Typography> | ||
<Typography>{selectedReview.client.name}</Typography> | ||
</div> | ||
)} | ||
</DialogContent> | ||
</Dialog> | ||
</Box> | ||
); | ||
}; | ||
|
||
ManageReviewsForActivityTable.propTypes = { | ||
reviews: PropTypes.array.isRequired, | ||
}; | ||
|
||
export default ManageReviewsForActivityTable; |
Oops, something went wrong.