Provider guide

Provider invitation acceptance tutorial

This tutorial explains how a provider accepts an operator invitation, verifies their email with OTP, activates their account, and is redirected to the provider dashboard.

Invite token Email verification OTP Activation
Provider accept page · /provider/accept?token=...
Page overview
Accept a provider invitation using token and OTP
01
Purpose — lets a service provider accept an invitation from an operator.
Token source — reads the invite token from the URL search parameter.
Invite lookup — fetches invitation information from the provider accept API.
Email verification — sends a provider OTP to the invited email.
Activation — after OTP verification, the account is activated and invite token is cleared.
Redirect — after success, provider is redirected to their dashboard.
Best use: Send this link to new providers so they can activate their BookMyWave provider dashboard without manual setup.
What you see

You've been invited

Tooup Sailing has invited you as their preferred Catering on Bookmywave.

Your email
provider@example.com
Provider accept page · Activation state machine
Acceptance flow
The page moves through loading, info, otp, done, and error states
02
loading — initial state while the token is checked.
info — invitation is valid and provider is not active yet.
otp — OTP has been sent and user must enter the code.
done — account activated successfully and redirect is scheduled.
invalid — token missing, invalid, already used, or lookup failed.
already_active — provider account exists and is already active.
Flow states
1
Loading
Check token
2
Info
Show invite
3
OTP
Verify email
Done
Activate account
!
Invalid
Bad token
Provider accept page · Loading token
Loading invitation
Initial invite-token check
03
useSearchParams — reads token from the URL.
No token — immediately switches to invalid state.
Invite fetch — requests invite details using the token.
Success — stores invite data and pre-fills contact email.
Provider already active — sends user to already_active state instead of info state.
Fetch failure — shows invalid invite message.
Loading card
Loading invitation...
Provider accept page · Valid invitation info
Invitation info state
Shows who invited the provider and which category they are invited for
04
Title — “You've been invited”.
Operator name — shows invite.operator_name as the inviting operator.
Category — shows invite.category, for example Catering, DJ, Photography, or another provider category.
Email box — displays the invited contact email.
Primary CTA — “Verify email & activate account” sends the OTP.
Error area — if OTP send fails, an error message appears above the button.
Invite info card

You've been invited

BookMyWave Operator has invited you as their preferred Photography on Bookmywave.

Your email
photo@example.com
Provider accept page · Send OTP
Sending the OTP
Email verification code for provider user type
05
Endpoint — sends POST request to auth OTP send endpoint.
Email — sends to the invited provider email shown in the card.
User type — uses provider as user_type so the OTP applies to provider login/activation.
Success — moves the page to otp state.
Failure — shows “Failed to send OTP. Try again.”
Important: The provider must have access to this email inbox to activate the account.
Send OTP request
POST /api/auth/otp/send { "email": "provider@example.com", "user_type": "provider" }
Error copy: Failed to send OTP. Try again.
Provider accept page · OTP verification
Enter your code
Six-digit numeric OTP input
06
Title — “Enter your code”.
Email reminder — tells provider the code was sent to their email.
Numeric input — inputMode numeric and maxLength 6.
Digit cleanup — non-digits are removed as the provider types.
Disabled button — Activate button stays disabled until six digits are entered.
Back button — returns to info state so provider can resend or review email.
User expectation: The code should be exactly six digits, no spaces or letters.
OTP card

Enter your code

We sent a 6-digit code to provider@example.com

Provider accept page · Verify and activate
Activation success
Verify OTP, activate provider, then redirect
07
Verify OTP — sends email, code, and provider user type to OTP verify endpoint.
Incorrect code — shows “Incorrect code. Try again.”
Activation POST — after OTP success, calls provider accept endpoint with the invite token.
Done state — shows “Account activated! Redirecting to your dashboard...”
Redirect — automatically pushes the user to provider dashboard after a short delay.
Result: Provider account becomes active and the invitation token is no longer usable.
Done card
✓ Account activated! Redirecting to your dashboard...
Activation request
POST /api/provider/accept { "token": "invite-token-from-url" }
Provider accept page · Invalid invite state
Invalid or already-used link
Shown when token is missing, bad, expired, or consumed
08
No token — URL has no token search parameter.
API error — invite lookup returns data.error.
Fetch failure — request fails or cannot parse valid invitation.
Message — tells provider the invitation link is invalid or already used.
Support action: The operator should resend a new invite if the provider cannot activate from this link.
Invalid state
This invitation link is invalid or has already been used.
Provider accept page · Already active state
Account already active
Provider is sent to login instead of activation
09
provider_active check — if invite says the provider is already active, page does not show OTP flow.
Message — tells the provider their account is already active.
Sign in link — points to provider login.
Meaning: The link may still be valid enough to identify the provider, but there is no need to activate again.
Already active card
Your account is already active. Sign in →
Provider accept page · Suspense wrapper
Suspense and search params
The page wraps the client component in Suspense
10
AcceptPage — exports a wrapper component that renders AcceptInner inside Suspense.
AcceptInner — contains the actual state machine, search params, router, and API calls.
Why Suspense — client search params can require a Suspense boundary in App Router.
Fallback — this code uses an empty Suspense fallback, so the internal loading card handles the visible loading state.
Component structure
export default function AcceptPage() { return ( <Suspense> <AcceptInner /> </Suspense> ); }
Visible loading: The card shows “Loading invitation...” from the component state.
Provider accept page · Mobile layout
Mobile layout
Centered card remains readable on small screens
11
Full-height wrapper — card is vertically and horizontally centered.
Safe padding — wrapper padding prevents the card touching screen edges.
Max width — card is capped at 420px but becomes full-width on narrow phones.
OTP input — large centered digits make verification easier on mobile.
Full-width CTA — primary action button fills the card width.
Good UX: This is a one-task page, so a centered card is the right layout for mobile activation.
Mobile-style card

Enter your code

We sent a 6-digit code to provider@example.com