toga-ai 1.0.123 → 1.0.124
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.
- package/knowledge/2.0/apps/toga2-commerce/INDEX.md +5 -0
- package/knowledge/2.0/apps/toga2-commerce/features/cart-notification-emails.md +79 -0
- package/knowledge/INDEX.md +1 -0
- package/knowledge/clients/compass-canada/profile.md +3 -2
- package/knowledge/clients/compass-usa/profile.md +3 -2
- package/knowledge/registry.json +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# toga2-commerce (TOGa Commerce) — 2.0 knowledge
|
|
2
|
+
|
|
3
|
+
| Doc | Summary | Files |
|
|
4
|
+
|-----|---------|-------|
|
|
5
|
+
| [Cart Notification Emails — duplicate prevention](features/cart-notification-emails.md) | On the cart "Notifications" section a user can add CC email addresses to an order. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/stores/useEmailOptionsStore.ts, src/stores/useCartSalesQuoteZu.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts |
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cart Notification Emails — duplicate prevention
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: toga2-commerce
|
|
5
|
+
project: TOGa Commerce
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-18
|
|
10
|
+
owners: ["bala"]
|
|
11
|
+
files:
|
|
12
|
+
- src/pages/Cart/CartPage.tsx
|
|
13
|
+
- src/pages/Cart/view/cartForm/CartForm.tsx
|
|
14
|
+
- src/stores/useEmailOptionsStore.ts
|
|
15
|
+
- src/stores/useCartSalesQuoteZu.ts
|
|
16
|
+
- src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts
|
|
17
|
+
related: []
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Summary
|
|
21
|
+
On the cart "Notifications" section a user can add CC email addresses to an order. Adding the
|
|
22
|
+
same address twice (often with different casing) used to slip through to the API and blow up on
|
|
23
|
+
submit with a MySQL 1062 duplicate-key error on the `SalesOrderEmailAddresses.salesOrderId_emailAddress`
|
|
24
|
+
unique index (whose collation `utf8mb4_0900_ai_ci` is case-insensitive). This feature blocks
|
|
25
|
+
duplicates case-insensitively in the frontend and shows a sapphire info message instead of letting
|
|
26
|
+
the error reach the user.
|
|
27
|
+
|
|
28
|
+
## Key files / entry points
|
|
29
|
+
- `CartPage.tsx` — `handleAddEmail`: validates the email regex, then on success calls
|
|
30
|
+
`addEmailOption` (UI options list) and `addEmail` (the cart sales-quote store that builds the
|
|
31
|
+
`salesOrderEmailAddresses` payload). Normalizes the input once with `.trim()`.
|
|
32
|
+
- `CartForm.tsx` — owns the duplicate UX. `handleAddEmailWithDuplicateCheck` wraps the passed-in
|
|
33
|
+
`handleAddEmail`: it case-insensitively checks the existing `emails` list and, on a match, shows
|
|
34
|
+
the message instead of adding. The **Add Email** button calls this wrapper.
|
|
35
|
+
- `useEmailOptionsStore.ts` — `addEmailOption` de-dupes the checkbox list.
|
|
36
|
+
- `useCartSalesQuoteZu.ts` — `addEmail` de-dupes the actual `salesOrderEmailAddresses` payload.
|
|
37
|
+
|
|
38
|
+
## How it works
|
|
39
|
+
1. **Before (manual add):** clicking Add Email runs `handleAddEmailWithDuplicateCheck` in
|
|
40
|
+
`CartForm`. It compares `(e.email ?? "").trim().toLowerCase()` against the normalized input. On a
|
|
41
|
+
match it sets `duplicateEmailMessage` and returns (does not add).
|
|
42
|
+
2. **After (auto-add on user select):** when the order user is chosen, their email (and manager's)
|
|
43
|
+
is auto-added via `addEmailOption`. Both stores de-dupe case-insensitively, so a case-variant of
|
|
44
|
+
an already-present address is silently dropped rather than duplicated.
|
|
45
|
+
3. **Display:** the message renders via the shared `InfoBanner` component (the same one used for the
|
|
46
|
+
"view as" / "edit order" banners), styled `text-sapphire-700 text-xs`, no icon. It is NOT a
|
|
47
|
+
toaster and NOT a red `setError` validation — it is a sapphire info message.
|
|
48
|
+
4. The message text comes from the `notifications.duplicateEmailAddressError.label` field config,
|
|
49
|
+
present in every `CARTPAGE.ts` (all client/role/language variants, English + French).
|
|
50
|
+
5. A `useEffect` clears the message when the input, selected user (`orderForUser?.uuid`), or email
|
|
51
|
+
list (`emails.length`) changes.
|
|
52
|
+
|
|
53
|
+
## Data model
|
|
54
|
+
Frontend only. The payload list maps to the `SalesOrderEmailAddresses` table (api2/backend), which
|
|
55
|
+
has a case-insensitive unique index on `(salesOrderId, emailAddress)`.
|
|
56
|
+
|
|
57
|
+
## Client variations
|
|
58
|
+
The de-dupe mechanism is uniform across clients. Only the message label text differs per client
|
|
59
|
+
config: English `"This email has already been added"`; French (Compass Canada)
|
|
60
|
+
`"Cette adresse e-mail a déjà été ajoutée"`. The label must exist in every `CARTPAGE.ts` variant or
|
|
61
|
+
the message resolves to `undefined` and renders blank.
|
|
62
|
+
|
|
63
|
+
## Gotchas / known issues
|
|
64
|
+
- The real source of the 1062 was `useCartSalesQuoteZu.addEmail` comparing with `===`
|
|
65
|
+
(case-sensitive). Both stores must compare case-insensitively; fixing only the UI list is not
|
|
66
|
+
enough because `addEmail` builds the payload.
|
|
67
|
+
- Normalize with `(x ?? "").trim().toLowerCase()`, not `x?.trim().toLowerCase()` — both are
|
|
68
|
+
nullish-safe (optional chaining short-circuits the whole chain, it does not throw), but `(x ?? "")`
|
|
69
|
+
guarantees a string and avoids an `undefined === undefined` match edge.
|
|
70
|
+
- Adding the label to only some `CARTPAGE.ts` files leaves other client/role/language users with a
|
|
71
|
+
blank message.
|
|
72
|
+
- Do not use a toaster or `setError` (red) for this — product wants the sapphire info style.
|
|
73
|
+
|
|
74
|
+
## Change history
|
|
75
|
+
- 2026-06-18 — Initial: case-insensitive de-dupe in both cart stores, sapphire `InfoBanner` message in
|
|
76
|
+
CartForm, `duplicateEmailAddressError` label added to all CARTPAGE.ts variants (bala)
|
|
77
|
+
|
|
78
|
+
## Related docs
|
|
79
|
+
None yet.
|
package/knowledge/INDEX.md
CHANGED
|
@@ -25,6 +25,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
25
25
|
- **talos** (TOGa IQ) — 6 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
|
|
26
26
|
- **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
|
|
27
27
|
- **ai-bdr** (AI-BDR) — 4 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
|
|
28
|
+
- **toga2-commerce** (TOGa Commerce) — 1 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
|
|
28
29
|
|
|
29
30
|
## standalone framework
|
|
30
31
|
|
|
@@ -5,14 +5,15 @@ apps:
|
|
|
5
5
|
- _underscore
|
|
6
6
|
- api2
|
|
7
7
|
- toga2-supply
|
|
8
|
+
- toga2-commerce
|
|
8
9
|
- worker
|
|
9
10
|
- dbchanges2
|
|
10
11
|
project: _Underscore
|
|
11
12
|
client: compass-canada
|
|
12
13
|
type: profile
|
|
13
14
|
status: active
|
|
14
|
-
updated: 2026-06-
|
|
15
|
-
owners: [jcardinal]
|
|
15
|
+
updated: 2026-06-18
|
|
16
|
+
owners: [jcardinal, bala]
|
|
16
17
|
files: []
|
|
17
18
|
related:
|
|
18
19
|
- ../compass-usa/profile.md
|
|
@@ -5,14 +5,15 @@ apps:
|
|
|
5
5
|
- _underscore
|
|
6
6
|
- api2
|
|
7
7
|
- toga2-supply
|
|
8
|
+
- toga2-commerce
|
|
8
9
|
- worker
|
|
9
10
|
- dbchanges2
|
|
10
11
|
project: _Underscore
|
|
11
12
|
client: compass-usa
|
|
12
13
|
type: profile
|
|
13
14
|
status: active
|
|
14
|
-
updated: 2026-06-
|
|
15
|
-
owners: [jcardinal]
|
|
15
|
+
updated: 2026-06-18
|
|
16
|
+
owners: [jcardinal, bala]
|
|
16
17
|
files: []
|
|
17
18
|
related:
|
|
18
19
|
- features/asn-to-item-fulfillment.md
|
package/knowledge/registry.json
CHANGED
package/package.json
CHANGED