toga-ai 1.0.183 → 1.0.184

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ # toga2-view (TOGa View Frontend) — 2.0 knowledge
2
+
3
+ | Doc | Summary | Files |
4
+ |-----|---------|-------|
5
+ | [TOGa View Frontend (toga2-view) Architecture](architecture.md) | `toga2-view` is the **React/TypeScript single-page frontend** for the TOGa 2.0 platform — the customer-facing web app (home warranty / tech-support portals). | toga2-view/src/main.tsx, toga2-view/src/App.tsx, toga2-view/src/routes.tsx, toga2-view/src/api/axiosInstance.ts, toga2-view/src/api/apiFunctions.ts, toga2-view/src/utils/queryHelpers.ts, toga2-view/src/contexts/AuthContext.tsx, toga2-view/src/contexts/useUserStore.ts, toga2-view/src/hooks/useAuthenticationFlow.ts, toga2-view/vite.config.ts, toga2-view/package.json |
@@ -0,0 +1,184 @@
1
+ ---
2
+ title: TOGa View Frontend (toga2-view) Architecture
3
+ framework: "2.0"
4
+ repo: toga2-view
5
+ project: TOGa View Frontend
6
+ client: shared
7
+ type: architecture
8
+ status: active
9
+ updated: 2026-06-24
10
+ owners: [apeterson]
11
+ files:
12
+ - toga2-view/src/main.tsx
13
+ - toga2-view/src/App.tsx
14
+ - toga2-view/src/routes.tsx
15
+ - toga2-view/src/api/axiosInstance.ts
16
+ - toga2-view/src/api/apiFunctions.ts
17
+ - toga2-view/src/utils/queryHelpers.ts
18
+ - toga2-view/src/contexts/AuthContext.tsx
19
+ - toga2-view/src/contexts/useUserStore.ts
20
+ - toga2-view/src/hooks/useAuthenticationFlow.ts
21
+ - toga2-view/vite.config.ts
22
+ - toga2-view/package.json
23
+ related:
24
+ - clients/rate/profile.md
25
+ - clients/rate/features/saml-sso.md
26
+ - clients/rate/features/service-card-entitlements.md
27
+ ---
28
+
29
+ ## Summary
30
+
31
+ `toga2-view` is the **React/TypeScript single-page frontend** for the TOGa 2.0
32
+ platform — the customer-facing web app (home warranty / tech-support portals). It is
33
+ a pure client: it holds no server logic and talks exclusively to the **`api2`** backend
34
+ (the `/v2/...` JSON API) for all data and auth. It is **not** a PHP app and does **not**
35
+ build on `_underscore` directly — its only runtime dependency is `api2` (declared in
36
+ `registry.json` as `dependsOn: ["api2"]`).
37
+
38
+ **Stack:** React 18 + TypeScript, built with **Vite 7**. Routing via **React Router v7**
39
+ (`createBrowserRouter`). Server state via **TanStack React Query v5** (persisted to
40
+ `localStorage`). Client/global state via **Zustand** (user) + **React Context** (auth).
41
+ HTTP via a single **Axios** instance with auth/transaction interceptors. Styling via
42
+ **Tailwind CSS v3 + SCSS**. Shared UI primitives come from the **`@agilant/toga-blox`**
43
+ component library (npm package, versioned). Errors report to **Sentry**. Forms use
44
+ `react-hook-form`; animation via `framer-motion`; icons from FontAwesome Pro.
45
+
46
+ ## Project layout
47
+
48
+ ```
49
+ src/
50
+ ├── main.tsx # Vite entry; mounts <App/>, imports global styles
51
+ ├── App.tsx # Providers: PersistQueryClientProvider + AuthProvider + RouterProvider
52
+ ├── routes.tsx # createBrowserRouter route table + route guards
53
+ ├── api/ # Shared HTTP layer
54
+ │ ├── axiosInstance.ts # Single axios client + interceptors (auth, transactionId, 401 refresh)
55
+ │ ├── apiFunctions.ts # Generic apiGet / apiPost / apiPut / apiDelete<TData> wrappers
56
+ │ └── genericApi.ts
57
+ ├── contexts/
58
+ │ ├── AuthContext.tsx # isAuthenticated, user, login(), logout(); cross-tab sync
59
+ │ └── useUserStore.ts # Zustand user store (persisted to localStorage "zu-user")
60
+ ├── hooks/ # Shared hooks reused across pages
61
+ │ ├── useAuthenticationFlow.ts # SAML + domain-SSO orchestration (see Auth)
62
+ │ ├── useApiQuery.ts / useApiMutation.ts # React Query wrappers
63
+ │ ├── useBundleServices.ts / useActiveServices.ts # shared service-data hooks
64
+ │ └── useBreakpoint.tsx, useAnnouncements.ts, ...
65
+ ├── components/ # Reusable, non-page UI (BaseButton, BaseInputs, MobileNav, ...)
66
+ ├── pages/<Page>/ # Feature pages — see "Page convention" below
67
+ ├── utils/
68
+ │ └── queryHelpers.ts # assembleOptions(): JS query object → /v2 query string
69
+ ├── services/ # External integrations (e.g. paypalService.ts)
70
+ └── styles/ # index.scss (source) → index.css (Tailwind + SCSS output)
71
+ ```
72
+
73
+ ## Page convention (the dominant pattern)
74
+
75
+ Each feature lives under `src/pages/<PageName>/` with a **view / viewModel / api** split:
76
+
77
+ ```
78
+ pages/<PageName>/
79
+ ├── view/
80
+ │ ├── <PageName>.tsx # presentational component; consumes the viewModel hook
81
+ │ └── components/ # page-local subcomponents
82
+ ├── viewModels/ # business-logic hooks (⚠ some pages use singular "viewModel/")
83
+ │ ├── use<PageName>ViewModel.ts
84
+ │ └── DUMMYFIELDS/*.json # static labels/copy for the page
85
+ ├── api/<page>Api.ts # page-specific API calls (build options, call apiGet/apiPost)
86
+ ├── types.ts # page-local TypeScript interfaces
87
+ └── index.ts # re-exports the view component
88
+ ```
89
+
90
+ **ViewModel-hook pattern.** The view component is "dumb": it calls
91
+ `use<PageName>ViewModel()` and renders what it returns. The hook owns all state,
92
+ data-fetching, and event handlers, and returns a typed object
93
+ (`<PageName>ViewModel` interface). It composes shared hooks (`useUserStore()`,
94
+ `useBundleServices()`, `useNavigate()`, …) and the page's own `api/` functions.
95
+
96
+ > **Convention drift to know:** most pages name the folder `viewModels/` (plural), but a
97
+ > few (e.g. `CheckOut`, `Login`) use `viewModel/` (singular). When adding a page, match the
98
+ > plural form unless editing one of the existing singular ones. The hook itself is always
99
+ > `use<PageName>ViewModel` (singular "ViewModel").
100
+
101
+ ## API / data layer
102
+
103
+ All HTTP goes through the single axios instance in `src/api/axiosInstance.ts`. Never
104
+ create ad-hoc `fetch`/`axios` calls in components — go through `apiFunctions.ts`
105
+ (`apiGet`/`apiPost`/`apiPut`/`apiDelete`) and React Query.
106
+
107
+ - **Base URL is resolved per-hostname.** The instance reads the first label of
108
+ `window.location.hostname`, upper-cases it, and looks up `VITE_API_<LABEL>`, falling
109
+ back to `VITE_API`. E.g. `homewarranty.rate.com` → `VITE_API_HOMEWARRANTY`. This is why
110
+ there are many `.env.<mode>` files and per-subdomain `VITE_API_*` vars.
111
+ - **transactionId** — a fresh UUID is attached to every request's query params (request
112
+ interceptor) for end-to-end tracing.
113
+ - **Query builder** — `assembleOptions()` in `utils/queryHelpers.ts` converts a structured
114
+ JS object (`fields`, `where`, `join`/`ojoin`, `sort`) into the `api2` `/v2` query string.
115
+ Use `ojoin` (LEFT JOIN) when a related row may be absent — `join` (INNER JOIN) silently
116
+ drops parent rows that have no match.
117
+
118
+ ## Auth & tokens
119
+
120
+ - **AuthContext** holds `isAuthenticated`, `user`, `login()`, `logout()`. It persists to
121
+ `localStorage` and syncs across browser tabs via the `storage` event.
122
+ - **`useAuthenticationFlow.ts`** orchestrates two entry paths:
123
+ 1. **SAML landing** — a `?saml=<payload>` query param on load: the param is **stripped
124
+ immediately via `replaceState`** (leaving it in causes stale-payload replay on
125
+ refresh — this was a live bug), then exchanged at the API for tokens + user, after
126
+ which `login()` runs and the app navigates to `/landing`.
127
+ 2. **Domain SSO check** — if not authenticated and no `?saml=`, it queries `/domains`
128
+ for the current host; if the client is SSO-type it redirects to the IdP, otherwise
129
+ it falls through to `/login`.
130
+ - **Token storage (localStorage):** `accessToken`, `refreshToken`, `user`. Unauthenticated
131
+ requests use a **public token** auto-fetched via `POST /auth/public`. A `401` triggers a
132
+ one-shot refresh via `POST /auth/refresh`; if refresh fails, a `UserLoginRequired` window
133
+ event is dispatched to force re-login.
134
+
135
+ ## Routing & guards
136
+
137
+ Routes are defined in `src/routes.tsx` with `createBrowserRouter`:
138
+ - `/` → `AuthRedirect` (sends to `/login` or `/landing` by auth state).
139
+ - `/login` → public (redirects already-authenticated users away).
140
+ - Everything else sits behind **`PrivateRoute`** (checks `useAuth().isAuthenticated`,
141
+ shows a loading state while `useAuthenticationFlow` resolves) and is wrapped by
142
+ `MobileNavToggle`. Pages: `/home`, `/landing`, `/services`, `/activity`, `/checkout`,
143
+ `/zip-validation`, `/payment-success`, `/activation`, `/get-support`, `/select-service`,
144
+ `/create-ticket`, `/choose-plan`.
145
+
146
+ ## Build, environments & deploy
147
+
148
+ - **Tooling:** `npm run dev` (Vite dev server, port 5173), `npm run build`
149
+ (`tsc && vite build --mode production`), plus `buildBeta` / `buildGamma`. `npm run lint`
150
+ runs ESLint with `--max-warnings 0`. E2E via Cypress (`npm run cypress`).
151
+ - **Many environments:** `.env.{development,alpha,beta,gamma,sprint,stage,test,production}`.
152
+ Each supplies the `VITE_API_*` base URLs consumed by `axiosInstance.ts`. A client/brand is
153
+ selected by hostname at runtime (not a separate build), via the `VITE_API_<SUBDOMAIN>`
154
+ lookup.
155
+
156
+ ## Critical rules
157
+
158
+ - **All HTTP goes through `axiosInstance` + `apiFunctions`** — never raw `fetch`/`axios` in
159
+ components. The shared instance is what attaches auth, the transactionId, and 401-refresh.
160
+ - **Use `ojoin` (LEFT JOIN), not `join` (INNER JOIN), in `assembleOptions` queries** when a
161
+ joined row may be missing — an inner join silently drops parent records.
162
+ - **Strip the `?saml=` param before using it** (already handled in `useAuthenticationFlow`);
163
+ do not reintroduce code paths that leave it in the URL.
164
+ - **Append `T00:00:00` to date-only strings before parsing** to avoid timezone shift moving
165
+ a date back a day (a recurring display bug on service/entitlement dates).
166
+ - **Keep view components presentational** — logic, state, and side effects belong in the
167
+ `use<PageName>ViewModel` hook, not the `.tsx` view.
168
+ - **Shared hooks fan out.** A change to a shared hook (e.g. `useBundleServices`) affects every
169
+ page/viewModel that consumes it — check call sites before changing its shape.
170
+ - **Tokens live in `localStorage`** (`accessToken`/`refreshToken`/`user`). Treat them as
171
+ sensitive; never log token values or echo them into Sentry extras.
172
+
173
+ ## Client notes
174
+
175
+ **Rate** is the primary consumer of this frontend (SAML-only auth via Azure AD; warranty
176
+ service cards show Address instead of Price). See `clients/rate/profile.md` and the Rate
177
+ feature docs in `related:` for client-specific behavior layered on top of this architecture.
178
+
179
+ ## Gaps / not yet captured
180
+
181
+ - `2.0/standards/frontend.md` — no shared 2.0 React/TS standard doc exists yet; conventions
182
+ above are documented here per-repo until one is written.
183
+ - Per-page feature docs (Home, Activity, Checkout, etc.) are not individually captured; add
184
+ under `2.0/apps/toga2-view/features/` as they stabilize.
@@ -21,7 +21,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
21
21
  - **dbchanges2** (Database Changes) _(framework core)_ — 2 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
22
22
  - **toga2-supply** (TOGa Supply) — 3 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
23
23
  - **saml** (SAML SSO Gateway) — 2 doc(s) → [2.0/apps/saml/INDEX.md](2.0/apps/saml/INDEX.md)
24
- - **toga2-view** (TOGa View Frontend) — 1 doc(s) → [2.0/apps/toga2-view/INDEX.md](2.0/apps/toga2-view/INDEX.md)
24
+ - **toga2-view** (TOGa View Frontend) — 2 doc(s) → [2.0/apps/toga2-view/INDEX.md](2.0/apps/toga2-view/INDEX.md)
25
25
  - **toga2-hub** (TOGa Hub) — 2 doc(s) → [2.0/apps/toga2-hub/INDEX.md](2.0/apps/toga2-hub/INDEX.md)
26
26
  - **talos** (TOGa IQ) — 6 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
27
27
  - **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.183",
3
+ "version": "1.0.184",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",