Path: blob/main/components/dashboard/src/onboarding/StepOrgInfo.tsx
2500 views
/**1* Copyright (c) 2023 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { FC, useCallback, useMemo, useState } from "react";7import { CheckboxInputField, CheckboxListField } from "../components/forms/CheckboxInputField";8import { SelectInputField } from "../components/forms/SelectInputField";9import { TextInputField } from "../components/forms/TextInputField";10import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutation";11import { useOnBlurError } from "../hooks/use-onblur-error";12import { EXPLORE_REASON_WORK, getExplorationReasons } from "./exploration-reasons";13import { getJobRoleOptions, JOB_ROLE_OTHER } from "./job-roles";14import { OnboardingStep } from "./OnboardingStep";15import { getSignupGoalsOptions, SIGNUP_GOALS_OTHER } from "./signup-goals";16import { getCompanySizeOptions } from "./company-size";17import { useCurrentOrg } from "../data/organizations/orgs-query";18import { useCreateOrgMutation } from "../data/organizations/create-org-mutation";19import { User } from "@gitpod/public-api/lib/gitpod/v1/user_pb";2021type Props = {22user: User;23onComplete(user: User): void;24};25export const StepOrgInfo: FC<Props> = ({ user, onComplete }) => {26const updateUser = useUpdateCurrentUserMutation();27const jobRoleOptions = useMemo(getJobRoleOptions, []);28const explorationReasonsOptions = useMemo(getExplorationReasons, []);29const signupGoalsOptions = useMemo(getSignupGoalsOptions, []);30const companySizeOptions = useMemo(getCompanySizeOptions, []);31const currentOrg = useCurrentOrg();32const createOrg = useCreateOrgMutation();3334const [jobRole, setJobRole] = useState(user.profile?.jobRole ?? "");35const [jobRoleOther, setJobRoleOther] = useState(user.profile?.jobRoleOther ?? "");36const [explorationReasons, setExplorationReasons] = useState<string[]>(user.profile?.explorationReasons ?? []);37const [signupGoals, setSignupGoals] = useState<string[]>(user.profile?.signupGoals ?? []);38const [signupGoalsOther, setSignupGoalsOther] = useState(user.profile?.signupGoalsOther ?? "");39const [companySize, setCompanySize] = useState(user.profile?.companySize ?? "");4041const addSignupGoal = useCallback(42(goal: string) => {43if (!signupGoals.includes(goal)) {44setSignupGoals([...signupGoals, goal]);45}46},47[signupGoals],48);4950const removeSignupGoal = useCallback(51(goal: string) => {52if (signupGoals.includes(goal)) {53const idx = signupGoals.indexOf(goal);54const newGoals = [...signupGoals];55newGoals.splice(idx, 1);56setSignupGoals(newGoals);57}58// clear out freeform other if removing option59if (goal === SIGNUP_GOALS_OTHER) {60setSignupGoalsOther("");61}62},63[signupGoals],64);6566const addExplorationReason = useCallback(67(reason: string) => {68if (!explorationReasons.includes(reason)) {69setExplorationReasons([...explorationReasons, reason]);70}71},72[explorationReasons],73);7475const removeExplorationReason = useCallback(76(reason: string) => {77if (explorationReasons.includes(reason)) {78const idx = explorationReasons.indexOf(reason);79const newReasons = [...explorationReasons];80newReasons.splice(idx, 1);81setExplorationReasons(newReasons);82}83if (reason === EXPLORE_REASON_WORK) {84setCompanySize("");85}86},87[explorationReasons],88);8990const handleSubmit = useCallback(async () => {91// create an org if the user is not a member of one already92if (!currentOrg.data) {93let orgName = "My Org";94function orgify(name: string) {95let result = name.split(" ")[0];96if (result.endsWith("s")) {97return result + `' Org`;98}99return result + `'s Org`;100}101if (user.name) {102orgName = orgify(user.name);103}104await createOrg.mutateAsync({105name: orgName,106});107}108109// Filter out any values not present in options110const filteredReasons = explorationReasons.filter((val) =>111explorationReasonsOptions.find((o) => o.value === val),112);113const filteredGoals = signupGoals.filter((val) => signupGoalsOptions.find((o) => o.value === val));114115const updates = {116additionalData: {117profile: {118jobRole,119jobRoleOther,120explorationReasons: filteredReasons,121signupGoals: filteredGoals,122signupGoalsOther,123companySize,124},125},126};127128try {129const updatedUser = await updateUser.mutateAsync(updates);130onComplete(updatedUser);131} catch (e) {132console.error(e);133}134}, [135companySize,136createOrg,137currentOrg.data,138explorationReasons,139explorationReasonsOptions,140jobRole,141jobRoleOther,142onComplete,143signupGoals,144signupGoalsOptions,145signupGoalsOther,146updateUser,147user.name,148]);149150const jobRoleError = useOnBlurError("Please select one", !!jobRole);151const companySizeError = useOnBlurError(152"Please select one",153!explorationReasons.includes(EXPLORE_REASON_WORK) || !!companySize,154);155const isValid =156jobRoleError.isValid && companySizeError.isValid && signupGoals.length > 0 && explorationReasons.length > 0;157158return (159<OnboardingStep160title="Tell us more about you"161error={updateUser.isError ? "There was a problem saving your answers" : ""}162isValid={isValid}163isSaving={updateUser.isLoading}164onSubmit={handleSubmit}165>166<SelectInputField167value={jobRole}168label="What best describes your role"169onChange={(val) => {170if (val !== "other") {171setJobRoleOther("");172}173setJobRole(val);174}}175error={jobRoleError.message}176onBlur={jobRoleError.onBlur}177>178{jobRoleOptions.map((o) => (179<option key={o.value} value={o.value}>180{o.label}181</option>182))}183</SelectInputField>184185{jobRole === JOB_ROLE_OTHER && (186<TextInputField value={jobRoleOther} onChange={setJobRoleOther} placeholder="Please share (optional)" />187)}188189<CheckboxListField label="You're exploring Gitpod for">190{explorationReasonsOptions.map((o) => (191<CheckboxInputField192key={o.value}193value={o.value}194label={o.label}195checked={explorationReasons.includes(o.value)}196topMargin={false}197onChange={(checked) => {198if (checked) {199addExplorationReason(o.value);200} else {201removeExplorationReason(o.value);202}203}}204/>205))}206</CheckboxListField>207208{explorationReasons.includes(EXPLORE_REASON_WORK) && (209<SelectInputField210value={companySize}211label="How large is your engineering organization?"212onChange={setCompanySize}213error={companySizeError.message}214onBlur={companySizeError.onBlur}215>216{companySizeOptions.map((o) => (217<option key={o.value} value={o.value}>218{o.label}219</option>220))}221</SelectInputField>222)}223224<CheckboxListField label="I'm hoping to use Gitpod for" sublabel="Select all that apply">225{signupGoalsOptions.map((o) => (226<CheckboxInputField227key={o.value}228value={o.value}229label={o.label}230checked={signupGoals.includes(o.value)}231topMargin={false}232onChange={(checked) => {233if (checked) {234addSignupGoal(o.value);235} else {236removeSignupGoal(o.value);237}238}}239/>240))}241</CheckboxListField>242243{signupGoals.includes(SIGNUP_GOALS_OTHER) && (244<TextInputField245value={signupGoalsOther}246placeholder="Please share (optional)"247onChange={setSignupGoalsOther}248/>249)}250</OnboardingStep>251);252};253254255