feat(user-profile): update organisation onboarding questions (#8206)

* feat: update org onboarding questions

* feat: type updates

* chore(user-profile): update the onboarding questions

---------

Co-authored-by: Vikrant Gupta <vikrant@signoz.io>
This commit is contained in:
Yunus M 2025-06-23 18:57:05 +05:30 committed by GitHub
parent 133c0deaa8
commit ebcb172614
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 95 additions and 124 deletions

View File

@ -3,15 +3,15 @@ import '../OnboardingQuestionaire.styles.scss';
import { Color } from '@signozhq/design-tokens';
import { Button, Input, Typography } from 'antd';
import TextArea from 'antd/lib/input/TextArea';
import logEvent from 'api/common/logEvent';
import { ArrowLeft, ArrowRight, CheckCircle } from 'lucide-react';
import { useEffect, useState } from 'react';
export interface SignozDetails {
hearAboutSignoz: string | null;
interestInSignoz: string | null;
otherInterestInSignoz: string | null;
otherAboutSignoz: string | null;
discoverSignoz: string | null;
}
interface AboutSigNozQuestionsProps {
@ -21,15 +21,6 @@ interface AboutSigNozQuestionsProps {
onBack: () => void;
}
const hearAboutSignozOptions: Record<string, string> = {
search: 'Google / Search',
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',
@ -42,24 +33,20 @@ export function AboutSigNozQuestions({
onNext,
onBack,
}: AboutSigNozQuestionsProps): JSX.Element {
const [hearAboutSignoz, setHearAboutSignoz] = useState<string | null>(
signozDetails?.hearAboutSignoz || null,
);
const [otherAboutSignoz, setOtherAboutSignoz] = useState<string>(
signozDetails?.otherAboutSignoz || '',
);
const [interestInSignoz, setInterestInSignoz] = useState<string | null>(
signozDetails?.interestInSignoz || null,
);
const [otherInterestInSignoz, setOtherInterestInSignoz] = useState<string>(
signozDetails?.otherInterestInSignoz || '',
);
const [discoverSignoz, setDiscoverSignoz] = useState<string>(
signozDetails?.discoverSignoz || '',
);
const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true);
useEffect((): void => {
if (
hearAboutSignoz !== null &&
(hearAboutSignoz !== 'Others' || otherAboutSignoz !== '') &&
discoverSignoz !== '' &&
interestInSignoz !== null &&
(interestInSignoz !== 'Others' || otherInterestInSignoz !== '')
) {
@ -67,24 +54,17 @@ export function AboutSigNozQuestions({
} else {
setIsNextDisabled(true);
}
}, [
hearAboutSignoz,
otherAboutSignoz,
interestInSignoz,
otherInterestInSignoz,
]);
}, [interestInSignoz, otherInterestInSignoz, discoverSignoz]);
const handleOnNext = (): void => {
setSignozDetails({
hearAboutSignoz,
otherAboutSignoz,
discoverSignoz,
interestInSignoz,
otherInterestInSignoz,
});
logEvent('Org Onboarding: Answered', {
hearAboutSignoz,
otherAboutSignoz,
discoverSignoz,
interestInSignoz,
otherInterestInSignoz,
});
@ -94,8 +74,7 @@ export function AboutSigNozQuestions({
const handleOnBack = (): void => {
setSignozDetails({
hearAboutSignoz,
otherAboutSignoz,
discoverSignoz,
interestInSignoz,
otherInterestInSignoz,
});
@ -115,52 +94,16 @@ export function AboutSigNozQuestions({
<div className="questions-form-container">
<div className="questions-form">
<div className="form-group">
<div className="question">Where did you hear about SigNoz?</div>
<div className="two-column-grid">
{Object.keys(hearAboutSignozOptions).map((option: string) => (
<Button
key={option}
type="primary"
className={`onboarding-questionaire-button ${
hearAboutSignoz === option ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz(option)}
>
{hearAboutSignozOptions[option]}
{hearAboutSignoz === option && (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
)}
</Button>
))}
<div className="question">How did you first come across SigNoz?</div>
{hearAboutSignoz === 'Others' ? (
<Input
type="text"
className="onboarding-questionaire-other-input"
placeholder="How you got to know about us"
value={otherAboutSignoz}
autoFocus
addonAfter={
otherAboutSignoz !== '' ? (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
) : (
''
)
}
onChange={(e): void => setOtherAboutSignoz(e.target.value)}
/>
) : (
<Button
type="primary"
className={`onboarding-questionaire-button ${
hearAboutSignoz === 'Others' ? 'active' : ''
}`}
onClick={(): void => setHearAboutSignoz('Others')}
>
Others
</Button>
)}
</div>
<TextArea
className="discover-signoz-input"
placeholder="e.g., Google Search, Hacker News, Reddit, a friend, ChatGPT, a blog post, a conference, etc."
value={discoverSignoz}
autoFocus
rows={4}
onChange={(e): void => setDiscoverSignoz(e.target.value)}
/>
</div>
<div className="form-group">

View File

@ -84,6 +84,23 @@
}
}
.discover-signoz-input {
width: 100%;
height: 100px;
resize: none;
border: 1px solid var(--bg-slate-400);
background: var(--bg-ink-300);
color: var(--bg-vanilla-100);
border-radius: 4px;
font-size: 14px;
padding: 12px;
&::placeholder {
color: var(--bg-vanilla-400);
opacity: 1;
}
}
&.invite-team-members-form {
min-height: calc(420px - 24px);
max-height: calc(420px - 24px);
@ -123,7 +140,7 @@
height: 32px;
background: var(--Ink-300, #16181d);
border: 1px solid var(--bg-slate-400);
border: 1px solid var(--Greyscale-Slate-400, #1d212d);
color: var(--bg-vanilla-400);
}
@ -445,6 +462,17 @@
}
}
.discover-signoz-input {
border: 1px solid var(--bg-vanilla-300);
background: var(--bg-vanilla-100);
color: var(--text-ink-300);
&::placeholder {
color: var(--bg-slate-400);
opacity: 1;
}
}
&.invite-team-members-form {
.invite-team-members-container {
max-height: 260px;

View File

@ -21,7 +21,7 @@ export interface OrgDetails {
usesObservability: boolean | null;
observabilityTool: string | null;
otherTool: string | null;
familiarity: string | null;
usesOtel: boolean | null;
}
interface OrgQuestionsProps {
@ -40,13 +40,6 @@ const observabilityTools = {
Honeycomb: 'Honeycomb',
};
const o11yFamiliarityOptions: Record<string, string> = {
beginner: 'Beginner',
intermediate: 'Intermediate',
expert: 'Expert',
notFamiliar: "I'm not familiar with it",
};
function OrgQuestions({
currentOrgData,
orgDetails,
@ -69,9 +62,6 @@ function OrgQuestions({
const [otherTool, setOtherTool] = useState<string>(
orgDetails?.otherTool || '',
);
const [familiarity, setFamiliarity] = useState<string | null>(
orgDetails?.familiarity || null,
);
const [isNextDisabled, setIsNextDisabled] = useState<boolean>(true);
useEffect(() => {
@ -80,6 +70,10 @@ function OrgQuestions({
const [isLoading, setIsLoading] = useState<boolean>(false);
const [usesOtel, setUsesOtel] = useState<boolean | null>(
orgDetails?.usesOtel || null,
);
const handleOrgNameUpdate = async (): Promise<void> => {
/* Early bailout if orgData is not set or if the organisation name is not set or if the organisation name is empty or if the organisation name is the same as the one in the orgData */
if (
@ -92,7 +86,7 @@ function OrgQuestions({
usesObservability,
observabilityTool,
otherTool,
familiarity,
usesOtel,
});
onNext({
@ -100,7 +94,7 @@ function OrgQuestions({
usesObservability,
observabilityTool,
otherTool,
familiarity,
usesOtel,
});
return;
@ -123,7 +117,7 @@ function OrgQuestions({
usesObservability,
observabilityTool,
otherTool,
familiarity,
usesOtel,
});
onNext({
@ -131,7 +125,7 @@ function OrgQuestions({
usesObservability,
observabilityTool,
otherTool,
familiarity,
usesOtel,
});
} else {
logEvent('Org Onboarding: Org Name Update Failed', {
@ -177,7 +171,7 @@ function OrgQuestions({
useEffect(() => {
const isValidObservability = isValidUsesObservability();
if (organisationName !== '' && familiarity !== null && isValidObservability) {
if (organisationName !== '' && usesOtel !== null && isValidObservability) {
setIsNextDisabled(false);
} else {
setIsNextDisabled(true);
@ -186,7 +180,7 @@ function OrgQuestions({
}, [
organisationName,
usesObservability,
familiarity,
usesOtel,
observabilityTool,
otherTool,
]);
@ -317,25 +311,37 @@ function OrgQuestions({
)}
<div className="form-group">
<div className="question">
Are you familiar with setting up observability (o11y)?
</div>
<div className="question">Do you already use OpenTelemetry?</div>
<div className="two-column-grid">
{Object.keys(o11yFamiliarityOptions).map((option: string) => (
<Button
key={option}
type="primary"
className={`onboarding-questionaire-button ${
familiarity === option ? 'active' : ''
}`}
onClick={(): void => setFamiliarity(option)}
>
{o11yFamiliarityOptions[option]}
{familiarity === option && (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
)}
</Button>
))}
<Button
type="primary"
name="usesObservability"
className={`onboarding-questionaire-button ${
usesOtel === true ? 'active' : ''
}`}
onClick={(): void => {
setUsesOtel(true);
}}
>
Yes{' '}
{usesOtel === true && (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
)}
</Button>
<Button
type="primary"
className={`onboarding-questionaire-button ${
usesOtel === false ? 'active' : ''
}`}
onClick={(): void => {
setUsesOtel(false);
}}
>
No{' '}
{usesOtel === false && (
<CheckCircle size={12} color={Color.BG_FOREST_500} />
)}
</Button>
</div>
</div>
</div>

View File

@ -42,14 +42,13 @@ const INITIAL_ORG_DETAILS: OrgDetails = {
usesObservability: true,
observabilityTool: '',
otherTool: '',
familiarity: '',
usesOtel: null,
};
const INITIAL_SIGNOZ_DETAILS: SignozDetails = {
hearAboutSignoz: '',
interestInSignoz: '',
otherInterestInSignoz: '',
otherAboutSignoz: '',
discoverSignoz: '',
};
const INITIAL_OPTIMISE_SIGNOZ_DETAILS: OptimiseSignozDetails = {
@ -168,22 +167,17 @@ function OnboardingQuestionaire(): JSX.Element {
});
updateProfile({
familiarity_with_observability: orgDetails?.familiarity as string,
uses_otel: orgDetails?.usesOtel as boolean,
has_existing_observability_tool: orgDetails?.usesObservability as boolean,
existing_observability_tool:
orgDetails?.observabilityTool === 'Others'
? (orgDetails?.otherTool as string)
: (orgDetails?.observabilityTool as string),
where_did_you_discover_signoz: signozDetails?.discoverSignoz as string,
reasons_for_interest_in_signoz:
signozDetails?.interestInSignoz === 'Others'
? (signozDetails?.otherInterestInSignoz as string)
: (signozDetails?.interestInSignoz as string),
where_did_you_hear_about_signoz:
signozDetails?.hearAboutSignoz === 'Others'
? (signozDetails?.otherAboutSignoz as string)
: (signozDetails?.hearAboutSignoz as string),
logs_scale_per_day_in_gb: optimiseSignozDetails?.logsPerDay as number,
number_of_hosts: optimiseSignozDetails?.hostsPerDay as number,
number_of_services: optimiseSignozDetails?.services as number,

View File

@ -1,10 +1,10 @@
export interface UpdateProfileProps {
reasons_for_interest_in_signoz: string;
familiarity_with_observability: string;
uses_otel: boolean;
has_existing_observability_tool: boolean;
existing_observability_tool: string;
logs_scale_per_day_in_gb: number;
number_of_services: number;
number_of_hosts: number;
where_did_you_hear_about_signoz: string;
where_did_you_discover_signoz: string;
}