Skip to content

Commit 7a94157

Browse files
authored
Merge pull request #553 from bluewave-labs/532-create-the-frontend-for-tours
532 create the frontend for tours
2 parents 5beb258 + b668639 commit 7a94157

35 files changed

+1754
-1816
lines changed

frontend/package-lock.json

+484-1,266
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"private": true,
55
"type": "module",
66
"dependencies": {
7+
"@dnd-kit/core": "^6.3.1",
8+
"@dnd-kit/sortable": "^10.0.0",
9+
"@dnd-kit/utilities": "^3.2.2",
710
"@emotion/react": "^11.13.3",
811
"@emotion/styled": "^11.13.0",
912
"@mui/icons-material": "^6.1.5",
@@ -34,6 +37,7 @@
3437
"react-router": "^6.27.0",
3538
"react-router-dom": "^6.27.0",
3639
"turndown": "^7.2.0",
40+
"uuid": "^11.1.0",
3741
"yup": "^1.4.0"
3842
},
3943
"devDependencies": {
@@ -48,8 +52,8 @@
4852
"jsdom": "^24.0.0",
4953
"prop-types": "^15.8.1",
5054
"sass-embedded": "^1.79.4",
51-
"vite": "^5.4.14",
52-
"vitest": "^1.6.1",
55+
"vite": "^6.2.0",
56+
"vitest": "^3.0.7",
5357
"webpack": "^5.93.0"
5458
},
5559
"scripts": {

frontend/public/no-background.jpg

3.21 KB
Loading

frontend/src/App.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import ProgressStepsMain from "./scenes/progressSteps/ProgressStepsMain";
1111
import Settings from "./scenes/settings/Settings";
1212
import BannerDefaultPage from "./scenes/banner/BannerDefaultPage";
1313
import LinksDefaultPage from "./scenes/links/LinksDefaultPage";
14-
import ToursDefaultPage from "./scenes/tours/ToursDefaultPage";
14+
import TourDefaultPage from "./scenes/tours/TourDefaultPage";
1515
import PopupDefaultPage from "./scenes/popup/PopupDefaultPage";
1616
import HintDefaultPage from "./scenes/hints/HintDefaultPage";
1717
import { Error404 } from "./scenes/errors/404";
@@ -41,7 +41,7 @@ const App = () => {
4141
<Route path="/" element={<Private Component={HomePageTemplate} />}>
4242
<Route index element={<Home />} />
4343
<Route path="/link" element={<LinksDefaultPage />} />
44-
<Route path="/tour" element={<ToursDefaultPage />} />
44+
<Route path="/tour" element={<TourDefaultPage />} />
4545
<Route path="/banner" element={<BannerDefaultPage /> }/>
4646
<Route path="/popup" element={<PopupDefaultPage /> }/>
4747
<Route path="/hint" element={<HintDefaultPage />} />

frontend/src/assets/icons/utilityIcons.jsx

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import IconWrapper from "./IconWrapper";
1+
import IconWrapper from './IconWrapper';
22

33
export const DuplicateIcon = () => (
44
<IconWrapper role="img" aria-label="Duplicate item">
@@ -12,11 +12,11 @@ export const DuplicateIcon = () => (
1212
</IconWrapper>
1313
);
1414

15-
export const TrashIcon = () => (
15+
export const TrashIcon = ({ stroke }) => (
1616
<IconWrapper role="img" aria-label="Delete item">
1717
<path
1818
d="M13.3333 4.99996V4.33329C13.3333 3.39987 13.3333 2.93316 13.1517 2.57664C12.9919 2.26304 12.7369 2.00807 12.4233 1.84828C12.0668 1.66663 11.6001 1.66663 10.6667 1.66663H9.33333C8.39991 1.66663 7.9332 1.66663 7.57668 1.84828C7.26308 2.00807 7.00811 2.26304 6.84832 2.57664C6.66667 2.93316 6.66667 3.39987 6.66667 4.33329V4.99996M8.33333 9.58329V13.75M11.6667 9.58329V13.75M2.5 4.99996H17.5M15.8333 4.99996V14.3333C15.8333 15.7334 15.8333 16.4335 15.5608 16.9683C15.3212 17.4387 14.9387 17.8211 14.4683 18.0608C13.9335 18.3333 13.2335 18.3333 11.8333 18.3333H8.16667C6.76654 18.3333 6.06647 18.3333 5.53169 18.0608C5.06129 17.8211 4.67883 17.4387 4.43915 16.9683C4.16667 16.4335 4.16667 15.7334 4.16667 14.3333V4.99996"
19-
stroke="var(--border-error-solid)"
19+
stroke={stroke || 'var(--border-error-solid)'}
2020
strokeWidth="1.66667"
2121
strokeLinecap="round"
2222
strokeLinejoin="round"
@@ -35,3 +35,15 @@ export const EditIcon = () => (
3535
/>
3636
</IconWrapper>
3737
);
38+
39+
export const Hamburger = ({ styles }) => (
40+
<IconWrapper style={styles} role="img" aria-label="Drag handle">
41+
<path
42+
d="M12.5259 5.33333H1.78906M12.5259 14H1.78906M12.5259 1H1.78906M12.5259 9.66667H1.78906"
43+
stroke="#98A2B3"
44+
strokeWidth="2"
45+
strokeLinecap="round"
46+
strokeLinejoin="round"
47+
/>
48+
</IconWrapper>
49+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import PropTypes from 'prop-types';
2+
import styles from './DraggableTourStep.module.scss';
3+
import { useSortable } from '@dnd-kit/sortable';
4+
import { CSS } from '@dnd-kit/utilities';
5+
import { Hamburger, TrashIcon } from '../../assets/icons/utilityIcons';
6+
7+
const DraggableTourStep = ({
8+
id,
9+
text,
10+
isActive,
11+
stepsLength,
12+
stepNameChangeHandler,
13+
onSelectHandler,
14+
onDeleteHandler,
15+
}) => {
16+
const {
17+
attributes,
18+
listeners,
19+
setNodeRef,
20+
transform,
21+
transition,
22+
isDragging,
23+
} = useSortable({ id });
24+
25+
const style = {
26+
transform: CSS.Transform.toString(transform),
27+
transition,
28+
opacity: isDragging ? 0.5 : 1,
29+
};
30+
31+
return (
32+
<div
33+
ref={setNodeRef}
34+
style={style}
35+
className={`${styles.stepContainer} ${
36+
isActive ? styles.stepContainer__isActive : ''
37+
}`}
38+
onClick={onSelectHandler}
39+
>
40+
<div
41+
{...attributes}
42+
{...listeners}
43+
className={styles.stepContainer__grabHandle}
44+
>
45+
<Hamburger />
46+
</div>
47+
48+
<div style={{ flexGrow: 1, paddingLeft: '1rem' }}>
49+
<input
50+
type="text"
51+
value={text}
52+
onChange={stepNameChangeHandler}
53+
className={`${styles.stepContainer__customInput}`}
54+
/>
55+
</div>
56+
57+
<button
58+
className={styles.stepContainer__button}
59+
disabled={stepsLength === 1}
60+
onClick={(e) => {
61+
e.stopPropagation();
62+
onDeleteHandler();
63+
}}
64+
>
65+
<TrashIcon stroke="var(--second-text-color)" />
66+
</button>
67+
</div>
68+
);
69+
};
70+
71+
DraggableTourStep.propTypes = {
72+
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
73+
text: PropTypes.string,
74+
isActive: PropTypes.bool,
75+
onSelectHandler: PropTypes.func,
76+
onDeleteHandler: PropTypes.func,
77+
};
78+
79+
export default DraggableTourStep;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.stepContainer {
2+
display: flex;
3+
align-items: center;
4+
justify-content: space-between;
5+
padding: 3px 0px;
6+
background-color: var(--header-background);
7+
border: 1.23px solid var(--light-border-color);
8+
border-radius: 8px;
9+
10+
&__isActive {
11+
border: 1.23px solid var(--main-purple);
12+
}
13+
14+
&__button {
15+
border: none;
16+
border-radius: 1rem;
17+
height: 30px;
18+
width: 30px;
19+
display: flex;
20+
align-items: center;
21+
justify-content: center;
22+
z-index: 10;
23+
cursor: pointer;
24+
margin-right: 0.5rem;
25+
background-color: var(--header-background);
26+
27+
&:hover {
28+
background-color: var(--gray-200);
29+
}
30+
31+
&:disabled {
32+
cursor: not-allowed;
33+
}
34+
}
35+
36+
&__grabHandle {
37+
cursor: grab;
38+
width: 10px;
39+
height: 14px;
40+
padding-left: 0.5rem;
41+
}
42+
43+
&__customInput {
44+
padding: 3px 0.5rem;
45+
border-radius: 8px;
46+
font-size: 13px;
47+
color: var(--main-text-color);
48+
cursor: text;
49+
outline: none;
50+
width: 100px;
51+
border: 1px solid transparent;
52+
background-color: var(--header-background);
53+
54+
&:focus {
55+
border: 1px solid var(--light-border-color);
56+
background-color: white;
57+
}
58+
}
59+
}

frontend/src/components/DropdownList/DropdownList.jsx

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import MenuItem from "@mui/material/MenuItem";
2-
import Select from "@mui/material/Select";
3-
import React, { useState, useEffect } from "react";
4-
import PropTypes from "prop-types";
5-
import "./DropdownList.css";
1+
import MenuItem from '@mui/material/MenuItem';
2+
import Select from '@mui/material/Select';
3+
import React, { useState, useEffect } from 'react';
4+
import PropTypes from 'prop-types';
5+
import './DropdownList.css';
66

77
const DropdownList = ({
88
actions = [],
99
onActionChange,
1010
selectedActionIndex = 0,
11-
selectedActionString = "",
12-
className = "",
13-
name = "select"
11+
selectedActionString = '',
12+
className = '',
13+
name = 'select',
14+
styles = {},
1415
}) => {
15-
1616
const [selectedAction, setSelectedAction] = useState('');
1717

1818
const getInitialSelectedAction = () => {
1919
if (selectedActionString) {
20-
const index = actions.findIndex(action =>
21-
action.toLowerCase() === selectedActionString.toLowerCase()
20+
const index = actions.findIndex(
21+
(action) => action.toLowerCase() === selectedActionString.toLowerCase()
2222
);
23-
return index !== -1 ? actions[index] : actions[0] || "";
23+
return index !== -1 ? actions[index] : actions[0] || '';
2424
}
25-
return actions[selectedActionIndex] || "";
25+
return actions[selectedActionIndex] || '';
2626
};
2727

2828
useEffect(() => {
@@ -43,7 +43,7 @@ const DropdownList = ({
4343
value={selectedAction}
4444
onChange={handleChange}
4545
className={`select ${className}`}
46-
sx={{marginTop: 1 }}
46+
sx={{ marginTop: 1, ...styles }}
4747
>
4848
{actions.length > 0 ? (
4949
actions.map((action, index) => (
@@ -67,6 +67,7 @@ DropdownList.propTypes = {
6767
selectedActionString: PropTypes.string,
6868
className: PropTypes.string,
6969
name: PropTypes.string,
70+
styles: PropTypes.object,
7071
};
7172

7273
export default DropdownList;

frontend/src/components/Links/ColorInput/ColorInput.module.scss

+10-1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,13 @@ $box-shadow-color: rgba(16, 24, 40, 0.05);
7171
border: 1.5px solid #000;
7272
}
7373
}
74-
}
74+
75+
&__error {
76+
font-family: var(--font-family-inter);
77+
font-size: var(--font-size-sm);
78+
font-weight: 400;
79+
line-height: 1.45;
80+
margin-top: 0px;
81+
color: var(--error-color);
82+
}
83+
}

0 commit comments

Comments
 (0)