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

Feature/issue 75 develop a page for creating new product tour items #108

Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
406f916
Issue 75: resolve warnings related to demodata for list item
SimerdeepSinghGrewal Jul 21, 2024
a445c4f
Issue 75: remove isRequired from all propTypes
SimerdeepSinghGrewal Jul 22, 2024
97ccbb6
Issue 75: add homePageTempelate to home.jsx
SimerdeepSinghGrewal Jul 24, 2024
9e2a24d
Merge branch 'develop' into feature/Issue-75-Develop-a-page-for-creat…
SimerdeepSinghGrewal Jul 24, 2024
4542876
Issue 75: update leftmenu navigate
SimerdeepSinghGrewal Jul 25, 2024
f1c2364
Merge branch 'feature/Issue-75-Develop-a-page-for-creating-new-produc…
SimerdeepSinghGrewal Jul 25, 2024
cd217bf
Issue 75: change svg icon and use var colors
SimerdeepSinghGrewal Jul 27, 2024
02e08f7
Issue75: update theme and update listitem to use theme
SimerdeepSinghGrewal Jul 30, 2024
e979942
Issue 75: update App.jsx
SimerdeepSinghGrewal Aug 1, 2024
15adcad
Merge branch 'develop' into feature/Issue-75-Develop-a-page-for-creat…
uparkalau Aug 3, 2024
6fcf50e
Merge branch 'develop' into feature/Issue-75-Develop-a-page-for-creat…
SimerdeepSinghGrewal Aug 6, 2024
480ac33
Merge branch 'feature/Issue-75-Develop-a-page-for-creating-new-produc…
SimerdeepSinghGrewal Aug 6, 2024
a423b86
Issue 75: update Home.jsx from develop, changed tourdefaultpage butto…
SimerdeepSinghGrewal Aug 9, 2024
629cda4
Issue 75: add components to TourComponents folder
SimerdeepSinghGrewal Aug 9, 2024
76645ec
Merge branch 'develop' of https://github.com/bluewave-labs/bluewave-o…
SimerdeepSinghGrewal Aug 9, 2024
163fdd1
Merge branch 'develop' into feature/Issue-75-Develop-a-page-for-creat…
SimerdeepSinghGrewal Aug 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions frontend/src/assets/theme.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { createTheme } from "@mui/material";

const theme = createTheme({
palette: {
primary: {
main: "#7f56d9",
},
background: {
default: "#FFFFFF",
},
},
components: {
MuiAppBar: {
styleOverrides: {
28 changes: 28 additions & 0 deletions frontend/src/components/List/List.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import ListItem from './ListItem/ListItem';

const List = ({ items, onSelectItem }) => {
return (
<div>
{items.map(item => (
<ListItem
key={item.idItem}
title={item.title}
text={item.text}
id={item.idItem}
onClick={() => onSelectItem(item.idItem)}
onDelete={item.onDelete}
onEdit={item.onEdit}
/>
))}
</div>
);
};

List.propTypes = {
items: PropTypes.arrayOf(PropTypes.object),
onSelectItem: PropTypes.func,
};

export default List;
81 changes: 81 additions & 0 deletions frontend/src/components/List/ListItem/ListItem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
width: 758px;
height: 78px;
padding: 10px;
border: 1px solid var(--grey-border);
border-radius: 10px;
cursor: pointer;
margin-bottom: 30px;
}

.list-item:hover,
.list-item:focus {
border: 1px solid var(--main-purple);
}

.list-item-info {
display: flex;
flex-direction: column;
margin-left: 10px;
}

.list-item-header {
display: flex;
align-items: center;
}

.list-item-icon-container {
display: flex;
align-items: center;
position: relative;
width: 24px;
height: 24px;
margin-right: 10px;
}

.list-item-icon {
width: 12px;
height: 12px;
color: #7F56D9;
}

.list-item-dot {
position: absolute;
top: 50%;
left: 50%;
width: 10px;
height: 10px;
background-color: #FFFFFF;
border-radius: 50%;
transform: translate(-50%, -50%);
}

.list-item-info h4 {
margin: 0;
font-size: 16px;
color: #344054;
}

.list-item-info p {
margin: 2px 0 0 33px;
font-size: 14px;
color: #667085;
}

.item-id {
margin: 2px 0 0 0;
font-size: 12px;
color: #667085;
}

.list-item-actions {
display: flex;
align-items: center;
}

.list-item-actions .MuiIconButton-root {
color: #344054;
}
46 changes: 46 additions & 0 deletions frontend/src/components/List/ListItem/ListItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import { IconButton, useTheme } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
import SettingsIcon from '@mui/icons-material/Settings';
import CircleIcon from '@mui/icons-material/Circle';
import './ListItem.css';

const ListItem = ({ title, text, id, onClick, onDelete, onEdit }) => {
const theme = useTheme();

return (
<div className="list-item" onClick={onClick}>
<div className="list-item-info">
<div className="list-item-header">
<div className="list-item-icon-container">
<CircleIcon className="list-item-icon" style={{ fill: theme.palette.primary.main }} />
<div className="list-item-dot" style={{ backgroundColor: theme.palette.background.default }}></div>
</div>
<h4>{title}</h4>
</div>
{text && <p>{text}</p>}
{id && <p className="item-id">ID: {id}</p>}
</div>
<div className="list-item-actions">
<IconButton onClick={onEdit}>
<SettingsIcon />
</IconButton>
<IconButton onClick={onDelete}>
<DeleteIcon />
</IconButton>
</div>
</div>
);
};

ListItem.propTypes = {
title: PropTypes.string,
text: PropTypes.string,
id: PropTypes.string,
onClick: PropTypes.func,
onDelete: PropTypes.func,
onEdit: PropTypes.func,
};

export default ListItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Button } from '@mui/material';

const ConfirmationPopup = ({ open, onConfirm, onCancel }) => {
return (
<Dialog open={open} onClose={onCancel}>
<DialogTitle>Confirm Action</DialogTitle>
<DialogContent>
<DialogContentText>Are you sure you want to perform this action?</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>Cancel</Button>
<Button onClick={onConfirm} color="primary">Confirm</Button>
</DialogActions>
</Dialog>
);
};

ConfirmationPopup.propTypes = {
open: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
};

export default ConfirmationPopup;
13 changes: 13 additions & 0 deletions frontend/src/components/TourComponents/ContentArea/ContentArea.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

import React from 'react';
import PropTypes from 'prop-types';

const ContentArea = ({ children }) => {
return <div className="content-area">{children}</div>;
};

ContentArea.propTypes = {
children: PropTypes.node,
};

export default ContentArea;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';

const ContentHeader = ({ title }) => {
return <h2 className="content-header">{title}</h2>;
};

ContentHeader.propTypes = {
title: PropTypes.string,
};

export default ContentHeader;
21 changes: 21 additions & 0 deletions frontend/src/components/TourComponents/InfoTooltip/InfoTooltip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip, IconButton } from '@mui/material';
import InfoIcon from '@mui/icons-material/Info';

const InfoTooltip = ({ text, title }) => {
return (
<Tooltip title={text}>
<IconButton>
<InfoIcon />
</IconButton>
</Tooltip>
);
};

InfoTooltip.propTypes = {
text: PropTypes.string,
title: PropTypes.string,
};

export default InfoTooltip;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';

const TourDescriptionText = ({ description }) => {
return <p className="tour-description-text">{description}</p>;
};

TourDescriptionText.propTypes = {
description: PropTypes.string,
};

export default TourDescriptionText;
2 changes: 1 addition & 1 deletion frontend/src/scenes/home/Home.jsx
Original file line number Diff line number Diff line change
@@ -27,4 +27,4 @@ const Home = () => {
);
};

export default Home;
export default Home;
81 changes: 81 additions & 0 deletions frontend/src/scenes/tours/ProductTour.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useState, useEffect } from 'react';
import List from '../../components/List/List';
import ContentArea from '../../components/TourComponents/ContentArea/ContentArea';
import ContentHeader from '../../components/TourComponents/ContentHeader/ContentHeader';
import ConfirmationPopup from '../../components/TourComponents/ConfirmationPopup/ConfirmationPopup';
import Button from '../../components/Button/Button';
import './ProductTourStyles.css';
import TourDescriptionText from '../../components/TourComponents/TourDescriptionText/TourDescriptionText';
import InfoTooltip from '../../components/TourComponents/InfoTooltip/InfoTooltip';

const TourPage = ({ items }) => {
const [selectedItem, setSelectedItem] = useState(null);
const [isPopupOpen, setPopupOpen] = useState(false);
const [showDemoItems, setShowDemoItems] = useState(false);

useEffect(() => {
setShowDemoItems(items.length === 0);
}, [items]);

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

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

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

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

const handleCreateItem = () => {
};

const demoItems = [
{
title: 'Main dashboard - first login tour',
timestamp: '10:00 AM',
idItem: '12548',
text: 'This pops up the first time the user logins to the dashboard.',
onDelete: () => { },
onEdit: () => { }
},
];

return (
<div className="product-page-container">
<div className="product-page-header">
<ContentHeader title={showDemoItems ? "Demo Tours" : "All Tours"} />
<Button text="Create a new tour" variant="contained" className="button-primary create-tour-button" />
</div>
<div className="product-page">
<ContentArea className="content-area">
<List items={showDemoItems ? demoItems : items} onSelectItem={handleSelect} />
<List items={showDemoItems ? demoItems : items} onSelectItem={handleSelect} />
<List items={showDemoItems ? demoItems : items} onSelectItem={handleSelect} />
</ContentArea>
<div className="tour-info-container">
<div className="tour-info-box">
<h4>What is a product tour?</h4>
<p>
A product onboarding tour is a guided walkthrough or tutorial that introduces users to a new product or service.
It typically occurs when a user first signs up or logs into the product.
The purpose of the onboarding tour is to familiarize users with the key features, functionalities, and benefits of the product in order to enhance their understanding.
During the onboarding tour, users are typically shown around the interface, given demonstrations of how to perform key tasks, and provided with explanations of important features.
</p>
</div>
</div>
</div>
{/* <TourDescriptionText description="A product onboarding tour is a guided walkthrough or tutorial..." />
<InfoTooltip text="More info here" title="What is a product tour?" /> */}
<ConfirmationPopup open={isPopupOpen} onConfirm={handleDelete} onCancel={handleClosePopup} />
</div>
);
};

export default TourPage;
45 changes: 45 additions & 0 deletions frontend/src/scenes/tours/ProductTourStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.product-page-container {
padding: 2% 3%;
}

.product-page-header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 20px;
}

.product-page {
display: flex;
align-items: flex-start;
}

.content-area {
flex: 2;
margin-right: 20px;
}

.tour-info-container {
flex: 1;
}

.tour-info-box {
padding: 16px;
border-radius: 8px;
border: 1px solid var(--grey-border);
}

.tour-info-box h4 {
margin-top: 0;
color: var(--main-purple);
}

.tour-info-box p {
margin-bottom: 0;
color: #6b7280;
}

.create-tour-button {
padding: 8px 16px;
}
35 changes: 23 additions & 12 deletions frontend/src/scenes/tours/ToursDefaultPage.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import CreateActivityButton from "../../components/CreateActivityButton/CreateActivityButton"
import HomePageTemplate from "../../components/templates/HomePageTemplate"
import React, { useState } from 'react';
import CreateActivityButton from "../../components/CreateActivityButton/CreateActivityButton";
import HomePageTemplate from "../../components/templates/HomePageTemplate";
import { ACTIVITY_TYPES } from "../../data/CreateActivityButtonData";
import ParagraphCSS from "../../components/ParagraphCSS/ParagraphCSS";
import TourPage from './ProductTour';

const ToursDefaultPage = () => {
const [showTourPage, setShowTourPage] = useState(false);

const handleButtonClick = () => {
setShowTourPage(true);
};

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

return (
<HomePageTemplate>
<div style={style}>
<ParagraphCSS />
<CreateActivityButton type={ACTIVITY_TYPES.TOURS} />
</div>

{showTourPage ? (
<TourPage items={[]} />
) : (
<div style={style}>
<ParagraphCSS />
<CreateActivityButton type={ACTIVITY_TYPES.TOURS} onClick={handleButtonClick} />
</div>
)}
</HomePageTemplate>
)
}

export default ToursDefaultPage
);
};

export default ToursDefaultPage;