@faststore/core 4.8.1-dev.0 → 4.8.1-dev.1
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/.turbo/turbo-generate.log +3 -3
- package/.turbo/turbo-test.log +152 -114
- package/CHANGELOG.md +10 -0
- package/cms/faststore/my-account/components/cms_component__accountnavigation.jsonc +10 -0
- package/cms/faststore/my-account/components/cms_component__accountorderdelivery.jsonc +80 -0
- package/cms/faststore/my-account/components/cms_component__accountorderdetails.jsonc +25 -0
- package/cms/faststore/my-account/components/cms_component__accountorderslist.jsonc +10 -0
- package/cms/faststore/my-account/components/cms_component__accountorderstatus.jsonc +90 -0
- package/cms/faststore/my-account/components/cms_component__accountordersummary.jsonc +25 -0
- package/package.json +6 -6
- package/src/components/account/Drawer/OrganizationDrawer/OrganizationDrawerFooter.tsx +13 -2
- package/src/components/account/orders/ListOrders/FilterSlider/FilterFacetPendingApproval/FilterFacetPendingApproval.tsx +8 -3
- package/src/components/account/orders/ListOrders/FilterSlider/FilterSlider.tsx +1 -0
- package/src/components/account/orders/ListOrders/ListOrders.tsx +2 -2
- package/src/components/account/orders/ListOrders/listOrdersLabels.ts +4 -0
- package/src/components/account/orders/OrderDetails/BuyingPolicyAlert/BuyingPolicyAlert.tsx +45 -9
- package/src/components/account/orders/OrderDetails/DeliveryCard/DeliveryCard.tsx +14 -3
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordion.tsx +4 -1
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionDeliveryInfo.tsx +14 -7
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionProducts.tsx +8 -5
- package/src/components/account/orders/OrderDetails/OrderDetailsHeader.tsx +5 -0
- package/src/components/account/orders/OrderDetails/StatusCard/StatusCard.tsx +26 -89
- package/src/components/account/orders/OrderDetails/StatusCard/statusCardLocalization.ts +114 -0
- package/src/components/account/orders/OrderDetails/SummaryCard/SummaryCard.tsx +2 -1
- package/src/components/account/orders/OrderDetails/SummaryCard/getOrderTotalLabel.ts +19 -0
- package/src/components/account/orders/OrderDetails/getDeliveryOptionLabel.ts +135 -0
- package/src/components/account/orders/OrderDetails/orderDetailsLabels.ts +73 -0
- package/src/components/sections/Account/AccountOrderDelivery.tsx +3 -1
- package/src/components/sections/Account/AccountOrderDetails.tsx +16 -0
- package/src/components/sections/Account/AccountOrderStatus.tsx +27 -3
- package/src/components/sections/Account/AccountOrdersList.tsx +4 -0
- package/src/pages/api/graphql.ts +108 -69
- package/src/sdk/account/accountPageContext.ts +14 -3
- package/src/sdk/account/getMyAccountRoutes.ts +2 -0
- package/src/sdk/overrides/PageProvider.tsx +1 -1
- package/test/components/account/OrganizationDrawerFooter.browser.test.tsx +95 -1
- package/test/components/account/orders/BuyingPolicyAlert.browser.test.tsx +342 -0
- package/test/components/account/orders/DeliveryCard.browser.test.tsx +36 -0
- package/test/components/account/orders/DeliveryOptionAccordion.browser.test.tsx +76 -0
- package/test/components/account/orders/DeliveryOptionAccordionDeliveryInfo.browser.test.tsx +41 -0
- package/test/components/account/orders/DeliveryOptionAccordionProducts.browser.test.tsx +35 -0
- package/test/components/account/orders/FilterFacetPendingApproval.browser.test.tsx +25 -0
- package/test/components/account/orders/StatusCard.browser.test.tsx +37 -0
- package/test/components/account/orders/StatusCard.test.ts +101 -0
- package/test/components/account/orders/SummaryCard.browser.test.tsx +59 -0
- package/test/components/account/orders/getDeliveryOptionLabel.test.ts +129 -0
- package/test/components/account/orders/getOrderTotalLabel.test.ts +35 -0
- package/test/components/account/orders/listOrdersLabels.test.ts +23 -0
- package/test/components/account/orders/orderDetailsLabels.test.ts +13 -0
- package/test/components/sections/Account/AccountOrderDelivery.browser.test.tsx +72 -0
- package/test/components/sections/Account/AccountOrderDetails.browser.test.tsx +151 -0
- package/test/components/sections/Account/AccountOrderStatus.browser.test.tsx +59 -0
- package/test/components/sections/Account/AccountOrdersList.browser.test.tsx +67 -0
- package/test/pages/api/graphql.test.ts +27 -1
- package/test/sdk/account/getMyAccountRoutes.test.ts +11 -1
- package/test/utils/userOrderStatus.test.ts +22 -0
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import { Icon as UIIcon, Skeleton as UISkeleton } from '@faststore/ui'
|
|
2
|
+
import { useRouter } from 'next/router'
|
|
2
3
|
import { useRef, type ReactNode } from 'react'
|
|
3
4
|
import Card from 'src/components/account/components/Card'
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
orderStatusMap,
|
|
7
|
+
type OrderStatusCmsLabels,
|
|
8
|
+
type OrderStatusKey,
|
|
9
|
+
} from 'src/utils/userOrderStatus'
|
|
5
10
|
import { useConnectorPositioning } from './useConnectorPositioning'
|
|
6
11
|
import type { ServerOrderDetailsQueryQuery } from '@generated/graphql'
|
|
7
12
|
import {
|
|
8
13
|
type OrderStatusSectionLabels,
|
|
9
14
|
resolveOrderStatusLabels,
|
|
10
15
|
} from '../orderDetailsLabels'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
| 'processing'
|
|
18
|
-
| 'shipping'
|
|
16
|
+
import {
|
|
17
|
+
formatDate,
|
|
18
|
+
getDisplayStepLabel,
|
|
19
|
+
type StepKey,
|
|
20
|
+
type StepStatus,
|
|
21
|
+
} from './statusCardLocalization'
|
|
19
22
|
|
|
20
23
|
interface Step {
|
|
21
24
|
label: ReactNode
|
|
@@ -27,63 +30,24 @@ interface StatusCardProps {
|
|
|
27
30
|
status: OrderStatusKey
|
|
28
31
|
creationDate: ServerOrderDetailsQueryQuery['userOrder']['creationDate']
|
|
29
32
|
labels?: OrderStatusSectionLabels
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Define custom labels for each step based on their status
|
|
33
|
-
// This allows us to show different text for the same step depending on its current state
|
|
34
|
-
const STEP_LABELS: Record<StepKey, Record<StepStatus, string>> = {
|
|
35
|
-
order: {
|
|
36
|
-
completed: 'Order Placed',
|
|
37
|
-
loading: 'Order Placed',
|
|
38
|
-
'not-started': 'Order Placed',
|
|
39
|
-
failed: 'Order Placed',
|
|
40
|
-
},
|
|
41
|
-
approval: {
|
|
42
|
-
completed: 'Approved', // Custom
|
|
43
|
-
loading: 'Pending approval', // Use from orderStatusMap
|
|
44
|
-
'not-started': 'Pending approval',
|
|
45
|
-
failed: 'Denied', // Custom
|
|
46
|
-
},
|
|
47
|
-
payment: {
|
|
48
|
-
completed: 'Payment Approved', // Use from orderStatusMap
|
|
49
|
-
loading: 'Payment Pending', // Use from orderStatusMap
|
|
50
|
-
'not-started': 'Payment authorization', // Custom
|
|
51
|
-
failed: 'Payment Denied', // Use from orderStatusMap
|
|
52
|
-
},
|
|
53
|
-
processing: {
|
|
54
|
-
completed: 'Ready for Delivery', // Use from orderStatusMap
|
|
55
|
-
loading: 'Handling order', // Custom
|
|
56
|
-
'not-started': 'Handling order', // Custom
|
|
57
|
-
failed: 'Canceled', // Use from orderStatusMap
|
|
58
|
-
},
|
|
59
|
-
shipping: {
|
|
60
|
-
completed: 'Invoiced', // Use from orderStatusMap
|
|
61
|
-
loading: 'Shipping order', // Custom
|
|
62
|
-
'not-started': 'Ship order', // Custom
|
|
63
|
-
failed: 'Canceled', // Use from orderStatusMap
|
|
64
|
-
},
|
|
33
|
+
statusLabels?: OrderStatusCmsLabels
|
|
65
34
|
}
|
|
66
35
|
|
|
67
36
|
// Define the visual progression of order steps from start to finish
|
|
68
37
|
const VISUAL_STEPS = [
|
|
69
38
|
{
|
|
70
|
-
label: (stepStatus: StepStatus) => STEP_LABELS.order[stepStatus],
|
|
71
39
|
key: 'order',
|
|
72
40
|
},
|
|
73
41
|
{
|
|
74
|
-
label: (stepStatus: StepStatus) => STEP_LABELS.approval[stepStatus],
|
|
75
42
|
key: 'approval',
|
|
76
43
|
},
|
|
77
44
|
{
|
|
78
|
-
label: (stepStatus: StepStatus) => STEP_LABELS.payment[stepStatus],
|
|
79
45
|
key: 'payment',
|
|
80
46
|
},
|
|
81
47
|
{
|
|
82
|
-
label: (stepStatus: StepStatus) => STEP_LABELS.processing[stepStatus],
|
|
83
48
|
key: 'processing',
|
|
84
49
|
},
|
|
85
50
|
{
|
|
86
|
-
label: (stepStatus: StepStatus) => STEP_LABELS.shipping[stepStatus],
|
|
87
51
|
key: 'shipping',
|
|
88
52
|
},
|
|
89
53
|
] as const
|
|
@@ -105,24 +69,6 @@ const CANCELED_LABELS = ['Cancellation Requested', 'Canceled']
|
|
|
105
69
|
// Define which order status labels indicate a failed state
|
|
106
70
|
const FAILED_LABELS = ['Payment Denied']
|
|
107
71
|
|
|
108
|
-
const formatDate = (date: string) => {
|
|
109
|
-
const dateObj = new Date(date)
|
|
110
|
-
|
|
111
|
-
const dateString = new Intl.DateTimeFormat('en-US', {
|
|
112
|
-
month: '2-digit',
|
|
113
|
-
day: '2-digit',
|
|
114
|
-
year: 'numeric',
|
|
115
|
-
}).format(dateObj)
|
|
116
|
-
|
|
117
|
-
const timeString = new Intl.DateTimeFormat('en-US', {
|
|
118
|
-
hour: 'numeric',
|
|
119
|
-
minute: '2-digit',
|
|
120
|
-
hour12: true,
|
|
121
|
-
}).format(dateObj)
|
|
122
|
-
|
|
123
|
-
return { date: dateString, time: timeString }
|
|
124
|
-
}
|
|
125
|
-
|
|
126
72
|
const StepIcon = ({
|
|
127
73
|
status,
|
|
128
74
|
isCanceled,
|
|
@@ -221,8 +167,10 @@ function StatusCard({
|
|
|
221
167
|
status,
|
|
222
168
|
creationDate,
|
|
223
169
|
labels: labelsProp,
|
|
224
|
-
|
|
170
|
+
statusLabels,
|
|
171
|
+
}: Readonly<StatusCardProps>) {
|
|
225
172
|
const labels = resolveOrderStatusLabels(labelsProp)
|
|
173
|
+
const { locale = 'en-US' } = useRouter()
|
|
226
174
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
227
175
|
|
|
228
176
|
useConnectorPositioning(containerRef)
|
|
@@ -244,25 +192,14 @@ function StatusCard({
|
|
|
244
192
|
isFailed,
|
|
245
193
|
})
|
|
246
194
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
stepLabel = labels.orderPlacedStep
|
|
256
|
-
} else if (step.key === 'payment' && stepStatus === 'loading') {
|
|
257
|
-
stepLabel = labels.paymentPendingStep
|
|
258
|
-
} else if (step.key === 'processing' && stepStatus === 'loading') {
|
|
259
|
-
stepLabel = labels.handlingStep
|
|
260
|
-
} else if (step.key === 'shipping' && stepStatus === 'completed') {
|
|
261
|
-
stepLabel = labels.invoicedStep
|
|
262
|
-
} else if (step.key === 'shipping' && stepStatus === 'loading') {
|
|
263
|
-
stepLabel = labels.deliveredStep
|
|
264
|
-
}
|
|
265
|
-
}
|
|
195
|
+
const stepLabel = getDisplayStepLabel({
|
|
196
|
+
stepKey: step.key,
|
|
197
|
+
stepStatus,
|
|
198
|
+
labels,
|
|
199
|
+
status,
|
|
200
|
+
statusLabels,
|
|
201
|
+
isCanceled,
|
|
202
|
+
})
|
|
266
203
|
|
|
267
204
|
// Add creation date to the order step when it's completed or failed
|
|
268
205
|
let completedAt: string | undefined
|
|
@@ -304,10 +241,10 @@ function StatusCard({
|
|
|
304
241
|
{step.completedAt && (
|
|
305
242
|
<div data-fs-shipping-step-details>
|
|
306
243
|
<span data-fs-shipping-step-date>
|
|
307
|
-
{formatDate(step.completedAt).date}
|
|
244
|
+
{formatDate(step.completedAt, locale).date}
|
|
308
245
|
</span>
|
|
309
246
|
<span data-fs-shipping-step-time>
|
|
310
|
-
{formatDate(step.completedAt).time}
|
|
247
|
+
{formatDate(step.completedAt, locale).time}
|
|
311
248
|
</span>
|
|
312
249
|
</div>
|
|
313
250
|
)}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getOrderStatusLabel,
|
|
3
|
+
type OrderStatusCmsLabels,
|
|
4
|
+
type OrderStatusKey,
|
|
5
|
+
} from 'src/utils/userOrderStatus'
|
|
6
|
+
import type { OrderStatusSectionLabels } from '../orderDetailsLabels'
|
|
7
|
+
|
|
8
|
+
export type StepStatus = 'completed' | 'loading' | 'not-started' | 'failed'
|
|
9
|
+
export type StepKey =
|
|
10
|
+
| 'order'
|
|
11
|
+
| 'approval'
|
|
12
|
+
| 'payment'
|
|
13
|
+
| 'processing'
|
|
14
|
+
| 'shipping'
|
|
15
|
+
|
|
16
|
+
export function getStepLabel(
|
|
17
|
+
stepKey: StepKey,
|
|
18
|
+
stepStatus: StepStatus,
|
|
19
|
+
labels: Required<OrderStatusSectionLabels>
|
|
20
|
+
): string {
|
|
21
|
+
const stepLabels: Record<StepKey, Record<StepStatus, string>> = {
|
|
22
|
+
order: {
|
|
23
|
+
completed: labels.orderPlacedStep,
|
|
24
|
+
loading: labels.orderPlacedStep,
|
|
25
|
+
'not-started': labels.orderPlacedStep,
|
|
26
|
+
failed: labels.orderPlacedStep,
|
|
27
|
+
},
|
|
28
|
+
approval: {
|
|
29
|
+
completed: labels.approvedStep,
|
|
30
|
+
loading: labels.pendingApprovalStep,
|
|
31
|
+
'not-started': labels.pendingApprovalStep,
|
|
32
|
+
failed: labels.deniedStep,
|
|
33
|
+
},
|
|
34
|
+
payment: {
|
|
35
|
+
completed: labels.paymentApprovedStep,
|
|
36
|
+
loading: labels.paymentPendingStep,
|
|
37
|
+
'not-started': labels.paymentAuthorizationStep,
|
|
38
|
+
failed: labels.paymentDeniedStep,
|
|
39
|
+
},
|
|
40
|
+
processing: {
|
|
41
|
+
completed: labels.readyForDeliveryStep,
|
|
42
|
+
loading: labels.handlingStep,
|
|
43
|
+
'not-started': labels.handlingStep,
|
|
44
|
+
failed: labels.canceledStep,
|
|
45
|
+
},
|
|
46
|
+
shipping: {
|
|
47
|
+
completed: labels.invoicedStep,
|
|
48
|
+
loading: labels.deliveredStep,
|
|
49
|
+
'not-started': labels.shipOrderStep,
|
|
50
|
+
failed: labels.canceledStep,
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return stepLabels[stepKey][stepStatus]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getDisplayStepLabel({
|
|
58
|
+
stepKey,
|
|
59
|
+
stepStatus,
|
|
60
|
+
labels,
|
|
61
|
+
status,
|
|
62
|
+
statusLabels,
|
|
63
|
+
isCanceled,
|
|
64
|
+
}: {
|
|
65
|
+
stepKey: StepKey
|
|
66
|
+
stepStatus: StepStatus
|
|
67
|
+
labels: Required<OrderStatusSectionLabels>
|
|
68
|
+
status: OrderStatusKey
|
|
69
|
+
statusLabels?: OrderStatusCmsLabels
|
|
70
|
+
isCanceled: boolean
|
|
71
|
+
}): string {
|
|
72
|
+
if (isCanceled) {
|
|
73
|
+
return stepKey === 'payment'
|
|
74
|
+
? getOrderStatusLabel({ status, cmsLabels: statusLabels })
|
|
75
|
+
: '—'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
stepStatus === 'failed' &&
|
|
80
|
+
(stepKey === 'processing' || stepKey === 'shipping')
|
|
81
|
+
) {
|
|
82
|
+
return getOrderStatusLabel({
|
|
83
|
+
status: 'canceled',
|
|
84
|
+
cmsLabels: statusLabels,
|
|
85
|
+
statusFallback: labels.canceledStep,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (stepStatus === 'failed' && stepKey === 'payment') {
|
|
90
|
+
return getOrderStatusLabel({
|
|
91
|
+
status,
|
|
92
|
+
cmsLabels: statusLabels,
|
|
93
|
+
statusFallback: labels.paymentDeniedStep,
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return getStepLabel(stepKey, stepStatus, labels)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function formatDate(date: string, locale: string) {
|
|
101
|
+
const dateObj = new Date(date)
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
date: new Intl.DateTimeFormat(locale, {
|
|
105
|
+
month: '2-digit',
|
|
106
|
+
day: '2-digit',
|
|
107
|
+
year: 'numeric',
|
|
108
|
+
}).format(dateObj),
|
|
109
|
+
time: new Intl.DateTimeFormat(locale, {
|
|
110
|
+
hour: 'numeric',
|
|
111
|
+
minute: '2-digit',
|
|
112
|
+
}).format(dateObj),
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type OrderSummarySectionLabels,
|
|
5
5
|
resolveOrderSummaryLabels,
|
|
6
6
|
} from '../orderDetailsLabels'
|
|
7
|
+
import { getOrderTotalLabel } from './getOrderTotalLabel'
|
|
7
8
|
|
|
8
9
|
// Interface for order totals (items, shipping, discounts)
|
|
9
10
|
// TODO: Use type from API
|
|
@@ -83,7 +84,7 @@ function SummaryCard({
|
|
|
83
84
|
<Card title={labels.summaryTitle} data-fs-order-summary-card>
|
|
84
85
|
{displayTotals.map((total) => (
|
|
85
86
|
<div key={total.id} data-fs-order-summary-item>
|
|
86
|
-
<span>{total
|
|
87
|
+
<span>{getOrderTotalLabel(total, labels)}</span>
|
|
87
88
|
<span>{formatPrice(total.value, currencyCode)}</span>
|
|
88
89
|
</div>
|
|
89
90
|
))}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { OrderSummarySectionLabels } from '../orderDetailsLabels'
|
|
2
|
+
|
|
3
|
+
const TOTAL_LABEL_KEYS = {
|
|
4
|
+
items: 'itemsTotalLabel',
|
|
5
|
+
discounts: 'discountsTotalLabel',
|
|
6
|
+
shipping: 'shippingTotalLabel',
|
|
7
|
+
tax: 'taxTotalLabel',
|
|
8
|
+
change: 'changeTotalLabel',
|
|
9
|
+
interest: 'interestLabel',
|
|
10
|
+
} as const satisfies Record<string, keyof OrderSummarySectionLabels>
|
|
11
|
+
|
|
12
|
+
export function getOrderTotalLabel(
|
|
13
|
+
total: { id: string; name: string },
|
|
14
|
+
labels: Required<OrderSummarySectionLabels>
|
|
15
|
+
): string {
|
|
16
|
+
const labelKey = TOTAL_LABEL_KEYS[total.id.toLowerCase()]
|
|
17
|
+
|
|
18
|
+
return labelKey ? labels[labelKey] : total.name
|
|
19
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { OrderDeliverySectionLabels } from './orderDetailsLabels'
|
|
2
|
+
|
|
3
|
+
type DeliveryOptionLabelData = {
|
|
4
|
+
selectedSla?: string | null
|
|
5
|
+
deliveryChannel?: string | null
|
|
6
|
+
deliveryCompany?: string | null
|
|
7
|
+
seller?: string | null
|
|
8
|
+
shippingEstimate?: string | null
|
|
9
|
+
shippingEstimateDate?: string | null
|
|
10
|
+
friendlyDeliveryOptionName?: string | null
|
|
11
|
+
address?: {
|
|
12
|
+
neighborhood?: string | null
|
|
13
|
+
addressId?: string | null
|
|
14
|
+
} | null
|
|
15
|
+
pickupStoreInfo?: {
|
|
16
|
+
address?: { neighborhood?: string | null } | null
|
|
17
|
+
} | null
|
|
18
|
+
deliveryWindow?: {
|
|
19
|
+
startDateUtc?: string | null
|
|
20
|
+
endDateUtc?: string | null
|
|
21
|
+
} | null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type EstimateUnit = 'bd' | 'd' | 'h' | 'm'
|
|
25
|
+
type EstimateQuantity = 'zero' | 'one' | 'other'
|
|
26
|
+
|
|
27
|
+
const ESTIMATE_LABEL_KEYS: Record<
|
|
28
|
+
EstimateUnit,
|
|
29
|
+
Record<EstimateQuantity, keyof OrderDeliverySectionLabels>
|
|
30
|
+
> = {
|
|
31
|
+
bd: {
|
|
32
|
+
zero: 'businessDaysZeroTemplate',
|
|
33
|
+
one: 'businessDaysOneTemplate',
|
|
34
|
+
other: 'businessDaysOtherTemplate',
|
|
35
|
+
},
|
|
36
|
+
d: {
|
|
37
|
+
zero: 'daysZeroTemplate',
|
|
38
|
+
one: 'daysOneTemplate',
|
|
39
|
+
other: 'daysOtherTemplate',
|
|
40
|
+
},
|
|
41
|
+
h: {
|
|
42
|
+
zero: 'hoursZeroTemplate',
|
|
43
|
+
one: 'hoursOneTemplate',
|
|
44
|
+
other: 'hoursOtherTemplate',
|
|
45
|
+
},
|
|
46
|
+
m: {
|
|
47
|
+
zero: 'minutesZeroTemplate',
|
|
48
|
+
one: 'minutesOneTemplate',
|
|
49
|
+
other: 'minutesOtherTemplate',
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const CHANNEL_LABEL_KEYS: Record<
|
|
54
|
+
string,
|
|
55
|
+
keyof OrderDeliverySectionLabels | undefined
|
|
56
|
+
> = {
|
|
57
|
+
delivery: 'deliveryChannelLabel',
|
|
58
|
+
pickup: 'pickupChannelLabel',
|
|
59
|
+
'pickup-in-point': 'pickupChannelLabel',
|
|
60
|
+
'take-away': 'takeAwayChannelLabel',
|
|
61
|
+
'': undefined,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isEstimateUnit(unit: string): unit is EstimateUnit {
|
|
65
|
+
return unit === 'bd' || unit === 'd' || unit === 'h' || unit === 'm'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getLocalizedEstimate(
|
|
69
|
+
estimate: string,
|
|
70
|
+
labels: Required<OrderDeliverySectionLabels>
|
|
71
|
+
): string | undefined {
|
|
72
|
+
const count = estimate.split(/\D+/)[0]
|
|
73
|
+
const unit = estimate.split(/\d+/)[1]
|
|
74
|
+
|
|
75
|
+
if (count === '' || Number.isNaN(Number(count)) || !isEstimateUnit(unit)) {
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let quantity: EstimateQuantity = 'other'
|
|
80
|
+
if (Number(count) === 0) {
|
|
81
|
+
quantity = 'zero'
|
|
82
|
+
} else if (Number(count) < 2) {
|
|
83
|
+
quantity = 'one'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const template = labels[ESTIMATE_LABEL_KEYS[unit][quantity]]
|
|
87
|
+
|
|
88
|
+
return template.replace('{count}', count)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getDeliveryOptionKey(option: DeliveryOptionLabelData): string {
|
|
92
|
+
return [
|
|
93
|
+
option.selectedSla,
|
|
94
|
+
option.deliveryChannel,
|
|
95
|
+
option.deliveryCompany,
|
|
96
|
+
option.seller,
|
|
97
|
+
option.shippingEstimate,
|
|
98
|
+
option.shippingEstimateDate,
|
|
99
|
+
option.address?.addressId,
|
|
100
|
+
option.deliveryWindow?.startDateUtc,
|
|
101
|
+
option.deliveryWindow?.endDateUtc,
|
|
102
|
+
].join('|')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getDeliveryOptionLabel(
|
|
106
|
+
option: DeliveryOptionLabelData,
|
|
107
|
+
labels: Required<OrderDeliverySectionLabels>
|
|
108
|
+
): string {
|
|
109
|
+
const channelLabelKey =
|
|
110
|
+
CHANNEL_LABEL_KEYS[option.deliveryChannel ?? 'unknown']
|
|
111
|
+
const estimate = option.shippingEstimate
|
|
112
|
+
? getLocalizedEstimate(option.shippingEstimate, labels)
|
|
113
|
+
: undefined
|
|
114
|
+
|
|
115
|
+
if (channelLabelKey === undefined && option.deliveryChannel) {
|
|
116
|
+
return option.friendlyDeliveryOptionName ?? ''
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!estimate) {
|
|
120
|
+
return channelLabelKey
|
|
121
|
+
? labels[channelLabelKey]
|
|
122
|
+
: (option.friendlyDeliveryOptionName ?? '')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const neighborhood =
|
|
126
|
+
option.address?.neighborhood ??
|
|
127
|
+
option.pickupStoreInfo?.address?.neighborhood
|
|
128
|
+
const destination = neighborhood
|
|
129
|
+
? labels.toNeighborhoodTemplate.replace('{neighborhood}', neighborhood)
|
|
130
|
+
: ''
|
|
131
|
+
|
|
132
|
+
return [channelLabelKey ? labels[channelLabelKey] : '', estimate, destination]
|
|
133
|
+
.filter(Boolean)
|
|
134
|
+
.join(' ')
|
|
135
|
+
}
|
|
@@ -13,15 +13,31 @@ export type OrderDetailsHeaderLabels = {
|
|
|
13
13
|
/** Supports the `{policy}` placeholder, replaced with the policy name. */
|
|
14
14
|
rejectModalMessage?: string
|
|
15
15
|
rejectModalConfirmText?: string
|
|
16
|
+
/** Supports the `{policy}` placeholder, replaced with the policy name. */
|
|
17
|
+
approveSuccessToast?: string
|
|
18
|
+
approveErrorToast?: string
|
|
19
|
+
/** Supports the `{policy}` placeholder, replaced with the policy name. */
|
|
20
|
+
rejectSuccessToast?: string
|
|
21
|
+
rejectErrorToast?: string
|
|
22
|
+
pendingFurtherApprovalsAlert?: string
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
export type OrderStatusSectionLabels = {
|
|
19
26
|
statusTitle?: string
|
|
20
27
|
orderPlacedStep?: string
|
|
28
|
+
approvedStep?: string
|
|
29
|
+
pendingApprovalStep?: string
|
|
30
|
+
deniedStep?: string
|
|
31
|
+
paymentApprovedStep?: string
|
|
21
32
|
paymentPendingStep?: string
|
|
33
|
+
paymentAuthorizationStep?: string
|
|
34
|
+
paymentDeniedStep?: string
|
|
35
|
+
readyForDeliveryStep?: string
|
|
22
36
|
handlingStep?: string
|
|
37
|
+
canceledStep?: string
|
|
23
38
|
invoicedStep?: string
|
|
24
39
|
deliveredStep?: string
|
|
40
|
+
shipOrderStep?: string
|
|
25
41
|
}
|
|
26
42
|
|
|
27
43
|
export type OrderPaymentSectionLabels = {
|
|
@@ -50,12 +66,33 @@ export type OrderDeliverySectionLabels = {
|
|
|
50
66
|
eachLabel?: string
|
|
51
67
|
taxesLabel?: string
|
|
52
68
|
totalLabel?: string
|
|
69
|
+
deliveryChannelLabel?: string
|
|
70
|
+
pickupChannelLabel?: string
|
|
71
|
+
takeAwayChannelLabel?: string
|
|
72
|
+
businessDaysZeroTemplate?: string
|
|
73
|
+
businessDaysOneTemplate?: string
|
|
74
|
+
businessDaysOtherTemplate?: string
|
|
75
|
+
daysZeroTemplate?: string
|
|
76
|
+
daysOneTemplate?: string
|
|
77
|
+
daysOtherTemplate?: string
|
|
78
|
+
hoursZeroTemplate?: string
|
|
79
|
+
hoursOneTemplate?: string
|
|
80
|
+
hoursOtherTemplate?: string
|
|
81
|
+
minutesZeroTemplate?: string
|
|
82
|
+
minutesOneTemplate?: string
|
|
83
|
+
minutesOtherTemplate?: string
|
|
84
|
+
toNeighborhoodTemplate?: string
|
|
53
85
|
}
|
|
54
86
|
|
|
55
87
|
export type OrderSummarySectionLabels = {
|
|
56
88
|
summaryTitle?: string
|
|
57
89
|
totalLabel?: string
|
|
58
90
|
interestLabel?: string
|
|
91
|
+
itemsTotalLabel?: string
|
|
92
|
+
discountsTotalLabel?: string
|
|
93
|
+
shippingTotalLabel?: string
|
|
94
|
+
taxTotalLabel?: string
|
|
95
|
+
changeTotalLabel?: string
|
|
59
96
|
}
|
|
60
97
|
|
|
61
98
|
export type OrderOrderedBySectionLabels = {
|
|
@@ -91,15 +128,30 @@ export const defaultOrderDetailsHeaderLabels: Required<OrderDetailsHeaderLabels>
|
|
|
91
128
|
rejectModalMessage:
|
|
92
129
|
"You're about to reject this approval request, triggered by the {policy} policy. Rejecting any approval request will deny the entire order.\n\nThis action is permanent and cannot be undone.",
|
|
93
130
|
rejectModalConfirmText: 'Reject',
|
|
131
|
+
approveSuccessToast: '{policy} policy approved successfully.',
|
|
132
|
+
approveErrorToast: "Policy couldn't be approved due to a technical issue.",
|
|
133
|
+
rejectSuccessToast: '{policy} policy rejected successfully. Order denied.',
|
|
134
|
+
rejectErrorToast: "Policy couldn't be rejected due to a technical issue.",
|
|
135
|
+
pendingFurtherApprovalsAlert:
|
|
136
|
+
'Your approval is recorded. This order is still pending further approvals.',
|
|
94
137
|
}
|
|
95
138
|
|
|
96
139
|
export const defaultOrderStatusLabels: Required<OrderStatusSectionLabels> = {
|
|
97
140
|
statusTitle: 'Status',
|
|
98
141
|
orderPlacedStep: 'Order placed',
|
|
142
|
+
approvedStep: 'Approved',
|
|
143
|
+
pendingApprovalStep: 'Pending approval',
|
|
144
|
+
deniedStep: 'Denied',
|
|
145
|
+
paymentApprovedStep: 'Payment Approved',
|
|
99
146
|
paymentPendingStep: 'Payment Pending',
|
|
147
|
+
paymentAuthorizationStep: 'Payment authorization',
|
|
148
|
+
paymentDeniedStep: 'Payment Denied',
|
|
149
|
+
readyForDeliveryStep: 'Ready for Delivery',
|
|
100
150
|
handlingStep: 'Handling order',
|
|
151
|
+
canceledStep: 'Canceled',
|
|
101
152
|
invoicedStep: 'Invoiced',
|
|
102
153
|
deliveredStep: 'Delivered',
|
|
154
|
+
shipOrderStep: 'Ship order',
|
|
103
155
|
}
|
|
104
156
|
|
|
105
157
|
export const defaultOrderPaymentLabels: Required<OrderPaymentSectionLabels> = {
|
|
@@ -129,12 +181,33 @@ export const defaultOrderDeliveryLabels: Required<OrderDeliverySectionLabels> =
|
|
|
129
181
|
eachLabel: 'Each',
|
|
130
182
|
taxesLabel: 'Taxes',
|
|
131
183
|
totalLabel: 'Total',
|
|
184
|
+
deliveryChannelLabel: 'Delivery',
|
|
185
|
+
pickupChannelLabel: 'Pickup',
|
|
186
|
+
takeAwayChannelLabel: 'Take away',
|
|
187
|
+
businessDaysZeroTemplate: 'Today',
|
|
188
|
+
businessDaysOneTemplate: 'In 1 business day',
|
|
189
|
+
businessDaysOtherTemplate: 'Up to {count} business days',
|
|
190
|
+
daysZeroTemplate: 'Today',
|
|
191
|
+
daysOneTemplate: 'In 1 day',
|
|
192
|
+
daysOtherTemplate: 'Up to {count} days',
|
|
193
|
+
hoursZeroTemplate: 'Now',
|
|
194
|
+
hoursOneTemplate: 'In 1 hour',
|
|
195
|
+
hoursOtherTemplate: 'Up to {count} hours',
|
|
196
|
+
minutesZeroTemplate: 'Now',
|
|
197
|
+
minutesOneTemplate: 'In 1 minute',
|
|
198
|
+
minutesOtherTemplate: 'Up to {count} minutes',
|
|
199
|
+
toNeighborhoodTemplate: 'to {neighborhood}',
|
|
132
200
|
}
|
|
133
201
|
|
|
134
202
|
export const defaultOrderSummaryLabels: Required<OrderSummarySectionLabels> = {
|
|
135
203
|
summaryTitle: 'Summary',
|
|
136
204
|
totalLabel: 'Total',
|
|
137
205
|
interestLabel: 'Interest',
|
|
206
|
+
itemsTotalLabel: 'Items Total',
|
|
207
|
+
discountsTotalLabel: 'Discounts Total',
|
|
208
|
+
shippingTotalLabel: 'Shipping Total',
|
|
209
|
+
taxTotalLabel: 'Tax Total',
|
|
210
|
+
changeTotalLabel: 'Change Total',
|
|
138
211
|
}
|
|
139
212
|
|
|
140
213
|
export const defaultOrderOrderedByLabels: Required<OrderOrderedBySectionLabels> =
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type OrderDeliverySectionLabels,
|
|
5
5
|
defaultOrderDeliveryLabels,
|
|
6
6
|
} from 'src/components/account/orders/OrderDetails/orderDetailsLabels'
|
|
7
|
+
import { getDeliveryOptionKey } from 'src/components/account/orders/OrderDetails/getDeliveryOptionLabel'
|
|
7
8
|
import type {
|
|
8
9
|
UserOrderDeliveryOption,
|
|
9
10
|
UserOrderDeliveryOptionsData,
|
|
@@ -35,10 +36,11 @@ const AccountOrderDelivery = (props: AccountOrderDeliveryProps) => {
|
|
|
35
36
|
?.fields || []
|
|
36
37
|
}
|
|
37
38
|
title={labels.deliveryTitle}
|
|
39
|
+
labels={labels}
|
|
38
40
|
/>
|
|
39
41
|
{order.deliveryOptionsData.deliveryOptions.map((option) => (
|
|
40
42
|
<DeliveryOptionAccordion
|
|
41
|
-
key={option
|
|
43
|
+
key={getDeliveryOptionKey(option)}
|
|
42
44
|
deliveryOption={option as UserOrderDeliveryOption}
|
|
43
45
|
contact={order.deliveryOptionsData.contact}
|
|
44
46
|
currencyCode={order.storePreferencesData.currencyCode}
|
|
@@ -22,6 +22,14 @@ const AccountOrderDetails = ({
|
|
|
22
22
|
cancelErrorToast = defaultOrderDetailsHeaderLabels.cancelErrorToast,
|
|
23
23
|
approveLabel = defaultOrderDetailsHeaderLabels.approveLabel,
|
|
24
24
|
rejectLabel = defaultOrderDetailsHeaderLabels.rejectLabel,
|
|
25
|
+
rejectModalTitle = defaultOrderDetailsHeaderLabels.rejectModalTitle,
|
|
26
|
+
rejectModalMessage = defaultOrderDetailsHeaderLabels.rejectModalMessage,
|
|
27
|
+
rejectModalConfirmText = defaultOrderDetailsHeaderLabels.rejectModalConfirmText,
|
|
28
|
+
approveSuccessToast = defaultOrderDetailsHeaderLabels.approveSuccessToast,
|
|
29
|
+
approveErrorToast = defaultOrderDetailsHeaderLabels.approveErrorToast,
|
|
30
|
+
rejectSuccessToast = defaultOrderDetailsHeaderLabels.rejectSuccessToast,
|
|
31
|
+
rejectErrorToast = defaultOrderDetailsHeaderLabels.rejectErrorToast,
|
|
32
|
+
pendingFurtherApprovalsAlert = defaultOrderDetailsHeaderLabels.pendingFurtherApprovalsAlert,
|
|
25
33
|
}: AccountOrderDetailsProps) => {
|
|
26
34
|
const { order, orderStatusLabels } =
|
|
27
35
|
useAccountPageData<AccountOrderDetailsPageData>()
|
|
@@ -46,6 +54,14 @@ const AccountOrderDetails = ({
|
|
|
46
54
|
cancelErrorToast,
|
|
47
55
|
approveLabel,
|
|
48
56
|
rejectLabel,
|
|
57
|
+
rejectModalTitle,
|
|
58
|
+
rejectModalMessage,
|
|
59
|
+
rejectModalConfirmText,
|
|
60
|
+
approveSuccessToast,
|
|
61
|
+
approveErrorToast,
|
|
62
|
+
rejectSuccessToast,
|
|
63
|
+
rejectErrorToast,
|
|
64
|
+
pendingFurtherApprovalsAlert,
|
|
49
65
|
}}
|
|
50
66
|
/>
|
|
51
67
|
</Section>
|