Skip to content

Commit

Permalink
Merge pull request #471 from bluewave-labs/466-add-duplicate-button
Browse files Browse the repository at this point in the history
466 add duplicate button
  • Loading branch information
erenfn authored Jan 7, 2025
2 parents c0fd8aa + 77d4926 commit 50fb7dc
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 11 deletions.
4 changes: 3 additions & 1 deletion frontend/src/scenes/banner/BannerDefaultPage.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import { useLocation } from "react-router-dom";
import { ACTIVITY_TYPES_INFO } from "../../data/guideMainPageData";
import { deleteBanner, getBanners } from "../../services/bannerServices";
import { addBanner, getBannerById, deleteBanner, getBanners } from "../../services/bannerServices";
import DefaultPageTemplate from "../../templates/DefaultPageTemplate/DefaultPageTemplate";
import { useDialog } from "../../templates/GuideTemplate/GuideTemplateContext";
import BannerPage from "./CreateBannerPage";
Expand Down Expand Up @@ -30,6 +30,8 @@ const BannerDefaultPage = () => {
itemTypeInfo={ACTIVITY_TYPES_INFO.BANNERS}
getItemDetails={getBannerDetails}
itemsUpdated={itemsUpdated}
getItemById={getBannerById}
duplicateItem={addBanner}
/>
{isOpen && (
<BannerPage
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/scenes/hints/HintDefaultPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useLocation } from "react-router-dom"
import DefaultPageTemplate from "../../templates/DefaultPageTemplate/DefaultPageTemplate";
import CreateHintPage from "./CreateHintPage";
import { ACTIVITY_TYPES_INFO } from "../../data/guideMainPageData";
import { getHints, deleteHint } from '../../services/hintServices';
import { addHint, getHintById, getHints, deleteHint } from '../../services/hintServices';
import { useDialog } from "../../templates/GuideTemplate/GuideTemplateContext";

const HintDefaultPage = () => {
Expand All @@ -29,6 +29,8 @@ const HintDefaultPage = () => {
itemTypeInfo={ACTIVITY_TYPES_INFO.HINTS}
getItemDetails={getHintDetails}
itemsUpdated={itemsUpdated}
getItemById={getHintById}
duplicateItem={addHint}
/>
{isOpen && (
<CreateHintPage
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/scenes/links/LinksDefaultPage.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { ACTIVITY_TYPES_INFO } from "../../data/guideMainPageData";
import { deleteHelper, getHelpers } from "../../services/helperLinkService";
import { createHelper, getHelperById, deleteHelper, getHelpers } from "../../services/helperLinkService";
import HelperLinkProvider from "../../services/linksProvider";
import DefaultPageTemplate from "../../templates/DefaultPageTemplate/DefaultPageTemplate";
import { useDialog } from "../../templates/GuideTemplate/GuideTemplateContext";
Expand Down Expand Up @@ -41,6 +41,8 @@ const LinksDefaultPage = () => {
itemType={ACTIVITY_TYPES_INFO.HELPERLINKS}
itemTypeInfo={ACTIVITY_TYPES_INFO.HELPERLINKS}
getItemDetails={getItemDetails}
getItemById={getHelperById}
duplicateItem={createHelper}
/>
</div>
</HelperLinkProvider>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/scenes/popup/PopupDefaultPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from 'react';
import {useLocation} from "react-router-dom"
import DefaultPageTemplate from '../../templates/DefaultPageTemplate/DefaultPageTemplate';
import CreatePopupPage from './CreatePopupPage';
import { getPopups, deletePopup } from '../../services/popupServices';
import { addPopup, getPopupById, getPopups, deletePopup } from '../../services/popupServices';
import { ACTIVITY_TYPES_INFO } from '../../data/guideMainPageData';
import { useDialog } from '../../templates/GuideTemplate/GuideTemplateContext';

Expand Down Expand Up @@ -30,6 +30,8 @@ const PopupDefaultPage = () => {
itemTypeInfo={ACTIVITY_TYPES_INFO.POPUPS}
getItemDetails={getPopupDetails}
itemsUpdated={itemsUpdated}
getItemById={getPopupById}
duplicateItem={addPopup}
/>
{isOpen && (
<CreatePopupPage
Expand Down
34 changes: 31 additions & 3 deletions frontend/src/templates/DefaultPageTemplate/DefaultPageTemplate.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import { renderIfAuthorized } from '../../utils/generalHelper';
import { useDialog } from "../GuideTemplate/GuideTemplateContext";


const DefaultPageTemplate = ({ getItems, deleteItem, setIsEdit, setItemId, itemType, itemTypeInfo, getItemDetails, itemsUpdated }) => {
const DefaultPageTemplate = ({ getItems, deleteItem, setIsEdit, setItemId, itemType, itemTypeInfo, getItemDetails, itemsUpdated, getItemById, duplicateItem }) => {
const [items, setItems] = useState([]);
const [isPopupOpen, setPopupOpen] = useState(false);
const [itemToDelete, setItemToDelete] = useState();
const [itemDeleted, setItemDeleted] = useState(false);
const [itemsDuplicated, setItemsDuplicated] = useState(false);
const [loading, setLoading] = useState(true);
const [load, setLoad] = useState(true)
const { userInfo } = useAuth();
Expand All @@ -33,6 +34,7 @@ const DefaultPageTemplate = ({ getItems, deleteItem, setIsEdit, setItemId, itemT
setItemId(null);
openDialog();
};

const handleDelete = async () => {
try {
await deleteItem(itemToDelete);
Expand All @@ -47,6 +49,30 @@ const DefaultPageTemplate = ({ getItems, deleteItem, setIsEdit, setItemId, itemT
}
};

const duplicateHandler = async (id) => {
try {
if (itemType === 'helper links') {
const { createdBy, id: fetchedId, links, ...helper } = await getItemById(id);
const updatedLinks = links.map(({ id, ...data }) => data);

await duplicateItem(helper, updatedLinks);

} else {
const { createdBy, id: fetchedId, ...data } = await getItemById(id);
await duplicateItem(data);
}

toastEmitter.emit(TOAST_EMITTER_KEY, `${itemType.charAt(0).toUpperCase() + itemType.slice(1, -1)} duplicated successfully`);

setItemsDuplicated((prev) => !prev);
} catch (error) {
const errorMessage = error.response?.data?.message
? `Error: ${error.response.data.message}`
: 'An unexpected error occurred. Please try again.';
toastEmitter.emit(TOAST_EMITTER_KEY, errorMessage);
}
};

const handleOpenPopup = (id) => {
setItemToDelete(id);
setPopupOpen(true);
Expand Down Expand Up @@ -74,14 +100,15 @@ const DefaultPageTemplate = ({ getItems, deleteItem, setIsEdit, setItemId, itemT
}
};
fetchData();
}, [itemDeleted, itemsUpdated]);
}, [itemDeleted, itemsUpdated, itemsDuplicated]);

const mappedItems = useMemo(() => items.map(item => ({
idItem: item.id,
...getItemDetails(item),
onDelete: () => handleOpenPopup(item.id),
onEdit: () => openEditPopupDialog(item.id),
})), [items, getItemDetails, handleOpenPopup, openNewPopupDialog]);
onDuplicate: () => duplicateHandler(item.id)
})), [items, getItemDetails, handleOpenPopup, openNewPopupDialog, duplicateHandler]);

return (
<>
Expand Down Expand Up @@ -118,6 +145,7 @@ DefaultPageTemplate.propTypes = {
itemType: PropTypes.string.isRequired,
itemTypeInfo: PropTypes.string.isRequired,
getItemDetails: PropTypes.func.isRequired,
duplicateItem: PropTypes.func.isRequired,
};

export default DefaultPageTemplate;
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const List = ({ items }) => {
onClick={() => {}}
onDelete={item.onDelete}
onEdit={item.onEdit}
onDuplicate={item.onDuplicate}
/>
))}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { useState, useEffect } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { IconButton, useTheme } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
import CircleIcon from '@mui/icons-material/Circle';
import ContentCopyTwoToneIcon from '@mui/icons-material/ContentCopyTwoTone';
import './ListItem.css';
import { useAuth } from '../../../../../services/authProvider';
import { renderIfAuthorized } from '../../../../../utils/generalHelper';

const ListItem = ({ title, text, id, onClick, onDelete, onEdit }) => {
const ListItem = ({ title, text, id, onClick, onDelete, onEdit, onDuplicate }) => {
const theme = useTheme();
const { userInfo } = useAuth();
const role = userInfo.role;
Expand All @@ -26,16 +27,20 @@ const ListItem = ({ title, text, id, onClick, onDelete, onEdit }) => {
{text && <p>{text}</p>}
{id && <p className="item-id">ID: {id}</p>}
</div>

<div className="list-item-actions">
{renderIfAuthorized(role, 'admin',
<>
<IconButton onClick={onDuplicate}>
<ContentCopyTwoToneIcon sx={{ color: 'var(--main-text-color)' }} />
</IconButton>
<IconButton onClick={onEdit}>
<EditIcon />
</IconButton>
)}
{renderIfAuthorized(role, 'admin',
<IconButton onClick={onDelete}>
<DeleteIcon />
</IconButton>
</>
)}
</div>
</div>
Expand All @@ -49,6 +54,7 @@ ListItem.propTypes = {
onClick: PropTypes.func,
onDelete: PropTypes.func,
onEdit: PropTypes.func,
onDuplicate: PropTypes.func,
};

export default ListItem;

0 comments on commit 50fb7dc

Please sign in to comment.