Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show banner popup items #152

Merged
merged 11 commits into from
Aug 23, 2024
Merged
13 changes: 13 additions & 0 deletions backend/src/controllers/banner.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@ class BannerController {
res.status(statusCode).json(payload);
}
}
async getBanners(req, res) {
try {
const userId = req.user.id;
const banners = await bannerService.getBanners(userId);
res.status(200).json(banners);
} catch (err) {
const { statusCode, payload } = internalServerError(
"GET\_BANNERS_ERROR",
err.message,
);
res.status(statusCode).json(payload);
}
}
}

module.exports = new BannerController();
14 changes: 14 additions & 0 deletions backend/src/controllers/popupController.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,20 @@ class PopupController {
res.status(statusCode).json(payload);
}
}

async getPopups(req, res) {
try {
const userId = req.user.id;
const popups = await popupService.getPopups(userId);
res.status(200).json(popups);
} catch (err) {
const { statusCode, payload } = internalServerError(
"GET_POPUPS_ERROR",
err.message,
);
res.status(statusCode).json(payload);
}
}
}

module.exports = new PopupController();
5 changes: 5 additions & 0 deletions backend/src/models/Banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ module.exports = (sequelize, DataTypes) => {
allowNull: false,
defaultValue: "#FFFFFF",
},
bannerText: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: "",
},

createdBy: {
type: DataTypes.INTEGER,
Expand Down
10 changes: 10 additions & 0 deletions backend/src/models/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ module.exports = (sequelize, DataTypes) => {
allowNull: false,
defaultValue: "#FFFFFF",
},
header: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: "",
},
content: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: "",
},
createdBy: {
type: DataTypes.INTEGER,
allowNull: false,
Expand Down
1 change: 1 addition & 0 deletions backend/src/routes/banner.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ router.post("/add_banner", authenticateJWT, bannerController.addBanner);
router.delete("/delete_banner/:id", authenticateJWT, bannerController.deleteBanner);
router.put("/edit_banner/:id", authenticateJWT, bannerController.editBanner);
router.get("/all_banners", authenticateJWT, bannerController.getAllBanners);
router.get("/banners", authenticateJWT, bannerController.getBanners);

module.exports = router;
1 change: 1 addition & 0 deletions backend/src/routes/popup.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ router.post("/add_popup", authenticateJWT, popupController.addPopup);
router.delete("/delete_popup/:id", authenticateJWT, popupController.deletePopup);
router.put("/edit_popup/:id", authenticateJWT, popupController.editPopup);
router.get("/all_popups", authenticateJWT, popupController.getAllPopups);
router.get("/popups", authenticateJWT, popupController.getPopups);

module.exports = router;
9 changes: 9 additions & 0 deletions backend/src/service/banner.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ class BannerService {
});
}

async getBanners(userId) {
return await Banner.findAll({
where: {
createdBy: userId
},
include: [{ model: db.User, as: "creator" }],
});
}

async createBanner(data) {
return await Banner.create(data);
}
Expand Down
9 changes: 9 additions & 0 deletions backend/src/service/popup.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ class PopupService {
});
}

async getPopups(userId) {
return await Popup.findAll({
where: {
createdBy: userId
},
include: [{ model: db.User, as: "creator" }],
});
}

async createPopup(data) {
return await Popup.create(data);
}
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"classnames": "^2.5.1",
"date-fns": "^3.6.0",
"dompurify": "^3.1.6",
"js-cookie": "^3.0.5",
"punycode": "^2.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ function App() {
<Route path="/check-email" element={<CheckYourEmailPage />} />
<Route path="/set-new-password" element={<SetNewPasswordPage />} />
<Route path="/progress-steps" element={<ProgressStepsMain />} />
<Route path="/banner/create" element={<BannerPage />} />
<Route path="/popup/create" element={<CreatePopupPage />} />
<Route path="/banner" element={<BannerDefaultPage />} />
<Route path="/popup" element={<PopupDefaultPage />} />
<Route path="/banner/create" element={<Private Component={BannerPage} />} />
<Route path="/popup/create" element={<Private Component={CreatePopupPage} />} />
<Route path="/banner" element={<Private Component={BannerDefaultPage} />} />
<Route path="/popup" element={<Private Component={PopupDefaultPage }/>} />
<Route path="/link" element={<LinksDefaultPage />} />
<Route path="/tour" element={<ToursDefaultPage />} />
<Route path="/hint" element={<HintDefaultPage />} />
Expand Down
31 changes: 23 additions & 8 deletions frontend/src/components/Header/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
import React, { useState } from 'react';
import './Header.css';
import React, { useState, useEffect } from 'react';
import './Header.css';
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
import DropdownMenu from './DropdownMenu/DropdownMenu';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import Avatar from './Avatar/Avatar';
import Avatar from './Avatar/Avatar';
import { getCurrentUser } from '../../services/loginServices';
import Cookies from 'js-cookie';

function Header({ }) {
const initialUsername = Cookies.get('username') || 'username';
const initialRole = Cookies.get('role') || 'role';

function Header({ user }) {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [user, setUser] = useState({ username: initialUsername, role: initialRole });

useEffect(() => {
const fetchUser = async () => {
const userData = await getCurrentUser();
setUser(userData);
};
fetchUser();
}, [user]);


const handleDropdownClick = () => {
setIsDropdownOpen(!isDropdownOpen);
};

return (
<div className="top-banner">
<div className="logo">BlueWave Onboard</div>
<div className="user-info">
<Avatar src="/vendetta.png" alt="User" size="medium"/>
<div className="logo">BlueWave Onboard</div>
<div className="user-info">
<Avatar src="/vendetta.png" alt="User" size="medium" />
<div className="user-details">
<div className="user-name">{user.username}</div>
<div className="user-role">{user.role}</div>
</div>
<button className="dropdown-button" onClick={handleDropdownClick}>
{isDropdownOpen ? <>< KeyboardArrowUpIcon/><DropdownMenu /></> : <KeyboardArrowDownOutlinedIcon /> }
{isDropdownOpen ? <>< KeyboardArrowUpIcon /><DropdownMenu /></> : <KeyboardArrowDownOutlinedIcon />}
</button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ListItem from './ListItem/ListItem';

const List = ({ items, onSelectItem }) => {
return (
<div>
<>
{items.map(item => (
<ListItem
key={item.idItem}
Expand All @@ -16,7 +16,7 @@ const List = ({ items, onSelectItem }) => {
onEdit={item.onEdit}
/>
))}
</div>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
display: flex;
justify-content: space-between;
align-items: center;
width: 758px;
height: 78px;
padding: 10px;
border: 1px solid var(--grey-border);
border-radius: 10px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const ListItem = ({ title, text, id, onClick, onDelete, onEdit }) => {
ListItem.propTypes = {
title: PropTypes.string,
text: PropTypes.string,
id: PropTypes.string,
id: PropTypes.number,
onClick: PropTypes.func,
onDelete: PropTypes.func,
onEdit: PropTypes.func,
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/data/GuideMainPageData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const ACTIVITY_TYPES_INFO = {
HINTS: "hints",
POPUPS: "popups",
BANNERS: "banners",
HELPERLINKS: "helper links",
TOURS: "tours",
};

export const activityInfoData = {
[ACTIVITY_TYPES_INFO.POPUPS]: {
heading: "What is a popup?",
paragraph: "Popups can enhance user experience, communication, and engagement within a SaaS dashboard when used effectively \n Popups can display promotional messages, special offers, or discounts to encourage users to upgrade their subscription, purchase additional features, or engage more with the software \n They can also notify users about important updates, announcements, or events related to the software or their account.",
buttonText: "Create a new popup",
title: "All popups"
},
[ACTIVITY_TYPES_INFO.BANNERS]: {
heading: "What is a banner?",
paragraph: "A banner is a strip or bar typically displayed at the top or bottom of the user interface. \n Banners can be used to convey important announcements such as new features, product updates, scheduled maintenance, or system downtime. \n They can also display promotional messages, special offers, discounts, or upcoming events to attract users' attention and encourage engagement. \n Banners can effectively communicate important information to users without disrupting their workflow within the SaaS application",
buttonText: "Create a new banner",
title: "All banners"
},
};
91 changes: 75 additions & 16 deletions frontend/src/scenes/bannerPage/BannerDefaultPage.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,87 @@
import CreateActivityButton from "../../components/Button/CreateActivityButton/CreateActivityButton"
import HomePageTemplate from "../../templates/HomePageTemplate/HomePageTemplate"
import React, { useState, useEffect } from 'react';
import CreateActivityButton from "../../components/Button/CreateActivityButton/CreateActivityButton";
import HomePageTemplate from "../../templates/HomePageTemplate/HomePageTemplate";
import { ACTIVITY_TYPES } from "../../data/CreateActivityButtonData";
import ParagraphCSS from "../../components/ParagraphCSS/ParagraphCSS";
import { useNavigate } from 'react-router-dom';
import GuideMainPageTemplate from "../../templates/GuideMainPageTemplate/GuideMainPageTemplate";
import { getBanners } from "../../services/bannerServices";
import { ACTIVITY_TYPES_INFO } from '../../data/GuideMainPageData';

const BannerDefaultPage = () => {
const navigate = useNavigate();
const [banners, setBanners] = useState([]);
const [selectedItem, setSelectedItem] = useState(null);
const [isPopupOpen, setPopupOpen] = useState(false);

const handleSelect = (idItem) => {
setSelectedItem(idItem);
};

const handleDelete = () => {
setPopupOpen(false);
};

const handleOpenPopup = () => {
setPopupOpen(true);
};

const handleClosePopup = () => {
setPopupOpen(false);
};

const handleCreateItem = () => {
};

const navigateToCreate = () => {navigate('/banner/create')}

useEffect(() => {
const fetchBanners = async () => {
try {
const bannerData = await getBanners();
setBanners(bannerData);
} catch (error) {
console.error("Failed to fetch banners:", error);
}
};

fetchBanners();
}, []);

const style = {
"display": "flex",
"flex-direction": "column",
"width": "100%",
"justify-content": "center",
"align-items": "center",
}

display: "flex",
flexDirection: "column",
width: "100%",
justifyContent: "center",
alignItems: "center",
};

const items = banners.map(banners => ({
idItem: banners.id,
title: `Banner ${banners.id}`,
text: banners.bannerText,
onDelete: () => console.log(`Delete banner ${banners.id}`), // Placeholder for delete function
onEdit: () => console.log(`Edit banner ${banners.id}`), // Placeholder for edit function
}));

return (
<HomePageTemplate>
<div style={style}>
<ParagraphCSS />
<CreateActivityButton type={ACTIVITY_TYPES.BANNERS} onClick={() => navigate('/banner/create')}/>
</div>

{banners.length === 0 ? (
<div style={style}>
<ParagraphCSS />
<CreateActivityButton type={ACTIVITY_TYPES.BANNERS} onClick={navigateToCreate} />
</div>
) : (
<GuideMainPageTemplate items={items}
handleSelect={handleSelect}
handleDelete={handleDelete}
isPopupOpen={isPopupOpen}
handleClosePopup={handleClosePopup}
type={ACTIVITY_TYPES_INFO.BANNERS}
onClick={navigateToCreate}/>
)}
</HomePageTemplate>
)
);
}

export default BannerDefaultPage
export default BannerDefaultPage;
3 changes: 2 additions & 1 deletion frontend/src/scenes/bannerPage/BannerPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const BannerPage = () => {
fontColor:fontColor,
url:url,
position: isTopPosition ? 'top' : 'bottom',
closeButtonAction:buttonAction.toLowerCase()
closeButtonAction:buttonAction.toLowerCase(),
bannerText: bannerText
};
try {
const response = await addBanner(bannerData);
Expand Down
13 changes: 6 additions & 7 deletions frontend/src/scenes/dashboard/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,23 @@ import { useNavigate } from "react-router-dom";
const Dashboard = ({ username }) => {
const navigate = useNavigate();
const metrics = [
{ metricName: "Monthly active users", metricValue: 1000, changeRate: 10 },
{ metricName: "Tour views", metricValue: 5000, changeRate: 5 },
{ metricName: "Popup views", metricValue: 5000, changeRate: 5 },
{ metricName: "Hint views", metricValue: 2000, changeRate: -20 },
{ metricName: "Popup Views", metricValue: 3000, changeRate: 15 },
{ metricName: "Banner Views", metricValue: 3000, changeRate: 15 },
];

const buttons = [
{
placeholder: "Create a welcome tour",
onClick: () => navigate("/welcome-tour-route"),
placeholder: "Create a popup",
onClick: () => navigate("/popup/create"),
},
{
placeholder: "Add a hint to your app",
onClick: () => navigate("/hint-route"),
onClick: () => navigate("/hint/create"),
},
{
placeholder: "Create a new banner",
onClick: () => navigate("/new-banner-route"),
onClick: () => navigate("/banner/create"),
},
];
return (
Expand Down
Loading
Loading