style: onboarding, chore: refactoring (#474)

* style: onboarding screens

* style: onboarding card component and refactoring

* fix: onboarding card text fix

* fix: merge conflict fix
This commit is contained in:
Anmol Singh Bhatia 2023-03-18 11:34:09 +05:30 committed by GitHub
parent 350e183375
commit 5739d95ab4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 442 additions and 332 deletions

View File

@ -1,33 +0,0 @@
// next
import Image from "next/image";
// images
import Module from "public/onboarding/module.png";
const BreakIntoModules: React.FC = () => (
<div className="h-full space-y-4">
<div className="relative h-1/2">
<div
className="absolute bottom-0 z-10 h-8 w-full bg-white"
style={{
background: "linear-gradient(0deg, #fff 84.2%, rgba(255, 255, 255, 0) 34.35%)",
}}
/>
<Image
src={Module}
className="h-full"
objectFit="contain"
layout="fill"
alt="Plane- Modules"
/>
</div>
<div className="mx-auto h-1/2 space-y-4 lg:w-1/2">
<h2 className="text-2xl font-medium">Break into Modules</h2>
<p className="text-sm text-gray-400">
Modules break your big thing into Projects or Features, to help you organize better.
</p>
<p className="text-sm text-gray-400">4/5</p>
</div>
</div>
);
export default BreakIntoModules;

View File

@ -1,24 +0,0 @@
// next
import Image from "next/image";
// images
import Commands from "public/onboarding/command-menu.png";
const CommandMenu: React.FC = () => (
<div className="h-full space-y-4">
<div className="h-1/2 space-y-4">
<h5 className="text-sm text-gray-500">Open the contextual menu with:</h5>
<div className="relative h-1/2">
<Image src={Commands} objectFit="contain" layout="fill" alt="Plane- Issues" />
</div>
</div>
<div className="mx-auto h-1/2 space-y-4 lg:w-2/3">
<h2 className="text-2xl font-medium">Command Menu</h2>
<p className="text-sm text-gray-400">
With Command Menu, you can create, update and navigate across the platform.
</p>
<p className="text-sm text-gray-400">5/5</p>
</div>
</div>
);
export default CommandMenu;

View File

@ -0,0 +1,4 @@
export * from "./invite-members";
export * from "./onboarding-card";
export * from "./user-details";
export * from "./workspace";

View File

@ -4,14 +4,15 @@ import useToast from "hooks/use-toast";
import workspaceService from "services/workspace.service";
import { IUser } from "types";
// ui components
import { MultiInput, OutlineButton } from "components/ui";
import { MultiInput, PrimaryButton, SecondaryButton } from "components/ui";
type Props = {
setStep: React.Dispatch<React.SetStateAction<number>>;
workspace: any;
};
const InviteMembers: React.FC<Props> = ({ setStep, workspace }) => {
export const InviteMembers: React.FC<Props> = ({ setStep, workspace }) => {
const { setToastAlert } = useToast();
const {
@ -39,43 +40,50 @@ const InviteMembers: React.FC<Props> = ({ setStep, workspace }) => {
return (
<form
className="grid w-full place-items-center space-y-8"
className="flex w-full items-center justify-center"
onSubmit={handleSubmit(onSubmit)}
onKeyDown={(e) => {
if (e.code === "Enter") e.preventDefault();
}}
>
<div className="w-full space-y-8 rounded-lg bg-white p-8 md:w-2/5">
<div className="space-y-4">
<h2 className="text-2xl font-medium">Invite co-workers to your team</h2>
<div className="space-y-4">
<div className="col-span-2 space-y-2">
<div className="flex w-full max-w-xl flex-col gap-12">
<div className="flex flex-col gap-6 rounded-[10px] bg-white px-10 py-7 shadow-md">
<h2 className="text-2xl font-medium ">Invite co-workers to your team</h2>
<div className="flex flex-col items-start justify-center gap-2.5 ">
<span>Email</span>
<div className="w-full">
<MultiInput
label="Enter e-mails to invite"
name="emails"
placeholder="dummy@plane.so"
placeholder="Enter co-workers email id"
watch={watch}
setValue={setValue}
className="w-full"
/>
</div>
</div>
</div>
<div className="mx-auto flex h-1/4 gap-2 lg:w-1/2">
<button
<div className="flex w-full flex-col items-center justify-center gap-3 ">
<PrimaryButton
type="submit"
className="w-full rounded-md bg-gray-200 px-4 py-2 text-sm"
className="flex w-1/2 items-center justify-center text-center"
disabled={isSubmitting}
size="md"
>
{isSubmitting ? "Inviting..." : "Continue"}
</PrimaryButton>
<SecondaryButton
type="button"
className="w-1/2 rounded-lg bg-transparent border-none"
size="md"
outline
onClick={() => setStep(4)}
>
{isSubmitting ? "Inviting..." : "Invite"}
</button>
<OutlineButton theme="secondary" className="w-full" onClick={() => setStep(4)}>
Skip
</OutlineButton>
</SecondaryButton>
</div>
</div>
</form>
);
};
export default InviteMembers;

View File

@ -1,34 +0,0 @@
// next
import Image from "next/image";
// images
import Cycle from "public/onboarding/cycle.png";
const MoveWithCycles: React.FC = () => (
<div className="h-full space-y-4">
<div className="relative h-1/2">
<div
className="absolute bottom-0 z-10 h-8 w-full bg-white"
style={{
background: "linear-gradient(0deg, #fff 84.2%, rgba(255, 255, 255, 0) 34.35%)",
}}
/>
<Image
src={Cycle}
className="h-full"
objectFit="contain"
layout="fill"
alt="Plane- Cycles"
/>
</div>
<div className="mx-auto h-1/2 space-y-4 lg:w-2/3">
<h2 className="text-2xl font-medium">Move with Cycles</h2>
<p className="text-sm text-gray-400">
Cycles help you and your team to progress faster, similar to the sprints commonly used in
agile development.
</p>
<p className="text-sm text-gray-400">3/5</p>
</div>
</div>
);
export default MoveWithCycles;

View File

@ -0,0 +1,24 @@
import React from "react";
import Image from "next/image";
interface IOnboardingCard {
step: string;
title: string;
description: React.ReactNode | string;
imgURL: string;
}
type Props = {
data: IOnboardingCard;
};
export const OnboardingCard: React.FC<Props> = ({ data }) => (
<>
<div className="h-44 w-full">
<Image src={data.imgURL} height="180" width="450" alt={data.title} />
</div>
<h3 className="text-3xl font-medium">{data.title}</h3>
<p className="text-base text-gray-400">{data.description}</p>
<span className="text-base text-gray-400">{data.step}</span>
</>
);

View File

@ -1,34 +0,0 @@
// next
import Image from "next/image";
// images
import Issue from "public/onboarding/issue.png";
const PlanWithIssues: React.FC = () => (
<div className="h-full space-y-4">
<div className="relative h-1/2">
<div
className="absolute bottom-0 z-10 h-8 w-full bg-white"
style={{
background: "linear-gradient(0deg, #fff 84.2%, rgba(255, 255, 255, 0) 34.35%)",
}}
/>
<Image
src={Issue}
className="h-full"
objectFit="contain"
layout="fill"
alt="Plane- Issues"
/>
</div>
<div className="mx-auto h-1/2 space-y-4 lg:w-2/3">
<h2 className="text-2xl font-medium">Plan with Issues</h2>
<p className="text-sm text-gray-400">
The issue is the building block of the Plane. Most concepts in Plane are either associated
with issues and their properties.
</p>
<p className="text-sm text-gray-400">2/5</p>
</div>
</div>
);
export default PlanWithIssues;

View File

@ -1,15 +1,17 @@
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { Controller, useForm } from "react-hook-form";
// hooks
import useToast from "hooks/use-toast";
// services
import userService from "services/user.service";
// ui
import { Input } from "components/ui";
import { CustomSelect, Input, PrimaryButton } from "components/ui";
// types
import { IUser } from "types";
// constant
import { USER_ROLE } from "constants/workspace";
const defaultValues: Partial<IUser> = {
first_name: "",
@ -22,12 +24,13 @@ type Props = {
setStep: React.Dispatch<React.SetStateAction<number>>;
};
const UserDetails: React.FC<Props> = ({ user, setStep }) => {
export const UserDetails: React.FC<Props> = ({ user, setStep }) => {
const { setToastAlert } = useToast();
const {
register,
handleSubmit,
control,
reset,
formState: { errors, isSubmitting },
} = useForm<IUser>({
@ -59,61 +62,72 @@ const UserDetails: React.FC<Props> = ({ user, setStep }) => {
}, [user, reset]);
return (
<form className="grid w-full place-items-center" onSubmit={handleSubmit(onSubmit)}>
<div className="w-full space-y-8 rounded-lg bg-white p-8 md:w-2/5">
<div className="grid grid-cols-2 gap-4">
<div>
<Input
label="First Name"
name="first_name"
placeholder="Enter first name"
autoComplete="off"
register={register}
validations={{
required: "First name is required",
}}
error={errors.first_name}
/>
<form className="flex w-full items-center justify-center" onSubmit={handleSubmit(onSubmit)}>
<div className="flex w-full max-w-xl flex-col gap-12">
<div className="flex flex-col rounded-[10px] bg-white shadow-md">
<div className="flex flex-col justify-between gap-3 px-10 py-7 sm:flex-row">
<div className="flex flex-col items-start justify-center gap-2.5">
<span>First name</span>
<Input
name="first_name"
autoComplete="off"
register={register}
validations={{
required: "First name is required",
}}
error={errors.first_name}
/>
</div>
<div className="flex flex-col items-start justify-center gap-2.5">
<span>Last name</span>
<Input
name="last_name"
autoComplete="off"
register={register}
validations={{
required: "Last name is required",
}}
error={errors.last_name}
/>
</div>
</div>
<div>
<Input
label="Last Name"
name="last_name"
placeholder="Enter last name"
autoComplete="off"
register={register}
validations={{
required: "Last name is required",
}}
error={errors.last_name}
/>
</div>
<div className="col-span-2">
<Input
label="Role"
name="role"
placeholder="What is your role?"
autoComplete="off"
register={register}
validations={{
required: "Role is required",
}}
error={errors.role}
/>
<div className="flex flex-col items-start justify-center gap-2.5 border-t border-gray-300 px-10 py-7">
<span>What is your role?</span>
<div className="w-full">
<Controller
name="role"
control={control}
rules={{ required: "This field is required" }}
render={({ field: { value, onChange } }) => (
<CustomSelect
value={value}
onChange={onChange}
label={value ? value.toString() : "Select your role"}
input
width="w-full"
>
{USER_ROLE?.map((item) => (
<CustomSelect.Option key={item.value} value={item.value}>
{item.label}
</CustomSelect.Option>
))}
</CustomSelect>
)}
/>
</div>
</div>
</div>
<div className="mx-auto h-1/4 lg:w-1/2">
<button
<div className="flex w-full items-center justify-center ">
<PrimaryButton
type="submit"
className="w-full rounded-md bg-gray-200 px-4 py-2 text-sm"
className="flex w-1/2 items-center justify-center text-center"
size="md"
disabled={isSubmitting}
>
{isSubmitting ? "Updating..." : "Continue"}
</button>
</PrimaryButton>
</div>
</div>
</form>
);
};
export default UserDetails;

View File

@ -1,21 +0,0 @@
// next
import Image from "next/image";
// icons
import Logo from "public/logo.png";
const Welcome: React.FC = () => (
<div className="h-full space-y-4">
<div className="h-1/2">
<Image src={Logo} height={100} width={100} alt="Plane Logo" />
</div>
<div className="mx-auto h-1/2 space-y-4 lg:w-2/3">
<h2 className="text-2xl font-medium">Welcome to Plane</h2>
<p className="text-sm text-gray-400">
Plane helps you plan your issues, cycles, and product modules to ship faster.
</p>
<p className="text-sm text-gray-400">1/5</p>
</div>
</div>
);
export default Welcome;

View File

@ -14,13 +14,16 @@ import { IWorkspaceMemberInvitation } from "types";
import { USER_WORKSPACE_INVITATIONS } from "constants/fetch-keys";
// constants
import { CreateWorkspaceForm } from "components/workspace";
// ui
import { PrimaryButton } from "components/ui";
type Props = {
setStep: React.Dispatch<React.SetStateAction<number>>;
setWorkspace: React.Dispatch<React.SetStateAction<any>>;
};
const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
export const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false);
const [invitationsRespond, setInvitationsRespond] = useState<string[]>([]);
@ -59,28 +62,39 @@ const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
return (
<div className="grid w-full place-items-center">
<Tab.Group as="div" className="w-full rounded-lg bg-white p-8 md:w-2/5">
<Tab.Group
as="div"
className="flex w-full max-w-xl flex-col rounded-[10px] bg-white shadow-md"
>
<Tab.List
as="div"
className="grid grid-cols-2 items-center gap-2 rounded-lg bg-gray-100 p-2 text-sm"
className="text-gray-8 flex items-center justify-start gap-3 px-10 pt-7 text-base"
>
<Tab
className={({ selected }) =>
`rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}`
`rounded-3xl border px-5 py-2 outline-none ${
selected
? "border-theme bg-theme text-white"
: "border-gray-300 bg-white hover:bg-hover-gray"
}`
}
>
New workspace
New Workspace
</Tab>
<Tab
className={({ selected }) =>
`rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}`
`rounded-3xl border px-5 py-2 outline-none ${
selected
? "border-theme bg-theme text-white"
: "border-gray-300 bg-white hover:bg-hover-gray"
}`
}
>
Invited workspaces
Invited Workspace
</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel className="pt-4">
<Tab.Panel>
<CreateWorkspaceForm
onSubmit={(res) => {
setWorkspace(res);
@ -89,8 +103,8 @@ const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
/>
</Tab.Panel>
<Tab.Panel>
<div className="mt-4 space-y-8">
<div className="divide-y">
<div className="mt-6" >
<div className="divide-y py-8">
{invitations && invitations.length > 0 ? (
invitations.map((invitation) => (
<div key={invitation.id}>
@ -149,19 +163,19 @@ const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
</div>
)}
</div>
<div className="mx-auto h-1/4 lg:w-1/2">
<button
<div className="flex w-full items-center justify-center rounded-b-[10px] py-7 ">
<PrimaryButton
type="submit"
className={`w-full rounded-md bg-gray-200 px-4 py-2 text-sm ${
className={`flex w-1/2 items-center justify-center text-center text-sm ${
isJoiningWorkspaces || invitationsRespond.length === 0
? "cursor-not-allowed opacity-80"
: ""
}`}
size="md"
disabled={isJoiningWorkspaces || invitationsRespond.length === 0}
onClick={submitInvitations}
>
Join Workspace
</button>
</PrimaryButton>
</div>
</div>
</Tab.Panel>
@ -170,5 +184,3 @@ const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
</div>
);
};
export default Workspace;

View File

@ -9,7 +9,7 @@ import workspaceService from "services/workspace.service";
// hooks
import useToast from "hooks/use-toast";
// ui
import { CustomSelect, Input } from "components/ui";
import { CustomSelect, Input, PrimaryButton } from "components/ui";
// types
import { IWorkspace } from "types";
// fetch-keys
@ -17,6 +17,7 @@ import { USER_WORKSPACES } from "constants/fetch-keys";
// constants
import { COMPANY_SIZE } from "constants/workspace";
type Props = {
onSubmit: (res: IWorkspace) => void;
};
@ -77,78 +78,87 @@ export const CreateWorkspaceForm: React.FC<Props> = ({ onSubmit }) => {
}, [reset]);
return (
<form className="space-y-8" onSubmit={handleSubmit(handleCreateWorkspace)}>
<div className="w-full space-y-4 bg-white">
<div className="grid grid-cols-1 gap-4">
<div>
<Input
name="name"
register={register}
label="Workspace name"
placeholder="Enter name"
autoComplete="off"
onChange={(e) =>
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"))
}
validations={{
required: "Workspace name is required",
}}
error={errors.name}
/>
</div>
<div>
<h6 className="text-gray-500">Workspace slug</h6>
<div className="flex items-center rounded-md border border-gray-300 px-3">
<span className="text-sm text-slate-600">{"https://app.plane.so/"}</span>
<form
className="flex w-full items-center justify-center"
onSubmit={handleSubmit(handleCreateWorkspace)}
>
<div className="flex w-full max-w-xl flex-col">
<div className="flex flex-col rounded-[10px] bg-white shadow-md">
<div className="flex flex-col justify-between gap-3 px-10 py-7">
<div className="flex flex-col items-start justify-center gap-2.5">
<span>Workspace name</span>
<Input
mode="trueTransparent"
autoComplete="off"
name="slug"
name="name"
register={register}
className="block w-full rounded-md bg-transparent py-2 px-0 text-sm"
autoComplete="off"
onChange={(e) =>
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"))
}
validations={{
required: "Workspace name is required",
}}
error={errors.name}
/>
</div>
{slugError && (
<span className="-mt-3 text-sm text-red-500">Workspace URL is already taken!</span>
)}
</div>
<div>
<h6 className="text-gray-500">Company size</h6>
<Controller
name="company_size"
control={control}
rules={{ required: "This field is required" }}
render={({ field: { value, onChange } }) => (
<CustomSelect
value={value}
onChange={onChange}
label={value ? value.toString() : "Select company size"}
input
width="w-full"
>
{COMPANY_SIZE?.map((item) => (
<CustomSelect.Option key={item.value} value={item.value}>
{item.label}
</CustomSelect.Option>
))}
</CustomSelect>
<div className="flex flex-col items-start justify-center gap-2.5">
<span>Workspace URL</span>
<div className="flex w-full items-center rounded-md border border-gray-300 px-3">
<span className="text-sm text-slate-600">{"https://app.plane.so/"}</span>
<Input
mode="trueTransparent"
autoComplete="off"
name="slug"
register={register}
className="block w-full rounded-md bg-transparent py-2 px-0 text-sm"
/>
</div>
{slugError && (
<span className="-mt-3 text-sm text-red-500">Workspace URL is already taken!</span>
)}
/>
{errors.company_size && (
</div>
</div>
<div className="flex flex-col items-start justify-center gap-2.5 border-t border-gray-300 px-10 py-7">
<span>How large is your company</span>
<div className="w-full">
<Controller
name="company_size"
control={control}
rules={{ required: "This field is required" }}
render={({ field: { value, onChange } }) => (
<CustomSelect
value={value}
onChange={onChange}
label={value ? value.toString() : "Select company size"}
input
width="w-full"
>
{COMPANY_SIZE?.map((item) => (
<CustomSelect.Option key={item.value} value={item.value}>
{item.label}
</CustomSelect.Option>
))}
</CustomSelect>
)}
/>
{errors.company_size && (
<span className="text-sm text-red-500">{errors.company_size.message}</span>
)}
</div>
</div>
<div className="flex w-full items-center justify-center rounded-b-[10px] py-7 ">
<PrimaryButton
type="submit"
className="flex w-1/2 items-center justify-center text-center"
size="md"
disabled={isSubmitting}
>
{isSubmitting ? "Creating..." : "Create Workspace"}
</PrimaryButton>
</div>
</div>
</div>
<div className="mx-auto h-1/4 lg:w-1/2">
<button
type="submit"
className="w-full rounded-md bg-gray-200 px-4 py-2 text-sm"
disabled={isSubmitting}
>
{isSubmitting ? "Creating..." : "Continue"}
</button>
</div>
</form>
);
};

View File

@ -1,3 +1,9 @@
import Welcome from "public/onboarding/welcome.svg";
import Issue from "public/onboarding/issue.svg";
import Cycle from "public/onboarding/cycle.svg";
import Module from "public/onboarding/module.svg";
import CommandMenu from "public/onboarding/command-menu.svg";
export const ROLE = {
5: "Guest",
10: "Viewer",
@ -11,3 +17,49 @@ export const COMPANY_SIZE = [
{ value: 25, label: "25" },
{ value: 50, label: "50" },
];
export const USER_ROLE = [
{ value: "Founder or leadership team", label: "Founder or leadership team" },
{ value: "Product manager", label: "Product manager" },
{ value: "Designer", label: "Designer" },
{ value: "Software developer", label: "Software developer" },
{ value: "Freelancer", label: "Freelancer" },
{ value: "Other", label: "Other" },
];
export const ONBOARDING_CARDS = {
welcome: {
imgURL: Welcome,
step: "1/5",
title: "Welcome to Plane",
description:
"Plane helps you plan your issues, cycles, and product modules to ship faster.",
},
issue: {
imgURL: Issue,
step: "2/5",
title: "Plan with Issues",
description:
"The issue is the building block of the Plane. Most concepts in Plane are either associated with issues and their properties.",
},
cycle: {
imgURL: Cycle,
step: "3/5",
title: "Move with Cycles",
description:
"Cycles help you and your team to progress faster, similar to the sprints commonly used in agile development.",
},
module: {
imgURL: Module,
step: "4/5",
title: "Break into Modules ",
description:
"Modules break your big think into Projects or Features , to help you organize better.",
},
commandMenu: {
imgURL: CommandMenu,
step: "5 /5",
title: "Command Menu",
description: "With Command Menu, you can create, update and navigate across the platform.",
},
};

View File

@ -12,14 +12,11 @@ import useUser from "hooks/use-user";
// layouts
import DefaultLayout from "layouts/default-layout";
// components
import Welcome from "components/onboarding/welcome";
import PlanWithIssues from "components/onboarding/plan-with-issues";
import MoveWithCycles from "components/onboarding/move-with-cycles";
import BreakIntoModules from "components/onboarding/break-into-modules";
import UserDetails from "components/onboarding/user-details";
import Workspace from "components/onboarding/workspace";
import InviteMembers from "components/onboarding/invite-members";
import CommandMenu from "components/onboarding/command-menu";
import { InviteMembers, OnboardingCard, UserDetails, Workspace } from "components/onboarding";
// ui
import { PrimaryButton } from "components/ui";
// constant
import { ONBOARDING_CARDS } from "constants/workspace";
// images
import Logo from "public/onboarding/logo.svg";
// types
@ -38,9 +35,9 @@ const Onboarding: NextPage = () => {
<DefaultLayout>
<div className="grid h-full place-items-center p-5">
{step <= 3 ? (
<div className="w-full space-y-4">
<div className="text-center">
<Image src={Logo} height="40" alt="Plane Logo" />
<div className="w-full">
<div className="text-center mb-8">
<Image src={Logo} height="50" alt="Plane Logo" />
</div>
{step === 1 ? (
<UserDetails user={user} setStep={setStep} />
@ -51,39 +48,40 @@ const Onboarding: NextPage = () => {
)}
</div>
) : (
<div className="h-max min-h-[360px] w-full rounded-lg bg-white px-8 py-10 text-center md:w-1/2">
<div className="h-3/4 w-full">
<div className="flex w-full max-w-2xl flex-col gap-12">
<div className="flex flex-col items-center justify-center gap-7 rounded-[10px] bg-white px-14 py-10 text-center shadow-md">
{step === 4 ? (
<Welcome />
<OnboardingCard data={ONBOARDING_CARDS.welcome} />
) : step === 5 ? (
<PlanWithIssues />
<OnboardingCard data={ONBOARDING_CARDS.issue} />
) : step === 6 ? (
<MoveWithCycles />
<OnboardingCard data={ONBOARDING_CARDS.cycle} />
) : step === 7 ? (
<BreakIntoModules />
<OnboardingCard data={ONBOARDING_CARDS.module} />
) : (
<CommandMenu />
<OnboardingCard data={ONBOARDING_CARDS.commandMenu} />
)}
</div>
<div className="mx-auto flex h-1/4 items-end lg:w-1/2">
<button
type="button"
className="w-full rounded-md bg-gray-200 px-4 py-2 text-sm"
onClick={() => {
if (step === 8) {
userService
.updateUserOnBoard()
.then(() => {
router.push("/");
})
.catch((err) => {
console.log(err);
});
} else setStep((prevData) => prevData + 1);
}}
>
{step === 4 || step === 8 ? "Get Started" : "Next"}
</button>
<div className="mx-auto flex h-1/4 items-end lg:w-1/2">
<PrimaryButton
type="button"
className="flex w-full items-center justify-center text-center "
size="md"
onClick={() => {
if (step === 8) {
userService
.updateUserOnBoard()
.then(() => {
router.push("/");
})
.catch((err) => {
console.log(err);
});
} else setStep((prevData) => prevData + 1);
}}
>
{step === 4 || step === 8 ? "Get Started" : "Next"}
</PrimaryButton>
</div>
</div>
</div>
)}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,5 @@
<svg width="450" height="180" viewBox="0 0 450 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M293.949 21.0508H202.016V67.0193H247.981V112.984H293.949V21.0508Z" fill="#3F76FF"/>
<path d="M202.016 67.0195H156.051V112.881H202.016V67.0195Z" fill="#3F76FF"/>
<path d="M247.98 112.984H202.118V158.949H247.98V112.984Z" fill="#3F76FF"/>
</svg>

After

Width:  |  Height:  |  Size: 352 B