@akinon/pz-theme 2.0.157-rc.12 → 2.0.157
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 +3 -38
- package/package.json +4 -4
- package/src/__tests__/editor-locale-bridge.test.tsx +1 -32
- package/src/blocks/__tests__/text-block.test.tsx +6 -34
- package/src/blocks/item-template.tsx +19 -25
- package/src/blocks/order-detail-block.tsx +96 -116
- package/src/blocks/order-list-block.tsx +2 -25
- package/src/blocks/text-block.tsx +2 -6
- package/src/chrome/__tests__/page-context-builders.test.ts +1 -14
- package/src/chrome/page-context.ts +0 -4
- package/src/custom/README.md +219 -120
- package/src/custom/__tests__/use-theme-setting.test.tsx +0 -97
- package/src/custom/collect.ts +9 -4
- package/src/custom/property-types.ts +15 -15
- package/src/custom/use-theme-setting.ts +5 -21
- package/src/editor-locale-bridge.tsx +11 -39
- package/src/theme-placeholder-wrapper.tsx +0 -3
- package/src/__tests__/row-scope.test.tsx +0 -118
- package/src/blocks/__tests__/order-line-actions.test.tsx +0 -54
- package/src/blocks/__tests__/order-list-rows.test.tsx +0 -112
- package/src/blocks/order-line-actions.ts +0 -45
- package/src/blocks/row-scope.tsx +0 -35
- package/src/utils/__tests__/sanitize-rich-text.test.ts +0 -80
- package/src/utils/sanitize-rich-text.ts +0 -215
package/CHANGELOG.md
CHANGED
|
@@ -1,47 +1,12 @@
|
|
|
1
1
|
# @akinon/pz-theme
|
|
2
2
|
|
|
3
|
-
## 2.0.157
|
|
3
|
+
## 2.0.157
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
-
- 8e040731: ZERO-5235: let brands hang actions on order detail lines
|
|
8
|
-
- c761b9fd: ZERO-5296: fall back to the storefront default language in the text block
|
|
9
|
-
- 17a598da: ZERO-5296: report the storefront default language to the editor
|
|
10
|
-
- 3b05a407: ZERO-5232: allow richtext settings on custom blocks
|
|
11
|
-
- ad5240c4: ZERO-5254: add custom render and theme editor support to pz-rate-review
|
|
12
7
|
- Updated dependencies [219164a3]
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Updated dependencies [97d29893]
|
|
16
|
-
- Updated dependencies [324f97d55]
|
|
17
|
-
- Updated dependencies [51ea06888]
|
|
18
|
-
- Updated dependencies
|
|
19
|
-
- Updated dependencies [2fea41430]
|
|
20
|
-
- Updated dependencies [b55acb768]
|
|
21
|
-
- Updated dependencies [760258c1c]
|
|
22
|
-
- Updated dependencies [143be2b9d]
|
|
23
|
-
- Updated dependencies [7889b08fe]
|
|
24
|
-
- Updated dependencies [9f8cd3bc5]
|
|
25
|
-
- Updated dependencies [bfafa3f49]
|
|
26
|
-
- Updated dependencies [57d7eb305]
|
|
27
|
-
- Updated dependencies [d99a6a7d5]
|
|
28
|
-
- Updated dependencies [9db81a714]
|
|
29
|
-
- Updated dependencies [591e345e1]
|
|
30
|
-
- Updated dependencies [4de5303c5]
|
|
31
|
-
- Updated dependencies [95b139dc1]
|
|
32
|
-
- Updated dependencies [1d00f2d06]
|
|
33
|
-
- Updated dependencies [4ac7b2a1e]
|
|
34
|
-
- Updated dependencies [4998a9631]
|
|
35
|
-
- Updated dependencies [804d2bd6c]
|
|
36
|
-
- Updated dependencies [3909d3224]
|
|
37
|
-
- Updated dependencies [6a3d8a631]
|
|
38
|
-
- Updated dependencies [e18836b20]
|
|
39
|
-
- Updated dependencies [b1111d7b1]
|
|
40
|
-
- Updated dependencies [1595d458e]
|
|
41
|
-
- Updated dependencies [dca128112]
|
|
42
|
-
- Updated dependencies [9c778307]
|
|
43
|
-
- @akinon/next@2.0.157-rc.12
|
|
44
|
-
- @akinon/theme-contract@2.0.157-rc.12
|
|
8
|
+
- @akinon/next@2.0.157
|
|
9
|
+
- @akinon/theme-contract@2.0.157
|
|
45
10
|
|
|
46
11
|
## 2.0.156
|
|
47
12
|
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-theme",
|
|
3
3
|
"description": "Theme package for Project Zero Next — ThemePlaceholder system and theme editor infrastructure",
|
|
4
|
-
"version": "2.0.157
|
|
4
|
+
"version": "2.0.157",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "jest"
|
|
9
9
|
},
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@akinon/next": "2.0.157
|
|
11
|
+
"@akinon/next": "2.0.157",
|
|
12
12
|
"react": "^18.0.0 || ^19.0.0",
|
|
13
13
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@akinon/theme-contract": "2.0.157
|
|
16
|
+
"@akinon/theme-contract": "2.0.157",
|
|
17
17
|
"clsx": "2.1.1",
|
|
18
18
|
"lottie-web": "^5.13.0",
|
|
19
19
|
"react-multi-carousel": "2.8.4",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"zod": "4.4.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@akinon/next": "2.0.157
|
|
24
|
+
"@akinon/next": "2.0.157",
|
|
25
25
|
"@testing-library/jest-dom": "5.16.4",
|
|
26
26
|
"@testing-library/react": "16.3.2",
|
|
27
27
|
"@testing-library/user-event": "14.1.1",
|
|
@@ -28,7 +28,6 @@ const SETTINGS_LOCALES = [
|
|
|
28
28
|
const mockLocalization = {
|
|
29
29
|
locale: 'tr',
|
|
30
30
|
locales: SETTINGS_LOCALES as Array<Record<string, unknown>>,
|
|
31
|
-
defaultLocaleValue: 'tr',
|
|
32
31
|
setLocale: jest.fn()
|
|
33
32
|
};
|
|
34
33
|
|
|
@@ -107,7 +106,6 @@ beforeEach(() => {
|
|
|
107
106
|
postMessage.mockClear();
|
|
108
107
|
mockLocalization.locale = 'tr';
|
|
109
108
|
mockLocalization.locales = SETTINGS_LOCALES;
|
|
110
|
-
mockLocalization.defaultLocaleValue = 'tr';
|
|
111
109
|
mockLocalization.setLocale = jest.fn();
|
|
112
110
|
delete (window as { __iframeReadySent?: boolean }).__iframeReadySent;
|
|
113
111
|
});
|
|
@@ -146,8 +144,7 @@ describe('inside the editor', () => {
|
|
|
146
144
|
{ value: 'en', label: 'English' },
|
|
147
145
|
{ value: 'tr', label: 'Türkçe' },
|
|
148
146
|
{ value: 'de', label: 'de' }
|
|
149
|
-
]
|
|
150
|
-
defaultLocale: 'tr'
|
|
147
|
+
]
|
|
151
148
|
}
|
|
152
149
|
})
|
|
153
150
|
]);
|
|
@@ -157,34 +154,6 @@ describe('inside the editor', () => {
|
|
|
157
154
|
expect(targetOrigin).toBe(EDITOR_ORIGIN);
|
|
158
155
|
});
|
|
159
156
|
|
|
160
|
-
it('posts the languages before the document reports ready', () => {
|
|
161
|
-
// The editor holds every per-language write until IFRAME_READY and takes
|
|
162
|
-
// "ready without languages" to mean they are never coming, so the order
|
|
163
|
-
// of the two frames is part of the contract.
|
|
164
|
-
render(placeholder('header'));
|
|
165
|
-
|
|
166
|
-
const types = postMessage.mock.calls.map(([message]) => message?.type);
|
|
167
|
-
expect(types).toContain('LOCALE_UPDATE');
|
|
168
|
-
expect(types).toContain('IFRAME_READY');
|
|
169
|
-
expect(types.indexOf('LOCALE_UPDATE')).toBeLessThan(
|
|
170
|
-
types.indexOf('IFRAME_READY')
|
|
171
|
-
);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("posts the brand's default language, whichever it is", () => {
|
|
175
|
-
// The editor's per-language text controls take the plain-string form to
|
|
176
|
-
// mean this language; left to guess, the editor assumed English.
|
|
177
|
-
mockLocalization.defaultLocaleValue = 'de';
|
|
178
|
-
|
|
179
|
-
render(<EditorLocaleBridge />);
|
|
180
|
-
|
|
181
|
-
expect(localeFrames()).toEqual([
|
|
182
|
-
expect.objectContaining({
|
|
183
|
-
data: expect.objectContaining({ locale: 'tr', defaultLocale: 'de' })
|
|
184
|
-
})
|
|
185
|
-
]);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
157
|
it("follows the editor's switch exactly once, with several placeholders mounted", () => {
|
|
189
158
|
render(
|
|
190
159
|
<>
|
|
@@ -2,31 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
3
|
import TextBlock from '../text-block';
|
|
4
4
|
|
|
5
|
-
// The
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
const mockLocalization = { locale: 'en-us', defaultLocaleValue: 'en-us' };
|
|
9
|
-
|
|
10
|
-
jest.mock('@akinon/next/hooks', () => ({
|
|
11
|
-
__esModule: true,
|
|
12
|
-
useLocalization: () => ({
|
|
13
|
-
t: (path: string) => path,
|
|
14
|
-
setLocale: () => {},
|
|
15
|
-
setCurrency: () => {},
|
|
16
|
-
locale: mockLocalization.locale,
|
|
17
|
-
currency: 'USD',
|
|
18
|
-
locales: [{ value: 'en-us' }, { value: 'tr-tr' }],
|
|
19
|
-
currencies: ['USD'],
|
|
20
|
-
defaultLocaleValue: mockLocalization.defaultLocaleValue,
|
|
21
|
-
defaultCurrencyCode: 'USD',
|
|
22
|
-
localeUrlStrategy: 'hide-default-locale'
|
|
23
|
-
})
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
mockLocalization.locale = 'en-us';
|
|
28
|
-
mockLocalization.defaultLocaleValue = 'en-us';
|
|
29
|
-
});
|
|
5
|
+
// The mocked useLocalization (jest/__mocks__/akinon-next-hooks.js) returns
|
|
6
|
+
// locale: 'en-us'. process.env.NEXT_PUBLIC_DEFAULT_LOCALE is unset in the
|
|
7
|
+
// jest env, so the component's defaultLocale falls back to 'en'.
|
|
30
8
|
|
|
31
9
|
const renderBlock = (value: unknown, styles?: Record<string, unknown>) => {
|
|
32
10
|
const block: any = { id: 'b1', type: 'text', value, styles };
|
|
@@ -56,16 +34,10 @@ describe('TextBlock value-shape resolution', () => {
|
|
|
56
34
|
);
|
|
57
35
|
});
|
|
58
36
|
|
|
59
|
-
it(
|
|
60
|
-
|
|
61
|
-
// the block used to show: its default was read from an env variable
|
|
62
|
-
// that falls back to English, not from the storefront (ZERO-5296).
|
|
63
|
-
mockLocalization.locale = 'de-de';
|
|
64
|
-
mockLocalization.defaultLocaleValue = 'tr-tr';
|
|
65
|
-
|
|
66
|
-
const { container } = renderBlock({ en: 'EN', 'tr-tr': 'TR' });
|
|
37
|
+
it('falls back to defaultLocale ("en") when active locale is absent', () => {
|
|
38
|
+
const { container } = renderBlock({ en: 'EN', fr: 'FR' });
|
|
67
39
|
expect((container.querySelector('div') as HTMLDivElement).innerHTML).toBe(
|
|
68
|
-
'
|
|
40
|
+
'EN'
|
|
69
41
|
);
|
|
70
42
|
});
|
|
71
43
|
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
resolveItemProduct
|
|
16
16
|
} from './item-template-utils';
|
|
17
17
|
import { ThemeItemScopeProvider } from './product-block-utils';
|
|
18
|
-
import { ThemeRowScopeProvider } from './row-scope';
|
|
19
18
|
|
|
20
19
|
export {
|
|
21
20
|
findItemTemplate,
|
|
@@ -121,15 +120,20 @@ export const ItemTemplateList = ({
|
|
|
121
120
|
const scopesProducts = publishesProductItems(block.type);
|
|
122
121
|
// The same slice the iterator applied, so clone N is handed the row it
|
|
123
122
|
// was built from rather than row N.
|
|
124
|
-
const
|
|
123
|
+
const scopedRows = scopesProducts
|
|
124
|
+
? sliceIteratorItems(block, rows).items
|
|
125
|
+
: rows;
|
|
125
126
|
|
|
126
127
|
return (
|
|
127
128
|
<>
|
|
128
129
|
{clones.map((clone, index) => {
|
|
129
130
|
const key = clone.id || `${template.id}-item-${index}`;
|
|
130
|
-
const rowData = slicedRows[index] ?? {};
|
|
131
131
|
const row = (
|
|
132
132
|
<ThemeBlock
|
|
133
|
+
// Keyed here so the non-scoped branch is the element it always
|
|
134
|
+
// was: wrapping it in anything, even a fragment, would change the
|
|
135
|
+
// element type at this position and remount every existing row.
|
|
136
|
+
key={key}
|
|
133
137
|
block={clone}
|
|
134
138
|
placeholderId={placeholderId}
|
|
135
139
|
sectionId={sectionId}
|
|
@@ -139,32 +143,22 @@ export const ItemTemplateList = ({
|
|
|
139
143
|
currentBreakpoint={currentBreakpoint}
|
|
140
144
|
/>
|
|
141
145
|
);
|
|
142
|
-
const scoped = scopesProducts
|
|
143
|
-
? resolveItemProduct(block.type, rowData)
|
|
144
|
-
: null;
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
if (!scopesProducts) return row;
|
|
148
|
+
|
|
149
|
+
const scoped = resolveItemProduct(block.type, scopedRows[index]);
|
|
150
|
+
|
|
151
|
+
// Context only — the provider renders no element, so the markup a
|
|
152
|
+
// published row produces is unchanged.
|
|
149
153
|
return (
|
|
150
|
-
<
|
|
154
|
+
<ThemeItemScopeProvider
|
|
151
155
|
key={key}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
product={
|
|
157
|
+
scoped ?? (isDesigner ? DESIGNER_SAMPLE_PRODUCT : null)
|
|
158
|
+
}
|
|
155
159
|
>
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
product={
|
|
159
|
-
scoped ?? (isDesigner ? DESIGNER_SAMPLE_PRODUCT : null)
|
|
160
|
-
}
|
|
161
|
-
>
|
|
162
|
-
{row}
|
|
163
|
-
</ThemeItemScopeProvider>
|
|
164
|
-
) : (
|
|
165
|
-
row
|
|
166
|
-
)}
|
|
167
|
-
</ThemeRowScopeProvider>
|
|
160
|
+
{row}
|
|
161
|
+
</ThemeItemScopeProvider>
|
|
168
162
|
);
|
|
169
163
|
})}
|
|
170
164
|
</>
|
|
@@ -9,7 +9,6 @@ import { getResponsiveValue, partAttrs } from '../utils';
|
|
|
9
9
|
import { formatDate, formatMoney } from './commerce-format';
|
|
10
10
|
import { readMoneyStyle } from './money-style';
|
|
11
11
|
import { hasItemTemplate, ItemTemplateList } from './item-template';
|
|
12
|
-
import { renderOrderLineActions } from './order-line-actions';
|
|
13
12
|
import { BlockRendererProps } from './block-renderer-registry';
|
|
14
13
|
import {
|
|
15
14
|
DesignerPlaceholder,
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
readToggle
|
|
18
17
|
} from './product-block-utils';
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
interface OrderItemLike {
|
|
21
20
|
id?: number;
|
|
22
21
|
price?: string;
|
|
23
22
|
quantity?: string | number;
|
|
@@ -36,7 +35,7 @@ type OrderItemLike = {
|
|
|
36
35
|
absolute_url?: string;
|
|
37
36
|
attributes?: Record<string, unknown>;
|
|
38
37
|
} | null;
|
|
39
|
-
}
|
|
38
|
+
}
|
|
40
39
|
|
|
41
40
|
interface AddressLike {
|
|
42
41
|
first_name?: string;
|
|
@@ -373,9 +372,7 @@ const formatAddress = (address: AddressLike | null | undefined): string[] => {
|
|
|
373
372
|
* order key is read from the URL; the editor owns which sections are exposed,
|
|
374
373
|
* every caption and the styling.
|
|
375
374
|
* A designer can mark one child as the row layout for the order lines; without
|
|
376
|
-
* one the built-in line renders.
|
|
377
|
-
* built-in line through `registerOrderLineActions`; they render inside the
|
|
378
|
-
* line's `item-actions` part.
|
|
375
|
+
* one the built-in line renders.
|
|
379
376
|
* Properties: numberLabel, numberTag, dateLabel, headerTotalLabel,
|
|
380
377
|
* showInvoiceLink, invoiceLinkLabel, showCancelLink, cancelLinkLabel,
|
|
381
378
|
* showReturnLink, returnLinkLabel, cancelHrefBase, showShipmentStatus, showItems, showImage, imageWidth,
|
|
@@ -393,7 +390,7 @@ const formatAddress = (address: AddressLike | null | undefined): string[] => {
|
|
|
393
390
|
* currencyText, currencyPosition.
|
|
394
391
|
* Parts: detail, header, number, date, header-total, status,
|
|
395
392
|
* invoice-link, cancel-link, return-link, list, item, image, name, quantity,
|
|
396
|
-
* color, size, item-status, item-tracking, item-return-code,
|
|
393
|
+
* color, size, item-status, item-tracking, item-return-code,
|
|
397
394
|
* item-return-method, item-return-carrier, item-pickup-date, price, shipment,
|
|
398
395
|
* delivery, tracking, addresses, address, address-label, totals, total-row,
|
|
399
396
|
* total-label, total-value, grand-total, payment-info, payment-info-label.
|
|
@@ -933,21 +930,6 @@ const OrderDetailBlock = ({
|
|
|
933
930
|
showPickupDate && returnDetails.pickupDate
|
|
934
931
|
? formatPickupDate(returnDetails.pickupDate, locale)
|
|
935
932
|
: '';
|
|
936
|
-
const lineActions = renderOrderLineActions({
|
|
937
|
-
order,
|
|
938
|
-
line,
|
|
939
|
-
isDesigner
|
|
940
|
-
});
|
|
941
|
-
const showLineMeta =
|
|
942
|
-
showShipmentStatus &&
|
|
943
|
-
Boolean(
|
|
944
|
-
item.status?.label ||
|
|
945
|
-
trackingValue ||
|
|
946
|
-
returnCodeValue ||
|
|
947
|
-
returnMethodValue ||
|
|
948
|
-
returnCarrierValue ||
|
|
949
|
-
pickupDateValue
|
|
950
|
-
);
|
|
951
933
|
|
|
952
934
|
return (
|
|
953
935
|
<li
|
|
@@ -1063,100 +1045,98 @@ const OrderDetailBlock = ({
|
|
|
1063
1045
|
</div>
|
|
1064
1046
|
</div>
|
|
1065
1047
|
|
|
1066
|
-
{
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
</div>
|
|
1159
|
-
)}
|
|
1048
|
+
{showShipmentStatus &&
|
|
1049
|
+
(item.status?.label ||
|
|
1050
|
+
trackingValue ||
|
|
1051
|
+
returnCodeValue ||
|
|
1052
|
+
returnMethodValue ||
|
|
1053
|
+
returnCarrierValue ||
|
|
1054
|
+
pickupDateValue) && (
|
|
1055
|
+
<div
|
|
1056
|
+
style={{
|
|
1057
|
+
display: 'flex',
|
|
1058
|
+
flexDirection: 'column',
|
|
1059
|
+
alignItems: isMobile ? 'flex-start' : 'flex-end',
|
|
1060
|
+
textAlign: isMobile ? 'left' : 'right',
|
|
1061
|
+
gap: '4px',
|
|
1062
|
+
flex: isMobile ? '1 1 100%' : '0 0 auto'
|
|
1063
|
+
}}
|
|
1064
|
+
>
|
|
1065
|
+
{item.status?.label && (
|
|
1066
|
+
<span
|
|
1067
|
+
data-order-detail-item-status=""
|
|
1068
|
+
data-order-status-value={item.status.value}
|
|
1069
|
+
{...partAttrs('item-status')}
|
|
1070
|
+
style={{ display: 'inline-block' }}
|
|
1071
|
+
>
|
|
1072
|
+
{item.status.label}
|
|
1073
|
+
</span>
|
|
1074
|
+
)}
|
|
1075
|
+
{/* Label and value in their own spans, so a
|
|
1076
|
+
composition can colour them apart. */}
|
|
1077
|
+
{returnMethodValue && (
|
|
1078
|
+
<span
|
|
1079
|
+
data-order-detail-item-return-method=""
|
|
1080
|
+
{...partAttrs('item-return-method')}
|
|
1081
|
+
style={{ opacity: 0.8 }}
|
|
1082
|
+
>
|
|
1083
|
+
<span data-label="">{returnMethodLabel}</span>{' '}
|
|
1084
|
+
<span data-value="">{returnMethodValue}</span>
|
|
1085
|
+
</span>
|
|
1086
|
+
)}
|
|
1087
|
+
{returnCarrierValue && (
|
|
1088
|
+
<span
|
|
1089
|
+
data-order-detail-item-return-carrier=""
|
|
1090
|
+
{...partAttrs('item-return-carrier')}
|
|
1091
|
+
style={{ opacity: 0.8 }}
|
|
1092
|
+
>
|
|
1093
|
+
<span data-label="">{returnCarrierLabel}</span>{' '}
|
|
1094
|
+
<span data-value="">{returnCarrierValue}</span>
|
|
1095
|
+
</span>
|
|
1096
|
+
)}
|
|
1097
|
+
{pickupDateValue && (
|
|
1098
|
+
<span
|
|
1099
|
+
data-order-detail-item-pickup-date=""
|
|
1100
|
+
{...partAttrs('item-pickup-date')}
|
|
1101
|
+
style={{ opacity: 0.8 }}
|
|
1102
|
+
>
|
|
1103
|
+
<span data-label="">{pickupDateLabel}</span>{' '}
|
|
1104
|
+
<span data-value="">{pickupDateValue}</span>
|
|
1105
|
+
</span>
|
|
1106
|
+
)}
|
|
1107
|
+
{trackingValue && (
|
|
1108
|
+
<span
|
|
1109
|
+
data-order-detail-item-tracking=""
|
|
1110
|
+
{...partAttrs('item-tracking')}
|
|
1111
|
+
style={{ opacity: 0.8 }}
|
|
1112
|
+
>
|
|
1113
|
+
{lineTrackingLabel}{' '}
|
|
1114
|
+
{item.tracking_url ? (
|
|
1115
|
+
<a
|
|
1116
|
+
href={isDesigner ? '#' : item.tracking_url}
|
|
1117
|
+
onClick={guard}
|
|
1118
|
+
target={isDesigner ? undefined : '_blank'}
|
|
1119
|
+
rel="noreferrer"
|
|
1120
|
+
style={{ color: 'inherit' }}
|
|
1121
|
+
>
|
|
1122
|
+
{item.tracking_number || item.tracking_url}
|
|
1123
|
+
</a>
|
|
1124
|
+
) : (
|
|
1125
|
+
trackingValue
|
|
1126
|
+
)}
|
|
1127
|
+
</span>
|
|
1128
|
+
)}
|
|
1129
|
+
{returnCodeValue && (
|
|
1130
|
+
<span
|
|
1131
|
+
data-order-detail-item-return-code=""
|
|
1132
|
+
{...partAttrs('item-return-code')}
|
|
1133
|
+
style={{ opacity: 0.8 }}
|
|
1134
|
+
>
|
|
1135
|
+
{returnCodeLabel} {returnCodeValue}
|
|
1136
|
+
</span>
|
|
1137
|
+
)}
|
|
1138
|
+
</div>
|
|
1139
|
+
)}
|
|
1160
1140
|
</div>
|
|
1161
1141
|
</li>
|
|
1162
1142
|
);
|
|
@@ -13,14 +13,7 @@ import { readToggle } from './product-block-utils';
|
|
|
13
13
|
import { BlockRendererProps } from './block-renderer-registry';
|
|
14
14
|
|
|
15
15
|
interface OrderItemLike {
|
|
16
|
-
|
|
17
|
-
status?: { value?: string | number; label?: string };
|
|
18
|
-
product?: {
|
|
19
|
-
image?: string;
|
|
20
|
-
name?: string;
|
|
21
|
-
sku?: string;
|
|
22
|
-
base_code?: string;
|
|
23
|
-
} | null;
|
|
16
|
+
product?: { image?: string; name?: string } | null;
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
interface OrderLike {
|
|
@@ -255,23 +248,7 @@ const OrderListBlock = ({
|
|
|
255
248
|
maxImages
|
|
256
249
|
),
|
|
257
250
|
url: hrefFor(order),
|
|
258
|
-
href: hrefFor(order)
|
|
259
|
-
createdDate: order.created_date || '',
|
|
260
|
-
items: (Array.isArray(order.orderitem_set) ? order.orderitem_set : []).map(
|
|
261
|
-
(item, itemIndex) => ({
|
|
262
|
-
id: item?.id ?? itemIndex,
|
|
263
|
-
name: item?.product?.name || '',
|
|
264
|
-
image: item?.product?.image || '',
|
|
265
|
-
status: item?.status?.label || '',
|
|
266
|
-
statusValue: String(item?.status?.value ?? ''),
|
|
267
|
-
product: {
|
|
268
|
-
sku: item?.product?.sku || '',
|
|
269
|
-
base_code: item?.product?.base_code || '',
|
|
270
|
-
name: item?.product?.name || '',
|
|
271
|
-
image: item?.product?.image || ''
|
|
272
|
-
}
|
|
273
|
-
})
|
|
274
|
-
)
|
|
251
|
+
href: hrefFor(order)
|
|
275
252
|
}));
|
|
276
253
|
|
|
277
254
|
// A designer who marked a child as the row layout gets that layout repeated
|
|
@@ -7,7 +7,6 @@ import { getInnerRootInlineStyles, partAttrs } from '../utils';
|
|
|
7
7
|
import { useThemeSettingsContext } from '../theme-settings-context';
|
|
8
8
|
import { useLocalizeHref } from '../hooks/use-localize-href';
|
|
9
9
|
import { localizeHtmlLinks } from '../utils/localize-href';
|
|
10
|
-
import { useValueLocale } from '../utils/localized-value';
|
|
11
10
|
|
|
12
11
|
const TextBlock = ({
|
|
13
12
|
block,
|
|
@@ -15,7 +14,7 @@ const TextBlock = ({
|
|
|
15
14
|
}: BlockRendererProps) => {
|
|
16
15
|
const { locale } = useLocalization();
|
|
17
16
|
const localize = useLocalizeHref();
|
|
18
|
-
const
|
|
17
|
+
const defaultLocale = process.env.NEXT_PUBLIC_DEFAULT_LOCALE || 'en';
|
|
19
18
|
const themeSettings = useThemeSettingsContext();
|
|
20
19
|
|
|
21
20
|
const getLocalizedContent = (): string => {
|
|
@@ -31,10 +30,7 @@ const TextBlock = ({
|
|
|
31
30
|
|
|
32
31
|
if (typeof value === 'object' && value !== null) {
|
|
33
32
|
return (
|
|
34
|
-
value[locale] ||
|
|
35
|
-
(defaultLocale && value[defaultLocale]) ||
|
|
36
|
-
Object.values(value)[0] ||
|
|
37
|
-
''
|
|
33
|
+
value[locale] || value[defaultLocale] || Object.values(value)[0] || ''
|
|
38
34
|
);
|
|
39
35
|
}
|
|
40
36
|
|
|
@@ -41,7 +41,7 @@ const orderPayload = {
|
|
|
41
41
|
orderitem_set: [
|
|
42
42
|
{
|
|
43
43
|
price: '649.95',
|
|
44
|
-
status: {
|
|
44
|
+
status: { label: 'Shipped' },
|
|
45
45
|
product: {
|
|
46
46
|
name: 'Spring Sneaker',
|
|
47
47
|
image: '/i.jpg',
|
|
@@ -63,19 +63,6 @@ describe('buildOrderPageContext', () => {
|
|
|
63
63
|
expect(context.order.currency).toBe('TRY');
|
|
64
64
|
expect(context.order.items).toHaveLength(1);
|
|
65
65
|
expect(context.order.items[0].title).toBe('Spring Sneaker');
|
|
66
|
-
expect(context.order.items[0].status).toBe('Shipped');
|
|
67
|
-
expect(context.order.items[0].statusValue).toBe('500');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('stringifies a numeric order item status code', () => {
|
|
71
|
-
const context = buildOrderPageContext({
|
|
72
|
-
order: {
|
|
73
|
-
...orderPayload,
|
|
74
|
-
orderitem_set: [{ status: { value: 550, label: 'Delivered' } }]
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
expect(context.order.items[0].statusValue).toBe('550');
|
|
79
66
|
});
|
|
80
67
|
|
|
81
68
|
it('does not publish the identity fields the raw payload carries', () => {
|
|
@@ -59,9 +59,6 @@ const toRecord = (value: unknown): UnknownRecord =>
|
|
|
59
59
|
const toStringValue = (value: unknown, fallback = ''): string =>
|
|
60
60
|
typeof value === 'string' ? value : fallback;
|
|
61
61
|
|
|
62
|
-
const toCodeValue = (value: unknown): string =>
|
|
63
|
-
typeof value === 'number' ? String(value) : toStringValue(value);
|
|
64
|
-
|
|
65
62
|
const humanizeSlug = (value: string) =>
|
|
66
63
|
value
|
|
67
64
|
.split('-')
|
|
@@ -482,7 +479,6 @@ export const buildOrderPageContext = ({
|
|
|
482
479
|
unitPrice: toStringValue(item.price),
|
|
483
480
|
quantity: 1,
|
|
484
481
|
status: toStringValue(toRecord(item.status).label),
|
|
485
|
-
statusValue: toCodeValue(toRecord(item.status).value),
|
|
486
482
|
currency
|
|
487
483
|
};
|
|
488
484
|
});
|