feat: update onboarding ui

This commit is contained in:
Liyang Zhu
2022-06-05 20:50:10 +08:00
parent c26000f3f5
commit 78a585f137
9 changed files with 132 additions and 130 deletions
+15 -67
View File
@@ -1,12 +1,11 @@
import { useState } from "react"; import { useState } from "react";
import toast from "react-hot-toast"; import { Navigate } from "react-router-dom";
import StyledButton from "../../common/component/styled/Button"; import WelcomeStep from "./steps/1-welcome";
import FirstStep from "./steps/first"; import SpaceNameStep from "./steps/2-spaceName";
import SpaceNameStep from "./steps/spaceName"; import AdminCredentialsStep from "./steps/3-adminCredentials";
import AdminCredentialsStep from "./steps/adminCredentials"; import InviteRuleStep from "./steps/4-inviteRule";
import InviteRuleStep from "./steps/inviteRule"; import InviteLinkStep from "./steps/5-inviteLink";
import InviteLinkStep from "./steps/inviteLink"; import CompletedStep from "./steps/6-completed";
import LastStep from "./steps/last";
import StyledOnboardingPage from "./styled"; import StyledOnboardingPage from "./styled";
export default function OnboardingPage() { export default function OnboardingPage() {
@@ -18,70 +17,19 @@ export default function OnboardingPage() {
adminPassword2: "", adminPassword2: "",
inviteRule: null inviteRule: null
}); });
const props = { step, setStep, data, setData };
return ( return (
<StyledOnboardingPage> <StyledOnboardingPage>
<div className="horizontalBox"> <div className="horizontalBox">
<div className="verticalBox"> <div className="verticalBox">
{step > 0 && step < 5 && ( {step === 0 && <WelcomeStep {...props} />}
<> {step === 1 && <SpaceNameStep {...props} />}
<StyledButton className="buttonBack ghost border_less" onClick={() => setStep(step - 1)}> {step === 2 && <AdminCredentialsStep {...props} />}
Back {step === 3 && <InviteRuleStep {...props} />}
</StyledButton> {step === 4 && <InviteLinkStep {...props} />}
<StyledButton {step === 5 && <CompletedStep {...props} />}
className="buttonNext" {step === 6 && <Navigate replace to="/" />}
onClick={() => {
if (step === 1) {
// Verification for space name
if (data.spaceName === "") {
toast.error("Please enter space name!");
return;
}
setStep(step + 1);
} else if (step === 2) {
// Verification for admin credentials
if (data.adminEmail === "") {
toast.error("Please enter admin email!");
return;
} else if (data.adminPassword === "") {
toast.error("Please enter admin password!");
return;
} else if (data.adminPassword !== data.adminPassword2) {
toast.error("Two passwords do not match!");
return;
}
setStep(step + 1);
} else if (step === 3) {
// Verification for invitation rule
if (data.inviteRule === null) {
toast.error("Please choose one option!");
return;
}
setStep(step + 1);
} else if (step === 4) {
// Verification for invitation link
setStep(step + 1);
}
}}
>
Next
</StyledButton>
</>
)}
{step === 0 && <FirstStep onButtonClick={() => setStep(step + 1)} />}
{step === 1 && <SpaceNameStep data={data} setData={setData} />}
{step === 2 && <AdminCredentialsStep data={data} setData={setData} />}
{step === 3 && <InviteRuleStep data={data} setData={setData} />}
{step === 4 && <InviteLinkStep />}
{step === 5 && (
<LastStep
data={data}
onButtonClick={() => {
// TODO: finish it
console.log("onboarding steps completed:", data);
}}
/>
)}
</div> </div>
</div> </div>
</StyledOnboardingPage> </StyledOnboardingPage>
@@ -10,14 +10,14 @@ const StyledFirstStep = styled.div`
align-items: center; align-items: center;
`; `;
export default function FirstStep({ onButtonClick }) { export default function WelcomeStep({ step, setStep }) {
return ( return (
<StyledFirstStep> <StyledFirstStep>
<span className="primaryText">Welcome to your Rustchat!</span> <span className="primaryText">Welcome to your Rustchat!</span>
<span className="secondaryText"> <span className="secondaryText">
Everything in this space is owned by you. Lets set up your space! Everything in this space is owned by you. Lets set up your space!
</span> </span>
<StyledButton className="startButton" onClick={onButtonClick}> <StyledButton className="startButton" onClick={() => setStep(step + 1)}>
<img src={PlayIcon} alt="play icon" /> <img src={PlayIcon} alt="play icon" />
<span>Start</span> <span>Start</span>
</StyledButton> </StyledButton>
@@ -0,0 +1,55 @@
import styled from "styled-components";
import toast from "react-hot-toast";
import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
const StyledSpaceNameStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .secondaryText {
color: #667085;
}
> .button {
margin-top: 24px;
}
`;
export default function SpaceNameStep({ step, setStep, data, setData }) {
return (
<StyledSpaceNameStep>
<span className="primaryText">Create a new server</span>
<span className="secondaryText">
Servers are shared environments where teams can work on projects and chat.
</span>
<StyledInput
className="input"
placeholder="Enter server name"
value={data.spaceName}
onChange={(e) =>
setData({
...data,
spaceName: e.target.value
})
}
/>
<StyledButton
className="button"
onClick={() => {
// Verification for space name
if (data.spaceName === "") {
toast.error("Please enter server name!");
return;
}
setStep(step + 1);
}}
>
Create Server
</StyledButton>
</StyledSpaceNameStep>
);
}
@@ -1,5 +1,7 @@
import styled from "styled-components"; import styled from "styled-components";
import StyledInput from "../../../common/component/styled/Input"; import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
import toast from "react-hot-toast";
const StyledAdminCredentialsStep = styled.div` const StyledAdminCredentialsStep = styled.div`
height: 100%; height: 100%;
@@ -8,12 +10,16 @@ const StyledAdminCredentialsStep = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
> .input:not(:last-child) { > .input:not(:nth-last-child(2)) {
margin-bottom: 20px; margin-bottom: 20px;
} }
> .button {
margin-top: 24px;
}
`; `;
export default function AdminCredentialsStep({ data, setData }) { export default function AdminCredentialsStep({ step, setStep, data, setData }) {
return ( return (
<StyledAdminCredentialsStep> <StyledAdminCredentialsStep>
<span className="primaryText">Now lets set up your admin account</span> <span className="primaryText">Now lets set up your admin account</span>
@@ -53,6 +59,25 @@ export default function AdminCredentialsStep({ data, setData }) {
}) })
} }
/> />
<StyledButton
className="button"
onClick={() => {
// Verification for admin credentials
if (data.adminEmail === "") {
toast.error("Please enter admin email!");
return;
} else if (data.adminPassword === "") {
toast.error("Please enter admin password!");
return;
} else if (data.adminPassword !== data.adminPassword2) {
toast.error("Two passwords do not match!");
return;
}
setStep(step + 1);
}}
>
Sign Up
</StyledButton>
</StyledAdminCredentialsStep> </StyledAdminCredentialsStep>
); );
} }
@@ -1,5 +1,6 @@
import styled from "styled-components"; import styled from "styled-components";
import StyledRadio from "../../../common/component/styled/Radio"; import StyledRadio from "../../../common/component/styled/Radio";
import StyledButton from "../../../common/component/styled/Button";
const StyledInviteRuleStep = styled.div` const StyledInviteRuleStep = styled.div`
height: 100%; height: 100%;
@@ -8,12 +9,12 @@ const StyledInviteRuleStep = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
> .input:not(:last-child) { > .input:not(:nth-last-child(2)) {
margin-bottom: 20px; margin-bottom: 20px;
} }
`; `;
export default function InviteRuleStep({ data, setData }) { export default function InviteRuleStep({ step, setStep, data, setData }) {
return ( return (
<StyledInviteRuleStep> <StyledInviteRuleStep>
<span className="primaryText">Last step: invite others!</span> <span className="primaryText">Last step: invite others!</span>
@@ -21,13 +22,19 @@ export default function InviteRuleStep({ data, setData }) {
<StyledRadio <StyledRadio
options={["Everyone", "Invitation link only"]} options={["Everyone", "Invitation link only"]}
value={data.inviteRule} value={data.inviteRule}
onChange={(v) => onChange={(v) => {
setData({ setData({
...data, ...data,
inviteRule: v inviteRule: v
}) });
} setTimeout(() => {
setStep(step + 1);
}, 750);
}}
/> />
<StyledButton className="button border_less ghost" onClick={() => setStep(step + 1)}>
Skip
</StyledButton>
</StyledInviteRuleStep> </StyledInviteRuleStep>
); );
} }
@@ -51,7 +51,7 @@ const StyledInviteLinkStep = styled.div`
} }
`; `;
export default function InviteLinkStep() { export default function InviteLinkStep({ step, setStep }) {
const { link, linkCopied, copyLink } = useInviteLink(); const { link, linkCopied, copyLink } = useInviteLink();
return ( return (
@@ -65,6 +65,9 @@ export default function InviteLinkStep() {
{linkCopied ? "Copied" : `Copy`} {linkCopied ? "Copied" : `Copy`}
</StyledButton> </StyledButton>
</div> </div>
<StyledButton className="button border_less ghost" onClick={() => setStep(step + 1)}>
Skip
</StyledButton>
</StyledInviteLinkStep> </StyledInviteLinkStep>
); );
} }
@@ -14,7 +14,7 @@ const StyledLastStep = styled.div`
} }
> .tip { > .tip {
width: 588px; width: 560px;
font-size: 20px; font-size: 20px;
line-height: 24px; line-height: 24px;
text-align: center; text-align: center;
@@ -26,7 +26,7 @@ const StyledLastStep = styled.div`
} }
`; `;
export default function LastStep({ data, onButtonClick }) { export default function CompletedStep({ data, step, setStep }) {
return ( return (
<StyledLastStep> <StyledLastStep>
<span className="primaryText">Welcome to {data.spaceName}</span> <span className="primaryText">Welcome to {data.spaceName}</span>
@@ -35,7 +35,7 @@ export default function LastStep({ data, onButtonClick }) {
More settings, including domain resolution, privileges, securities, and invites are available in{" "} More settings, including domain resolution, privileges, securities, and invites are available in{" "}
<span className="strong">Settings</span> <span className="strong">Settings</span>
</span> </span>
<StyledButton className="startButton" onClick={onButtonClick}> <StyledButton className="startButton" onClick={() => setStep(step + 1)}>
<img src={PlayIcon} alt="play icon" /> <img src={PlayIcon} alt="play icon" />
<span>Start</span> <span>Start</span>
</StyledButton> </StyledButton>
-34
View File
@@ -1,34 +0,0 @@
import styled from "styled-components";
import StyledInput from "../../../common/component/styled/Input";
const StyledSpaceNameStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .secondaryText {
color: #667085;
}
`;
export default function SpaceNameStep({ data, setData }) {
return (
<StyledSpaceNameStep>
<span className="primaryText">Lets start with name:</span>
<span className="secondaryText">This space is called: </span>
<StyledInput
className="input"
placeholder="Enter space name"
value={data.spaceName}
onChange={(e) =>
setData({
...data,
spaceName: e.target.value
})
}
/>
</StyledSpaceNameStep>
);
}
+14 -16
View File
@@ -16,21 +16,6 @@ const StyledOnboardingPage = styled.div`
border: 1px solid #f2f4f7; border: 1px solid #f2f4f7;
border-radius: 12px; border-radius: 12px;
box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06); box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
> .buttonBack,
> .buttonNext {
position: absolute;
bottom: 32px;
}
> .buttonBack {
left: 30px;
color: #98a2b3;
}
> .buttonNext {
right: 30px;
}
} }
} }
@@ -84,8 +69,21 @@ const StyledOnboardingPage = styled.div`
line-height: 24px; line-height: 24px;
padding: 10px 14px; padding: 10px 14px;
border: 1px solid #d0d5dd; border: 1px solid #d0d5dd;
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px; border-radius: 8px;
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
}
.button {
width: 360px;
&.ghost.border_less {
width: fit-content;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #98a2b3;
margin-top: 14px;
}
} }
`; `;