Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
7 changes: 6 additions & 1 deletion apps/web/core/components/onboarding/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ export const OnboardingHeader = observer(function OnboardingHeader(props: Onboar
// derived values
const currentStepNumber = getCurrentStepNumber();
const totalSteps = hasInvitations ? 4 : 5; // 4 if invites available, 5 if not
const userName = user?.display_name ?? `${user?.first_name} ${user?.last_name}` ?? user?.email;
const userName = user?.display_name
? user?.display_name
: user?.first_name
? `${user?.first_name} ${user?.last_name ?? ""}`
: user?.email;


return (
<div className="flex flex-col gap-4 sticky top-0 z-10">
Expand Down
49 changes: 30 additions & 19 deletions apps/web/core/components/onboarding/profile-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type TProfileSetupFormValues = {
password?: string;
confirm_password?: string;
role?: string;
use_case?: string;
use_case?: string[];
};

const defaultValues: Partial<TProfileSetupFormValues> = {
Expand All @@ -43,7 +43,7 @@ const defaultValues: Partial<TProfileSetupFormValues> = {
password: undefined,
confirm_password: undefined,
role: undefined,
use_case: undefined,
use_case: [],
};

type Props = {
Expand Down Expand Up @@ -139,7 +139,7 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) {
avatar_url: formData.avatar_url ?? undefined,
};
const profileUpdatePayload: Partial<TUserProfile> = {
use_case: formData.use_case,
use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined,
role: formData.role,
};
try {
Expand All @@ -151,7 +151,7 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) {
captureSuccess({
eventName: USER_TRACKER_EVENTS.add_details,
payload: {
use_case: formData.use_case,
use_case: profileUpdatePayload.use_case,
role: formData.role,
},
});
Expand Down Expand Up @@ -212,7 +212,7 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) {

const handleSubmitUserPersonalization = async (formData: TProfileSetupFormValues) => {
const profileUpdatePayload: Partial<TUserProfile> = {
use_case: formData.use_case,
use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined,
role: formData.role,
};
try {
Expand All @@ -223,7 +223,7 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) {
captureSuccess({
eventName: USER_TRACKER_EVENTS.add_details,
payload: {
use_case: formData.use_case,
use_case: profileUpdatePayload.use_case,
role: formData.role,
},
});
Expand Down Expand Up @@ -537,27 +537,38 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) {
className="text-sm text-custom-text-300 font-medium after:content-['*'] after:ml-0.5 after:text-red-500"
htmlFor="use_case"
>
What is your domain expertise? Choose one.
What is your domain expertise? Choose one or more.
</label>
<Controller
control={control}
name="use_case"
rules={{
required: "This field is required",
required: "Please select at least one option",
validate: (value) => (value && value.length > 0) || "Please select at least one option",
}}
render={({ field: { value, onChange } }) => (
<div className="flex flex-wrap gap-2 py-2 overflow-auto break-all">
{USER_DOMAIN.map((userDomain) => (
<div
key={userDomain}
className={`flex-shrink-0 border-[0.5px] hover:cursor-pointer hover:bg-custom-background-90 ${
value === userDomain ? "border-custom-primary-100" : "border-custom-border-300"
} rounded px-3 py-1.5 text-sm font-medium`}
onClick={() => onChange(userDomain)}
>
{userDomain}
</div>
))}
{USER_DOMAIN.map((userDomain) => {
const isSelected = value?.includes(userDomain) || false;
return (
<div
key={userDomain}
className={`flex-shrink-0 border-[0.5px] hover:cursor-pointer hover:bg-custom-background-90 ${
isSelected ? "border-custom-primary-100" : "border-custom-border-300"
} rounded px-3 py-1.5 text-sm font-medium`}
onClick={() => {
const currentValue = value || [];
if (isSelected) {
onChange(currentValue.filter((item) => item !== userDomain));
} else {
onChange([...currentValue, userDomain]);
}
}}
>
{userDomain}
</div>
);
})}
</div>
)}
/>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/core/components/onboarding/steps/profile/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export type TProfileSetupFormValues = {
password?: string;
confirm_password?: string;
role?: string;
use_case?: string;
use_case?: string[];
has_marketing_email_consent?: boolean;
};

Expand Down
24 changes: 16 additions & 8 deletions apps/web/core/components/onboarding/steps/usecase/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Props = {
};

const defaultValues = {
use_case: "",
use_case: [] as string[],
};

export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepChange }: Props) {
Expand All @@ -36,15 +36,15 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC
} = useForm<TProfileSetupFormValues>({
defaultValues: {
...defaultValues,
use_case: profile?.use_case,
use_case: profile?.use_case ? profile.use_case.split(". ") : [],
},
mode: "onChange",
});

// handle submit
const handleSubmitUserPersonalization = async (formData: TProfileSetupFormValues) => {
const profileUpdatePayload: Partial<TUserProfile> = {
use_case: formData.use_case,
use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined,
};
try {
await Promise.all([
Expand All @@ -54,7 +54,7 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC
captureSuccess({
eventName: USER_TRACKER_EVENTS.add_details,
payload: {
use_case: formData.use_case,
use_case: profileUpdatePayload.use_case,
},
});
setToast({
Expand Down Expand Up @@ -100,25 +100,33 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC

{/* Use Case Selection */}
<div className="flex flex-col gap-3">
<p className="text-sm font-medium text-custom-text-400">Select any</p>
<p className="text-sm font-medium text-custom-text-400">Select one or more</p>

<Controller
control={control}
name="use_case"
rules={{
required: "This field is required",
required: "Please select at least one option",
validate: (value) => (value && value.length > 0) || "Please select at least one option",
}}
render={({ field: { value, onChange } }) => (
<div className="flex flex-col gap-3">
{USE_CASES.map((useCase) => {
const isSelected = value === useCase;
const isSelected = value?.includes(useCase) || false;
return (
<button
key={useCase}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onChange(useCase);
const currentValue = value || [];
if (isSelected) {
// Remove from array
onChange(currentValue.filter((item) => item !== useCase));
} else {
// Add to array
onChange([...currentValue, useCase]);
}
}}
className={`w-full px-3 py-2 rounded-lg border transition-all duration-200 flex items-center gap-2 ${
isSelected
Expand Down
Loading