Parent approval map never shows a domestic child's requested states (wishlistRegions unbound; orange 'requested' style gated to minor mode; no region approval store)
#727
Repro (live, 2026-07-20): child @toddcan (domestic travel only) filled his profile and picked states — his doc has `Travel.WishlistRegions = ["US-ID","US-LA"]`, `Sponsorship.Enabled = true` (parent-enabled at 01:29Z, saved cleanly — the #431 approval-chain fix is live), `ParentalControls` correctly linked to the parent, `Permissions.ApprovedCountries = []`. Parent's children tab shows no states at all — nothing orange to approve.
Root cause — three stacked frontend/model defects (backend saves are all fine):
The parent map is bound to the wrong array at the wrong scope. `children-tab.component.html` (~121-129) passes `[wishlistCountries]="child.travel.wishlistCountries"` with no `scope`/`countryCode` inputs, so `app-country-map` defaults to `scope="world"` and renders world countries. A domestic-only child's picks live in `child.travel.wishlistRegions` (hyphenated codes, e.g. `US-ID`), which is never passed and would need `scope="country"` + `[countryCode]` to load the states GeoJSON (compare the correct child-side wiring in `travel-tab.component.html:77-90`). Net: domestic children's `wishlistCountries` is empty ⇒ parent map highlights nothing.
Orange 'requested' can never render for the parent. `country-map.component.ts` `getFeatureStyle()` (~425-430) renders the orange `requested` color only when `mode()==='minor'`; in `parent-approve` mode an unapproved wishlist entry falls through to blue — even though the parent-approve legend advertises an orange 'requested' swatch (`getLegendItems()` ~648). Legend/style mismatch.
States have nowhere to be approved. `FeaturePermissions` has only `approvedCountries`; there is no region/state approval store. Backend note: the server never computes 'pending' — `GET /api/Profile/parental/children` returns both wishlist + approved lists and the SPA diffs them; `PUT /api/Profile/parental/permissions/{childUserId}` overwrites `ApprovedCountries` wholesale and is code-agnostic (flat `List`).
Suggested fix (frontend-only is possible):
Children tab: for domestic children render the map with `scope="country"`, `[countryCode]` = child's home country, `[wishlistCountries]="child.travel.wishlistRegions"` (or a merged view with a country/domestic toggle mirroring the child's travel tab).
`country-map`: in `parent-approve` mode render wishlist-not-approved as orange `requested` (matches the legend already shipped).
Approval store: reuse the existing flat `approvedCountries` list for hyphenated region codes ('approved destinations' semantics — zero backend/schema change, the wholesale-overwrite write path and the client set-diff both already handle arbitrary codes). Alternatively add a parallel `approvedRegions` field for symmetry with the wishlist split, at the cost of a backend DTO+model change. Recommend the former; the frontend already partitions hyphenated codes (`TravelStateService.load()`), so keep that convention consistent when diffing.
Not implicated: sponsorship staff approval (separate `api/sponsor` queue — `Sponsorship.ApprovedByStaff=false` is expected until staff approves), the #431 owned-nav fix (deployed, saves clean), `GetChildrenQueryHandler` gates (child passes `IsMinor && ParentalControls.ParentKeycloakUserId` match — verified live).
**Repro (live, 2026-07-20):** child @toddcan (domestic travel only) filled his profile and picked states — his doc has \`Travel.WishlistRegions = [\"US-ID\",\"US-LA\"]\`, \`Sponsorship.Enabled = true\` (parent-enabled at 01:29Z, saved cleanly — the #431 approval-chain fix is live), \`ParentalControls\` correctly linked to the parent, \`Permissions.ApprovedCountries = []\`. Parent's children tab shows **no states at all** — nothing orange to approve.
**Root cause — three stacked frontend/model defects (backend saves are all fine):**
1. **The parent map is bound to the wrong array at the wrong scope.** \`children-tab.component.html\` (~121-129) passes \`[wishlistCountries]=\"child.travel.wishlistCountries\"\` with no \`scope\`/\`countryCode\` inputs, so \`app-country-map\` defaults to \`scope=\"world\"\` and renders world countries. A domestic-only child's picks live in \`child.travel.wishlistRegions\` (hyphenated codes, e.g. \`US-ID\`), which is **never passed** and would need \`scope=\"country\"\` + \`[countryCode]\` to load the states GeoJSON (compare the correct child-side wiring in \`travel-tab.component.html:77-90\`). Net: domestic children's \`wishlistCountries\` is empty ⇒ parent map highlights nothing.
2. **Orange 'requested' can never render for the parent.** \`country-map.component.ts\` \`getFeatureStyle()\` (~425-430) renders the orange \`requested\` color only when \`mode()==='minor'\`; in \`parent-approve\` mode an unapproved wishlist entry falls through to blue — even though the parent-approve **legend** advertises an orange 'requested' swatch (\`getLegendItems()\` ~648). Legend/style mismatch.
3. **States have nowhere to be approved.** \`FeaturePermissions\` has only \`approvedCountries\`; there is no region/state approval store. Backend note: the server never computes 'pending' — \`GET /api/Profile/parental/children\` returns both wishlist + approved lists and the SPA diffs them; \`PUT /api/Profile/parental/permissions/{childUserId}\` overwrites \`ApprovedCountries\` wholesale and is code-agnostic (flat \`List<string>\`).
**Suggested fix (frontend-only is possible):**
- Children tab: for domestic children render the map with \`scope=\"country\"\`, \`[countryCode]\` = child's home country, \`[wishlistCountries]=\"child.travel.wishlistRegions\"\` (or a merged view with a country/domestic toggle mirroring the child's travel tab).
- \`country-map\`: in \`parent-approve\` mode render wishlist-not-approved as orange \`requested\` (matches the legend already shipped).
- Approval store: reuse the existing flat \`approvedCountries\` list for hyphenated region codes ('approved destinations' semantics — zero backend/schema change, the wholesale-overwrite write path and the client set-diff both already handle arbitrary codes). Alternatively add a parallel \`approvedRegions\` field for symmetry with the wishlist split, at the cost of a backend DTO+model change. Recommend the former; the frontend already partitions hyphenated codes (\`TravelStateService.load()\`), so keep that convention consistent when diffing.
**Not implicated:** sponsorship staff approval (separate \`api/sponsor\` queue — \`Sponsorship.ApprovedByStaff=false\` is expected until staff approves), the #431 owned-nav fix (deployed, saves clean), \`GetChildrenQueryHandler\` gates (child passes \`IsMinor && ParentalControls.ParentKeycloakUserId\` match — verified live).
Verified complete: spikersoft-angular PR #453 merged ('surface a domestic child's requested states on the parent approval map') — 1:1 with the reported bug. Closing.
Verified complete: spikersoft-angular PR #453 merged ('surface a domestic child's requested states on the parent approval map') — 1:1 with the reported bug. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Repro (live, 2026-07-20): child @toddcan (domestic travel only) filled his profile and picked states — his doc has `Travel.WishlistRegions = ["US-ID","US-LA"]`, `Sponsorship.Enabled = true` (parent-enabled at 01:29Z, saved cleanly — the #431 approval-chain fix is live), `ParentalControls` correctly linked to the parent, `Permissions.ApprovedCountries = []`. Parent's children tab shows no states at all — nothing orange to approve.
Root cause — three stacked frontend/model defects (backend saves are all fine):
The parent map is bound to the wrong array at the wrong scope. `children-tab.component.html` (~121-129) passes `[wishlistCountries]="child.travel.wishlistCountries"` with no `scope`/`countryCode` inputs, so `app-country-map` defaults to `scope="world"` and renders world countries. A domestic-only child's picks live in `child.travel.wishlistRegions` (hyphenated codes, e.g. `US-ID`), which is never passed and would need `scope="country"` + `[countryCode]` to load the states GeoJSON (compare the correct child-side wiring in `travel-tab.component.html:77-90`). Net: domestic children's `wishlistCountries` is empty ⇒ parent map highlights nothing.
Orange 'requested' can never render for the parent. `country-map.component.ts` `getFeatureStyle()` (~425-430) renders the orange `requested` color only when `mode()==='minor'`; in `parent-approve` mode an unapproved wishlist entry falls through to blue — even though the parent-approve legend advertises an orange 'requested' swatch (`getLegendItems()` ~648). Legend/style mismatch.
States have nowhere to be approved. `FeaturePermissions` has only `approvedCountries`; there is no region/state approval store. Backend note: the server never computes 'pending' — `GET /api/Profile/parental/children` returns both wishlist + approved lists and the SPA diffs them; `PUT /api/Profile/parental/permissions/{childUserId}` overwrites `ApprovedCountries` wholesale and is code-agnostic (flat `List`).
Suggested fix (frontend-only is possible):
Not implicated: sponsorship staff approval (separate `api/sponsor` queue — `Sponsorship.ApprovedByStaff=false` is expected until staff approves), the #431 owned-nav fix (deployed, saves clean), `GetChildrenQueryHandler` gates (child passes `IsMinor && ParentalControls.ParentKeycloakUserId` match — verified live).
Verified complete: spikersoft-angular PR #453 merged ('surface a domestic child's requested states on the parent approval map') — 1:1 with the reported bug. Closing.