AdPlatform Registration Portal
Client-facing registration wizard for new AdPlatform prospects. Collects contact and business information through a multi-step wizard, then submits to the Registration Azure Function for review.
Architecture
RegistrationPortal/ React frontend (webpack)
├── src/
│ ├── auth/ Entra External ID (CIAM) auth provider
│ ├── context/ RegistrationContext — wizard state management
│ ├── services/ API service layer (calls Registration Function)
│ ├── components/
│ │ ├── Shell.jsx Layout wrapper (matches Admin shell)
│ │ ├── ProgressStepper Visual step indicator
│ │ └── steps/ Individual wizard step components
│ └── styles/ CSS (custom properties, matches Admin theme)
│
Registration/ Azure Function backend (already deployed)
├── Functions/ HTTP endpoints (register, pending, complete, reject)
├── Data/ Interface + SqlDataService (SP caller)
└── Mock/ In-memory mock for development
Wizard Flow
| Step | Component | API Call |
|---|---|---|
| 0 - Sign In | SignInStep |
Entra External ID (MSAL popup) |
| 1 - Contact | ContactStep |
(client-side only) |
| 2 - Business | BusinessStep |
(client-side only) |
| 3 - Review | ReviewStep |
POST /api/registration/register |
| 4 - Confirm | ConfirmationStep |
— |
Data is collected across steps 1–2 and submitted as a single RegisterRequest in step 3, matching the Registration Function's contract.
Data Contract
The wizard submits a RegisterRequest matching RegistrationFunctions.cs:
{
"businessName": "Acme Corp",
"websiteUrl": "https://acme.com",
"businessCategory": "retail",
"businessDescription": "...",
"contactName": "Jane Smith",
"contactEmail": "jane@acme.com",
"contactPhone": "(555) 123-4567",
"entraSubjectId": "entra-abc123"
}
Development
npm install
npm start # http://localhost:3001
Runs in mock mode when API_BASE_URL is empty in authConfig.js. To connect to the real Registration Function, update the constants in src/auth/authConfig.js:
export const API_BASE_URL = 'https://portal.positivespend.com';
export const API_FUNCTION_KEY = 'your-function-key';
Auth Setup (TODO)
The AuthProvider is currently stubbed for development. To wire Entra External ID:
- Create an External ID tenant in Azure
- Register an app with redirect URI = portal URL
- Enable social providers (Google, Apple) in the External ID user flows
- Update
authConfig.jswith tenant details - Replace stub logic in
AuthProvider.jsxwith MSALloginPopup/logoutPopup
Approval Flow
After submission, the Registration Function holds the application as Pending. The Admin console's Clients → Pending tab shows these for review. When an admin clicks Approve, the system:
- Calls
POST /api/registration/action/{id}/completewith aplatformClientId - Creates advertising sub-accounts with naming convention:
ADP-{BusinessName}-{ClientId}- Google Ads (under MCC)
- Meta Business Manager
- TikTok Business Center
- Creates the client record in the main platform database
Conventions
- React: Context pattern (createContext / useHook / Provider), no prop drilling
- CSS: Custom properties, DM Sans, kebab-case class names
- Build: Webpack + Babel (matches Admin project)
- API: Azure Functions with
x-functions-keyauth - Backend:
@action/@rqst/@respstored procedure pattern