chore: bulk commit of pre-existing changes
Build & Deploy / Build & Push Docker Image (push) Successful in 48s
Test / API Unit Tests (push) Successful in 9m48s
Test / Marketplace Unit Tests (push) Successful in 9m38s
Test / Admin Unit Tests (push) Successful in 9m33s
Build & Deploy / Deploy to VPS (push) Has been cancelled
Test / Dashboard Unit Tests (push) Has been cancelled
Test / API Integration Tests (push) Has been cancelled
Build & Deploy / Build & Push Docker Image (push) Successful in 48s
Test / API Unit Tests (push) Successful in 9m48s
Test / Marketplace Unit Tests (push) Successful in 9m38s
Test / Admin Unit Tests (push) Successful in 9m33s
Build & Deploy / Deploy to VPS (push) Has been cancelled
Test / Dashboard Unit Tests (push) Has been cancelled
Test / API Integration Tests (push) Has been cancelled
Includes: - Admin dashboard layout and page updates - API account auth module (routes, schemas, service) - Dashboard sign-up form extraction, middleware refactor - Marketplace proxy and middleware updates - CORS origins expansion for dev environment - Seed email domain correction (.com → .ma) - Docs: create-account guide, fleet page, signup plan - Various UI component and layout refinements
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
# Create Account Guide
|
||||
|
||||
How to create a new company workspace on RentalDriveGo.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Creating an account registers a new rental company on the platform. The flow has **4 steps** presented as a multi-step form on the dashboard's public sign-up page. After completion, the company owner receives a confirmation email and can sign in to manage their workspace.
|
||||
|
||||
**Supported languages:** English, French, Arabic
|
||||
**Billing currency:** MAD (Moroccan Dirham)
|
||||
|
||||
---
|
||||
|
||||
## 1. Accessing the Sign-up Page
|
||||
|
||||
### From the marketplace homepage (port 3000)
|
||||
|
||||
- Click **"Create Agency Space"** in the header navigation.
|
||||
- Click **"Get Started"** on any pricing plan card (`/pricing` page).
|
||||
|
||||
Both actions navigate to:
|
||||
|
||||
```
|
||||
http://localhost:3000/dashboard/sign-up
|
||||
```
|
||||
|
||||
The marketplace proxies this request to the dashboard app (port 3001), which renders the multi-step form.
|
||||
|
||||
### URL parameters (optional)
|
||||
|
||||
| Parameter | Example | Purpose |
|
||||
|---|---|---|
|
||||
| `plan` | `STARTER`, `GROWTH`, `PRO` | Pre-selects a pricing plan |
|
||||
| `billing` | `MONTHLY`, `ANNUAL` | Pre-selects billing period |
|
||||
| `currency` | `MAD` | Pre-selects currency (only MAD) |
|
||||
|
||||
Example: `/dashboard/sign-up?plan=GROWTH&billing=ANNUAL¤cy=MAD`
|
||||
|
||||
---
|
||||
|
||||
## 2. Form Steps
|
||||
|
||||
### Step 1 — Account User
|
||||
|
||||
Required fields marked with `*`:
|
||||
|
||||
| Field | Type | Details |
|
||||
|---|---|---|
|
||||
| Manager/Owner first name * | Bilingual (FR + AR) | Max 80 characters |
|
||||
| Manager/Owner last name * | Bilingual (FR + AR) | Max 80 characters |
|
||||
| Manager/Owner email * | Email | Used as login identifier |
|
||||
| Password * | Password | Minimum 8 characters |
|
||||
| Confirm password * | Password | Must match |
|
||||
| Preferred language * | Selection | English / Français / العربية |
|
||||
|
||||
**Note:** The same email can be reused for the owner account, company contact, and responsible person.
|
||||
|
||||
### Step 2 — Company Info
|
||||
|
||||
#### Legal Identity section
|
||||
|
||||
| Field | Type | Details |
|
||||
|---|---|---|
|
||||
| Commercial name * | Bilingual (FR + AR) | The public-facing business name |
|
||||
| Legal company name * | Text | Max 160 characters |
|
||||
| Legal form * | Select | `SARL`, `SARL AU`, `SA`, `SAS`, `AUTO_ENTREPRENEUR`, `EI`, `OTHER` |
|
||||
| Commercial Registry (RC) * | Text | Max 120 characters |
|
||||
| ICE number * | Text | Max 120 characters |
|
||||
| Fiscal ID (IF) * | Text | Max 120 characters |
|
||||
| Operating license number * | Text | Max 120 characters |
|
||||
| License issue date * | Date | Format: YYYY-MM-DD |
|
||||
| Issuing authority * | Text | Max 160 characters |
|
||||
|
||||
#### Company Contact section
|
||||
|
||||
| Field | Type | Details |
|
||||
|---|---|---|
|
||||
| Phone * | Text | Max 80 characters |
|
||||
| Company contact email * | Email | Max 254 characters |
|
||||
| Fax | Text | Optional |
|
||||
| Years active * | Select | `Less than 1 year`, `1 to 5 years`, `More than 5 years` |
|
||||
| Street Address * | Bilingual (FR + AR) | Max 200 characters |
|
||||
| City * | Bilingual (FR + AR) | Max 120 characters |
|
||||
| Country * | Bilingual (FR + AR) | Max 120 characters |
|
||||
| Zip code * | Text | Max 40 characters |
|
||||
|
||||
#### Legal Representative section
|
||||
|
||||
| Field | Type | Details |
|
||||
|---|---|---|
|
||||
| Legal representative name | Text | Optional, max 160 characters |
|
||||
| Legal representative title | Text | Optional, max 120 characters |
|
||||
|
||||
#### Responsible Person section
|
||||
|
||||
| Field | Type | Details |
|
||||
|---|---|---|
|
||||
| Responsible person name * | Text | Max 160 characters |
|
||||
| Responsible person role * | Text | Max 120 characters |
|
||||
| Responsible person ID number * | Text | Max 120 characters |
|
||||
| Qualification / diploma * | Text | Optional, max 200 characters |
|
||||
| Responsible person phone * | Text | Max 80 characters |
|
||||
| Responsible person email * | Email | Max 254 characters |
|
||||
|
||||
### Step 3 — Choose Plan
|
||||
|
||||
Select one of three plans:
|
||||
|
||||
| Plan | Description |
|
||||
|---|---|
|
||||
| **STARTER** | Core fleet, offers, and bookings |
|
||||
| **GROWTH** | Featured marketplace placement and more room to scale |
|
||||
| **PRO** | Full white-label and premium controls |
|
||||
|
||||
Additional options:
|
||||
|
||||
| Field | Options |
|
||||
|---|---|
|
||||
| Billing period | Monthly / Annual |
|
||||
| Primary provider | AmanPay / PayPal |
|
||||
|
||||
Currency is fixed to **MAD**.
|
||||
|
||||
### Step 4 — Review and Launch
|
||||
|
||||
Review all entered information. Click **"Create workspace"** to submit.
|
||||
|
||||
After successful submission, the page displays a confirmation with:
|
||||
- The company name
|
||||
- The owner email
|
||||
- A link to **"Enter dashboard"** to start using the workspace
|
||||
|
||||
---
|
||||
|
||||
## 3. Backend API
|
||||
|
||||
### Endpoint
|
||||
|
||||
```
|
||||
POST /api/v1/auth/company/signup
|
||||
```
|
||||
|
||||
### Request body (validated by `companySignupSchema`)
|
||||
|
||||
```json
|
||||
{
|
||||
"firstName": "string (max 80)",
|
||||
"lastName": "string (max 80)",
|
||||
"email": "valid email",
|
||||
"password": "string (8-128 chars)",
|
||||
"companyName": "string (2-120)",
|
||||
"legalName": "string (2-160)",
|
||||
"legalForm": "string",
|
||||
"registrationNumber": "string",
|
||||
"iceNumber": "string",
|
||||
"taxId": "string",
|
||||
"operatingLicenseNumber": "string",
|
||||
"operatingLicenseIssuedAt": "string",
|
||||
"operatingLicenseIssuedBy": "string",
|
||||
"streetAddress": "string",
|
||||
"city": "string",
|
||||
"country": "string",
|
||||
"zipCode": "string",
|
||||
"companyPhone": "string",
|
||||
"companyEmail": "valid email",
|
||||
"fax": "string (optional)",
|
||||
"yearsActive": "string",
|
||||
"representativeName": "string (optional)",
|
||||
"representativeTitle": "string (optional)",
|
||||
"responsibleName": "string",
|
||||
"responsibleRole": "string",
|
||||
"responsibleIdentityNumber": "string",
|
||||
"responsibleQualification": "string (optional)",
|
||||
"responsiblePhone": "string",
|
||||
"responsibleEmail": "valid email",
|
||||
"preferredLanguage": "en | fr | ar",
|
||||
"plan": "STARTER | GROWTH | PRO",
|
||||
"billingPeriod": "MONTHLY | ANNUAL",
|
||||
"currency": "MAD",
|
||||
"paymentProvider": "AMANPAY | PAYPAL"
|
||||
}
|
||||
```
|
||||
|
||||
### Response (201 Created)
|
||||
|
||||
```json
|
||||
{
|
||||
"companyId": "uuid",
|
||||
"companyName": "string",
|
||||
"slug": "string",
|
||||
"trialEndsAt": "ISO date or null",
|
||||
"nextStep": "onboarding",
|
||||
"emailDelivery": {
|
||||
"attempted": true,
|
||||
"success": true,
|
||||
"error": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. After Sign-up
|
||||
|
||||
### Sign in
|
||||
|
||||
Navigate to `/sign-in` (redirects to `/dashboard/sign-in`). Enter the owner email and the password set during sign-up.
|
||||
|
||||
### Onboarding
|
||||
|
||||
After first sign-in, the user is directed to the **onboarding** page (`/onboarding`) where they can:
|
||||
|
||||
1. **Step 1 — Company profile**: Set display name, tagline, brand color, and public location.
|
||||
2. **Step 2 — Payments**: Configure AmanPay merchant ID / PayPal email and marketplace listing preference.
|
||||
3. **Step 3 — Completion**: Redirect to the dashboard home.
|
||||
|
||||
### Subscription
|
||||
|
||||
New accounts start on a **90-day free trial** with the selected plan. The subscription status is shown in a banner on the dashboard home. Users can manage billing from the `/subscription` page.
|
||||
|
||||
---
|
||||
|
||||
## 5. Relevant Code Files
|
||||
|
||||
### Frontend
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `apps/marketplace/src/app/renter/sign-up/page.tsx` | Marketplace redirect page to dashboard sign-up |
|
||||
| `apps/dashboard/src/app/sign-up/[[...sign-up]]/page.tsx` | Main multi-step sign-up form (4 steps, 937 lines) |
|
||||
| `apps/dashboard/src/components/ui/BilingualInput.tsx` | Bilingual (FR/AR) input component |
|
||||
| `apps/dashboard/src/components/layout/PublicShell.tsx` | Public layout wrapper for the sign-up page |
|
||||
| `apps/dashboard/src/app/onboarding/page.tsx` | Post-sign-up onboarding (company profile, payments) |
|
||||
| `apps/dashboard/src/app/forgot-password/page.tsx` | Password reset flow |
|
||||
| `apps/dashboard/src/app/reset-password/page.tsx` | Reset password page |
|
||||
| `apps/dashboard/src/app/onboarding/accept-invite/page.tsx` | Accept team invitation |
|
||||
|
||||
### Navigation links to sign-up
|
||||
|
||||
| File | Location |
|
||||
|---|---|
|
||||
| `apps/marketplace/src/components/MarketplaceHeader.tsx` | "Create Agency Space" button |
|
||||
| `apps/marketplace/src/components/WorkspaceTabs.tsx` | "Owner sign in" link |
|
||||
| `apps/marketplace/src/app/(public)/pricing/PricingClient.tsx` | "Get Started" pricing CTA |
|
||||
| `apps/marketplace/src/app/(public)/HomeContent.tsx` | Homepage CTA |
|
||||
|
||||
### Backend
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `apps/api/src/modules/auth/auth.company.routes.ts` | Express routes (`POST /signup`) |
|
||||
| `apps/api/src/modules/auth/auth.company.service.ts` | Business logic: creates company, owner, workspace, sends email |
|
||||
| `apps/api/src/modules/auth/auth.company.schemas.ts` | Zod validation schema for signup request body |
|
||||
| `apps/api/src/lib/emailTranslations.ts` | Email templates in EN/FR/AR |
|
||||
+1252
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
# Progressive Account Creation — Redesign Plan
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
The current sign-up flow (`apps/dashboard/src/app/sign-up/[[...sign-up]]/page.tsx`) asks for **everything at once**:
|
||||
|
||||
- Owner identity & credentials
|
||||
- Full legal/company identity (RC, ICE, IF, license, issuing authority…)
|
||||
- Company contact & address (bilingual)
|
||||
- Responsible person details
|
||||
- Plan + billing + payment provider
|
||||
|
||||
That's ~30 required fields across 4 steps before a user has even seen the product. This is the classic cause of sign-up abandonment: the perceived effort to "just try the app" is too high.
|
||||
|
||||
**Goal:** Let someone create an account with almost nothing, start exploring the dashboard immediately, and only be asked for a specific piece of information **right when an action requires it** — never before.
|
||||
|
||||
This pattern is commonly called **progressive profiling** or **just-in-time (JIT) data collection**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Principle
|
||||
|
||||
> Collect the minimum data needed to create an identity. Collect everything else lazily, tied to the action that needs it, not to a step number.
|
||||
|
||||
Two reframes that drive the whole design:
|
||||
|
||||
1. **Stop thinking in "steps."** Replace the 4-step wizard with a single **account state machine**. The account always exists in some state (Created → Active → Listing-Ready → Payable → Compliant → Subscribed), and each state unlocks more of the product.
|
||||
2. **Stop thinking in "forms."** Replace big forms with **micro-prompts**: a single field, or a tiny group of 2-3 tightly related fields, asked contextually, usually as a modal/drawer over the action the user just tried to take.
|
||||
|
||||
---
|
||||
|
||||
## 3. New Sign-up Flow (Minimum Viable Signup)
|
||||
|
||||
### Step 0 — only step that blocks entry
|
||||
|
||||
| Field | Why it's required immediately |
|
||||
|---|---|
|
||||
| Owner email | Login identifier, needed to send confirmation |
|
||||
| Password | Needed to create a session |
|
||||
| Preferred language | Needed to render anything afterward correctly |
|
||||
|
||||
That's it. No name, no company, no legal data, no plan.
|
||||
|
||||
```
|
||||
POST /api/v1/auth/account/start
|
||||
{
|
||||
"email": "string",
|
||||
"password": "string (8-128)",
|
||||
"preferredLanguage": "en | fr | ar"
|
||||
}
|
||||
```
|
||||
|
||||
Response creates:
|
||||
- A `User` record (owner)
|
||||
- A `Company` record in a `DRAFT` state with `name = null` and a system-generated placeholder slug
|
||||
- A session/JWT so the user is **logged in immediately**
|
||||
|
||||
The user lands directly in the dashboard home, in a clearly "draft workspace" visual state (banner: *"Your workspace is being set up — finish anytime"*).
|
||||
|
||||
This single change — going from ~30 required fields to 3 — is the biggest win and should be shipped first even before the rest of the JIT system exists.
|
||||
|
||||
---
|
||||
|
||||
## 4. Account Maturity Model
|
||||
|
||||
Replace the rigid 4-step form with an explicit состояние/state on the `Company` record:
|
||||
|
||||
| State | Unlocked by | What it unlocks |
|
||||
|---|---|---|
|
||||
| `DRAFT` | Step 0 above | Browsing dashboard UI, exploring settings, reading docs |
|
||||
| `IDENTIFIED` | Owner first/last name + company display name | Personalizing UI, inviting teammates |
|
||||
| `LISTABLE` | Company contact info + address | Creating/saving a fleet item or offer as **draft** |
|
||||
| `PUBLISHABLE` | Legal identity block (legal name, legal form, RC, ICE, IF, license) | Publishing a listing live on the marketplace |
|
||||
| `PAYABLE` | Payment provider config (AmanPay/PayPal) + responsible person | Accepting bookings/payments |
|
||||
| `SUBSCRIBED` | Plan + billing period selection | Past the 90-day trial, billed account |
|
||||
|
||||
Each state is just a derived boolean/computed field (`companyState`) based on which fields are filled — not a separate workflow table. The UI reads this state to decide what to show/lock.
|
||||
|
||||
This also directly maps the **existing legal/compliance fields** (RC, ICE, IF, operating license) to the **one moment they actually matter**: right before something goes live on the marketplace. Today they're collected on day 1, before the user has even decided to publish anything.
|
||||
|
||||
---
|
||||
|
||||
## 5. Just-In-Time Prompt Catalog
|
||||
|
||||
Map every current form field to the **specific user action** that should trigger asking for it. This is the heart of the redesign — a table the eng + product team should review and tune together.
|
||||
|
||||
| Action the user takes | Data requested at that moment | Fields involved |
|
||||
|---|---|---|
|
||||
| First login after signup | Display name | Owner first/last name, company commercial name |
|
||||
| Click "Add a vehicle / offer" | Basic company contact | Phone, company email, address, city, country, zip |
|
||||
| Click "Publish" on a listing | Legal identity | Legal name, legal form, RC, ICE, IF, license #, issue date, issuing authority |
|
||||
| Click "Enable bookings" / "Connect payments" | Payment + responsible person | Payment provider, responsible person name/role/ID/phone/email |
|
||||
| Visit `/subscription` or trial reaches day 75 | Plan selection | Plan, billing period |
|
||||
| Click "Invite teammate" | (no new data) | — |
|
||||
| Optional, never blocking | Fax, legal representative name/title, qualification/diploma | These stay fully optional, surfaced only in Settings |
|
||||
|
||||
Design rule: **never ask for more than 1 group of tightly-related fields in a single prompt.** E.g. "Legal identity" can still be ~8 fields, but it's one cohesive concept the user understands ("info needed to verify your business"), not an arbitrary step number.
|
||||
|
||||
---
|
||||
|
||||
## 6. UX Pattern: Contextual Prompt, Not a Form Page
|
||||
|
||||
When a user triggers an action that needs missing data:
|
||||
|
||||
1. The action is allowed to start optimistically (e.g. they can build a full listing draft).
|
||||
2. On the actual gating action (Publish, Enable bookings…), intercept with a **slide-over panel or modal**, not a full-page redirect.
|
||||
3. The modal:
|
||||
- States *why* in one line: "We need your business registration details before this listing can go public."
|
||||
- Shows only the missing fields (if some were already filled earlier, don't ask again).
|
||||
- Has a "Save and publish" primary action, and a "Save as draft, finish later" secondary action.
|
||||
4. On submit, persist via a generic incremental-update endpoint, recompute `companyState`, and continue the original action automatically.
|
||||
|
||||
This keeps the user inside their task instead of bouncing them to a separate "complete your profile" flow.
|
||||
|
||||
A persistent, low-key "Workspace setup: 60% complete" indicator (e.g. in the sidebar) lets motivated users finish everything in one sitting if they prefer — progressive disclosure should never *block* someone who wants to do it all at once.
|
||||
|
||||
---
|
||||
|
||||
## 7. Backend Changes
|
||||
|
||||
### 7.1 Schema
|
||||
|
||||
- Make nearly all `Company` fields nullable (`legalName`, `registrationNumber`, `iceNumber`, etc. all become optional at the DB level — required-ness becomes a **business rule per action**, not a DB constraint).
|
||||
- Add `companyState` (computed/cached enum) or compute on read.
|
||||
- Add `profileCompletionPercent` for the UI progress indicator.
|
||||
|
||||
### 7.2 API
|
||||
|
||||
Replace the single big `POST /auth/company/signup` with:
|
||||
|
||||
```
|
||||
POST /api/v1/auth/account/start → minimal signup (Section 3)
|
||||
PATCH /api/v1/company/profile → generic partial update, accepts any subset of fields
|
||||
PATCH /api/v1/company/legal-identity → group endpoint for legal fields (own validation rules)
|
||||
PATCH /api/v1/company/payment-setup → group endpoint for payment + responsible person
|
||||
PATCH /api/v1/company/plan → plan/billing selection
|
||||
GET /api/v1/company/state → returns companyState + missing fields per state
|
||||
```
|
||||
|
||||
Each `PATCH` endpoint validates only its own slice with its own Zod schema (split `auth.company.schemas.ts` into per-group schemas), instead of one monolithic `companySignupSchema`.
|
||||
|
||||
### 7.3 Gating middleware
|
||||
|
||||
Add a small middleware/guard used on the actions that require a given state, e.g.:
|
||||
|
||||
```ts
|
||||
requireCompanyState("PUBLISHABLE") // on POST /listings/:id/publish
|
||||
requireCompanyState("PAYABLE") // on POST /bookings, /payments/connect
|
||||
```
|
||||
|
||||
If the guard fails, return a structured error listing exactly which fields are missing, so the frontend can render the right contextual modal without guessing.
|
||||
|
||||
### 7.4 Email confirmation
|
||||
|
||||
Confirmation email still sends immediately after Step 0, but its copy changes from "your account is ready" to "your account is ready — finish setup anytime to start publishing," since there's much less to confirm.
|
||||
|
||||
---
|
||||
|
||||
## 8. Frontend Changes
|
||||
|
||||
- Replace the 937-line multi-step page with:
|
||||
- A short `~/sign-up` page (Step 0 only).
|
||||
- A set of small, reusable "completion modals," one per group in Section 5, each built from the existing `BilingualInput` and form components (these don't need to be rebuilt, just reorganized).
|
||||
- Introduce a `useCompanyState()` hook that fetches `GET /company/state` and exposes `{state, missingFields, completionPercent}` to any component that needs to gate an action.
|
||||
- Add a generic `<RequireCompanyState state="PUBLISHABLE">` wrapper component used to gate the relevant buttons/actions, opening the right modal when triggered.
|
||||
|
||||
---
|
||||
|
||||
## 9. Edge Cases & Risks
|
||||
|
||||
| Risk | Mitigation |
|
||||
|---|---|
|
||||
| Users abandon before ever reaching `PUBLISHABLE`/`PAYABLE` | That's expected and fine — they were never going to finish the old form either. Track funnel by state instead of all-or-nothing. |
|
||||
| Marketplace ends up with unpublishable "ghost" companies | `DRAFT`/`IDENTIFIED` companies are simply never shown publicly — only `PUBLISHABLE`+ companies appear, so this is a non-issue by construction. |
|
||||
| Legal/compliance requirements might mandate some data before *any* account exists, in some jurisdictions | Confirm with legal/compliance which fields (if any) are truly required by regulation before allowing a transaction vs. before allowing signup at all. Likely only the `PAYABLE` gate has real regulatory weight. |
|
||||
| Users get repeatedly interrupted by modals | Batch by group (Section 5), not by individual field; show the completion indicator so users see how close they are; never re-ask for data already given. |
|
||||
| Existing accounts (already fully filled out under the old flow) | No migration needed — they'll simply compute as `SUBSCRIBED`/fully complete already. |
|
||||
| Analytics/CRM relying on full data at signup | Will need to adjust to track partial profiles; add a scheduled job/report on stalled accounts per state for sales/CS follow-up. |
|
||||
|
||||
---
|
||||
|
||||
## 10. Suggested Rollout Phases
|
||||
|
||||
1. **Phase 1 — Minimal signup.** Ship Section 3 (3-field signup) behind a flag. Move all other fields to a single post-signup "Settings → Complete your profile" page (not yet contextual, just relocated). This alone should meaningfully cut signup abandonment.
|
||||
2. **Phase 2 — State machine + gating.** Add `companyState`, the `requireCompanyState` guard, and the `GET /company/state` endpoint. Gate "Publish" and "Enable bookings" only.
|
||||
3. **Phase 3 — Contextual modals.** Replace the static Settings page prompts with the in-context slide-over modals described in Section 6.
|
||||
4. **Phase 4 — Polish.** Add the sidebar completion indicator, refine copy per modal, A/B test prompt timing (e.g. ask for legal identity right after first draft listing vs. only at publish time).
|
||||
|
||||
---
|
||||
|
||||
## 11. Summary of File-Level Changes
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `apps/dashboard/src/app/sign-up/[[...sign-up]]/page.tsx` | Shrink to Step 0 only (~50-100 lines instead of 937) |
|
||||
| `apps/api/src/modules/auth/auth.company.routes.ts` | Replace single signup route with `account/start` + add new `PATCH` group routes |
|
||||
| `apps/api/src/modules/auth/auth.company.service.ts` | Split `createCompanyAndOwner` into minimal creation + separate update-group methods |
|
||||
| `apps/api/src/modules/auth/auth.company.schemas.ts` | Split into `accountStartSchema`, `companyContactSchema`, `legalIdentitySchema`, `paymentSetupSchema`, `planSchema` |
|
||||
| New: `apps/api/src/modules/company/company.state.ts` | Computes `companyState` + missing fields from a `Company` record |
|
||||
| New: `apps/api/src/middleware/requireCompanyState.ts` | Gating middleware described in 7.3 |
|
||||
| New: `apps/dashboard/src/components/profile/CompletionModal*.tsx` | Set of contextual prompt modals, one per group |
|
||||
| New: `apps/dashboard/src/hooks/useCompanyState.ts` | Frontend hook described in Section 8 |
|
||||
Reference in New Issue
Block a user