Onboarding Page (pages/onboarding/index.tsx)¶
Overview¶
The Onboarding page guides new users through the initial setup process for their BidScript account. It collects essential company information, user preferences, and sets up the workspace for optimal use.
Features¶
- Multi-step onboarding wizard
- Company profile setup
- User preference configuration
- Document template selection
- Guided tutorial for core features
- Progress tracking and persistence
- Quick start option for immediate access
URL Parameters¶
quick: Optional - Boolean flag to enable quick onboarding process
Implementation¶
State Management¶
// Form data state
const [companyFormData, setCompanyFormData] = useState<CompanyFormData>({
companyName: "",
tradingName: "",
registeredCompanyNumber: "",
vatNumber: "",
dateOfIncorporation: "",
businessAddress: "",
registeredAddress: {
street: "",
city: "",
county: "",
postcode: "",
country: "",
},
operatingAddress: {
street: "",
city: "",
county: "",
postcode: "",
country: "",
},
contactDetails: {
fullName: "",
jobTitle: "",
email: "",
phone: "",
},
generalEmail: "",
websiteUrl: "",
companyProfile: {
description: "",
employeeCount: "",
annualTurnover: "",
sectors: [],
geographicCoverage: "",
},
legalDetails: {
entityType: "",
parentCompany: "",
accreditations: "",
insurance: "",
},
});
// Onboarding progress tracking
const [currentStep, setCurrentStep] = useState<number>(0);
const [completedSteps, setCompletedSteps] = useState<number[]>([]);
const [isQuickStart, setIsQuickStart] = useState<boolean>(false);
Methods¶
// Form navigation and validation
const handleNextStep = () =>
// Validates current step and advances to the next
const handlePreviousStep = () =>
// Returns to the previous onboarding step
const validateStep = (step: number) =>
// Validates the data for a specific step
// Data submission
const handleSubmitCompanyProfile = async () =>
// Submits the completed company profile data
const handleQuickStart = async () =>
// Skips full onboarding for a minimal setup
// Navigation
const completeOnboarding = () =>
// Finalises onboarding and redirects to dashboard
HTML Structure¶
<div className="onboarding-container min-h-screen flex flex-col bg-gradient-to-br from-blue-50 to-white">
{/* Header */}
<header className="py-6 px-8 flex justify-between items-center border-b">
<div className="logo">
<img src="/logo.svg" alt="BidScript Logo" className="h-10" />
</div>
{!isQuickStart && (
<Button variant="ghost" onClick={handleQuickStart}>
Quick Start
</Button>
)}
</header>
{/* Progress indicator */}
<div className="progress-container px-8 py-4">
<div className="flex justify-between items-center max-w-3xl mx-auto">
{steps.map((step, index) => (
<div key={index} className="flex flex-col items-center">
<div
className={`step-indicator h-10 w-10 rounded-full flex items-center justify-center ${
completedSteps.includes(index)
? "bg-green-500 text-white"
: currentStep === index
? "bg-blue-500 text-white"
: "bg-gray-200 text-gray-500"
}`}
>
{completedSteps.includes(index) ? (
<CheckIcon className="h-5 w-5" />
) : (
index + 1
)}
</div>
<span className="text-sm mt-2">{step.title}</span>
</div>
))}
</div>
</div>
{/* Step content */}
<div className="flex-grow flex items-center justify-center py-8">
<div className="max-w-3xl w-full px-6">
<AnimatePresence mode="wait">
<motion.div
key={currentStep}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
>
{currentStep === 0 && (
<CompanyInformationStep
formData={companyFormData}
updateFormData={updateCompanyFormData}
/>
)}
{currentStep === 1 && (
<AddressInformationStep
formData={companyFormData}
updateFormData={updateCompanyFormData}
/>
)}
{currentStep === 2 && (
<ContactInformationStep
formData={companyFormData}
updateFormData={updateCompanyFormData}
/>
)}
{currentStep === 3 && (
<CompanyProfileStep
formData={companyFormData}
updateFormData={updateCompanyFormData}
/>
)}
{currentStep === 4 && (
<LegalInformationStep
formData={companyFormData}
updateFormData={updateCompanyFormData}
/>
)}
{currentStep === 5 && (
<ReviewAndSubmitStep
formData={companyFormData}
onSubmit={handleSubmitCompanyProfile}
/>
)}
</motion.div>
</AnimatePresence>
</div>
</div>
{/* Navigation buttons */}
<div className="navigation-container border-t py-6 px-8">
<div className="flex justify-between max-w-3xl mx-auto">
<Button
variant="outline"
onClick={handlePreviousStep}
disabled={currentStep === 0}
>
Previous
</Button>
<Button
onClick={
currentStep === steps.length - 1
? handleSubmitCompanyProfile
: handleNextStep
}
>
{currentStep === steps.length - 1 ? "Complete Setup" : "Next"}
</Button>
</div>
</div>
</div>
Props¶
No props - page component
Components/API Routes Used¶
Components¶
- CompanyInformationStep
- AddressInformationStep
- ContactInformationStep
- CompanyProfileStep
- LegalInformationStep
- ReviewAndSubmitStep
API Routes¶
/api/onboarding/company- Saves company profile information/api/onboarding/quickStart- Initiates quick start setup/api/onboarding/progress- Tracks onboarding progress
Routes to Page¶
- Direct:
/onboarding - Quick start:
/onboarding/quick - From: Sign-up completion redirect
- From: First login redirect
Dependencies¶
import { useEffect, useState } from "react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { motion, AnimatePresence } from "framer-motion";
import { ensureCompany, getApiPath } from "@/lib/apiUtils";
Notes¶
- Automatically redirects authenticated users who have completed onboarding
- Persists progress for users who exit onboarding midway
- Provides optional quick start path for minimal setup
- Implements form validation for each step
- Features smooth animations between steps
- Optimised for mobile and desktop devices