Skip to content

jbwui — JBW360 Web Portal (React)

Module path: st-integration/jbwui/ · package jbw-client v0.1.0 · Create React App

The web front-end for the JB Warranties ServiceTitan integration (“JB360”, hosted at jbw360.jbwarranties.com). It is an internal/partner portal — login only, no public signup. Two roles via Cognito groups:

  • jbw-admin — JB Warranties staff: dashboards, dealer onboarding, user management, admin tools.
  • jbw-dealer — HVAC dealers/contractors: their own dashboard, agreement sync, claims.

Core flows: Cognito auth (incl. forced new-password, forgot/reset, idle timeout), a 4–5 step dealer onboarding wizard (ServiceTitan or Workiz), agreement sync/matching/approval against ServiceTitan data, claims management (with embedded JB&Associates iframes), and admin/dealer KPI dashboards.

ConcernChoice
FrameworkReact 18.3 (CRA / react-scripts 5), JavaScript (no TypeScript)
UIMUI v5 + MUI X (DataGrid, Charts, DatePickers), Emotion, styled-components
StateReact Context (src/AuthContext.jsx) + local state + localStorage; no Redux
FormsFormik + Yup
Routingreact-router-dom v6 (createBrowserRouter in src/App.js), guard in src/RouteGuard.jsx
AuthAWS Cognito via amazon-cognito-identity-js (src/services/jbwAuthServices.js)
HTTPaxios shared instance with interceptors (src/services/configs/axiosConfig.js)
Misccrypto-js (AES), lodash, date-fns/dayjs/moment, export-from-json

Public (under RootLayout):

RoutePagePurpose
/, /signin, /signin/:idpages/SignIn.jsCognito login; :id carries encrypted email+code for invited users. Post-login: admins → /home/overview, dealers → onboarding check → dashboard or wizard
/signuppages/Register.jsDealer/user registration (verify-then-register)
/forgotpasswordpages/VerifyUser.jsInitiate forgot-password
/resetpassword/:idpages/ResetPassword.jsReset with code
/changepassword/:idpages/ChangePassword.jsForced new-password challenge

Authenticated (/home, HomeLayout = TopBar + Sidebar):

RoutePagePurpose
/home, /home/overviewpages/Overview.jsAdmin dashboard: KPI cards, latest onboardings, Admin Tools console
/home/dealerdetails[/:id]pages/DealerDetails.jsxDealer dashboard: info, KPIs, tenants, agreements/claims/invoices tabs
/home/onboardinghomepages/Onboarding.jsAll dealers grid + “Onboard New Dealer” + per-dealer sync
/home/agreementssynchomepages/AgreementsSyncHome.jsxAgreement sync: Map Location / Pending Approval / Approved tabs, Sync Data button
/home/userslistpages/UsersList.jsUser management
/home/transactionlogpages/TransactionLogs.jsxTransmission/sync logs (from tblTransmissionDetails)
/home/jbwclaimspages/JBWarrantiesFrame.jsxEmbedded JB&Associates claim360.aspx iframe
/home/todohome[/:id]pages/ToDoHome.jsxEmail-notification inbox (sidebar link currently commented out)
/home/settingsStub (route renders an MUI icon; pages/settings.js exists but is unused)
/home/onboarding/*pages/onboarding/Wizard: ClientName → ClientLocation → ClientPlatform → (ST: ClientCustom → ClientId) / (Workiz: ClientAccountId) → CLientConnect
  • Cognito ID token (JWT) stored in localStorage["token"]; role read from cognito:groups[0] (any group ≠ jbw-dealer is treated as admin).
  • Axios request interceptor attaches Authorization: Bearer <token> and drives a global loader via api-loading events.
  • Response interceptor: on 401, refreshes the Cognito session once (queueing concurrent requests) and retries; on failure fires session-expired → re-auth dialog.
  • AuthContext proactively refreshes tokens when <5 min to expiry (60 s check loop) and enforces a 30-minute idle timeout (src/hooks/useIdleTimer.js).

All API calls go through the shared axios instance with baseURL = REACT_APP_AWS_GATEWAY_BASE_URL (the jbw-sam API Gateway). Service modules live in src/services/ — the complete endpoint-per-module list is in the code reference.

External (non-gateway) integrations:

  • ServiceTitan deep links: REACT_APP_ST_URL; Workiz job links: REACT_APP_WZ_URL.
  • JB&Associates member portal iframes (hardcoded jbandassociates.biz URLs): claims console (claim360.aspx), claim dialog (jb360claim.aspx, with postMessage origin check), agreement PDF (customeragpdf.aspx), payment link.
  • Release-notes PDF from REACT_APP_RELEASE_NOTE_URL.

Quirk: several callers branch on APP_ENV === "Development" to read res.data.body vs res.data (API Gateway proxy wrapping differs between stages).

CRA REACT_APP_* vars, baked into the bundle at build time. Files: .env (default = Production values), prod.env, stage.env; selected via env-cmd in npm scripts.

VariablePurpose
REACT_APP_MYVARNAMEEnv label (“Production”/“Staging”) — drives staging banner + dev response unwrapping
REACT_APP_USER_POOL_ID / REACT_APP_CLIENT_IDCognito user pool / app client
REACT_APP_AWS_GATEWAY_BASE_URLBackend API Gateway base URL
REACT_APP_ST_URL / REACT_APP_WZ_URLServiceTitan / Workiz deep-link bases
REACT_APP_RELEASE_NOTE_URL / REACT_APP_RELEASE_NOTE_MONTHRelease-notes PDF + label
REACT_APP_ISSTAGINGStaging flag (YES/NO)

Prod points at go.servicetitan.com and the prod API Gateway stage; stage points at integration.servicetitan.com and the dev stage.

Terminal window
npm install
npm start # dev server :3000, default .env (Production config!)
npm run start:stage # staging config, :3006
npm run build # production build (default .env)
npm run build:prod # production bundle from prod.env
npm run build:stage # staging bundle from stage.env

Note: npm scripts use Windows set PORT= syntax. There is no deploy config in the repo — the CRA build/ output is served from the S3 + CloudFront distribution defined in jbw-sam/template.yaml.

  • .env, stage.env, prod.env are committed to the repo (contain Cognito pool/client IDs and gateway URLs; not strictly secret since CRA bakes them into the public bundle, but worth knowing).
  • Hardcoded AES key in src/utils/encryption.js (used for the signin/reset URL payloads) — obfuscation only, not real encryption security.
  • .env and prod.env are near-duplicates that drift (release-notes URL differs).
  • Default npm start runs against production config.
  • No tests (@testing-library/* present, no test files); README is CRA boilerplate.
  • Unused deps: aws-amplify, react-google-recaptcha. Stub /home/settings route.