@vtex/faststore-plugin-buyer-portal 2.0.13 → 2.0.14
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/CHANGELOG.md +18 -1
- package/cms/b2b/components/.gitkeep +0 -0
- package/cms/b2b/pages/cms_content_type__i18n.jsonc +36 -0
- package/cypress/integration/localization.test.ts +482 -0
- package/cypress/support/commands.ts +8 -0
- package/docs/i18n/i18n-messages-format.md +391 -0
- package/docs/i18n/locales.json +701 -0
- package/docs/i18n/migration-inventory.md +959 -0
- package/package.json +3 -3
- package/specs/custom-localization-system.md +711 -0
- package/specs/multi-locale-e2e-validation.md +277 -0
- package/src/__mocks__/discovery.config.ts +12 -0
- package/src/features/accounting-fields/components/AccountingConfirmDelete/AccountingConfirmDelete.tsx +14 -4
- package/src/features/accounting-fields/components/AccountingFieldConfirmEdit/AccountingFieldConfirmEdit.tsx +11 -6
- package/src/features/accounting-fields/components/AccountingFieldDropdown/AccountingFieldDropdown.tsx +5 -3
- package/src/features/accounting-fields/components/AccountingFieldForm/AccountingFieldForm.tsx +33 -23
- package/src/features/accounting-fields/components/AccountingValueConfirmEdit/AccountingValueConfirmEdit.tsx +10 -6
- package/src/features/accounting-fields/components/AccountingValueDropdown/AccountingValueDropdown.tsx +19 -9
- package/src/features/accounting-fields/components/AccountingValueForm/AccountingValueForm.tsx +21 -10
- package/src/features/accounting-fields/components/CreateAccountingFieldDrawer/CreateAccountingFieldDrawer.tsx +11 -8
- package/src/features/accounting-fields/components/CreateAccountingValueDrawer/CreateAccountingValueDrawer.tsx +18 -7
- package/src/features/accounting-fields/components/DeleteAccountingFieldDrawer/DeleteAccountingFieldDrawer.tsx +14 -12
- package/src/features/accounting-fields/components/DeleteAccountingValueDrawer/DeleteAccountingValueDrawer.tsx +20 -10
- package/src/features/accounting-fields/components/EditAccountingFieldDrawer/EditAccountingFieldDrawer.tsx +5 -3
- package/src/features/accounting-fields/components/EditAccountingValueDrawer/EditAccountingValueDrawer.tsx +13 -6
- package/src/features/accounting-fields/components/RemoveValueFromUnitDrawer/RemoveValueFromUnitDrawer.tsx +19 -8
- package/src/features/accounting-fields/layouts/AccountingFieldLayout/AccountingFieldLayout.tsx +11 -9
- package/src/features/addresses/components/AddRecipientsDrawer/AddRecipientsDrawer.tsx +13 -7
- package/src/features/addresses/components/AddressDropdownMenu/AddressDropdownMenu.tsx +22 -20
- package/src/features/addresses/components/AddressForm/AddressForm.tsx +33 -22
- package/src/features/addresses/components/AddressLine/AddressLine.tsx +29 -25
- package/src/features/addresses/components/AddressLocationsList/AddressLocationsList.tsx +15 -6
- package/src/features/addresses/components/AddressRecipientsList/AddressRecipientsList.tsx +9 -4
- package/src/features/addresses/components/AddressesCard/AddressesCard.tsx +8 -5
- package/src/features/addresses/components/CreateAddressDrawer/CreateAddressDrawer.tsx +27 -14
- package/src/features/addresses/components/CreateAddressSettingsDrawer/CreateAddressSettingsDrawer.tsx +26 -21
- package/src/features/addresses/components/DeleteAddressDrawer/DeleteAddressDrawer.tsx +20 -16
- package/src/features/addresses/components/DeleteAddressLocationDrawer/DeleteAddressLocationDrawer.tsx +26 -14
- package/src/features/addresses/components/DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer.tsx +20 -17
- package/src/features/addresses/components/EditAddressDrawer/EditAddressDrawer.tsx +12 -6
- package/src/features/addresses/components/EditAddressLocationDrawer/EditAddressLocationDrawer.tsx +24 -17
- package/src/features/addresses/components/EditRecipientAddressDrawer/EditRecipientAddressDrawer.tsx +17 -15
- package/src/features/addresses/components/LocationForm/LocationField/LocationField.tsx +8 -5
- package/src/features/addresses/components/LocationForm/LocationForm.tsx +9 -3
- package/src/features/addresses/components/LocationsDrawer/LocationsDrawer.tsx +15 -9
- package/src/features/addresses/components/RecipientsForm/RecipientItem/RecipientItem.tsx +55 -46
- package/src/features/addresses/components/RecipientsForm/RecipientsForm.tsx +4 -1
- package/src/features/addresses/components/RemoveAddressDrawer/RemoveAddressDrawer.tsx +21 -14
- package/src/features/addresses/layouts/AddressDetailsLayout/AddressDetailsLayout.tsx +16 -9
- package/src/features/addresses/layouts/AddressesLayout/AddressesLayout.tsx +11 -8
- package/src/features/b2b-agent/layouts/B2BAgentLayout/B2BAgentLayout.tsx +3 -1
- package/src/features/budgets/components/BudgetAddForm/BudgetAddForm.tsx +14 -12
- package/src/features/budgets/components/BudgetAddSuccess/BudgetAddSuccess.tsx +16 -14
- package/src/features/budgets/components/BudgetAllocationsSelection/BudgetAllocationsSelection.tsx +8 -5
- package/src/features/budgets/components/BudgetAllocationsTable/BudgetAllocationsTable.tsx +9 -6
- package/src/features/budgets/components/BudgetDeleteDrawer/BudgetDeleteDrawer.tsx +23 -17
- package/src/features/budgets/components/BudgetEditNotificationDrawer/BudgetEditNotificationDrawer.tsx +13 -6
- package/src/features/budgets/components/BudgetNotificationForm/BudgetNotificationForm.tsx +31 -24
- package/src/features/budgets/components/BudgetNotificationsInfo/BudgetNotificationsInfo.tsx +15 -9
- package/src/features/budgets/components/BudgetRemainingBalance/BudgetRemainingBalance.tsx +6 -2
- package/src/features/budgets/components/BudgetSettingsInfo/BudgetSettingsInfo.tsx +27 -10
- package/src/features/budgets/components/BudgetUsersTable/BudgetUsersTable.tsx +14 -7
- package/src/features/budgets/components/BudgetsTable/BudgetsTable.tsx +11 -8
- package/src/features/budgets/components/CreateBudgetAllocationDrawer/CreateBudgetAllocationDrawer.tsx +8 -5
- package/src/features/budgets/components/CreateBudgetDrawer/CreateBudgetDrawer.tsx +31 -18
- package/src/features/budgets/components/DeleteBudgetAllocationDrawer/DeleteBudgetAllocationDrawer.tsx +17 -12
- package/src/features/budgets/components/EditBudgetDrawer/EditBudgetDrawer.tsx +14 -8
- package/src/features/budgets/components/EmptyState.tsx/EmptyState.tsx +4 -1
- package/src/features/budgets/layouts/BudgetsDetailsLayout/BudgetsDetailsLayout.tsx +7 -5
- package/src/features/budgets/layouts/BudgetsLayout/BudgetsLayout.tsx +5 -3
- package/src/features/budgets/messages/budgetNotifications.ts +5 -5
- package/src/features/budgets/utils/handleBudgetError.tsx +5 -8
- package/src/features/budgets/utils/handleBudgetError.types.ts +3 -0
- package/src/features/buying-policies/components/AccountingFieldCriteriaSelector/AccountingFieldCriteriaSelector.tsx +5 -3
- package/src/features/buying-policies/components/AccountingFieldCriteriaSelector/AccountingValueCriteriaSelector.tsx +20 -9
- package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +8 -5
- package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx +49 -33
- package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx +8 -2
- package/src/features/buying-policies/components/BuyingPolicyDropdownMenu/BuyingPolicyDropdownMenu.tsx +5 -3
- package/src/features/buying-policies/components/DeleteBuyingPolicyDrawer/DeleteBuyingPolicyDrawer.tsx +28 -24
- package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +10 -7
- package/src/features/buying-policies/layouts/BuyingPoliciesLayout/BuyingPoliciesLayout.tsx +11 -4
- package/src/features/buying-policies/layouts/BuyingPolicyDetailsLayout/BuyingPolicyDetailsLayout.tsx +26 -9
- package/src/features/buying-policies/utils/accountingFieldCriteriaHelpers.ts +2 -2
- package/src/features/buying-policies/utils/buyingPoliciesWorkflowTypes.ts +3 -3
- package/src/features/buying-policies/utils/orderFieldsCriteriaOptions.ts +8 -8
- package/src/features/buying-policies/utils/spendingLimitsCriteriaOptions.ts +6 -6
- package/src/features/contracts/components/ContractsCard/ContractsCard.tsx +7 -5
- package/src/features/contracts/layouts/ContractsLayout/ContractsLayout.tsx +9 -4
- package/src/features/credit-cards/components/CreateCreditCardDrawer/CreateCreditCardDrawer.tsx +17 -11
- package/src/features/credit-cards/components/CreditCardDropdownMenu/CreditCardDropdownMenu.tsx +17 -11
- package/src/features/credit-cards/components/CreditCardForm/CreditCardForm.tsx +8 -5
- package/src/features/credit-cards/components/CreditCardSettingsDrawer/CreditCardSettingsDrawer.tsx +10 -8
- package/src/features/credit-cards/components/DeleteCreditCardDrawer/DeleteCreditCardDrawer.tsx +19 -14
- package/src/features/credit-cards/components/EditCreditCardDrawer/EditCreditCardDrawer.tsx +14 -13
- package/src/features/credit-cards/components/RemoveCreditCardDrawer/RemoveCreditCardDrawer.tsx +18 -15
- package/src/features/credit-cards/layouts/CreditCardsLayout/CreditCardLayout.tsx +10 -4
- package/src/features/order-entry/layouts/OrderEntryLayout.tsx +3 -1
- package/src/features/org-units/components/AddAllToOrgUnitDropdown/AddAllToOrgUnitDropdown.tsx +11 -9
- package/src/features/org-units/components/AuthSetupDrawer/AuthSetupDrawer.tsx +28 -16
- package/src/features/org-units/components/CreateOrgUnitDrawer/CreateOrgUnitDrawer.tsx +18 -12
- package/src/features/org-units/components/DeleteOrgUnitDrawer/DeleteOrgUnitDrawer.tsx +28 -29
- package/src/features/org-units/components/OrgUnitBreadcrumb/OrgUnitBreadcrumbLink.tsx +4 -4
- package/src/features/org-units/components/OrgUnitDetailsDropdownMenu/OrgUnitDetailsDropdownMenu.tsx +4 -2
- package/src/features/org-units/components/OrgUnitDetailsNavbar/OrgUnitDetailsNavbar.tsx +23 -5
- package/src/features/org-units/components/OrgUnitDetailsNavbar/org-unit-details-navbar.scss +18 -2
- package/src/features/org-units/components/OrgUnitsDropdownMenu/OrgUnitsDropdownMenu.tsx +6 -4
- package/src/features/org-units/components/OrgUnitsHierarchyTree/OrgUnitsHierarchyTree.tsx +9 -6
- package/src/features/org-units/components/OrganizationalUnitsCard/OrganizationalUnitsCard.tsx +15 -7
- package/src/features/org-units/components/UpdateOrgUnitDrawer/UpdateOrgUnitDrawer.tsx +15 -9
- package/src/features/org-units/layouts/OrgUnitDetailsLayout/OrgUnitDetailsLayout.tsx +27 -26
- package/src/features/org-units/layouts/OrgUnitsLayout/OrgUnitsLayout.tsx +8 -3
- package/src/features/payment-methods/components/AddPaymentMethodsDrawer/AddPaymentMethodsDrawer.tsx +29 -18
- package/src/features/payment-methods/components/PaymentMethodSettingsDrawer/PaymentMethodSettingsDrawer.tsx +13 -9
- package/src/features/payment-methods/components/RemoveMethodButton/RemoveMethodButton.tsx +5 -2
- package/src/features/payment-methods/components/RemovePaymentMethodsDrawer/RemovePaymentMethodsDrawer.tsx +10 -7
- package/src/features/payment-methods/hooks/useRemovePaymentMethodSubmit.ts +6 -4
- package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +21 -15
- package/src/features/product-assortment/components/ProductAssortmentTable/ProductAssortmentTable.tsx +11 -7
- package/src/features/product-assortment/layouts/ProductAssortmentLayout/ProductAssortmentLayout.tsx +9 -6
- package/src/features/profile/components/ProfileCard/ProfileCard.tsx +8 -5
- package/src/features/profile/components/ProfileSummary/ProfileSummary.tsx +13 -6
- package/src/features/profile/layouts/ProfileLayout/ProfileLayout.tsx +16 -6
- package/src/features/roles/layout/RoleDetailsLayout/RoleDetailsLayout.tsx +4 -2
- package/src/features/roles/layout/RolesLayout/RolesLayout.tsx +5 -3
- package/src/features/shared/components/BasicCard/BasicCard.tsx +6 -4
- package/src/features/shared/components/BasicCard/BasicCardLine.tsx +5 -4
- package/src/features/shared/components/CustomerSwitch/CustomerSwitchDrawer.tsx +10 -2
- package/src/features/shared/components/CustomerSwitch/CustomerSwitchSearch.tsx +4 -1
- package/src/features/shared/components/DropdownFilter/DropdownFilter.tsx +11 -7
- package/src/features/shared/components/Error/Error.tsx +13 -6
- package/src/features/shared/components/HeaderInside/HeaderInside.tsx +5 -2
- package/src/features/shared/components/InternalSearch/InternalSearch.tsx +4 -1
- package/src/features/shared/components/InternalTopbar/InternalTopbar.tsx +7 -5
- package/src/features/shared/components/MainLinksDropdownMenu/MainLinksDropdownMenu.tsx +23 -8
- package/src/features/shared/components/OrgUnitInputSearch/OrgUnitInputSearch.tsx +7 -2
- package/src/features/shared/components/Pagination/Pagination.tsx +6 -2
- package/src/features/shared/components/Paginator/Counter.tsx +11 -5
- package/src/features/shared/components/Paginator/Interval.tsx +4 -3
- package/src/features/shared/components/Paginator/NextPageButton.tsx +6 -2
- package/src/features/shared/components/SettingsDrawer/SettingsDrawer.tsx +6 -4
- package/src/features/shared/components/SettingsDrawer/SettingsDrawerListType.tsx +11 -10
- package/src/features/shared/components/SettingsDrawer/listTypeOptions.ts +10 -7
- package/src/features/shared/components/SortFilter/SortFilter.tsx +15 -8
- package/src/features/shared/components/Table/TableRow/TableRow.tsx +5 -1
- package/src/features/shared/components/VerticalNav/VerticalNavLink.tsx +7 -3
- package/src/features/shared/layouts/BaseTabsLayout/Navbar.tsx +28 -4
- package/src/features/shared/layouts/BaseTabsLayout/about-drawer/AboutDrawer.tsx +15 -5
- package/src/features/shared/layouts/BaseTabsLayout/base-tabs-layout.scss +24 -9
- package/src/features/shared/layouts/BaseTabsLayout/sidebar-drawer/SidebarDrawer.tsx +5 -2
- package/src/features/shared/layouts/ContractTabsLayout/ContractTabsLayout.tsx +10 -5
- package/src/features/shared/layouts/ErrorTabsLayout/ErrorTabsLayout.tsx +7 -4
- package/src/features/shared/layouts/FinanceTabsLayout/FinanceTabsLayout.tsx +9 -4
- package/src/features/shared/layouts/LoadingTabsLayout/LoadingTabsLayout.tsx +7 -4
- package/src/features/shared/layouts/OrgUnitTabsLayout/OrgUnitTabLayout.tsx +3 -0
- package/src/features/shared/layouts/SumaPageLayout/FullSidebarNav.tsx +13 -7
- package/src/features/shared/layouts/SumaPageLayout/SumaSidebar.tsx +9 -5
- package/src/features/shared/localization/LocalizationContext.tsx +35 -0
- package/src/features/shared/localization/__tests__/createLocalize.test.ts +166 -0
- package/src/features/shared/localization/__tests__/get-localization-labels.service.test.ts +202 -0
- package/src/features/shared/localization/clients/LocalizationClient.ts +19 -0
- package/src/features/shared/localization/constants.ts +31 -0
- package/src/features/shared/localization/createLocalize.ts +78 -0
- package/src/features/shared/localization/services/get-localization-labels.service.ts +76 -0
- package/src/features/shared/localization/types.ts +66 -0
- package/src/features/shared/localization/withLocalization.tsx +22 -0
- package/src/features/shared/types/AuthRouteProps.ts +5 -0
- package/src/features/shared/types/LoaderData.ts +1 -0
- package/src/features/shared/utils/addresLabelToPropMapping.ts +10 -10
- package/src/features/shared/utils/constants.ts +1 -4
- package/src/features/shared/utils/getContractSettingsLinks.ts +17 -12
- package/src/features/shared/utils/getFinanceSettingsLinks.ts +14 -9
- package/src/features/shared/utils/getKeyByValue.ts +2 -2
- package/src/features/shared/utils/getOrganizationSettingsLinks.ts +13 -3
- package/src/features/shared/utils/getSumaListingSidebarLinks.ts +15 -10
- package/src/features/shared/utils/index.ts +2 -0
- package/src/features/shared/utils/routeLayoutMapping.ts +30 -30
- package/src/features/shared/utils/search.tsx +10 -0
- package/src/features/shared/utils/withAuth.tsx +6 -0
- package/src/features/shared/utils/withAuthLoader.ts +11 -0
- package/src/features/shared/utils/withLoaderErrorBoundary.ts +9 -0
- package/src/features/shared/utils/withProviders.tsx +13 -2
- package/src/features/users/components/CreateUserDrawer/CreateUserDrawer.tsx +39 -27
- package/src/features/users/components/CreateUserDrawerWithUsername/CreateUserDrawerWithUsername.tsx +41 -39
- package/src/features/users/components/DeleteUserDrawer/DeleteUserDrawer.tsx +27 -23
- package/src/features/users/components/EmailTransactionalSection/EmailTransactionalSection.tsx +6 -8
- package/src/features/users/components/LoginField/LoginField.tsx +4 -4
- package/src/features/users/components/ReassignOrgUnitDrawer/ReassignOrgUnitDrawer.tsx +22 -19
- package/src/features/users/components/ResetPasswordDrawer/ResetPasswordDrawer.tsx +16 -21
- package/src/features/users/components/UpdateUserDrawer/UpdateUserDrawer.tsx +26 -15
- package/src/features/users/components/UpdateUserDrawerWithUsername/UpdateUserDrawerWithUsername.tsx +22 -8
- package/src/features/users/components/UserDropdownMenu/UserDropdownMenu.tsx +7 -5
- package/src/features/users/components/UserFormFields/UserFormFields.tsx +9 -8
- package/src/features/users/components/UsersCard/UsersCard.tsx +4 -2
- package/src/features/users/layouts/UserDetailsLayout/UserDetailsLayout.tsx +26 -10
- package/src/features/users/layouts/UsersLayout/UsersLayout.tsx +12 -8
- package/src/pages/accounting-field.tsx +28 -15
- package/src/pages/address-details.tsx +37 -26
- package/src/pages/addresses.tsx +27 -12
- package/src/pages/budgets-details.tsx +25 -15
- package/src/pages/budgets.tsx +31 -17
- package/src/pages/buyer-organization-manager.tsx +23 -12
- package/src/pages/buying-policies.tsx +38 -20
- package/src/pages/buying-policy-details.tsx +20 -19
- package/src/pages/contracts.tsx +15 -1
- package/src/pages/credit-cards.tsx +30 -17
- package/src/pages/order-entry.tsx +26 -15
- package/src/pages/org-unit-details.tsx +20 -6
- package/src/pages/org-units.tsx +20 -6
- package/src/pages/payment-groups.tsx +15 -12
- package/src/pages/productAssortment.tsx +10 -1
- package/src/pages/profile.tsx +14 -1
- package/src/pages/role-details.tsx +19 -6
- package/src/pages/roles.tsx +27 -14
- package/src/pages/user-details.tsx +29 -17
- package/src/pages/users.tsx +11 -0
- package/vitest.config.ts +13 -0
- package/src/features/addresses/constants/messages.ts +0 -8
- package/src/features/credit-cards/constants/messages.ts +0 -6
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Multi-Locale E2E Validation (Org Account)
|
|
2
|
+
|
|
3
|
+
> **Status**: Done
|
|
4
|
+
> **Created**: 2026-07-09
|
|
5
|
+
> **Jira**: [B2BTEAM-3709](https://vtex-dev.atlassian.net/browse/B2BTEAM-3709)
|
|
6
|
+
> **Branch**: `feat/i18n`
|
|
7
|
+
|
|
8
|
+
## Checklist coverage (Jira B2BTEAM-3709)
|
|
9
|
+
|
|
10
|
+
Legend: ✅ automated & passing · 🐛 automated & correctly failing (real bug found) · ⚠️ partial/indirect · ❌ still manual-only (not automatable, or needs real CMS content this environment doesn't have yet)
|
|
11
|
+
|
|
12
|
+
**1. Infraestrutura e comportamento base**
|
|
13
|
+
- ❌ Páginas carregam normalmente com endpoint de localização lento — SSR-only fetch, not interceptable from Cypress
|
|
14
|
+
- ⚠️ Chave CMS inexistente → fallback para a própria chave, sem crash — unit-tested (`createLocalize.test.ts`); E2E covers "no raw key visible" broadly (see below) but not one specific unknown key
|
|
15
|
+
- ✅ Labels do `shared` aparecem sem crash (checked on selector, About drawer, sidebar)
|
|
16
|
+
- 🐛 Trocar locale + recarregar/navegar reflete no idioma — **found a real bug**: see Finding 3
|
|
17
|
+
- ✅ Nenhuma requisição extra de localização no client (SSR/loader only)
|
|
18
|
+
- ✅ Erro (client-side) mostra texto traduzido, não chave CMS — best-effort, reproduces intermittently (Finding 2)
|
|
19
|
+
|
|
20
|
+
**2. Seletor de locale**
|
|
21
|
+
- ✅ Botão visível na navbar principal e na navbar de Org Unit Details
|
|
22
|
+
- ✅ Labels do drawer não vazias, sem chave CMS crua
|
|
23
|
+
- 🐛 Persistência do idioma entre navegação/reload — Finding 3
|
|
24
|
+
- ✅ Não quebra layout em viewport mobile/tablet
|
|
25
|
+
|
|
26
|
+
**3. Navegação, sidebar e títulos**
|
|
27
|
+
- ✅ Sidebar, About drawer, seletor — sem chaves CMS cruas visíveis (generic sweep)
|
|
28
|
+
- ❌ Tabs "Contract"/"Organization"/"Finance and Compliance" traduzidas — needs real CMS content
|
|
29
|
+
- ⚠️ Breadcrumb traduzido — checked for locale-prefixed hrefs where a clickable breadcrumb exists; content translation needs real CMS entries
|
|
30
|
+
- ❌ Loading skeleton com título traduzido — too timing-dependent to automate reliably
|
|
31
|
+
- ✅ About drawer sem chaves cruas
|
|
32
|
+
- ✅ "Start shopping" respeita locale (both navbars) — **the original bug, fixed**
|
|
33
|
+
|
|
34
|
+
**4. URLs localizadas**
|
|
35
|
+
- ✅ **Bug conhecido do `href="/"` na Navbar principal — corrigido e testado**
|
|
36
|
+
- ✅ Link Org Unit Details respeita locale
|
|
37
|
+
- ⚠️ Links em cards/tabelas/breadcrumbs/drawers — checked breadcrumb + hierarchy-tree click-area (the latter hits Finding 1); table/card links not exhaustively covered
|
|
38
|
+
- 🐛 Links internos mantêm prefixo ao navegar — Finding 1 (client-side) and Finding 3 (server redirect)
|
|
39
|
+
|
|
40
|
+
**5. Interpolação de strings**
|
|
41
|
+
- ✅ Paginação com números reais, não placeholders crus
|
|
42
|
+
- ✅ Delete User: nome do usuário interpolado em um link real, não placeholder cru
|
|
43
|
+
- ❌ Budget Add Success / Recipient form ReactNode interpolation — need multi-step seed setup (fresh org unit with zero budgets; create+edit recipient) not practical to bolt onto this spec without duplicating other suites' setup
|
|
44
|
+
- ❌ Toasts multi-linha, filtros/dropdowns dinâmicos — not covered
|
|
45
|
+
|
|
46
|
+
## Findings (bugs discovered while validating, not part of this plugin's fix)
|
|
47
|
+
|
|
48
|
+
1. **Client-side SPA navigation can drop the active locale.** Clicking between tabs while
|
|
49
|
+
a non-default locale is active intermittently lands on a URL without the locale prefix,
|
|
50
|
+
even though the equivalent direct/SSR request is always correct (proven via `curl`).
|
|
51
|
+
Points to `@faststore/core`'s `useLink_unstable`/router-locale sync, not this plugin.
|
|
52
|
+
2. **Stale session/cart cookie causes a client-side error on locale switch outside the
|
|
53
|
+
selector's own flow.** Force-visiting a locale-prefixed page while a different-channel
|
|
54
|
+
session cookie is present can trigger the client error boundary (translated text
|
|
55
|
+
confirmed correct) on channel-sensitive pages (e.g. Assortments).
|
|
56
|
+
3. **The buyer-portal root redirect drops the locale prefix.** Confirmed deterministically
|
|
57
|
+
via a plain `curl` (no browser/client JS): `GET /pt-BR/pvt/organization-account` returns
|
|
58
|
+
`302 Found` with `Location: /pvt/organization-account/org-unit/{id}` — no `/pt-BR`
|
|
59
|
+
prefix — so the landing page renders `lang="en-US"`. This is a **server-side redirect**
|
|
60
|
+
issue, unrelated to `resolveLink` or client navigation, and is the most actionable of the
|
|
61
|
+
three findings since it's 100% reproducible outside a browser.
|
|
62
|
+
|
|
63
|
+
These three are documented in `cypress/integration/localization.test.ts` (one test is
|
|
64
|
+
deliberately left red, reproducing Finding 3) and should be reported to whoever owns
|
|
65
|
+
`@faststore/core`'s experimental localization feature / the host-store's redirect logic.
|
|
66
|
+
|
|
67
|
+
## Execution Notes
|
|
68
|
+
|
|
69
|
+
- **Code fix implemented**: `Navbar.tsx`'s "Start shopping" link now uses `resolveLink("/")`
|
|
70
|
+
via `useLink_unstable`, matching `OrgUnitDetailsNavbar`/`SidebarDrawer`. Verified with
|
|
71
|
+
`make lint`, `make typecheck` (0 new errors vs. the 143 pre-existing, unrelated
|
|
72
|
+
`@faststore/core`/`next/dynamic` type errors already on `feat/i18n`), and `make test`
|
|
73
|
+
(66/66 unit tests pass).
|
|
74
|
+
- **E2E test registered**: `cypress/integration/localization.test.ts` covers the checklist
|
|
75
|
+
items that are deterministically testable from the plugin repo — locale-prefixed "Start
|
|
76
|
+
shopping" links on both navbars, and the locale selector opening without crashing/blank
|
|
77
|
+
labels. `cy.login()` (`cypress/support/commands.ts`) now also accepts a `VTEX_AUTH_TOKEN`
|
|
78
|
+
env var to set the auth cookie directly, skipping the UI login flow — this wires up the
|
|
79
|
+
`VTEX_AUTH_TOKEN` secret already declared (but previously unused) in `.github/workflows/ci.yml`.
|
|
80
|
+
- **Live run: executed successfully** against `b2bfaststoredev.store`'s `feat/i18n-enable`
|
|
81
|
+
branch (which already has `contentSource: "CP"`, `localization.enabled: true`, `en-US`/
|
|
82
|
+
`pt-BR` locales, and the required `FS_DISCOVERY_APP_KEY`/`FS_DISCOVERY_APP_TOKEN` in
|
|
83
|
+
`vtex.env`), built and served locally (`faststore build && faststore serve`, Node 24) with
|
|
84
|
+
the plugin linked via `feat/i18n`. `cypress/integration/localization.test.ts` ran 3/3
|
|
85
|
+
passing, confirmed stable across 2 consecutive runs.
|
|
86
|
+
- **Real finding during the run**: clicking through the SPA (client-side Next.js navigation,
|
|
87
|
+
e.g. clicking "Profile" from the sidebar while on a `pt-BR`-prefixed page) intermittently
|
|
88
|
+
dropped the locale prefix from the resulting URL — reproduced 2 out of 3 times. Direct
|
|
89
|
+
`curl` requests to the same page, with and without the `/pt-BR` prefix, proved the
|
|
90
|
+
**server-rendered HTML is always correct** (`Navbar.tsx`'s fix included: the "Start
|
|
91
|
+
shopping" `href` is correctly `/pt-BR/` vs `/` depending on the request's locale, with
|
|
92
|
+
`Cache-Control: no-store` — no caching involved). So the SSR mechanism this plugin controls
|
|
93
|
+
(including the Navbar fix) is proven correct; the intermittent loss happens specifically
|
|
94
|
+
during **client-side (SPA) transitions**, which is `useLink_unstable`/Next.js router state
|
|
95
|
+
territory inside `@faststore/core`, outside this plugin's code. The test was adjusted to
|
|
96
|
+
assert against a direct, locale-prefixed re-request of the landed-on page (mirroring the
|
|
97
|
+
`curl` check) rather than the immediate post-click DOM state, so it deterministically tests
|
|
98
|
+
what this plugin renders. **Flagged separately for the Localization/`@faststore/core` team**:
|
|
99
|
+
SPA tab navigation while a non-default locale is active should be spot-checked for dropped
|
|
100
|
+
locale prefixes.
|
|
101
|
+
- **The spec still self-guards**: it visits a locale-prefixed URL first and skips (logs,
|
|
102
|
+
doesn't fail) if the environment doesn't resolve it to the Buyer Portal — so it stays green
|
|
103
|
+
against host-store environments where localization isn't enabled yet (e.g. `main`), and
|
|
104
|
+
enforces automatically wherever it is (like `feat/i18n-enable`, or once merged to `main`).
|
|
105
|
+
- **Added a 4th test** that verifies actual *content* changes with the locale (not just the
|
|
106
|
+
URL/routing), using the Assortments page title ("Assortments" vs "Sortimentos" — the one
|
|
107
|
+
page with real bilingual CMS entries today per this ticket). Also asserts `<html lang>`
|
|
108
|
+
changes. 4/4 passing, confirmed stable across 2 runs.
|
|
109
|
+
- **Second real finding while building that test**: force-visiting a locale-prefixed page
|
|
110
|
+
outside the selector's own Save+redirect flow, while a cart/session cookie from the
|
|
111
|
+
previous (default-locale) channel is still present, triggers a client-side error boundary
|
|
112
|
+
("Something went wrong!") on the Assortments page specifically — the SSR HTML itself is
|
|
113
|
+
still correct (proven via direct `curl`), but client-side session/cart validation
|
|
114
|
+
(`ValidateSession`/`ValidateCartMutation`) appears to choke on the channel mismatch. The
|
|
115
|
+
test works around this by clearing all cookies except the auth cookie before the
|
|
116
|
+
locale-prefixed visit (mirroring what a fresh visit would look like). **Also worth flagging
|
|
117
|
+
to the Localization/`@faststore/core` team**, alongside the SPA-navigation finding above —
|
|
118
|
+
both point to the same gap: locale changes outside the official selector flow aren't fully
|
|
119
|
+
session-safe yet.
|
|
120
|
+
- **Still manual-only** (not automatable from Cypress, since labels/fetches happen
|
|
121
|
+
server-side in the loader): CMS latency/failure fallback, sidebar/breadcrumb/tab copy
|
|
122
|
+
correctness, and ReactNode-interpolated messages (Delete User, Budget success, Recipient
|
|
123
|
+
form) — these depend on actual CMS entries owned by the Localization team.
|
|
124
|
+
|
|
125
|
+
## 1. Business Context
|
|
126
|
+
|
|
127
|
+
### Problem Statement
|
|
128
|
+
|
|
129
|
+
`feat/i18n` implements the custom localization system described in
|
|
130
|
+
`specs/custom-localization-system.md` and goes beyond that spec's scope: it migrates
|
|
131
|
+
hardcoded strings from **all** Org Account domains to CMS-backed labels consumed via `t()`.
|
|
132
|
+
Before merging, the delivery must be validated end-to-end so that no user-visible string
|
|
133
|
+
regresses to a CMS key, hardcoded English, or a broken interpolation.
|
|
134
|
+
|
|
135
|
+
A code audit against the validation checklist (see ticket) found one concrete regression:
|
|
136
|
+
the **"Start shopping" link in the main `Navbar`** (rendered on every tabbed page — Profile,
|
|
137
|
+
Addresses, Users, etc.) uses a hardcoded `href="/"`, instead of resolving the link through
|
|
138
|
+
FastStore's locale-aware `resolveLink`. Every other equivalent link in the codebase
|
|
139
|
+
(`OrgUnitDetailsNavbar`, `SidebarDrawer`, `ProfileSummary`, table rows, breadcrumbs, etc.)
|
|
140
|
+
already goes through `useLink_unstable().resolveLink()`. As a result, clicking "Start
|
|
141
|
+
shopping" from the main navbar drops the user's selected locale instead of preserving it.
|
|
142
|
+
|
|
143
|
+
### Goals
|
|
144
|
+
|
|
145
|
+
- Fix the "Start shopping" link in the main `Navbar` so it preserves the currently selected
|
|
146
|
+
locale, consistent with every other internal link in the portal.
|
|
147
|
+
- Leave a clear, actionable checklist of the remaining (non-code, browser-only) validation
|
|
148
|
+
items from the ticket for manual QA against `b2bfaststoredev.store`, since they require a
|
|
149
|
+
linked host store, a running browser session, and CMS entries — outside what a code-only
|
|
150
|
+
change can verify.
|
|
151
|
+
|
|
152
|
+
### User Stories
|
|
153
|
+
|
|
154
|
+
#### US-1: "Start shopping" preserves the selected locale
|
|
155
|
+
|
|
156
|
+
- **Story**: As a buyer-portal user who has switched the UI language via the locale
|
|
157
|
+
selector, I want the "Start shopping" link in the main navbar to open the storefront in
|
|
158
|
+
that same locale, so that I don't lose my language context when leaving the portal.
|
|
159
|
+
- **Acceptance Criteria**:
|
|
160
|
+
- **Given** the user is on any tabbed page (e.g. Profile, Addresses, Users) with locale
|
|
161
|
+
`pt-BR` selected, **when** they click "Start shopping" in the main `Navbar`, **then** the
|
|
162
|
+
link target is prefixed with `/pt-BR` (or the active locale), matching the behavior of
|
|
163
|
+
the "Start shopping" link in `OrgUnitDetailsNavbar`.
|
|
164
|
+
- **Given** no locale is selected (default locale), **when** the user clicks "Start
|
|
165
|
+
shopping", **then** the link still opens the storefront root, with no regression to
|
|
166
|
+
current default behavior.
|
|
167
|
+
|
|
168
|
+
### Key Scenarios
|
|
169
|
+
|
|
170
|
+
| Scenario | Pre-conditions | Steps | Expected Result |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| Happy path — locale preserved | Locale switched to `pt-BR` via `LocalizationButton` | Click "Start shopping" in main `Navbar` | New tab opens `/pt-BR/` (or active locale prefix), not bare `/` |
|
|
173
|
+
| Edge case — default locale | No locale switch performed | Click "Start shopping" | Opens storefront root as before (no regression) |
|
|
174
|
+
| Consistency check | Navigate to `/org-unit-details` | Compare "Start shopping" target in `OrgUnitDetailsNavbar` vs main `Navbar` | Both links resolve through the same `resolveLink` mechanism and produce equivalent locale-aware hrefs |
|
|
175
|
+
|
|
176
|
+
### Functional Requirements
|
|
177
|
+
|
|
178
|
+
- **FR-001**: The main `Navbar`'s "Start shopping" link must resolve its `href` through
|
|
179
|
+
`useLink_unstable().resolveLink()`, the same mechanism already used by
|
|
180
|
+
`OrgUnitDetailsNavbar`, `SidebarDrawer`, and other internal links.
|
|
181
|
+
|
|
182
|
+
### Non-Functional Requirements
|
|
183
|
+
|
|
184
|
+
- No new runtime dependencies; reuse the existing `@faststore/core/experimental` API already
|
|
185
|
+
imported in `Navbar.tsx` (`LocalizationButton_unstable`) — `useLink_unstable` is exported
|
|
186
|
+
from the same experimental surface.
|
|
187
|
+
- No visual/layout change: only the resolved `href` value changes, not the link's markup or
|
|
188
|
+
styling.
|
|
189
|
+
|
|
190
|
+
### Out of Scope
|
|
191
|
+
|
|
192
|
+
- All other checklist items from B2BTEAM-3709 that require a running, linked host store,
|
|
193
|
+
browser DevTools inspection, or live CMS entries (fallback behavior under CMS latency,
|
|
194
|
+
locale persistence across navigation, sidebar/breadcrumb/tab translations, interpolation
|
|
195
|
+
correctness in Delete User / Budget / Recipient flows, etc.). These are manual/E2E QA
|
|
196
|
+
items to be executed against `b2bfaststoredev.store` and are tracked directly on the Jira
|
|
197
|
+
ticket checklist, not implemented here.
|
|
198
|
+
- Any translation content/copy work (CMS entries) — owned by the Localization team per the
|
|
199
|
+
ticket description.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 2. Arch Decisions
|
|
204
|
+
|
|
205
|
+
### Proposed Solution
|
|
206
|
+
|
|
207
|
+
Replace the hardcoded `href="/"` in `src/features/shared/layouts/BaseTabsLayout/Navbar.tsx`
|
|
208
|
+
with `resolveLink("/")`, obtained from `useLink_unstable()` (already the pattern used
|
|
209
|
+
elsewhere in the codebase, e.g. `SidebarDrawer.tsx`). This is a one-line, isolated fix with
|
|
210
|
+
no architectural changes to the localization system itself.
|
|
211
|
+
|
|
212
|
+
### Alternatives Considered
|
|
213
|
+
|
|
214
|
+
| Alternative | Pros | Cons | Verdict |
|
|
215
|
+
|---|---|---|---|
|
|
216
|
+
| **A. Use `resolveLink("/")` via `useLink_unstable` (chosen)** | Matches existing convention across the codebase; zero new dependencies; minimal diff | None significant | **Accepted** |
|
|
217
|
+
| B. Manually prepend locale from `useLocalization`/router state | Avoids depending on experimental FastStore API | Duplicates logic FastStore already solves; localization context doesn't carry the active locale today | Rejected |
|
|
218
|
+
|
|
219
|
+
### Risks & Mitigations
|
|
220
|
+
|
|
221
|
+
| Risk | Impact | Likelihood | Mitigation |
|
|
222
|
+
|---|---|---|---|
|
|
223
|
+
| `useLink_unstable` behaves differently in SSR vs. client for this link (it's rendered eagerly, unlike `LocalizationButton` which is `dynamic({ ssr: false })`) | Low | Low | Mirror the exact usage already proven in `SidebarDrawer.tsx` / `OrgUnitDetailsNavbar.tsx`, which render `resolveLink` without SSR guards |
|
|
224
|
+
|
|
225
|
+
### Key Decisions
|
|
226
|
+
|
|
227
|
+
#### Decision 1: Reuse `useLink_unstable().resolveLink`, don't introduce a new abstraction
|
|
228
|
+
|
|
229
|
+
- **Status**: Accepted
|
|
230
|
+
- **Context**: Every other internal link in the portal already resolves through this hook.
|
|
231
|
+
Introducing a different mechanism just for this link would create inconsistency.
|
|
232
|
+
- **Decision**: Import `useLink_unstable as useLink` from `@faststore/core/experimental` in
|
|
233
|
+
`Navbar.tsx`, call `const { resolveLink } = useLink()`, and use `resolveLink("/")` as the
|
|
234
|
+
`href`.
|
|
235
|
+
- **Consequences**: One-line behavioral fix; no new patterns introduced; consistent with
|
|
236
|
+
`OrgUnitDetailsNavbar` and `SidebarDrawer`.
|
|
237
|
+
|
|
238
|
+
### Implementation Plan
|
|
239
|
+
|
|
240
|
+
1. Update `src/features/shared/layouts/BaseTabsLayout/Navbar.tsx`: import `useLink_unstable`,
|
|
241
|
+
call it, and replace `href="/"` with `href={resolveLink("/")}` on the "Start shopping"
|
|
242
|
+
link.
|
|
243
|
+
2. Add/extend a test for `Navbar` (if a test file exists) asserting the link's `href` uses
|
|
244
|
+
`resolveLink` output.
|
|
245
|
+
3. `make check` (lint + typecheck + test).
|
|
246
|
+
4. Hand off the remaining checklist items (browser/CMS-dependent) to manual QA against
|
|
247
|
+
`b2bfaststoredev.store`.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 3. Technical Contract
|
|
252
|
+
|
|
253
|
+
### Data Models
|
|
254
|
+
|
|
255
|
+
None — no new data models; this fix only changes how an existing `href` string is computed.
|
|
256
|
+
|
|
257
|
+
### Interfaces
|
|
258
|
+
|
|
259
|
+
- `useLink_unstable(): { resolveLink: (path: string) => string }` — existing FastStore
|
|
260
|
+
experimental hook, already used in this codebase (e.g.
|
|
261
|
+
`src/features/shared/layouts/BaseTabsLayout/sidebar-drawer/SidebarDrawer.tsx`).
|
|
262
|
+
|
|
263
|
+
### Integration Points
|
|
264
|
+
|
|
265
|
+
- `src/features/shared/layouts/BaseTabsLayout/Navbar.tsx` — sole file changed.
|
|
266
|
+
|
|
267
|
+
### Invariants & Constraints
|
|
268
|
+
|
|
269
|
+
- The "Start shopping" link must always resolve through `resolveLink`, never a hardcoded
|
|
270
|
+
path, to stay consistent with the rest of the portal's internal links.
|
|
271
|
+
- No change to the link's visible label, target (`_blank`), or `data-fs-*` attributes.
|
|
272
|
+
|
|
273
|
+
### Files to Create / Change
|
|
274
|
+
|
|
275
|
+
| File | Change |
|
|
276
|
+
|---|---|
|
|
277
|
+
| `src/features/shared/layouts/BaseTabsLayout/Navbar.tsx` | Replace hardcoded `href="/"` with `resolveLink("/")` via `useLink_unstable` |
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Stub for `discovery.config` — provided by the host store at runtime.
|
|
2
|
+
// This file is only loaded in the unit-test environment (via vitest alias).
|
|
3
|
+
// Keep all fields that are accessed anywhere in src/ so unrelated unit tests
|
|
4
|
+
// don't crash when they transitively import a module that reads this config.
|
|
5
|
+
const discoveryConfig = {
|
|
6
|
+
api: { storeId: "test-store" },
|
|
7
|
+
secureSubdomain: "https://test-store.vtex.com",
|
|
8
|
+
storeUrl: "https://test-store.vtex.com",
|
|
9
|
+
seo: { title: "Test Store" },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default discoveryConfig;
|
|
@@ -5,10 +5,13 @@ import {
|
|
|
5
5
|
ErrorMessage,
|
|
6
6
|
InputText,
|
|
7
7
|
} from "../../../shared/components";
|
|
8
|
+
import { useLocalization } from "../../../shared/localization/LocalizationContext";
|
|
8
9
|
|
|
9
10
|
type AccountingConfirmDeleteProps = {
|
|
10
11
|
title: string | ReactNode;
|
|
11
12
|
confirmTerm?: string;
|
|
13
|
+
confirmLabel?: string;
|
|
14
|
+
confirmRequiredMessage?: string;
|
|
12
15
|
loading?: boolean;
|
|
13
16
|
children?: string | ReactNode;
|
|
14
17
|
onConfirm?: () => void;
|
|
@@ -20,11 +23,18 @@ const LABEL_MAX_LENGTH = 30;
|
|
|
20
23
|
export const AccountingConfirmDelete = ({
|
|
21
24
|
title,
|
|
22
25
|
confirmTerm,
|
|
26
|
+
confirmLabel,
|
|
27
|
+
confirmRequiredMessage,
|
|
23
28
|
close,
|
|
24
29
|
loading,
|
|
25
30
|
onConfirm,
|
|
26
31
|
children,
|
|
27
32
|
}: AccountingConfirmDeleteProps) => {
|
|
33
|
+
const { t } = useLocalization();
|
|
34
|
+
const inputLabel = confirmLabel ?? t("accountingFields.forms.fieldLabel");
|
|
35
|
+
const requiredMessage =
|
|
36
|
+
confirmRequiredMessage ??
|
|
37
|
+
t("accountingFields.validation.fieldLabelRequired");
|
|
28
38
|
const [confirmField, setConfirmField] = useState("");
|
|
29
39
|
const [isTouched, setIsTouched] = useState(false);
|
|
30
40
|
|
|
@@ -44,7 +54,7 @@ export const AccountingConfirmDelete = ({
|
|
|
44
54
|
{confirmTerm && (
|
|
45
55
|
<form data-fs-bp-accounting-confirm-delete-form>
|
|
46
56
|
<InputText
|
|
47
|
-
label=
|
|
57
|
+
label={inputLabel}
|
|
48
58
|
value={confirmField}
|
|
49
59
|
onChange={(e) =>
|
|
50
60
|
setConfirmField(
|
|
@@ -58,7 +68,7 @@ export const AccountingConfirmDelete = ({
|
|
|
58
68
|
<div data-fs-bp-accounting-form-legend>
|
|
59
69
|
<ErrorMessage
|
|
60
70
|
show={isTouched && !confirmFieldIsValid}
|
|
61
|
-
message=
|
|
71
|
+
message={requiredMessage}
|
|
62
72
|
/>
|
|
63
73
|
<InputText.Legend>
|
|
64
74
|
{confirmField.length}/{LABEL_MAX_LENGTH}
|
|
@@ -69,7 +79,7 @@ export const AccountingConfirmDelete = ({
|
|
|
69
79
|
</BasicDrawer.Body>
|
|
70
80
|
<BasicDrawer.Footer>
|
|
71
81
|
<BasicDrawer.Button variant="ghost" onClick={close} disabled={loading}>
|
|
72
|
-
|
|
82
|
+
{t("shared.buttons.cancel")}
|
|
73
83
|
</BasicDrawer.Button>
|
|
74
84
|
<BasicDrawer.Button
|
|
75
85
|
variant="danger"
|
|
@@ -77,7 +87,7 @@ export const AccountingConfirmDelete = ({
|
|
|
77
87
|
onClick={handleDeleteClick}
|
|
78
88
|
disabled={disableDeleteBtn}
|
|
79
89
|
>
|
|
80
|
-
|
|
90
|
+
{t("shared.buttons.delete")}
|
|
81
91
|
</BasicDrawer.Button>
|
|
82
92
|
</BasicDrawer.Footer>
|
|
83
93
|
</>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BasicDrawer } from "../../../shared/components";
|
|
2
|
+
import { useLocalization } from "../../../shared/localization/LocalizationContext";
|
|
2
3
|
|
|
3
4
|
type AccountingFieldConfirmEditProps = {
|
|
4
5
|
onConfirm?: () => void;
|
|
@@ -13,16 +14,20 @@ export const AccountingFieldConfirmEdit = ({
|
|
|
13
14
|
onConfirm,
|
|
14
15
|
loading = false,
|
|
15
16
|
}: AccountingFieldConfirmEditProps) => {
|
|
17
|
+
const { t } = useLocalization();
|
|
18
|
+
|
|
16
19
|
return (
|
|
17
20
|
<>
|
|
18
|
-
<BasicDrawer.Heading
|
|
21
|
+
<BasicDrawer.Heading
|
|
22
|
+
onBack={onBack}
|
|
23
|
+
title={t("accountingFields.drawers.confirmFieldUpdateTitle")}
|
|
24
|
+
/>
|
|
19
25
|
<BasicDrawer.Body>
|
|
20
26
|
<p data-fs-bp-accounting-field-confirm-edit-text>
|
|
21
|
-
|
|
22
|
-
will affect all of them.
|
|
27
|
+
{t("accountingFields.messages.confirmFieldUpdateDescription")}
|
|
23
28
|
</p>
|
|
24
29
|
<p data-fs-bp-accounting-field-confirm-edit-text>
|
|
25
|
-
|
|
30
|
+
{t("accountingFields.messages.proceedWithUpdate")}
|
|
26
31
|
</p>
|
|
27
32
|
</BasicDrawer.Body>
|
|
28
33
|
<BasicDrawer.Footer>
|
|
@@ -31,14 +36,14 @@ export const AccountingFieldConfirmEdit = ({
|
|
|
31
36
|
onClick={onCancel}
|
|
32
37
|
disabled={loading}
|
|
33
38
|
>
|
|
34
|
-
|
|
39
|
+
{t("shared.buttons.cancel")}
|
|
35
40
|
</BasicDrawer.Button>
|
|
36
41
|
<BasicDrawer.Button
|
|
37
42
|
variant="confirm"
|
|
38
43
|
isLoading={loading}
|
|
39
44
|
onClick={onConfirm}
|
|
40
45
|
>
|
|
41
|
-
|
|
46
|
+
{t("shared.buttons.confirm")}
|
|
42
47
|
</BasicDrawer.Button>
|
|
43
48
|
</BasicDrawer.Footer>
|
|
44
49
|
</>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
import { BasicDropdownMenu, Icon } from "../../../shared/components";
|
|
11
11
|
import { useDrawerProps } from "../../../shared/hooks";
|
|
12
|
+
import { useLocalization } from "../../../shared/localization/LocalizationContext";
|
|
12
13
|
import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
|
|
13
14
|
import { CreateAccountingValueDrawer } from "../CreateAccountingValueDrawer/CreateAccountingValueDrawer";
|
|
14
15
|
import { DeleteAccountingFieldDrawer } from "../DeleteAccountingFieldDrawer/DeleteAccountingFieldDrawer";
|
|
@@ -31,6 +32,7 @@ export const AccountingFieldDropdown = ({
|
|
|
31
32
|
contractId,
|
|
32
33
|
refreshList,
|
|
33
34
|
}: AccountingFieldDropdownProps) => {
|
|
35
|
+
const { t } = useLocalization();
|
|
34
36
|
const router = useRouter();
|
|
35
37
|
const route = buyerPortalRoutes.accountingFields({
|
|
36
38
|
orgUnitId,
|
|
@@ -80,11 +82,11 @@ export const AccountingFieldDropdown = ({
|
|
|
80
82
|
<BasicDropdownMenu>
|
|
81
83
|
<DropdownItem onClick={openCreateAccountingValueDrawer}>
|
|
82
84
|
<Icon name="Add" width={ICON_SIZE} height={ICON_SIZE} />
|
|
83
|
-
|
|
85
|
+
{t("accountingFields.dropdown.addValues")}
|
|
84
86
|
</DropdownItem>
|
|
85
87
|
<DropdownItem onClick={openEditAccountingFieldDrawer}>
|
|
86
88
|
<Icon name="EditSettings" width={ICON_SIZE} height={ICON_SIZE} />
|
|
87
|
-
|
|
89
|
+
{t("accountingFields.dropdown.fieldSettings")}
|
|
88
90
|
</DropdownItem>
|
|
89
91
|
<BasicDropdownMenu.Separator />
|
|
90
92
|
<DropdownItem
|
|
@@ -92,7 +94,7 @@ export const AccountingFieldDropdown = ({
|
|
|
92
94
|
onClick={openDeleteAccountingFieldDrawer}
|
|
93
95
|
>
|
|
94
96
|
<Icon name="Delete" width={ICON_SIZE} height={ICON_SIZE} />
|
|
95
|
-
|
|
97
|
+
{t("shared.buttons.delete")}
|
|
96
98
|
</DropdownItem>
|
|
97
99
|
</BasicDropdownMenu>
|
|
98
100
|
</Dropdown>
|
package/src/features/accounting-fields/components/AccountingFieldForm/AccountingFieldForm.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
SettingsDrawerContext,
|
|
15
15
|
type SettingsDrawerContextType,
|
|
16
16
|
} from "../../../shared/components/SettingsDrawer/SettingsDrawerContext";
|
|
17
|
+
import { useLocalization } from "../../../shared/localization/LocalizationContext";
|
|
17
18
|
|
|
18
19
|
import type {
|
|
19
20
|
AccountingFieldLevel,
|
|
@@ -42,6 +43,7 @@ export function AccountingFieldForm({
|
|
|
42
43
|
isEdit = false,
|
|
43
44
|
context = {},
|
|
44
45
|
}: AccountingFieldFormProps) {
|
|
46
|
+
const { t } = useLocalization();
|
|
45
47
|
const [isTouched, setIsTouched] = useState(false);
|
|
46
48
|
const [formData, setFormData] =
|
|
47
49
|
useState<AccountingFieldFormData>(initialData);
|
|
@@ -67,8 +69,8 @@ export function AccountingFieldForm({
|
|
|
67
69
|
);
|
|
68
70
|
|
|
69
71
|
const listTypeOptions = useMemo(
|
|
70
|
-
() => createListTypeOptions(accountingFieldPlural),
|
|
71
|
-
[accountingFieldPlural]
|
|
72
|
+
() => createListTypeOptions(accountingFieldPlural, t),
|
|
73
|
+
[accountingFieldPlural, t]
|
|
72
74
|
);
|
|
73
75
|
|
|
74
76
|
return (
|
|
@@ -86,11 +88,12 @@ export function AccountingFieldForm({
|
|
|
86
88
|
{isEdit ? (
|
|
87
89
|
<>
|
|
88
90
|
<p data-fs-bp-edit-accounting-field-text>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
{t("accountingFields.messages.editFieldDescription", [
|
|
92
|
+
initialData.name,
|
|
93
|
+
])}
|
|
91
94
|
</p>
|
|
92
95
|
<SettingsDrawer.ListType
|
|
93
|
-
title="
|
|
96
|
+
title={t("accountingFields.settings.listTypeTitle")}
|
|
94
97
|
name={`${initialData.name}-list-type`}
|
|
95
98
|
value={listType}
|
|
96
99
|
onChange={setListType}
|
|
@@ -99,13 +102,12 @@ export function AccountingFieldForm({
|
|
|
99
102
|
</>
|
|
100
103
|
) : (
|
|
101
104
|
<p data-fs-bp-accounting-field-form-label>
|
|
102
|
-
|
|
103
|
-
at checkout
|
|
105
|
+
{t("accountingFields.messages.createFieldDescription")}
|
|
104
106
|
</p>
|
|
105
107
|
)}
|
|
106
108
|
<div data-fs-bp-accounting-field-form-item>
|
|
107
109
|
<InputText
|
|
108
|
-
label="
|
|
110
|
+
label={t("accountingFields.forms.fieldLabel")}
|
|
109
111
|
value={formData.name}
|
|
110
112
|
hasError={isTouched && !labelFieldIsValid}
|
|
111
113
|
name="field-label"
|
|
@@ -121,7 +123,7 @@ export function AccountingFieldForm({
|
|
|
121
123
|
icon={
|
|
122
124
|
<Tooltip
|
|
123
125
|
placement="left-center"
|
|
124
|
-
content="
|
|
126
|
+
content="" // TODO: Add message
|
|
125
127
|
>
|
|
126
128
|
<Icon name="InfoFilled" width={20} height={20} />
|
|
127
129
|
</Tooltip>
|
|
@@ -130,7 +132,7 @@ export function AccountingFieldForm({
|
|
|
130
132
|
<div data-fs-bp-accounting-form-legend>
|
|
131
133
|
<ErrorMessage
|
|
132
134
|
show={isTouched && !labelFieldIsValid}
|
|
133
|
-
message="
|
|
135
|
+
message={t("accountingFields.validation.fieldLabelRequired")}
|
|
134
136
|
/>
|
|
135
137
|
<InputText.Legend>
|
|
136
138
|
{formData.name.length}/{LABEL_MAX_LENGTH}
|
|
@@ -139,7 +141,7 @@ export function AccountingFieldForm({
|
|
|
139
141
|
</div>
|
|
140
142
|
<div data-fs-bp-accounting-field-form-item>
|
|
141
143
|
<p data-fs-bp-accounting-field-form-label className="radio">
|
|
142
|
-
|
|
144
|
+
{t("accountingFields.forms.inputLevel")}
|
|
143
145
|
</p>
|
|
144
146
|
<RadioGroup
|
|
145
147
|
name="level"
|
|
@@ -152,24 +154,24 @@ export function AccountingFieldForm({
|
|
|
152
154
|
}
|
|
153
155
|
>
|
|
154
156
|
<RadioOption
|
|
155
|
-
label="
|
|
157
|
+
label={t("accountingFields.forms.orderLevel")}
|
|
156
158
|
name="level"
|
|
157
159
|
value="order"
|
|
158
160
|
>
|
|
159
|
-
|
|
161
|
+
{t("accountingFields.forms.orderLevel")}
|
|
160
162
|
</RadioOption>
|
|
161
163
|
<RadioOption
|
|
162
|
-
label="
|
|
164
|
+
label={t("accountingFields.forms.itemLevel")}
|
|
163
165
|
name="level"
|
|
164
166
|
value="item"
|
|
165
167
|
>
|
|
166
|
-
|
|
168
|
+
{t("accountingFields.forms.itemLevel")}
|
|
167
169
|
</RadioOption>
|
|
168
170
|
</RadioGroup>
|
|
169
171
|
</div>
|
|
170
172
|
<div data-fs-bp-accounting-field-form-item>
|
|
171
173
|
<p data-fs-bp-accounting-field-form-label className="radio">
|
|
172
|
-
|
|
174
|
+
{t("accountingFields.forms.inputRequirement")}
|
|
173
175
|
</p>
|
|
174
176
|
<RadioGroup
|
|
175
177
|
name="requirement"
|
|
@@ -181,18 +183,26 @@ export function AccountingFieldForm({
|
|
|
181
183
|
}))
|
|
182
184
|
}
|
|
183
185
|
>
|
|
184
|
-
<RadioOption
|
|
185
|
-
|
|
186
|
+
<RadioOption
|
|
187
|
+
label={t("accountingFields.forms.required")}
|
|
188
|
+
name="requirement"
|
|
189
|
+
value="true"
|
|
190
|
+
>
|
|
191
|
+
{t("accountingFields.forms.required")}
|
|
186
192
|
</RadioOption>
|
|
187
|
-
<RadioOption
|
|
188
|
-
|
|
193
|
+
<RadioOption
|
|
194
|
+
label={t("accountingFields.forms.optional")}
|
|
195
|
+
name="requirement"
|
|
196
|
+
value="false"
|
|
197
|
+
>
|
|
198
|
+
{t("accountingFields.forms.optional")}
|
|
189
199
|
</RadioOption>
|
|
190
200
|
</RadioGroup>
|
|
191
201
|
</div>
|
|
192
202
|
<div data-fs-bp-accounting-field-form-item>
|
|
193
203
|
<CheckboxField
|
|
194
204
|
id="accounting-field-form-enable"
|
|
195
|
-
label="
|
|
205
|
+
label={t("accountingFields.forms.enableOpenTextInput")}
|
|
196
206
|
defaultChecked={formData.enabled}
|
|
197
207
|
onChange={(e) =>
|
|
198
208
|
setFormData((data) => ({
|
|
@@ -206,7 +216,7 @@ export function AccountingFieldForm({
|
|
|
206
216
|
</BasicDrawer.Body>
|
|
207
217
|
<BasicDrawer.Footer>
|
|
208
218
|
<BasicDrawer.Button variant="ghost" onClick={close} disabled={loading}>
|
|
209
|
-
|
|
219
|
+
{t("shared.buttons.cancel")}
|
|
210
220
|
</BasicDrawer.Button>
|
|
211
221
|
<BasicDrawer.Button
|
|
212
222
|
variant="confirm"
|
|
@@ -214,7 +224,7 @@ export function AccountingFieldForm({
|
|
|
214
224
|
isLoading={loading}
|
|
215
225
|
onClick={() => formRef.current?.requestSubmit()}
|
|
216
226
|
>
|
|
217
|
-
{isEdit ? "
|
|
227
|
+
{isEdit ? t("shared.buttons.save") : t("shared.buttons.create")}
|
|
218
228
|
</BasicDrawer.Button>
|
|
219
229
|
</BasicDrawer.Footer>
|
|
220
230
|
</SettingsDrawerContext.Provider>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BasicDrawer } from "../../../shared/components";
|
|
2
|
+
import { useLocalization } from "../../../shared/localization/LocalizationContext";
|
|
2
3
|
|
|
3
4
|
import type { AccountingField } from "../../types";
|
|
4
5
|
|
|
@@ -17,20 +18,23 @@ export const AccountingValueConfirmEdit = ({
|
|
|
17
18
|
onConfirm,
|
|
18
19
|
loading = false,
|
|
19
20
|
}: AccountingValueConfirmEditProps) => {
|
|
21
|
+
const { t } = useLocalization();
|
|
22
|
+
|
|
20
23
|
return (
|
|
21
24
|
<>
|
|
22
25
|
<BasicDrawer.Heading
|
|
23
|
-
title={
|
|
26
|
+
title={t("accountingFields.drawers.confirmValueUpdateTitle", [
|
|
27
|
+
accountingField.name,
|
|
28
|
+
])}
|
|
24
29
|
onClose={onCancel}
|
|
25
30
|
onBack={onBack}
|
|
26
31
|
/>
|
|
27
32
|
<BasicDrawer.Body>
|
|
28
33
|
<p data-fs-bp-accounting-value-confirm-edit-text>
|
|
29
|
-
|
|
30
|
-
all of them.
|
|
34
|
+
{t("accountingFields.messages.confirmValueUpdateDescription")}
|
|
31
35
|
</p>
|
|
32
36
|
<p data-fs-bp-accounting-value-confirm-edit-text>
|
|
33
|
-
|
|
37
|
+
{t("accountingFields.messages.proceedWithUpdate")}
|
|
34
38
|
</p>
|
|
35
39
|
</BasicDrawer.Body>
|
|
36
40
|
<BasicDrawer.Footer>
|
|
@@ -39,14 +43,14 @@ export const AccountingValueConfirmEdit = ({
|
|
|
39
43
|
onClick={onCancel}
|
|
40
44
|
disabled={loading}
|
|
41
45
|
>
|
|
42
|
-
|
|
46
|
+
{t("shared.buttons.cancel")}
|
|
43
47
|
</BasicDrawer.Button>
|
|
44
48
|
<BasicDrawer.Button
|
|
45
49
|
variant="confirm"
|
|
46
50
|
isLoading={loading}
|
|
47
51
|
onClick={onConfirm}
|
|
48
52
|
>
|
|
49
|
-
|
|
53
|
+
{t("shared.buttons.confirm")}
|
|
50
54
|
</BasicDrawer.Button>
|
|
51
55
|
</BasicDrawer.Footer>
|
|
52
56
|
</>
|