Both the tenant onboarding and store/branch forms only had free-text
address fields with no coordinates captured, even though the backend
already accepts and stores latitude/longitude on both tenants and
tenantlocations. Wires in the existing keyless AddressAutocomplete
(Nominatim) component used by UsersPanel so picking an address also
geocodes it, and threads latitude/longitude through both create payloads.
Quick-import buttons hardcoded quantity:1, which the backend writes straight
to the stock ledger as an "in" entry — letting one order go through for a
product that was never actually stocked. Default to 0 instead, and fix a
fallback path that was silently coercing an explicit 0 back to 1 via `|| 1`.
The consumer app resolves a storefront by scanning a QR that encodes
{tenantid, locationid}. Store Onboarding was creating the location but never
surfacing its QR, so operators had to hunt for it later in the store detail
view. Now that the backend returns the created location's locationid in the
onboarding response, render the existing StoreQRView component directly in
the "Store Branch Active!" success panel (both onboarding UI variants) so the
printable QR is available the moment the branch is created.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
UsersPanel.tsx was sending configid: 15 (Staff) / 6 (Rider) when creating
users, copied from an unrelated Hasura "role config" convention. Every
login call (auth.ts) queries app_users with configid: 1, so any account
created with 15/6 could never be found on login and was stuck before it
even reached the password-setup step. Both create paths and the
CreateUserInput default now consistently use configid: 1.
Also fixes getRiderLogs() calling riders/getriderlogs, which 404s since
the backend only registers this route under /partners.
checkEmailRequest only checked whether the account existed, so a
first-login account (no password set yet) was still sent to the
normal "enter your password" screen before the backend revealed there
was no password to check against — only then did it route to the
create-password step. checkEmailRequest now detects the same
setup-required signal PasswordSetupRequiredError does and skips
straight to it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AdminConsole renders the Tenant Onboarding form twice (embedded vs.
showHeader standalone) from two separate JSX blocks. The Primary
Outlet Name / Business Category fields added earlier only landed in
the embedded block, so the showHeader block SuperAdminPage actually
renders had no way to fill tenantForm.locationname — the required-
field check on submit failed unconditionally, no matter what was
filled in.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
catalogueApi.ts's fallback base URL ("/live/api/v1") was one path
segment short of where the routes actually live ("/live/api/v1/web"),
unlike every other service file's fallback. Any build without
VITE_FIESTA_URL set (it's gitignored, never committed) 404'd on every
catalogue call — browse, brands, categories, and import.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Accounts created by tenant/store onboarding (createtenantuser,
createtenantlocation) have no password set. Previously the login form
treated the backend's "please setup a password" response as a
successful login instead of prompting for one. Now auth.ts recognizes
it (PasswordSetupRequiredError) and LoginView routes to a create-
password step, then signs in immediately with the new password.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Header is position: fixed (h-16) and SuperAdminPage never offset its
content for that, so the onboarding form rendered underneath the
purple header bar. Add pt-16 to match how the rest of the app already
compensates for this same fixed header, and constrain content width
instead of stretching full-viewport.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
super_admin is now a real LoginRole, derived from the server's
issuperadmin flag (not a client-guessable roleid) — routes exclusively
to a new minimal SuperAdminPage, never the merchant console.
That page reuses the existing tenant/store/rider onboarding wizard
(AdminConsole) rather than duplicating it — its Tenant tab was already
calling the right composite endpoint but had nowhere to send location
data, and was never actually reachable from anywhere in the app. Now
it collects a primary outlet name + business category and sends a
nested tenantlocations object, so one submit provisions tenant +
active location + admin user instead of leaving the tenant
locationless. createTenantUser also moves off the mob API base onto
the web one, matching where this is actually called from.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Matches the backend: subcategory is no longer a required field in the
import modal (defaults to none/0 instead of blocking submission), and
the Category dropdown now comes from GET gettenantcategories (what
this tenant's own products actually use) instead of the global
categories list, which was missing categoryid 2 despite it being the
category tenant 1135 actually needs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Removes InventoryView's broken duplicate Global Catalogue tab, which
misused createproductlocation with catalogue ids that never match real
product ids (imports silently failed to land) and showed fabricated
Math.random() pricing/ratings. "Import Product" now routes to the
already-correct CatalogueBrowser instead.
Also fixes catalogueApi's product_count field mismatch (brand chip
counts were always blank), a pagination bug that capped the catalogue
at 100 of ~237 products with no way to see the rest, and replaces
ImportProductModal's free-text category id input with a real dropdown
scoped to the tenant's own categories, filtering subcategories to match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>