feat: add budget to order details#3130
Conversation
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
096568a to
5f27366
Compare
## What's the purpose of this pull request? Generate a new stable version. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - SEO: Product price amount meta tag now supports fixed fraction digits, configurable via PDP SEO settings. - Documentation - Updated changelogs with new development release entries. - Refreshed CLI README to reflect the latest development version. - Chores - Bumped package versions across the suite to new development releases. - Aligned internal dependencies with corresponding development versions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Larícia Mota <laricia.mota@vtex.com.br> Co-authored-by: Matheus P. Silva <cout.matheusps@gmail.com> Co-authored-by: Leandro Rodrigues <leandro.swf@gmail.com> Co-authored-by: vtexgithubbot <vtexgithubbot@github.com> Co-authored-by: Lucas Feijó <lucas.portela@vtex.com> Co-authored-by: Luiz Falcão <39093175+llfalcao@users.noreply.github.com> Co-authored-by: Artur Santiago <artur.santiago@cubos.io> Co-authored-by: Sahan Jayawardana <sahan@clouda.io> Co-authored-by: Mateus Pontes <mateuspo10@gmail.com> Co-authored-by: Matheus Martins <mathews_2010@outlook.com> Co-authored-by: renatomaurovtex <167437775+renatomaurovtex@users.noreply.github.com> Co-authored-by: Leandro Rodrigues <leandro.rodrigues@vtex.com> Co-authored-by: Fanny Chien <fanny.chien@vtex.com>
eduardoformiga
left a comment
There was a problem hiding this comment.
Nice! I left some comments along with the review 😉
...omponents/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx
Outdated
Show resolved
Hide resolved
...omponents/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx
Outdated
Show resolved
Hide resolved
...omponents/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx
Outdated
Show resolved
Hide resolved
...es/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/styles.scss
Show resolved
Hide resolved
...es/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/styles.scss
Outdated
Show resolved
Hide resolved
WalkthroughThe PR adds budget data exposure to user orders through GraphQL schema enhancements, a new React component for displaying budgets with responsive styling, and integration into the order details page with expanded query support. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ba46cad to
78c07ca
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/api/src/typeDefs/userOrder.graphql`:
- Around line 813-819: Rename the PascalCase field ToBeSpent to camelCase
toBeSpent in the GraphQL type UserOrderBudgetAllocation to match existing fields
like linkedEntity and cycleConfiguration; update any resolvers or field mappings
that reference UserOrderBudgetAllocation.ToBeSpent to return the value under
toBeSpent (or add an alias/resolver that maps the old name to the new field) so
schema consumers and future resolvers use the camelCase field name consistently.
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx`:
- Line 103: The code in MyAccountBudgetsCard uses a falsy check on available
which renders '—' for 0; update the conditional to explicitly check for
null/undefined (or use Number.isFinite) so zero is treated as a valid value:
e.g. render formatPrice(available, currencyCode) when available is not
null/undefined (or Number.isFinite(available)), otherwise render '—'. Locate the
usage of available and formatPrice in MyAccountBudgetsCard and replace the
truthy check with the explicit check.
- Around line 74-77: The MyAccountBudgetsCard component contains hardcoded UI
strings ("Budgets", "Name", "Available", "To be spent", "Remaining"); change it
to read these labels from CMS-config or from props passed by the parent (e.g.,
add a labels/strings prop to MyAccountBudgetsCard or map to the section content
keys used by your sections.json/content-types.json), replace the hardcoded <div>
texts with the prop/CMS values, and provide sensible defaults (or update the
parent to pass CMS-provided values) so localization and central configuration
are used instead of inline literals.
🧹 Nitpick comments (4)
packages/api/src/platforms/vtex/resolvers/query.ts (1)
486-486: Fallback{ budgets: [] }makes the parent conditional always truthy.The resolver always returns a non-null
budgetData, so the guard inMyAccountOrderDetails.tsx(order.budgetData && ...) will always pass — even for non-B2B orders. The card component handles this internally by returningnull, so there's no visual bug, but you could returnnullhere instead and let the parent conditional work as intended:♻️ Suggested tweak
- budgetData: order.budgetData ?? { budgets: [] }, + budgetData: order.budgetData ?? null,This way
MyAccountBudgetsCardwon't even mount for orders without budget data.packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx (2)
105-109: Redundant ternary — both branches produce the same result.
formatPrice(toBeSpent, currencyCode)already handles0correctly, so the conditional is unnecessary.♻️ Simplify
<div data-fs-budgets-to-be-spent> - {toBeSpent !== 0 - ? formatPrice(toBeSpent, currencyCode) - : formatPrice(0, currencyCode)} + {formatPrice(toBeSpent, currencyCode)} </div>
70-119: Table-like layout uses only<div>s — screen readers won't announce it as a table.For accessibility, consider adding ARIA roles (
role="table",role="rowgroup",role="row",role="columnheader",role="cell") to the respective<div>elements — or switch to semantic<table>/<thead>/<tbody>/<tr>/<th>/<td>elements. This ensures assistive technology can navigate the budget data meaningfully.As per coding guidelines, "Use semantic HTML and proper ARIA labels for accessibility".
packages/api/src/typeDefs/userOrder.graphql (1)
817-817: Define a typed GraphQL type forreservationsinstead of usingJSONObject.The
reservationsfield has a known structure: an object with numeric values (demonstrated by the frontend code that sums them). ReplacingJSONObjectwith a proper type (e.g.,input ReservationData { [key: String]: Float }or a concrete type) would:
- Eliminate runtime type validation in the frontend
- Provide compile-time type safety for TypeScript consumers
- Better document the expected structure
If the shape is truly stable, this refactor improves maintainability without adding complexity.
| type UserOrderBudgetAllocation { | ||
| id: String | ||
| linkedEntity: UserOrderBudgetAllocationLinkedEntity | ||
| balance: UserOrderBudgetBalance | ||
| reservations: JSONObject | ||
| ToBeSpent: Float | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
echo "=== References to ToBeSpent ==="
rg -n 'ToBeSpent' --type-add 'gql:*.graphql' --type-add 'tsx:*.tsx' --type-add 'ts:*.ts'
echo ""
echo "=== References to toBeSpent (camelCase) ==="
rg -n 'toBeSpent' --type-add 'gql:*.graphql' --type-add 'tsx:*.tsx' --type-add 'ts:*.ts'Repository: vtex/faststore
Length of output: 1731
🏁 Script executed:
#!/bin/bash
echo "=== GraphQL queries referencing UserOrderBudgetAllocation ==="
rg -A 10 'UserOrderBudgetAllocation' --type graphql
echo ""
echo "=== Check the userOrder.graphql file around the type definition ==="
sed -n '800,850p' packages/api/src/typeDefs/userOrder.graphqlRepository: vtex/faststore
Length of output: 732
🏁 Script executed:
#!/bin/bash
echo "=== Search for UserOrderBudgetAllocation in all files ==="
rg -n 'UserOrderBudgetAllocation'
echo ""
echo "=== Check for GraphQL fragments or queries that might use budget fields ==="
rg -n -B 5 -A 5 'budget|Budget' packages/api/src/typeDefs/userOrder.graphql | head -100
echo ""
echo "=== Look for resolver files that handle UserOrderBudgetAllocation ==="
find packages/api/src -name '*resolver*' -o -name '*budget*' | head -20Repository: vtex/faststore
Length of output: 3394
🏁 Script executed:
#!/bin/bash
echo "=== Check resolver implementations for UserOrderBudgetAllocation ==="
find packages/api/src/platforms -name '*.ts' -exec rg -l 'budget|Budget' {} \;
echo ""
echo "=== Look at resolver structure for userOrder ==="
find packages/api/src/platforms -type f -name '*.ts' | xargs rg -l 'userOrder|UserOrder' | head -5
echo ""
echo "=== Verify other field names in related types for camelCase consistency ==="
sed -n '787,825p' packages/api/src/typeDefs/userOrder.graphqlRepository: vtex/faststore
Length of output: 1324
🏁 Script executed:
#!/bin/bash
echo "=== Check userOrder resolver for budget-related code ==="
cat packages/api/src/platforms/vtex/resolvers/userOrder.tsRepository: vtex/faststore
Length of output: 7556
🏁 Script executed:
#!/bin/bash
echo "=== Check query resolver for budget field handling ==="
rg -n -B 5 -A 10 'budget|Budget' packages/api/src/platforms/vtex/resolvers/query.ts | head -150Repository: vtex/faststore
Length of output: 602
🏁 Script executed:
#!/bin/bash
echo "=== Check if budgetData is actually being used in any queries ==="
rg -n 'budgetData' packages/core/src --type tsx --type ts | head -20
echo ""
echo "=== Search for any OMS or upstream integration that might provide ToBeSpent ==="
rg -n 'ToBeSpent|to.*[Bb]e.*[Ss]pent' packages/api/src/platforms -A 2 -B 2Repository: vtex/faststore
Length of output: 249
🏁 Script executed:
#!/bin/bash
echo "=== Search for budgetData usage in core package ==="
find packages/core/src -type f \( -name "*.ts" -o -name "*.tsx" \) -exec rg -l 'budgetData' {} \;
echo ""
echo "=== Search more broadly for budget references ==="
rg -n 'budgetData' packages/core/src
echo ""
echo "=== Check if there are any queries that select budgetData field ==="
rg -n 'budgetData|allocations' packages/core/src -A 1 -B 1 | head -50Repository: vtex/faststore
Length of output: 7270
🏁 Script executed:
#!/bin/bash
echo "=== Get the full budget query from [id].tsx ==="
sed -n '260,280p' packages/core/src/pages/pvt/account/orders/[id].tsxRepository: vtex/faststore
Length of output: 424
🏁 Script executed:
#!/bin/bash
echo "=== Check if ToBeSpent is ever selected in any GraphQL query ==="
find packages -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.graphql" \) -exec grep -l 'ToBeSpent\|toBeSpent' {} \;
echo ""
echo "=== Look at the generated types to see if ToBeSpent is optional or required ==="
sed -n '1765,1780p' packages/core/@generated/graphql.tsRepository: vtex/faststore
Length of output: 1005
Rename ToBeSpent to toBeSpent for camelCase consistency with GraphQL conventions.
Every other field in the budget types uses camelCase (linkedEntity, cycleConfiguration, carryOverBalance, autoResetOnPeriodEnd). ToBeSpent is the sole PascalCase outlier.
Note: The field is currently unused in queries (not selected in the [id].tsx query), so renaming is safe. If exposed via resolver in the future, map the resolver to handle the field name.
Suggested fix
type UserOrderBudgetAllocation {
id: String
linkedEntity: UserOrderBudgetAllocationLinkedEntity
balance: UserOrderBudgetBalance
reservations: JSONObject
- ToBeSpent: Float
+ toBeSpent: Float
}🤖 Prompt for AI Agents
In `@packages/api/src/typeDefs/userOrder.graphql` around lines 813 - 819, Rename
the PascalCase field ToBeSpent to camelCase toBeSpent in the GraphQL type
UserOrderBudgetAllocation to match existing fields like linkedEntity and
cycleConfiguration; update any resolvers or field mappings that reference
UserOrderBudgetAllocation.ToBeSpent to return the value under toBeSpent (or add
an alias/resolver that maps the old name to the new field) so schema consumers
and future resolvers use the camelCase field name consistently.
| <div data-fs-budgets-header-name>Name</div> | ||
| <div data-fs-budgets-header-available>Available</div> | ||
| <div data-fs-budgets-header-to-be-spent>To be spent</div> | ||
| <div data-fs-budgets-header-remaining>Remaining</div> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, examine the MyAccountBudgetsCard file to see the full context
cat -n packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx | head -100Repository: vtex/faststore
Length of output: 4272
🏁 Script executed:
#!/bin/bash
# Check for i18n patterns in MyAccount-related components
rg -n 'useIntl|formatMessage|FormattedMessage|intl\.|useTranslation' packages/core/src/components/account/ -g '*.tsx' | head -30Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Search for how "Name", "Available" etc. are handled elsewhere in the codebase
rg -n '"Name"|"Available"|"To be spent"|"Remaining"' packages/core/src/components/account/ -g '*.tsx' | head -20Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check MyAccountCard to see if it processes the title prop
cat -n packages/core/src/components/account/components/MyAccountCard/MyAccountCard.tsx | head -100Repository: vtex/faststore
Length of output: 458
🏁 Script executed:
#!/bin/bash
# Look for other MyAccount card components to see if they also use hardcoded strings
fd -e tsx packages/core/src/components/account/orders/MyAccountOrderDetails/ | head -20Repository: vtex/faststore
Length of output: 627
🏁 Script executed:
#!/bin/bash
# Check other card files in the same directory
ls -la packages/core/src/components/account/orders/MyAccountOrderDetails/Repository: vtex/faststore
Length of output: 1191
🏁 Script executed:
#!/bin/bash
# Check MyAccountPaymentCard for hardcoded strings
cat -n packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountPaymentCard/MyAccountPaymentCard.tsx | head -80Repository: vtex/faststore
Length of output: 2708
🏁 Script executed:
#!/bin/bash
# Check MyAccountDeliveryCard for hardcoded strings
cat -n packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountDeliveryCard/MyAccountDeliveryCard.tsx | head -80Repository: vtex/faststore
Length of output: 1814
🏁 Script executed:
#!/bin/bash
# Search for how "Budgets" title is used - check if it's referenced in CMS or i18n anywhere
rg -i 'budgets' packages/core/src/components/account/ --type tsx | grep -i 'title\|message\|label' | head -20Repository: vtex/faststore
Length of output: 85
🏁 Script executed:
#!/bin/bash
# Look for sections.json files in the account/orders area
fd -e json . packages/core/src/components/account/orders/ | grep -i sectionRepository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Search for any CMS or sections configuration at the root level
fd -e json . packages/core/ | grep -i 'section\|cms\|i18n' | head -20Repository: vtex/faststore
Length of output: 186
🏁 Script executed:
#!/bin/bash
# Check if there's a locale or translation config in the project
find packages/core -name '*i18n*' -o -name '*locale*' -o -name '*translation*' 2>/dev/null | head -20Repository: vtex/faststore
Length of output: 110
🏁 Script executed:
#!/bin/bash
# Check the i18n pattern in profile
cat packages/core/src/components/account/profile/i18n.tsRepository: vtex/faststore
Length of output: 183
🏁 Script executed:
#!/bin/bash
# Search sections.json for MyAccountOrderDetails or Budgets references
rg -i 'budgets|myaccountorder|delivery|payment' packages/core/cms/faststore/sections.json -A 3 -B 1Repository: vtex/faststore
Length of output: 792
🏁 Script executed:
#!/bin/bash
# Check if there's an i18n file in the orders directory
find packages/core/src/components/account/orders -name '*i18n*' -o -name '*locale*'Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check the full profile i18n usage - how is it imported and used?
rg -n 'i18n\|strings' packages/core/src/components/account/profile/ -A 2Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check if MyAccountOrderDetails or any parent component imports i18n
rg -n 'i18n\|useIntl\|import.*string' packages/core/src/components/account/orders/MyAccountOrderDetails/ -g '*.tsx'Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Look for how content-types.json defines these components
rg -i 'myaccountbudget|myaccountorder' packages/core/cms/faststore/content-types.json -A 10 -B 2Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check if there's any i18n or translation mechanism being used for the order details page
rg -n 'useIntl|formatMessage|FormattedMessage|i18n\.|translation' packages/core/src/components/account/orders/ -g '*.tsx'Repository: vtex/faststore
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check the MyAccountOrderDetails parent component to see how it's structured
cat -n packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderDetails.tsx | head -150Repository: vtex/faststore
Length of output: 5502
🏁 Script executed:
#!/bin/bash
# Search for where MyAccountBudgetsCard is used - maybe the parent handles localization
rg -n 'MyAccountBudgetsCard' packages/core/src/ -g '*.tsx' -B 5 -A 5Repository: vtex/faststore
Length of output: 6418
Move hardcoded UI text to CMS configuration or component props.
The strings "Budgets", "Name", "Available", "To be spent", and "Remaining" are hardcoded instead of being sourced from CMS configuration. Per FastStore's pattern, UI text should come from CMS (sections.json, content-types.json) rather than hardcoded defaults, ensuring all localization is centralized and manageable. Either extract these to CMS config or pass them as props from the parent component.
🤖 Prompt for AI Agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx`
around lines 74 - 77, The MyAccountBudgetsCard component contains hardcoded UI
strings ("Budgets", "Name", "Available", "To be spent", "Remaining"); change it
to read these labels from CMS-config or from props passed by the parent (e.g.,
add a labels/strings prop to MyAccountBudgetsCard or map to the section content
keys used by your sections.json/content-types.json), replace the hardcoded <div>
texts with the prop/CMS values, and provide sensible defaults (or update the
parent to pass CMS-provided values) so localization and central configuration
are used instead of inline literals.
...omponents/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx`:
- Around line 70-114: The div-based table in MyAccountBudgetsCard should expose
a proper tabular structure for assistive tech: update the JSX in
MyAccountBudgetsCard (the container using budgetRows) to either convert the divs
to semantic table elements (<table>/<thead>/<tbody>/<tr>/<th>/<td>) or, if
keeping divs, add ARIA roles and attributes—role="table" on the outer container,
role="rowgroup" on the header/body wrappers, role="row" on each budget row,
role="columnheader" on the header cells (Name/Available/To be spent/Remaining)
and role="cell" on each data cell, and ensure header cells have
aria-colindex/aria-rowindex or use aria-labelledby on cells to reference their
headers; keep existing identifiers like MyAccountCard, budgetRows, budget.id,
budget.name, allocationIds, formatPrice and currencyCode when making the changes
so behavior and formatting remain unchanged.
🧹 Nitpick comments (2)
packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx (2)
101-105: Redundant ternary — both branches produce the same result.
toBeSpent !== 0 ? formatPrice(toBeSpent, currencyCode) : formatPrice(0, currencyCode)simplifies toformatPrice(toBeSpent, currencyCode)since when the condition is false,toBeSpentis already0.♻️ Simplify
<div data-fs-budgets-to-be-spent> - {toBeSpent !== 0 - ? formatPrice(toBeSpent, currencyCode) - : formatPrice(0, currencyCode)} + {formatPrice(toBeSpent, currencyCode)} </div>
46-46: Prefer?? 0over|| 0for numeric fallback.
|| 0would also replaceNaN,false, and""with0. While unlikely to cause a real bug here,?? 0(nullish coalescing) is the idiomatic and semantically correct choice for defaulting nullable numbers.♻️ Fix
- const remaining = budget.balance?.remaining || 0 + const remaining = budget.balance?.remaining ?? 0
| return ( | ||
| <MyAccountCard title="Budgets" data-fs-order-budgets-card> | ||
| <div data-fs-budgets-table> | ||
| <div data-fs-budgets-table-header> | ||
| <div data-fs-budgets-header-name>Name</div> | ||
| <div data-fs-budgets-header-available>Available</div> | ||
| <div data-fs-budgets-header-to-be-spent>To be spent</div> | ||
| <div data-fs-budgets-header-remaining>Remaining</div> | ||
| </div> | ||
| <div data-fs-budgets-table-body> | ||
| {budgetRows.map( | ||
| ( | ||
| { budget, allocationIds, toBeSpent, remaining, available }, | ||
| index | ||
| ) => { | ||
| const budgetName = budget.name || '' | ||
| const allocationsList = allocationIds || '' | ||
|
|
||
| return ( | ||
| <div data-fs-budgets-row key={budget.id || index}> | ||
| <div data-fs-budgets-name> | ||
| <div data-fs-budgets-name-primary>{budgetName}</div> | ||
| <div data-fs-budgets-name-secondary title={allocationsList}> | ||
| {allocationsList} | ||
| </div> | ||
| </div> | ||
| <div data-fs-budgets-available> | ||
| {Number.isFinite(available) | ||
| ? formatPrice(available, currencyCode) | ||
| : '—'} | ||
| </div> | ||
| <div data-fs-budgets-to-be-spent> | ||
| {toBeSpent !== 0 | ||
| ? formatPrice(toBeSpent, currencyCode) | ||
| : formatPrice(0, currencyCode)} | ||
| </div> | ||
| <div data-fs-budgets-remaining> | ||
| <strong>{formatPrice(remaining, currencyCode)}</strong> | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
| )} | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
Accessibility: div-based table needs ARIA roles for screen readers.
This renders a data table using plain <div> elements. Screen readers won't convey the tabular relationship between headers and cells. Add ARIA table roles or switch to semantic <table> / <thead> / <tbody> / <tr> / <th> / <td> elements.
At minimum, add roles to the existing div structure:
♿ Proposed ARIA role additions
- <div data-fs-budgets-table>
- <div data-fs-budgets-table-header>
- <div data-fs-budgets-header-name>Name</div>
- <div data-fs-budgets-header-available>Available</div>
- <div data-fs-budgets-header-to-be-spent>To be spent</div>
- <div data-fs-budgets-header-remaining>Remaining</div>
+ <div data-fs-budgets-table role="table" aria-label="Budgets">
+ <div data-fs-budgets-table-header role="row">
+ <div data-fs-budgets-header-name role="columnheader">Name</div>
+ <div data-fs-budgets-header-available role="columnheader">Available</div>
+ <div data-fs-budgets-header-to-be-spent role="columnheader">To be spent</div>
+ <div data-fs-budgets-header-remaining role="columnheader">Remaining</div>
</div>
- <div data-fs-budgets-table-body>
+ <div data-fs-budgets-table-body role="rowgroup">And for each row:
- <div data-fs-budgets-row key={budget.id || index}>
- <div data-fs-budgets-name>
+ <div data-fs-budgets-row key={budget.id || index} role="row">
+ <div data-fs-budgets-name role="cell">(same role="cell" for the available, to-be-spent, and remaining cells)
🤖 Prompt for AI Agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/MyAccountBudgetsCard.tsx`
around lines 70 - 114, The div-based table in MyAccountBudgetsCard should expose
a proper tabular structure for assistive tech: update the JSX in
MyAccountBudgetsCard (the container using budgetRows) to either convert the divs
to semantic table elements (<table>/<thead>/<tbody>/<tr>/<th>/<td>) or, if
keeping divs, add ARIA roles and attributes—role="table" on the outer container,
role="rowgroup" on the header/body wrappers, role="row" on each budget row,
role="columnheader" on the header cells (Name/Available/To be spent/Remaining)
and role="cell" on each data cell, and ensure header cells have
aria-colindex/aria-rowindex or use aria-labelledby on cells to reference their
headers; keep existing identifiers like MyAccountCard, budgetRows, budget.id,
budget.name, allocationIds, formatPrice and currencyCode when making the changes
so behavior and formatting remain unchanged.
What's the purpose of this pull request?
No contexto do B2B FastStore, clientes corporativos precisam visualizar informações sobre os budgets alocados em seus pedidos para ter transparência sobre como os orçamentos foram utilizados. Atualmente, essas informações não estão disponíveis na página de detalhes do pedido no My Account, dificultando o acompanhamento financeiro e a gestão de budgets pelos compradores B2B.
Esta implementação adiciona a exibição dos budgets alocados diretamente na página de detalhes do pedido, seguindo o mesmo padrão visual dos outros cards informativos (Payment, Delivery, Summary, etc.), proporcionando uma experiência consistente e completa para os usuários B2B.
How it works?
Esta feature adiciona um novo card
MyAccountBudgetsCardna página de detalhes do pedido (/pvt/account/orders/[id]) que exibe informações sobre os budgets alocados ao pedido.Implementação técnica:
GraphQL Schema (
packages/api/src/typeDefs/userOrder.graphql):UserOrderBudgetData: Container principal com lista de budgetsUserOrderBudget: Informações do budget (id, name, unitId, cycleConfiguration, balance, allocations)UserOrderBudgetAllocation: Informações de alocação específica (linkedEntity, balance, reservations, ToBeSpent)UserOrderBudgetBalance: Valores financeiros (amount, balanceAdjustment, remaining)UserOrderBudgetCycleConfiguration: Configuração do ciclo do budgetbudgetDataadicionado aos tiposUserOrdereUserOrderResultAPI Layer (
packages/api/src/platforms/vtex/resolvers/query.ts):userOrderagora retorna o campobudgetDatadiretamente da API VTEX OMS/api/oms/user/orders/${orderId}que já retorna essas informaçõesComponente React (
packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/):MyAccountBudgetsCardcriado seguindo o padrão dos outros cards do My AccountbudgetDataexistir e contiver budgets com allocations válidasIntegração (
packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderDetails.tsx):MyAccountBudgetsCardfoi integrado na página de detalhes do pedidoMyAccountSummaryCarde antes dos accordions de delivery optionsorder.budgetDataQuery GraphQL (
packages/core/src/pages/pvt/account/orders/[id].tsx):budgetDatana queryServerOrderDetailsQuerypara buscar todas as informações necessárias dos budgetsComportamento:
currencyCode)How to test it?
Pré-requisitos:
Passos para teste:
Configurar ambiente de desenvolvimento:
Acessar a página de detalhes do pedido:
/pvt/account/ordersVerificar a exibição do card de budgets:
Testar casos edge:
Verificar responsividade:
Starters Deploy Preview
References
Task relacionada:
Documentação:
Relacionado:
Checklist
You may erase this after checking them all 😉
PR Title and Commit Messages
feat,fix,chore,docs,style,refactor,ciandtestPR Description
breaking change,bug,contributing,performance,documentation..Dependencies
pnpm-lock.yamlfile when there were changes to the packagesDocumentation
@Mariana-Caetanoto review and update (Or submit a doc request)Summary by CodeRabbit