feat: maintain state and add log events

This commit is contained in:
Yunus M 2024-09-20 01:51:46 +05:30
parent 438cbcef87
commit 6664e1bc02
6 changed files with 499 additions and 247 deletions

View File

@ -1,23 +1,52 @@
/* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable sonarjs/cognitive-complexity */
import '../OnboardingQuestionaire.styles.scss'; import '../OnboardingQuestionaire.styles.scss';
import { Button, Typography } from 'antd'; import { Color } from '@signozhq/design-tokens';
import { ArrowLeft, ArrowRight } from 'lucide-react'; import { Button, Input, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import { ArrowLeft, ArrowRight, CheckCircle } from 'lucide-react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
interface AboutSigNozQuestionsProps { interface AboutSigNozQuestionsProps {
signozDetails: any;
setSignozDetails: (details: any) => void;
onNext: () => void; onNext: () => void;
onBack: () => void; onBack: () => void;
} }
const hearAboutSignozOptions: Record<string, string> = {
blog: 'Blog',
hackerNews: 'Hacker News',
linkedin: 'LinkedIn',
twitter: 'Twitter',
reddit: 'Reddit',
colleaguesFriends: 'Colleagues / Friends',
};
const interestedInOptions: Record<string, string> = {
savingCosts: 'Saving costs',
otelNativeStack: 'Interested in Otel-native stack',
allInOne: 'All in one',
};
export function AboutSigNozQuestions({ export function AboutSigNozQuestions({
signozDetails,
setSignozDetails,
onNext, onNext,
onBack, onBack,
}: AboutSigNozQuestionsProps): JSX.Element { }: AboutSigNozQuestionsProps): JSX.Element {
const [hearAboutSignoz, setHearAboutSignoz] = useState<string | null>(null); const [hearAboutSignoz, setHearAboutSignoz] = useState<string | null>(
const [otherAboutSignoz, setOtherAboutSignoz] = useState<string>(''); signozDetails?.hearAboutSignoz || null,
const [interestedSignoz, setInterestedSignoz] = useState<string | null>(null); );
const [otherInterest, setOtherInterest] = useState<string>(''); const [otherAboutSignoz, setOtherAboutSignoz] = useState<string>(
signozDetails?.otherAboutSignoz || '',
);
const [interestedSignoz, setInterestedSignoz] = useState<string | null>(
signozDetails?.interestedSignoz || null,
);
const [otherInterest, setOtherInterest] = useState<string>(
signozDetails?.otherInterest || '',
);
const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true); const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true);
useEffect((): void => { useEffect((): void => {
@ -33,6 +62,42 @@ export function AboutSigNozQuestions({
} }
}, [hearAboutSignoz, otherAboutSignoz, interestedSignoz, otherInterest]); }, [hearAboutSignoz, otherAboutSignoz, interestedSignoz, otherInterest]);
const handleOnNext = (): void => {
setSignozDetails({
hearAboutSignoz,
otherAboutSignoz,
interestedSignoz,
otherInterest,
});
logEvent('Onboarding: SigNoz Questions: Next', {
hearAboutSignoz,
otherAboutSignoz,
interestedSignoz,
otherInterest,
});
onNext();
};
const handleOnBack = (): void => {
setSignozDetails({
hearAboutSignoz,
otherAboutSignoz,
interestedSignoz,
otherInterest,
});
logEvent('Onboarding: SigNoz Questions: Back', {
hearAboutSignoz,
otherAboutSignoz,
interestedSignoz,
otherInterest,
});
onBack();
};
return ( return (
<div className="questions-container"> <div className="questions-container">
<Typography.Title level={3} className="title"> <Typography.Title level={3} className="title">
@ -46,78 +111,49 @@ export function AboutSigNozQuestions({
<div className="questions-form"> <div className="questions-form">
<div className="form-group"> <div className="form-group">
<div className="question">Where did you hear about SigNoz?</div> <div className="question">Where did you hear about SigNoz?</div>
<div className="tool-grid"> <div className="two-column-grid">
<button {Object.keys(hearAboutSignozOptions).map((option: string) => (
type="button" <Button
className={`tool-button ${hearAboutSignoz === 'Blog' ? 'active' : ''}`} key={option}
onClick={(): void => setHearAboutSignoz('Blog')} type="primary"
> className={`onboarding-questionaire-button ${
Blog hearAboutSignoz === option ? 'active' : ''
</button> }`}
<button onClick={(): void => setHearAboutSignoz(option)}
type="button" >
className={`tool-button ${ {hearAboutSignozOptions[option]}
hearAboutSignoz === 'Hacker News' ? 'active' : '' {hearAboutSignoz === option && (
}`} <CheckCircle size={12} color={Color.BG_FOREST_500} />
onClick={(): void => setHearAboutSignoz('Hacker News')} )}
> </Button>
Hacker News ))}
</button>
<button
type="button"
className={`tool-button ${
hearAboutSignoz === 'LinkedIn' ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz('LinkedIn')}
>
LinkedIn
</button>
<button
type="button"
className={`tool-button ${
hearAboutSignoz === 'Twitter' ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz('Twitter')}
>
Twitter
</button>
<button
type="button"
className={`tool-button ${
hearAboutSignoz === 'Reddit' ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz('Reddit')}
>
Reddit
</button>
<button
type="button"
className={`tool-button ${
hearAboutSignoz === 'colleagues/friends' ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz('colleagues/friends')}
>
Colleagues / Friends
</button>
{hearAboutSignoz === 'Others' ? ( {hearAboutSignoz === 'Others' ? (
<input <Input
type="text" type="text"
className="tool-button input-field" className="onboarding-questionaire-other-input"
placeholder="Please specify where you heard about SigNoz" placeholder="Please specify your interest"
value={otherAboutSignoz} value={otherAboutSignoz}
autoFocus
addonAfter={
otherAboutSignoz !== '' ? (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
) : (
''
)
}
onChange={(e): void => setOtherAboutSignoz(e.target.value)} onChange={(e): void => setOtherAboutSignoz(e.target.value)}
/> />
) : ( ) : (
<button <Button
type="button" type="primary"
className={`tool-button ${ className={`onboarding-questionaire-button ${
hearAboutSignoz === 'Others' ? 'active' : '' hearAboutSignoz === 'Others' ? 'active' : ''
}`} }`}
onClick={(): void => setHearAboutSignoz('Others')} onClick={(): void => setHearAboutSignoz('Others')}
> >
Others Others
</button> </Button>
)} )}
</div> </div>
</div> </div>
@ -126,62 +162,56 @@ export function AboutSigNozQuestions({
<div className="question"> <div className="question">
What are you interested in doing with SigNoz? What are you interested in doing with SigNoz?
</div> </div>
<div className="grid"> <div className="two-column-grid">
<button {Object.keys(interestedInOptions).map((option: string) => (
type="button" <Button
className={`grid-button ${ key={option}
interestedSignoz === 'Saving costs' ? 'active' : '' type="primary"
}`} className={`onboarding-questionaire-button ${
onClick={(): void => setInterestedSignoz('Saving costs')} interestedSignoz === option ? 'active' : ''
> }`}
Saving costs onClick={(): void => setInterestedSignoz(option)}
</button> >
<button {interestedInOptions[option]}
type="button" {interestedSignoz === option && (
className={`grid-button ${ <CheckCircle size={12} color={Color.BG_FOREST_500} />
interestedSignoz === 'Interested in Otel-native stack' ? 'active' : '' )}
}`} </Button>
onClick={(): void => ))}
setInterestedSignoz('Interested in Otel-native stack')
}
>
Interested in Otel-native stack
</button>
<button
type="button"
className={`grid-button ${
interestedSignoz === 'All-in-one' ? 'active' : ''
}`}
onClick={(): void => setInterestedSignoz('All-in-one')}
>
All-in-one
</button>
{interestedSignoz === 'Others' ? ( {interestedSignoz === 'Others' ? (
<input <Input
type="text" type="text"
className="tool-button input-field" className="onboarding-questionaire-other-input"
placeholder="Please specify your interest" placeholder="Please specify your interest"
value={otherInterest} value={otherInterest}
autoFocus
addonAfter={
otherInterest !== '' ? (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
) : (
''
)
}
onChange={(e): void => setOtherInterest(e.target.value)} onChange={(e): void => setOtherInterest(e.target.value)}
/> />
) : ( ) : (
<button <Button
type="button" type="primary"
className={`tool-button ${ className={`onboarding-questionaire-button ${
interestedSignoz === 'Others' ? 'active' : '' interestedSignoz === 'Others' ? 'active' : ''
}`} }`}
onClick={(): void => setInterestedSignoz('Others')} onClick={(): void => setInterestedSignoz('Others')}
> >
Others Others
</button> </Button>
)} )}
</div> </div>
</div> </div>
</div> </div>
<div className="next-prev-container"> <div className="next-prev-container">
<Button type="default" className="next-button" onClick={onBack}> <Button type="default" className="next-button" onClick={handleOnBack}>
<ArrowLeft size={14} /> <ArrowLeft size={14} />
Back Back
</Button> </Button>
@ -189,7 +219,7 @@ export function AboutSigNozQuestions({
<Button <Button
type="primary" type="primary"
className={`next-button ${isNextDisabled ? 'disabled' : ''}`} className={`next-button ${isNextDisabled ? 'disabled' : ''}`}
onClick={onNext} onClick={handleOnNext}
disabled={isNextDisabled} disabled={isNextDisabled}
> >
Next Next

View File

@ -1,7 +1,17 @@
import { Color } from '@signozhq/design-tokens';
import { Button, Input, Select, Typography } from 'antd'; import { Button, Input, Select, Typography } from 'antd';
import { ArrowLeft, ArrowRight } from 'lucide-react'; import {
ArrowLeft,
ArrowRight,
CheckCircle,
Plus,
TriangleAlert,
} from 'lucide-react';
import { useState } from 'react';
interface InviteTeamMembersProps { interface InviteTeamMembersProps {
teamMembers: string[];
setTeamMembers: (teamMembers: string[]) => void;
onNext: () => void; onNext: () => void;
onBack: () => void; onBack: () => void;
} }
@ -15,9 +25,39 @@ const userRolesOptions = (
); );
function InviteTeamMembers({ function InviteTeamMembers({
teamMembers,
setTeamMembers,
onNext, onNext,
onBack, onBack,
}: InviteTeamMembersProps): JSX.Element { }: InviteTeamMembersProps): JSX.Element {
const [teamMembersToInvite, setTeamMembersToInvite] = useState<string[]>(
teamMembers || [''],
);
const handleAddTeamMember = (): void => {
setTeamMembersToInvite([...teamMembersToInvite, '']);
};
const handleNext = (): void => {
console.log(teamMembersToInvite);
setTeamMembers(teamMembersToInvite);
onNext();
};
const handleOnChange = (
e: React.ChangeEvent<HTMLInputElement>,
index: number,
): void => {
const newTeamMembers = [...teamMembersToInvite];
newTeamMembers[index] = e.target.value;
setTeamMembersToInvite(newTeamMembers);
};
const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
return ( return (
<div className="questions-container"> <div className="questions-container">
<Typography.Title level={3} className="title"> <Typography.Title level={3} className="title">
@ -39,20 +79,44 @@ function InviteTeamMembers({
</div> </div>
<div className="invite-team-members-container"> <div className="invite-team-members-container">
<Input {teamMembersToInvite.map((member, index) => (
addonAfter={userRolesOptions} // eslint-disable-next-line react/no-array-index-key
placeholder="your-teammate@org.com" <div className="team-member-container" key={`${member}-${index}`}>
/> <Input
addonBefore={userRolesOptions}
addonAfter={
// eslint-disable-next-line no-nested-ternary
member.length > 0 ? (
isValidEmail(member) ? (
<CheckCircle size={14} color={Color.BG_FOREST_500} />
) : (
<TriangleAlert size={14} color={Color.BG_SIENNA_500} />
)
) : null
}
placeholder="your-teammate@org.com"
value={member}
type="email"
required
autoFocus
autoComplete="off"
onChange={(e: React.ChangeEvent<HTMLInputElement>): void =>
handleOnChange(e, index)
}
/>
</div>
))}
</div>
<Input <div className="invite-team-members-add-another-member-container">
addonAfter={userRolesOptions} <Button
placeholder="your-teammate@org.com" type="primary"
/> className="add-another-member-button"
icon={<Plus size={14} />}
<Input onClick={handleAddTeamMember}
addonAfter={userRolesOptions} >
placeholder="your-teammate@org.com" Member
/> </Button>
</div> </div>
</div> </div>
</div> </div>
@ -63,7 +127,7 @@ function InviteTeamMembers({
Back Back
</Button> </Button>
<Button type="primary" className="next-button" onClick={onNext}> <Button type="primary" className="next-button" onClick={handleNext}>
Send Invites Send Invites
<ArrowRight size={14} /> <ArrowRight size={14} />
</Button> </Button>

View File

@ -216,6 +216,7 @@
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
min-width: 258px; min-width: 258px;
cursor: pointer; cursor: pointer;
box-sizing: border-box;
} }
.radio-button.active, .radio-button.active,
@ -228,6 +229,61 @@
background: rgba(78, 116, 248, 0.2); background: rgba(78, 116, 248, 0.2);
} }
.two-column-grid {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr; /* Two equal columns */
gap: 10px;
}
.onboarding-questionaire-button,
.add-another-member-button {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 2px;
border: 1px solid var(--Greyscale-Slate-400, #1d212d);
background: var(--Ink-300, #16181d);
color: var(--Vanilla-400, var(--Greyscale-Vanilla-400, #c0c1c3));
box-shadow: none;
font-size: 14px;
font-style: normal;
text-align: left;
font-weight: 400;
transition: background-color 0.3s ease;
cursor: pointer;
height: 40px;
box-sizing: border-box;
&:hover {
border: 1px solid rgba(78, 116, 248, 0.4);
background: rgba(78, 116, 248, 0.2);
}
&:focus-visible {
outline: none;
}
&.active {
border: 1px solid rgba(78, 116, 248, 0.4);
background: rgba(78, 116, 248, 0.2);
}
}
.add-another-member-button {
font-size: 12px;
height: 32px;
}
.onboarding-questionaire-other-input {
.ant-input-group {
.ant-input {
border-top-right-radius: 0px !important;
border-bottom-right-radius: 0px !important;
}
}
}
.tool-grid { .tool-grid {
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
} }
@ -275,4 +331,12 @@
padding: 12px 24px; padding: 12px 24px;
box-sizing: border-box; box-sizing: border-box;
} }
.invite-team-members-add-another-member-container {
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 12px;
}
} }

View File

@ -1,7 +1,11 @@
import { Button, Slider, SliderSingleProps, Typography } from 'antd'; import { Button, Slider, SliderSingleProps, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import { ArrowLeft, ArrowRight, Minus } from 'lucide-react'; import { ArrowLeft, ArrowRight, Minus } from 'lucide-react';
import { useState } from 'react';
interface OptimiseSignozNeedsProps { interface OptimiseSignozNeedsProps {
optimiseSignozDetails: Record<string, number> | null;
setOptimiseSignozDetails: (details: Record<string, number> | null) => void;
onNext: () => void; onNext: () => void;
onBack: () => void; onBack: () => void;
} }
@ -32,9 +36,69 @@ const serviceMarks: SliderSingleProps['marks'] = {
}; };
function OptimiseSignozNeeds({ function OptimiseSignozNeeds({
optimiseSignozDetails,
setOptimiseSignozDetails,
onNext, onNext,
onBack, onBack,
}: OptimiseSignozNeedsProps): JSX.Element { }: OptimiseSignozNeedsProps): JSX.Element {
const [logsPerDay, setLogsPerDay] = useState<number>(
optimiseSignozDetails?.logsPerDay || 25,
);
const [hostsPerDay, setHostsPerDay] = useState<number>(
optimiseSignozDetails?.hostsPerDay || 40,
);
const [services, setServices] = useState<number>(
optimiseSignozDetails?.services || 10,
);
const handleOnNext = (): void => {
setOptimiseSignozDetails({
logsPerDay,
hostsPerDay,
services,
});
logEvent('Onboarding: Optimise SigNoz Needs: Next', {
logsPerDay,
hostsPerDay,
services,
});
onNext();
};
const handleOnBack = (): void => {
setOptimiseSignozDetails({
logsPerDay,
hostsPerDay,
services,
});
logEvent('Onboarding: Optimise SigNoz Needs: Back', {
logsPerDay,
hostsPerDay,
services,
});
onBack();
};
const handleWillDoLater = (): void => {
setOptimiseSignozDetails({
logsPerDay: 0,
hostsPerDay: 0,
services: 0,
});
logEvent('Onboarding: Optimise SigNoz Needs: Will do later', {
logsPerDay: 0,
hostsPerDay: 0,
services: 0,
});
onNext();
};
return ( return (
<div className="questions-container"> <div className="questions-container">
<Typography.Title level={3} className="title"> <Typography.Title level={3} className="title">
@ -57,7 +121,8 @@ function OptimiseSignozNeeds({
<div className="slider-container"> <div className="slider-container">
<Slider <Slider
marks={logMarks} marks={logMarks}
defaultValue={25} defaultValue={logsPerDay}
onChange={(value): void => setLogsPerDay(value)}
styles={{ styles={{
track: { track: {
background: '#4E74F8', background: '#4E74F8',
@ -69,12 +134,13 @@ function OptimiseSignozNeeds({
<div className="form-group"> <div className="form-group">
<label className="question" htmlFor="organisationName"> <label className="question" htmlFor="organisationName">
Metrics <Minus size={14} /> Number of Hosts / Day Metrics <Minus size={14} /> Number of Hosts
</label> </label>
<div className="slider-container"> <div className="slider-container">
<Slider <Slider
marks={hostMarks} marks={hostMarks}
defaultValue={40} defaultValue={hostsPerDay}
onChange={(value): void => setHostsPerDay(value)}
styles={{ styles={{
track: { track: {
background: '#4E74F8', background: '#4E74F8',
@ -91,7 +157,8 @@ function OptimiseSignozNeeds({
<div className="slider-container"> <div className="slider-container">
<Slider <Slider
marks={serviceMarks} marks={serviceMarks}
defaultValue={10} defaultValue={services}
onChange={(value): void => setServices(value)}
styles={{ styles={{
track: { track: {
background: '#4E74F8', background: '#4E74F8',
@ -103,19 +170,19 @@ function OptimiseSignozNeeds({
</div> </div>
<div className="next-prev-container"> <div className="next-prev-container">
<Button type="default" className="next-button" onClick={onBack}> <Button type="default" className="next-button" onClick={handleOnBack}>
<ArrowLeft size={14} /> <ArrowLeft size={14} />
Back Back
</Button> </Button>
<Button type="primary" className="next-button" onClick={onNext}> <Button type="primary" className="next-button" onClick={handleOnNext}>
Next Next
<ArrowRight size={14} /> <ArrowRight size={14} />
</Button> </Button>
</div> </div>
<div className="do-later-container"> <div className="do-later-container">
<Button type="link" onClick={onNext}> <Button type="link" onClick={handleWillDoLater}>
I&apos;ll do this later I&apos;ll do this later
</Button> </Button>
</div> </div>

View File

@ -1,27 +1,58 @@
/* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable sonarjs/cognitive-complexity */
import '../OnboardingQuestionaire.styles.scss'; import '../OnboardingQuestionaire.styles.scss';
import { Button, Typography } from 'antd'; import { Color } from '@signozhq/design-tokens';
import { ArrowRight } from 'lucide-react'; import { Button, Input, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import { ArrowRight, CheckCircle } from 'lucide-react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppReducer from 'types/reducer/app'; import AppReducer from 'types/reducer/app';
interface OrgQuestionsProps { interface OrgQuestionsProps {
orgDetails: any;
setOrgDetails: (details: any) => void;
onNext: () => void; onNext: () => void;
} }
function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element { const observabilityTools = [
const [organisationName, setOrganisationName] = useState<string>(''); 'AWS Cloudwatch',
'DataDog',
'New Relic',
'Grafana / Prometheus',
'Azure App Monitor',
'GCP-native o11y tools',
'Honeycomb',
];
const o11yFamiliarityOptions: Record<string, string> = {
new: "I'm completely new",
builtStack: "I've built a stack before",
experienced: 'I have some experience',
dontKnow: "I don't know what it is",
};
function OrgQuestions({
orgDetails,
setOrgDetails,
onNext,
}: OrgQuestionsProps): JSX.Element {
const [organisationName, setOrganisationName] = useState<string>(
orgDetails?.organisationName || '',
);
const [usesObservability, setUsesObservability] = useState<boolean | null>( const [usesObservability, setUsesObservability] = useState<boolean | null>(
null, orgDetails?.usesObservability || null,
); );
const [observabilityTool, setObservabilityTool] = useState<string | null>( const [observabilityTool, setObservabilityTool] = useState<string | null>(
null, orgDetails?.observabilityTool || null,
);
const [otherTool, setOtherTool] = useState<string>(
orgDetails?.otherTool || '',
);
const [familiarity, setFamiliarity] = useState<string | null>(
orgDetails?.familiarity || null,
); );
const [otherTool, setOtherTool] = useState<string>('');
const [familiarity, setFamiliarity] = useState<string | null>(null);
const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true); const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true);
const { user } = useSelector<AppState, AppReducer>((state) => state.app); const { user } = useSelector<AppState, AppReducer>((state) => state.app);
@ -45,6 +76,26 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
otherTool, otherTool,
]); ]);
const handleOnNext = (): void => {
setOrgDetails({
organisationName,
usesObservability,
observabilityTool,
otherTool,
familiarity,
});
logEvent('Onboarding: Org Questions: Next', {
organisationName,
usesObservability,
observabilityTool,
otherTool,
familiarity,
});
onNext();
};
return ( return (
<div className="questions-container"> <div className="questions-container">
<Typography.Title level={3} className="title"> <Typography.Title level={3} className="title">
@ -77,20 +128,25 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
Do you currently use any observability/monitoring tool? Do you currently use any observability/monitoring tool?
</label> </label>
<div className="radio-group"> <div className="two-column-grid">
<button <Button
type="button" type="primary"
name="usesObservability" name="usesObservability"
className={`radio-button ${usesObservability === true ? 'active' : ''}`} className={`onboarding-questionaire-button ${
usesObservability === true ? 'active' : ''
}`}
onClick={(): void => { onClick={(): void => {
setUsesObservability(true); setUsesObservability(true);
}} }}
> >
Yes Yes{' '}
</button> {usesObservability === true && (
<button <CheckCircle size={12} color={Color.BG_FOREST_500} />
type="button" )}
className={`radio-button ${ </Button>
<Button
type="primary"
className={`onboarding-questionaire-button ${
usesObservability === false ? 'active' : '' usesObservability === false ? 'active' : ''
}`} }`}
onClick={(): void => { onClick={(): void => {
@ -99,8 +155,11 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
setOtherTool(''); setOtherTool('');
}} }}
> >
No No{' '}
</button> {usesObservability === false && (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
)}
</Button>
</div> </div>
</div> </div>
@ -109,83 +168,44 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
<label className="question" htmlFor="observabilityTool"> <label className="question" htmlFor="observabilityTool">
Which observability tool do you currently use? Which observability tool do you currently use?
</label> </label>
<div className="tool-grid"> <div className="two-column-grid">
<button {observabilityTools.map((tool) => (
type="button" <Button
className={`tool-button ${ key={tool}
observabilityTool === 'AWS Cloudwatch' ? 'active' : '' type="primary"
}`} className={`onboarding-questionaire-button ${
onClick={(): void => setObservabilityTool('AWS Cloudwatch')} observabilityTool === tool ? 'active' : ''
> }`}
AWS Cloudwatch onClick={(): void => setObservabilityTool(tool)}
</button> >
<button {tool}
type="button"
className={`tool-button ${ {observabilityTool === tool && (
observabilityTool === 'DataDog' ? 'active' : '' <CheckCircle size={12} color={Color.BG_FOREST_500} />
}`} )}
onClick={(): void => setObservabilityTool('DataDog')} </Button>
> ))}
DataDog
</button>
<button
type="button"
className={`tool-button ${
observabilityTool === 'New Relic' ? 'active' : ''
}`}
onClick={(): void => setObservabilityTool('New Relic')}
>
New Relic
</button>
<button
type="button"
className={`tool-button ${
observabilityTool === 'Grafana / Prometheus' ? 'active' : ''
}`}
onClick={(): void => setObservabilityTool('Grafana / Prometheus')}
>
Grafana / Prometheus
</button>
<button
type="button"
className={`tool-button ${
observabilityTool === 'Azure App Monitor' ? 'active' : ''
}`}
onClick={(): void => setObservabilityTool('Azure App Monitor')}
>
Azure App Monitor
</button>
<button
type="button"
className={`tool-button ${
observabilityTool === 'GCP-native o11y tools' ? 'active' : ''
}`}
onClick={(): void => setObservabilityTool('GCP-native o11y tools')}
>
GCP-native o11y tools
</button>
<button
type="button"
className={`tool-button ${
observabilityTool === 'Honeycomb' ? 'active' : ''
}`}
onClick={(): void => setObservabilityTool('Honeycomb')}
>
Honeycomb
</button>
{observabilityTool === 'Others' ? ( {observabilityTool === 'Others' ? (
<input <Input
type="text" type="text"
className="tool-button input-field" className="onboarding-questionaire-other-input"
placeholder="Please specify the tool" placeholder="Please specify the tool"
value={otherTool} value={otherTool}
autoFocus
addonAfter={
otherTool !== '' ? (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
) : (
''
)
}
onChange={(e): void => setOtherTool(e.target.value)} onChange={(e): void => setOtherTool(e.target.value)}
/> />
) : ( ) : (
<button <button
type="button" type="button"
className={`tool-button ${ className={`onboarding-questionaire-button ${
observabilityTool === 'Others' ? 'active' : '' observabilityTool === 'Others' ? 'active' : ''
}`} }`}
onClick={(): void => setObservabilityTool('Others')} onClick={(): void => setObservabilityTool('Others')}
@ -201,39 +221,22 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
<div className="question"> <div className="question">
Are you familiar with observability (o11y)? Are you familiar with observability (o11y)?
</div> </div>
<div className="grid"> <div className="two-column-grid">
<button {Object.keys(o11yFamiliarityOptions).map((option: string) => (
type="button" <Button
className={`grid-button ${familiarity === 'new' ? 'active' : ''}`} key={option}
onClick={(): void => setFamiliarity('new')} type="primary"
> className={`onboarding-questionaire-button ${
I&apos;m completely new familiarity === option ? 'active' : ''
</button> }`}
<button onClick={(): void => setFamiliarity(option)}
type="button" >
className={`grid-button ${ {o11yFamiliarityOptions[option]}
familiarity === 'built-stack' ? 'active' : '' {familiarity === option && (
}`} <CheckCircle size={12} color={Color.BG_FOREST_500} />
onClick={(): void => setFamiliarity('built-stack')} )}
> </Button>
I&apos;ve built a stack before ))}
</button>
<button
type="button"
className={`grid-button ${
familiarity === 'experienced' ? 'active' : ''
}`}
onClick={(): void => setFamiliarity('experienced')}
>
I have some experience
</button>
<button
type="button"
className={`grid-button ${familiarity === 'dont-know' ? 'active' : ''}`}
onClick={(): void => setFamiliarity('dont-know')}
>
I don&apos;t know what it is
</button>
</div> </div>
</div> </div>
</div> </div>
@ -242,7 +245,7 @@ function OrgQuestions({ onNext }: OrgQuestionsProps): JSX.Element {
<Button <Button
type="primary" type="primary"
className={`next-button ${isNextDisabled ? 'disabled' : ''}`} className={`next-button ${isNextDisabled ? 'disabled' : ''}`}
onClick={onNext} onClick={handleOnNext}
disabled={isNextDisabled} disabled={isNextDisabled}
> >
Next Next

View File

@ -12,6 +12,20 @@ import OrgQuestions from './OrgQuestions/OrgQuestions';
function OnboardingQuestionaire(): JSX.Element { function OnboardingQuestionaire(): JSX.Element {
const [currentStep, setCurrentStep] = useState<number>(1); const [currentStep, setCurrentStep] = useState<number>(1);
const [orgDetails, setOrgDetails] = useState<Record<string, string> | null>(
null,
);
const [signozDetails, setSignozDetails] = useState<Record<
string,
string
> | null>(null);
const [optimiseSignozDetails, setOptimiseSignozDetails] = useState<Record<
string,
number
> | null>(null);
const [teamMembers, setTeamMembers] = useState<string[]>(['']);
return ( return (
<div className="onboarding-questionaire-container"> <div className="onboarding-questionaire-container">
<div className="onboarding-questionaire-header"> <div className="onboarding-questionaire-header">
@ -20,11 +34,17 @@ function OnboardingQuestionaire(): JSX.Element {
<div className="onboarding-questionaire-content"> <div className="onboarding-questionaire-content">
{currentStep === 1 && ( {currentStep === 1 && (
<OrgQuestions onNext={(): void => setCurrentStep(2)} /> <OrgQuestions
orgDetails={orgDetails}
setOrgDetails={setOrgDetails}
onNext={(): void => setCurrentStep(2)}
/>
)} )}
{currentStep === 2 && ( {currentStep === 2 && (
<AboutSigNozQuestions <AboutSigNozQuestions
signozDetails={signozDetails}
setSignozDetails={setSignozDetails}
onBack={(): void => setCurrentStep(1)} onBack={(): void => setCurrentStep(1)}
onNext={(): void => setCurrentStep(3)} onNext={(): void => setCurrentStep(3)}
/> />
@ -32,6 +52,8 @@ function OnboardingQuestionaire(): JSX.Element {
{currentStep === 3 && ( {currentStep === 3 && (
<OptimiseSignozNeeds <OptimiseSignozNeeds
optimiseSignozDetails={optimiseSignozDetails}
setOptimiseSignozDetails={setOptimiseSignozDetails}
onBack={(): void => setCurrentStep(2)} onBack={(): void => setCurrentStep(2)}
onNext={(): void => setCurrentStep(4)} onNext={(): void => setCurrentStep(4)}
/> />
@ -39,6 +61,8 @@ function OnboardingQuestionaire(): JSX.Element {
{currentStep === 4 && ( {currentStep === 4 && (
<InviteTeamMembers <InviteTeamMembers
teamMembers={teamMembers}
setTeamMembers={setTeamMembers}
onBack={(): void => setCurrentStep(3)} onBack={(): void => setCurrentStep(3)}
onNext={(): void => setCurrentStep(5)} onNext={(): void => setCurrentStep(5)}
/> />