Skip to content

Commit 1640348

Browse files
Merge branch 'layer5io:master' into master
2 parents 0d61d61 + 1fb6018 commit 1640348

File tree

21 files changed

+755
-9
lines changed

21 files changed

+755
-9
lines changed
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
1-
import { type TooltipProps } from '@mui/material';
1+
import { Tooltip, type TooltipProps } from '@mui/material';
22
import React from 'react';
3-
import { Tooltip } from '../../base/Tooltip';
3+
import { CHARCOAL, WHITE } from '../../theme';
44

55
type CustomTooltipProps = {
6-
title: string;
6+
title: string | React.ReactNode;
77
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
88
children: React.ReactNode;
99
} & Omit<TooltipProps, 'title' | 'onClick'>;
1010

11-
function StyledTooltip({
11+
function CustomTooltip({
1212
title,
1313
onClick,
1414
placement,
1515
children,
1616
...props
1717
}: CustomTooltipProps): JSX.Element {
1818
return (
19-
<Tooltip title={title} placement={placement} onClick={onClick} arrow {...props}>
19+
<Tooltip
20+
componentsProps={{
21+
tooltip: {
22+
sx: {
23+
background: CHARCOAL,
24+
color: WHITE,
25+
fontSize: '0.75rem',
26+
borderRadius: '0.9375rem',
27+
padding: '0.9rem',
28+
zIndex: '999999'
29+
}
30+
},
31+
popper: {
32+
sx: {
33+
opacity: '1'
34+
}
35+
}
36+
}}
37+
title={title}
38+
placement={placement}
39+
onClick={onClick}
40+
arrow
41+
{...props}
42+
>
2043
{children}
2144
</Tooltip>
2245
);
2346
}
2447

25-
export default StyledTooltip;
48+
export default CustomTooltip;

src/custom/ErrorBoundary/ErrorBoundary.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Box } from '../../base/Box';
55
import { Link } from '../../base/Link';
66
import { Typography } from '../../base/Typography';
77
import { BLACK, KEPPEL } from '../../theme/colors';
8+
import { DARK_JUNGLE_GREEN } from '../../theme/colors/colors';
89

910
const ErrorMessage = styled(Typography)(() => ({
1011
color: BLACK,
@@ -31,7 +32,7 @@ export function Fallback({ error, children }: FallbackComponentProps): JSX.Eleme
3132
<h2>Uh-oh!😔 Please pardon the mesh.</h2>
3233
<div
3334
style={{
34-
backgroundColor: '#1E2117',
35+
backgroundColor: DARK_JUNGLE_GREEN,
3536
color: '#FFFFFF',
3637
padding: '.85rem',
3738
borderRadius: '.2rem',
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import Typography from '@mui/material/Typography';
2+
import React, { CSSProperties, useRef, useState } from 'react';
3+
import {
4+
CalenderIcon,
5+
CloseIcon,
6+
FeedbackIcon,
7+
IdeaIcon,
8+
QuestionIcon,
9+
SuccessIcon
10+
} from '../../icons';
11+
import { CULTURED } from '../../theme';
12+
import { CustomTooltip } from '../CustomTooltip';
13+
import { ModalCard } from '../ModalCard';
14+
import {
15+
ActionWrapper,
16+
CloseButton,
17+
Container,
18+
FeedbackButton,
19+
FeedbackForm,
20+
FeedbackMessage,
21+
FeedbackMiniIcon,
22+
FeedbackOptionButton,
23+
FeedbackOptions,
24+
FeedbackSubmitButton,
25+
FeedbackTextArea,
26+
HelperWrapper,
27+
InnerComponentWrapper,
28+
StyledCheckbox,
29+
StyledLink,
30+
StyledTextArea
31+
} from './style';
32+
33+
const tooltipContent = (
34+
<p>
35+
Some account and system information may be sent to Layer5. We will use it to fix problems and
36+
improve our services, subject to our{' '}
37+
<StyledLink target="_blank" href="https://layer5.io/company/legal/privacy">
38+
Privacy Policy
39+
</StyledLink>{' '}
40+
and{' '}
41+
<StyledLink target="_blank" href="https://layer5.io/company/legal/terms-of-service">
42+
Terms of Service
43+
</StyledLink>
44+
. We may email you for more information or updates.
45+
</p>
46+
);
47+
48+
interface FeedbackDataItem {
49+
icon: JSX.Element;
50+
label: string;
51+
placeholder?: string;
52+
isTextInput: boolean;
53+
innerComponent?: JSX.Element;
54+
}
55+
56+
const feedbackData: FeedbackDataItem[] = [
57+
{
58+
icon: <FeedbackIcon />,
59+
label: 'Issue',
60+
placeholder: 'I’m having an issue with...',
61+
isTextInput: true
62+
},
63+
{
64+
icon: <IdeaIcon />,
65+
label: 'Suggestion',
66+
placeholder: 'I have a suggestion about...',
67+
isTextInput: true
68+
},
69+
{
70+
icon: <CalenderIcon />,
71+
label: 'Meet Request',
72+
isTextInput: false,
73+
innerComponent: (
74+
<div
75+
style={{
76+
display: 'flex',
77+
flexDirection: 'column',
78+
alignItems: 'center',
79+
justifyContent: 'space-between',
80+
height: '137px',
81+
color: 'black'
82+
}}
83+
>
84+
<Typography style={{ lineHeight: '2.5', textAlign: 'center' }}>
85+
Need help or have more feedback than fits here?
86+
<br /> Meet with us.
87+
</Typography>
88+
<StyledLink
89+
target="_blank"
90+
href="https://calendar.google.com/calendar/appointments/schedules/AcZssZ3pmcApaDP4xd8hvG5fy8ylxuFxD3akIRc5vpWJ60q-HemQi80SFFAVftbiIsq9pgiA2o8yvU56"
91+
>
92+
Select a time convenient for you.
93+
</StyledLink>
94+
</div>
95+
)
96+
}
97+
];
98+
99+
interface FeedbackComponentProps {
100+
onSubmit: (data: { label: string; message: string }) => void;
101+
containerStyles?: CSSProperties;
102+
feedbackOptionStyles?: CSSProperties;
103+
}
104+
105+
const FeedbackComponent: React.FC<FeedbackComponentProps> = ({
106+
onSubmit,
107+
containerStyles,
108+
feedbackOptionStyles
109+
}) => {
110+
const [isOpen, setIsOpen] = useState<boolean>(false);
111+
const [submitted, setSubmitted] = useState<boolean>(false);
112+
const [category, setCategory] = useState<FeedbackDataItem | undefined>();
113+
const [messageValue, setMessageValue] = useState<string | undefined>();
114+
const feedbackTextRef = useRef<HTMLTextAreaElement>(null);
115+
const [isChecked, setIsChecked] = useState<boolean>(false);
116+
117+
const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
118+
setIsChecked(event.target.checked);
119+
};
120+
121+
const handleFeedback = () => {
122+
setIsOpen(!isOpen);
123+
setCategory(feedbackData[0]);
124+
setSubmitted(false);
125+
setMessageValue('');
126+
};
127+
128+
const handleSubmit = () => {
129+
setSubmitted(true);
130+
if (messageValue && isChecked) {
131+
onSubmit({ label: category?.label || '', message: messageValue });
132+
}
133+
setTimeout(() => {
134+
setIsOpen(false);
135+
setCategory(undefined);
136+
setSubmitted(false);
137+
setMessageValue('');
138+
}, 2000);
139+
};
140+
141+
return (
142+
<Container isOpen={isOpen} style={containerStyles}>
143+
{submitted ? (
144+
<FeedbackMessage isOpen={isOpen}>
145+
<SuccessIcon width={'32'} height={'32'} />
146+
We got your concern. Thank you!
147+
</FeedbackMessage>
148+
) : (
149+
<>
150+
<FeedbackButton onClick={handleFeedback}>Feedback</FeedbackButton>
151+
152+
<ModalCard
153+
onClose={() => {}}
154+
open={true}
155+
closeComponent={
156+
<CloseButton onClick={() => setIsOpen(false)}>
157+
<CloseIcon width={'30'} height={'30'} fill={CULTURED} />
158+
</CloseButton>
159+
}
160+
actions={
161+
<div
162+
style={{
163+
display: 'flex',
164+
alignItems: 'center'
165+
}}
166+
>
167+
<ActionWrapper>
168+
<StyledCheckbox checked={isChecked} onChange={handleCheckboxChange} />
169+
<Typography style={{ color: 'white', fontSize: '12px', height: '15px' }}>
170+
We may email you for more information or updates
171+
</Typography>
172+
</ActionWrapper>
173+
<FeedbackSubmitButton
174+
type="submit"
175+
disabled={!(messageValue && isChecked)}
176+
isOpen={!(messageValue && isChecked)}
177+
onClick={handleSubmit}
178+
>
179+
Send
180+
</FeedbackSubmitButton>
181+
</div>
182+
}
183+
leftHeaderIcon={<FeedbackIcon />}
184+
title="Feedback"
185+
helpArea={
186+
<CustomTooltip placement="top" title={tooltipContent} arrow>
187+
<HelperWrapper>
188+
<QuestionIcon width={'30'} height={'30'} />
189+
</HelperWrapper>
190+
</CustomTooltip>
191+
}
192+
helpText={'Help'}
193+
content={
194+
<FeedbackForm>
195+
<FeedbackOptions>
196+
{feedbackData?.map((item) => (
197+
<FeedbackOptionButton
198+
key={item.label}
199+
style={feedbackOptionStyles}
200+
type="button"
201+
onClick={() => {
202+
setCategory(item);
203+
}}
204+
isOpen={category?.label === item.label}
205+
>
206+
<FeedbackMiniIcon>{item.icon}</FeedbackMiniIcon>
207+
<Typography>{item.label}</Typography>
208+
</FeedbackOptionButton>
209+
))}
210+
</FeedbackOptions>
211+
{category?.isTextInput ? (
212+
<FeedbackTextArea>
213+
<StyledTextArea
214+
value={messageValue || ''}
215+
onChange={(e) => {
216+
setMessageValue(e.target.value);
217+
}}
218+
ref={feedbackTextRef}
219+
required
220+
placeholder={category.placeholder}
221+
rows={5}
222+
cols={30}
223+
/>
224+
</FeedbackTextArea>
225+
) : (
226+
<InnerComponentWrapper>{category?.innerComponent}</InnerComponentWrapper>
227+
)}
228+
</FeedbackForm>
229+
}
230+
></ModalCard>
231+
</>
232+
)}
233+
</Container>
234+
);
235+
};
236+
237+
export default FeedbackComponent;

src/custom/Feedback/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import FeedbackButton from './FeedbackButton';
2+
3+
export { FeedbackButton };

0 commit comments

Comments
 (0)