@akinon/projectzero 2.0.0-beta.19 → 2.0.0-beta.20

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.
Files changed (223) hide show
  1. package/CHANGELOG.md +9 -7
  2. package/app-template/CHANGELOG.md +251 -204
  3. package/app-template/akinon.json +1 -1
  4. package/app-template/package.json +28 -28
  5. package/app-template/public/amex.svg +12 -0
  6. package/app-template/public/apple-pay.svg +16 -0
  7. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  8. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  9. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  10. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  11. package/app-template/public/google-pay.svg +16 -0
  12. package/app-template/public/locales/en/account.json +6 -3
  13. package/app-template/public/locales/en/auth.json +6 -7
  14. package/app-template/public/locales/en/basket.json +6 -6
  15. package/app-template/public/locales/en/blog.json +7 -0
  16. package/app-template/public/locales/en/category.json +3 -1
  17. package/app-template/public/locales/en/checkout.json +5 -4
  18. package/app-template/public/locales/en/common.json +11 -2
  19. package/app-template/public/locales/en/forgot_password.json +6 -7
  20. package/app-template/public/locales/en/product.json +4 -3
  21. package/app-template/public/locales/tr/account.json +6 -3
  22. package/app-template/public/locales/tr/auth.json +16 -17
  23. package/app-template/public/locales/tr/basket.json +4 -4
  24. package/app-template/public/locales/tr/blog.json +7 -0
  25. package/app-template/public/locales/tr/category.json +3 -1
  26. package/app-template/public/locales/tr/checkout.json +39 -38
  27. package/app-template/public/locales/tr/common.json +10 -1
  28. package/app-template/public/locales/tr/forgot_password.json +12 -13
  29. package/app-template/public/locales/tr/product.json +1 -0
  30. package/app-template/public/logo.svg +3 -27
  31. package/app-template/public/mastercard.svg +14 -0
  32. package/app-template/public/promotion-banner.jpg +0 -0
  33. package/app-template/public/shop-pay.svg +12 -0
  34. package/app-template/public/visa.svg +12 -0
  35. package/app-template/src/app/[commerce]/[locale]/[currency]/blog/[slug]/page.tsx +118 -0
  36. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +15 -0
  37. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  38. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  39. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  40. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  41. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  42. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  43. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  44. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  45. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  46. package/app-template/src/assets/globals.scss +4 -0
  47. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  48. package/app-template/src/assets/icons/cart.svg +4 -12
  49. package/app-template/src/assets/icons/check.svg +2 -18
  50. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  51. package/app-template/src/assets/icons/delete.svg +3 -0
  52. package/app-template/src/assets/icons/facebook.svg +2 -8
  53. package/app-template/src/assets/icons/fav-off.svg +5 -0
  54. package/app-template/src/assets/icons/fav-on.svg +5 -0
  55. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  56. package/app-template/src/assets/icons/heart.svg +3 -0
  57. package/app-template/src/assets/icons/instagram.svg +2 -13
  58. package/app-template/src/assets/icons/materials.svg +3 -0
  59. package/app-template/src/assets/icons/person.svg +4 -0
  60. package/app-template/src/assets/icons/pinterest.svg +5 -11
  61. package/app-template/src/assets/icons/ruler.svg +3 -0
  62. package/app-template/src/assets/icons/search.svg +8 -11
  63. package/app-template/src/assets/icons/share.svg +2 -9
  64. package/app-template/src/assets/icons/snapchat.svg +3 -0
  65. package/app-template/src/assets/icons/tiktok.svg +3 -0
  66. package/app-template/src/assets/icons/tumblr.svg +6 -0
  67. package/app-template/src/assets/icons/twitter.svg +2 -10
  68. package/app-template/src/assets/icons/vimeo.svg +3 -0
  69. package/app-template/src/assets/icons/youtube.svg +3 -0
  70. package/app-template/src/assets/icons/zoom.svg +8 -0
  71. package/app-template/src/components/accordion.tsx +33 -11
  72. package/app-template/src/components/action-tooltip.tsx +160 -0
  73. package/app-template/src/components/currency-select.tsx +149 -4
  74. package/app-template/src/components/icon.tsx +5 -6
  75. package/app-template/src/components/index.ts +4 -1
  76. package/app-template/src/components/language-select.tsx +88 -2
  77. package/app-template/src/components/pagination.tsx +132 -20
  78. package/app-template/src/components/quantity-input.tsx +63 -0
  79. package/app-template/src/components/quantity-selector.tsx +203 -0
  80. package/app-template/src/components/route-handler.tsx +50 -0
  81. package/app-template/src/components/select.tsx +89 -69
  82. package/app-template/src/components/types/index.ts +26 -0
  83. package/app-template/src/components/widget-content.tsx +323 -0
  84. package/app-template/src/data/server/theme.ts +70 -0
  85. package/app-template/src/hooks/use-fav-button.tsx +5 -2
  86. package/app-template/src/hooks/use-product-cart.ts +11 -8
  87. package/app-template/src/hooks/use-theme-settings.ts +42 -0
  88. package/app-template/src/lib/fonts.ts +149 -0
  89. package/app-template/src/settings.js +2 -2
  90. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  91. package/app-template/src/types/widget.ts +169 -0
  92. package/app-template/src/utils/formatDate.ts +48 -0
  93. package/app-template/src/utils/styles.ts +71 -0
  94. package/app-template/src/views/account/contact-form.tsx +147 -130
  95. package/app-template/src/views/basket/basket-item.tsx +691 -107
  96. package/app-template/src/views/basket/basket-summary-context.tsx +560 -0
  97. package/app-template/src/views/basket/designer-context.tsx +617 -0
  98. package/app-template/src/views/basket/index.ts +2 -0
  99. package/app-template/src/views/basket/summary.tsx +496 -75
  100. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +190 -0
  101. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +286 -0
  102. package/app-template/src/views/breadcrumb/constants.ts +15 -0
  103. package/app-template/src/views/breadcrumb/index.tsx +127 -0
  104. package/app-template/src/views/breadcrumb.tsx +13 -38
  105. package/app-template/src/views/category/category-banner.tsx +4 -23
  106. package/app-template/src/views/category/category-header.tsx +289 -66
  107. package/app-template/src/views/category/category-info.tsx +173 -24
  108. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  109. package/app-template/src/views/category/filters/index.tsx +208 -48
  110. package/app-template/src/views/category/layout.tsx +7 -4
  111. package/app-template/src/views/category/native-widget-context.tsx +257 -0
  112. package/app-template/src/views/category/product-list-registrar.tsx +665 -0
  113. package/app-template/src/views/checkout/auth.tsx +64 -40
  114. package/app-template/src/views/checkout/checkout-address-registrar.tsx +254 -0
  115. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +183 -0
  116. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +259 -0
  117. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +253 -0
  118. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +183 -0
  119. package/app-template/src/views/checkout/constants.ts +5 -0
  120. package/app-template/src/views/checkout/index.tsx +5 -0
  121. package/app-template/src/views/checkout/layout/header.tsx +9 -5
  122. package/app-template/src/views/checkout/steps/payment/index.tsx +5 -2
  123. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +72 -1
  124. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +15 -0
  125. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +18 -0
  126. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +171 -40
  127. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +74 -12
  128. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +128 -45
  129. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +232 -27
  130. package/app-template/src/views/checkout/summary.tsx +303 -29
  131. package/app-template/src/views/footer/footer-app-banner-context.tsx +326 -0
  132. package/app-template/src/views/footer/footer-bottom-context.tsx +215 -0
  133. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +74 -0
  134. package/app-template/src/views/footer/footer-layout-constants.ts +35 -0
  135. package/app-template/src/views/footer/footer-layout-registrar.tsx +342 -0
  136. package/app-template/src/views/footer/footer-layout-switcher.tsx +110 -0
  137. package/app-template/src/views/footer/footer-menu-context.tsx +211 -0
  138. package/app-template/src/views/footer/footer-native-widgets.tsx +60 -0
  139. package/app-template/src/views/footer/footer-social-context.tsx +254 -0
  140. package/app-template/src/views/footer/footer-subscription-context.tsx +210 -0
  141. package/app-template/src/views/footer/footer-utils.ts +43 -0
  142. package/app-template/src/views/footer/footer-value-props-context.tsx +326 -0
  143. package/app-template/src/views/footer/logo-settings.ts +183 -0
  144. package/app-template/src/views/footer/native-widget-config.ts +262 -0
  145. package/app-template/src/views/footer/subscription-settings.ts +122 -0
  146. package/app-template/src/views/footer/use-footer-logo.ts +162 -0
  147. package/app-template/src/views/footer.tsx +415 -13
  148. package/app-template/src/views/guest-login/index.tsx +62 -58
  149. package/app-template/src/views/header/action-menu.tsx +277 -45
  150. package/app-template/src/views/header/band.tsx +6 -21
  151. package/app-template/src/views/header/designer-context.tsx +261 -0
  152. package/app-template/src/views/header/header-announcement-registrar.tsx +267 -0
  153. package/app-template/src/views/header/header-client-wrapper.tsx +496 -0
  154. package/app-template/src/views/header/header-content.tsx +1026 -0
  155. package/app-template/src/views/header/header-currency-registrar.tsx +348 -0
  156. package/app-template/src/views/header/header-icons-context.tsx +262 -0
  157. package/app-template/src/views/header/header-language-registrar.tsx +348 -0
  158. package/app-template/src/views/header/header-layout-context.tsx +143 -0
  159. package/app-template/src/views/header/header-layout-registrar.tsx +658 -0
  160. package/app-template/src/views/header/header-logo-context.tsx +228 -0
  161. package/app-template/src/views/header/header-logo.tsx +118 -0
  162. package/app-template/src/views/header/header-mini-basket-context.tsx +524 -0
  163. package/app-template/src/views/header/header-search-registrar.tsx +511 -0
  164. package/app-template/src/views/header/header-text-slider-registrar.tsx +382 -0
  165. package/app-template/src/views/header/index.tsx +109 -47
  166. package/app-template/src/views/header/inline-search.tsx +262 -0
  167. package/app-template/src/views/header/mini-basket.tsx +819 -44
  168. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  169. package/app-template/src/views/header/mobile-menu.tsx +12 -0
  170. package/app-template/src/views/header/navbar-menu-context.tsx +219 -0
  171. package/app-template/src/views/header/navbar.tsx +178 -111
  172. package/app-template/src/views/header/search/index.tsx +71 -32
  173. package/app-template/src/views/header/search/results.tsx +127 -65
  174. package/app-template/src/views/header/search/search-input.tsx +61 -0
  175. package/app-template/src/views/header/server-settings-parser.ts +1105 -0
  176. package/app-template/src/views/header/use-header-icons.ts +241 -0
  177. package/app-template/src/views/header/use-header-logo.ts +213 -0
  178. package/app-template/src/views/header/use-navbar-menu.ts +179 -0
  179. package/app-template/src/views/login/index.tsx +54 -46
  180. package/app-template/src/views/product/accordion-section.tsx +61 -0
  181. package/app-template/src/views/product/accordion-wrapper.tsx +135 -43
  182. package/app-template/src/views/product/custom-button-group.tsx +69 -0
  183. package/app-template/src/views/product/favorites-button-section.tsx +69 -0
  184. package/app-template/src/views/product/find-in-store-section.tsx +60 -0
  185. package/app-template/src/views/product/index.ts +1 -0
  186. package/app-template/src/views/product/layout.tsx +6 -5
  187. package/app-template/src/views/product/misc-buttons.tsx +339 -25
  188. package/app-template/src/views/product/price-wrapper.tsx +3 -29
  189. package/app-template/src/views/product/product-actions.tsx +137 -8
  190. package/app-template/src/views/product/product-info-section.tsx +140 -0
  191. package/app-template/src/views/product/product-info.tsx +69 -31
  192. package/app-template/src/views/product/product-share.tsx +13 -8
  193. package/app-template/src/views/product/product-variants.tsx +2 -2
  194. package/app-template/src/views/product/quantity-section.tsx +73 -0
  195. package/app-template/src/views/product/sale-tag.tsx +10 -0
  196. package/app-template/src/views/product/share-section.tsx +357 -0
  197. package/app-template/src/views/product/slider.tsx +117 -79
  198. package/app-template/src/views/product/variant.tsx +69 -41
  199. package/app-template/src/views/product/variants-section.tsx +126 -0
  200. package/app-template/src/views/product-detail/constants.ts +272 -0
  201. package/app-template/src/views/product-detail/index.ts +10 -0
  202. package/app-template/src/views/product-detail/product-detail-registrar.tsx +616 -0
  203. package/app-template/src/views/product-item/index.tsx +119 -46
  204. package/app-template/src/views/register/index.tsx +14 -25
  205. package/app-template/src/views/share/index.tsx +9 -6
  206. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  207. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  208. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  209. package/app-template/src/widgets/footer-app-banner.tsx +444 -0
  210. package/app-template/src/widgets/footer-bottom.tsx +127 -0
  211. package/app-template/src/widgets/footer-menu-compact.tsx +238 -0
  212. package/app-template/src/widgets/footer-menu-two.tsx +298 -0
  213. package/app-template/src/widgets/footer-social-client.tsx +251 -0
  214. package/app-template/src/widgets/footer-social.tsx +47 -16
  215. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  216. package/app-template/src/widgets/footer-subscription/index.tsx +183 -17
  217. package/app-template/src/widgets/footer-value-props.tsx +201 -0
  218. package/app-template/src/widgets/index.ts +7 -0
  219. package/app-template/src/widgets/schemas/about-us.json +46 -0
  220. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  221. package/app-template/src/widgets/schemas/blog.json +29 -0
  222. package/app-template/tailwind.config.js +18 -2
  223. package/package.json +1 -1
@@ -11,9 +11,11 @@ import { AddressForm } from '@theme/views/account/address-form';
11
11
  import { useLocalization } from '@akinon/next/hooks';
12
12
  import PluginModule, { Component } from '@akinon/next/components/plugin-module';
13
13
  import { Trans } from '@akinon/next/components/trans';
14
+ import { useCheckoutAddress } from '@theme/views/checkout/checkout-address-registrar';
14
15
 
15
16
  const Addresses = () => {
16
17
  const { t } = useLocalization();
18
+ const { viewType, sectionStyles } = useCheckoutAddress();
17
19
 
18
20
  const [isModalOpen, setIsModalOpen] = useState(false);
19
21
  const addressList = useAppSelector(
@@ -93,6 +95,24 @@ const Addresses = () => {
93
95
  return props.title;
94
96
  };
95
97
 
98
+ const handleAddressSelect = (
99
+ addressPk: string,
100
+ addressType: CheckoutAddressType
101
+ ) => {
102
+ const pk = Number(addressPk);
103
+ if (addressType.requestParam === 'shippingAddressPk') {
104
+ if (isBillingAddressSame) {
105
+ setAddresses({ shippingAddressPk: pk, billingAddressPk: pk });
106
+ } else {
107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
+ setAddresses({ shippingAddressPk: pk } as any);
109
+ }
110
+ } else {
111
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
+ setAddresses({ billingAddressPk: pk } as any);
113
+ }
114
+ };
115
+
96
116
  return (
97
117
  <div className="w-full lg:w-3/5 lg:border-r lg:border-gray-400">
98
118
  {addressTypes
@@ -128,57 +148,120 @@ const Addresses = () => {
128
148
  }}
129
149
  />
130
150
  </p>
131
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
132
- {addressList.map((address) => (
133
- <AddressBox
134
- key={address.pk}
135
- addressType={addressType}
136
- address={address}
137
- isBillingAddressSame={isBillingAddressSame}
138
- data-testid={`checkout-address-${address.pk}`}
139
- disabled={
140
- delivery_option?.delivery_option_type ===
141
- 'retail_store' &&
142
- addressType.requestParam === 'shippingAddressPk'
143
- }
144
- />
145
- ))}
146
151
 
147
- <PluginModule
148
- component={Component.ClickCollect}
149
- props={{ addressTypeParam: addressType.requestParam }}
150
- />
151
-
152
- <div
153
- role="button"
154
- onClick={() => setIsModalOpen(true)}
155
- className={clsx(
156
- 'relative cursor-pointer w-full min-h-[8rem] border shadow p-4',
157
- "hover:after:content-[''] hover:after:border-4 hover:after:opacity-30 hover:after:transition-opacity",
158
- 'after:border-secondary-400 after:absolute after:inset-0 after:opacity-0 after:duration-150 after:-z-10',
159
- {
160
- 'opacity-30 select-none pointer-events-none':
161
- delivery_option?.delivery_option_type === 'retail_store'
162
- }
152
+ {viewType === 'dropdown' ? (
153
+ <div className="space-y-4">
154
+ <div className="w-full">
155
+ <select
156
+ className="w-full p-2 border border-gray-300 rounded-md"
157
+ value={addressType.value || ''}
158
+ onChange={(e) =>
159
+ handleAddressSelect(e.target.value, addressType)
160
+ }
161
+ disabled={
162
+ delivery_option?.delivery_option_type ===
163
+ 'retail_store' &&
164
+ addressType.requestParam === 'shippingAddressPk'
165
+ }
166
+ >
167
+ <option value="" disabled>
168
+ {t('checkout.address.select_label') || 'Select Address'}
169
+ </option>
170
+ {addressList.map((address) => (
171
+ <option key={address.pk} value={address.pk}>
172
+ {address.title} - {address.first_name}{' '}
173
+ {address.last_name}
174
+ </option>
175
+ ))}
176
+ </select>
177
+ </div>
178
+ {addressList.find((a) => a.pk === addressType.value) && (
179
+ <div className="p-4 bg-gray-50 rounded-md text-sm text-gray-600">
180
+ {(() => {
181
+ const addr = addressList.find(
182
+ (a) => a.pk === addressType.value
183
+ );
184
+ return addr ? (
185
+ <>
186
+ <p className="font-semibold">{addr.title}</p>
187
+ <p>{addr.line}</p>
188
+ <p>
189
+ {addr.township?.name} / {addr.city?.name}
190
+ </p>
191
+ </>
192
+ ) : null;
193
+ })()}
194
+ </div>
163
195
  )}
164
- >
165
- <div className="text-xs flex justify-center items-center h-full gap-x-2">
166
- <Icon name="plus" size={12} />
167
- <span data-testid="checkout-add-new-address">
196
+ <div className="mt-4">
197
+ <button
198
+ onClick={() => setIsModalOpen(true)}
199
+ className="text-primary-500 underline text-sm flex items-center gap-1"
200
+ >
201
+ <Icon name="plus" size={12} />
168
202
  {t('checkout.address.add_new_address')}
169
- </span>
203
+ </button>
170
204
  </div>
171
205
  </div>
172
- <Modal
173
- portalId="orders-checkout-new-address-modal"
174
- title={t('checkout.address.add_new_address')}
175
- open={isModalOpen}
176
- setOpen={setIsModalOpen}
177
- className="w-full sm:w-[28rem] max-h-[90vh] overflow-y-auto"
206
+ ) : (
207
+ <div
208
+ className="grid grid-cols-1 md:grid-cols-2"
209
+ style={{
210
+ gap: sectionStyles['box-gap'] || '12px'
211
+ }}
178
212
  >
179
- <AddressForm onSubmit={onSubmit} />
180
- </Modal>
181
- </div>
213
+ {addressList.map((address) => (
214
+ <AddressBox
215
+ key={address.pk}
216
+ addressType={addressType}
217
+ address={address}
218
+ isBillingAddressSame={isBillingAddressSame}
219
+ data-testid={`checkout-address-${address.pk}`}
220
+ disabled={
221
+ delivery_option?.delivery_option_type ===
222
+ 'retail_store' &&
223
+ addressType.requestParam === 'shippingAddressPk'
224
+ }
225
+ />
226
+ ))}
227
+
228
+ <PluginModule
229
+ component={Component.ClickCollect}
230
+ props={{ addressTypeParam: addressType.requestParam }}
231
+ />
232
+
233
+ <div
234
+ role="button"
235
+ onClick={() => setIsModalOpen(true)}
236
+ className={clsx(
237
+ 'relative cursor-pointer w-full min-h-[8rem] border shadow p-4',
238
+ "hover:after:content-[''] hover:after:border-4 hover:after:opacity-30 hover:after:transition-opacity",
239
+ 'after:border-secondary-400 after:absolute after:inset-0 after:opacity-0 after:duration-150 after:-z-10',
240
+ {
241
+ 'opacity-30 select-none pointer-events-none':
242
+ delivery_option?.delivery_option_type ===
243
+ 'retail_store'
244
+ }
245
+ )}
246
+ >
247
+ <div className="text-xs flex justify-center items-center h-full gap-x-2">
248
+ <Icon name="plus" size={12} />
249
+ <span data-testid="checkout-add-new-address">
250
+ {t('checkout.address.add_new_address')}
251
+ </span>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ )}
256
+ <Modal
257
+ portalId="orders-checkout-new-address-modal"
258
+ title={t('checkout.address.add_new_address')}
259
+ open={isModalOpen}
260
+ setOpen={setIsModalOpen}
261
+ className="w-full sm:w-[28rem] max-h-[90vh] overflow-y-auto"
262
+ >
263
+ <AddressForm onSubmit={onSubmit} />
264
+ </Modal>
182
265
  </div>
183
266
  </div>
184
267
  ))}
@@ -13,10 +13,39 @@ import {
13
13
  import { Price, Button, Radio } from '@theme/components';
14
14
  import { CheckoutStep } from '@akinon/next/types';
15
15
  import { useLocalization } from '@akinon/next/hooks';
16
+ import { useCheckoutDeliveryMethod } from '@theme/views/checkout/checkout-delivery-method-registrar';
17
+ import { useCheckoutButtons } from '@theme/views/checkout/checkout-buttons-registrar';
16
18
 
17
19
  const ShippingOptions: React.FC = () => {
18
20
  const { t } = useLocalization();
19
21
  const dispatch = useAppDispatch();
22
+ const { viewType, sectionStyles } = useCheckoutDeliveryMethod();
23
+ const { sectionStyles: buttonStyles } = useCheckoutButtons();
24
+
25
+ // Helper to get style value (already includes unit if needed)
26
+ const getStyleValue = (
27
+ key: string,
28
+ fallback: string | number = ''
29
+ ): string | number => {
30
+ const value = sectionStyles[key];
31
+ if (value === undefined || value === null || value === '') {
32
+ return fallback;
33
+ }
34
+ return value;
35
+ };
36
+
37
+ // Helper to get button style value
38
+ const getButtonStyle = (
39
+ key: string,
40
+ fallback: string | number = ''
41
+ ): string | number => {
42
+ const value = buttonStyles[key];
43
+ if (value === undefined || value === null || value === '') {
44
+ return fallback;
45
+ }
46
+ return value;
47
+ };
48
+
20
49
  const {
21
50
  steps,
22
51
  shippingOptions,
@@ -172,33 +201,144 @@ const ShippingOptions: React.FC = () => {
172
201
  {t('checkout.address.shipping.chosen_address')}:{' '}
173
202
  {shipping_address?.city.name}
174
203
  </p>
175
- {shippingOptions && shippingOptions.length > 0 && (
176
- <>
177
- {shippingOptions.map((option) => (
178
- <div
179
- key={option.pk}
180
- className="py-4 border-t border-gray-400 flex justify-between"
204
+
205
+ {/* Dropdown View */}
206
+ {viewType === 'dropdown' &&
207
+ shippingOptions &&
208
+ shippingOptions.length > 0 && (
209
+ <div className="mb-4">
210
+ <select
211
+ className="w-full transition-all duration-200"
212
+ style={{
213
+ borderColor: getStyleValue(
214
+ 'dropdown-border-color',
215
+ '#e5e7eb'
216
+ ) as string,
217
+ borderWidth: getStyleValue('dropdown-border-width', '1px'),
218
+ borderStyle: 'solid',
219
+ borderRadius: getStyleValue(
220
+ 'dropdown-border-radius',
221
+ '6px'
222
+ ),
223
+ backgroundColor: getStyleValue(
224
+ 'dropdown-background-color',
225
+ '#ffffff'
226
+ ) as string,
227
+ padding: getStyleValue('dropdown-padding', '12px'),
228
+ fontSize: getStyleValue('dropdown-font-size', '14px'),
229
+ color: getStyleValue('dropdown-color', '#030712') as string
230
+ }}
231
+ value={shipping_option?.pk || ''}
232
+ onChange={(e) => setShippingOption(Number(e.target.value))}
181
233
  >
182
- <Radio
183
- name="shipping"
184
- checked={option.pk === shipping_option?.pk}
185
- onChange={() => {
186
- setShippingOption(option.pk);
187
- }}
188
- onClick={() => {
189
- setShippingOption(option?.pk);
190
- }}
191
- data-testid={`checkout-shipping-option-${option.pk}`}
192
- >
193
- {option.name}
194
- </Radio>
195
- <span className="text-xs">
196
- <Price value={option.shipping_amount} />
197
- </span>
198
- </div>
199
- ))}
200
- </>
201
- )}
234
+ <option value="" disabled>
235
+ {t('checkout.address.shipping.select_method') ||
236
+ 'Select delivery method'}
237
+ </option>
238
+ {shippingOptions.map((option) => (
239
+ <option key={option.pk} value={option.pk}>
240
+ {option.name} - {option.shipping_amount}
241
+ </option>
242
+ ))}
243
+ </select>
244
+ </div>
245
+ )}
246
+
247
+ {/* Radio View */}
248
+ {viewType === 'radio' &&
249
+ shippingOptions &&
250
+ shippingOptions.length > 0 && (
251
+ <>
252
+ {shippingOptions.map((option) => {
253
+ const isSelected = option.pk === shipping_option?.pk;
254
+ return (
255
+ <div
256
+ key={option.pk}
257
+ className="flex justify-between cursor-pointer transition-all duration-200"
258
+ style={{
259
+ paddingTop: getStyleValue('item-padding-y', '16px'),
260
+ paddingBottom: getStyleValue('item-padding-y', '16px'),
261
+ borderTopWidth: getStyleValue(
262
+ 'item-border-width',
263
+ '1px'
264
+ ),
265
+ borderTopStyle: 'solid',
266
+ borderTopColor: isSelected
267
+ ? (getStyleValue(
268
+ 'item-selected-border-color',
269
+ '#3b82f6'
270
+ ) as string)
271
+ : (getStyleValue(
272
+ 'item-border-color',
273
+ '#e5e7eb'
274
+ ) as string),
275
+ backgroundColor: isSelected
276
+ ? (getStyleValue(
277
+ 'item-selected-background-color',
278
+ '#f0f9ff'
279
+ ) as string)
280
+ : (getStyleValue(
281
+ 'item-background-color',
282
+ 'transparent'
283
+ ) as string)
284
+ }}
285
+ onMouseEnter={(e) => {
286
+ if (!isSelected) {
287
+ e.currentTarget.style.backgroundColor = getStyleValue(
288
+ 'item-hover-background-color',
289
+ '#f9fafb'
290
+ ) as string;
291
+ }
292
+ }}
293
+ onMouseLeave={(e) => {
294
+ if (!isSelected) {
295
+ e.currentTarget.style.backgroundColor = getStyleValue(
296
+ 'item-background-color',
297
+ 'transparent'
298
+ ) as string;
299
+ }
300
+ }}
301
+ onClick={() => setShippingOption(option.pk)}
302
+ >
303
+ <Radio
304
+ name="shipping"
305
+ checked={isSelected}
306
+ onChange={() => setShippingOption(option.pk)}
307
+ data-testid={`checkout-shipping-option-${option.pk}`}
308
+ >
309
+ <span
310
+ style={{
311
+ fontSize: getStyleValue('label-font-size', '14px'),
312
+ fontWeight: getStyleValue(
313
+ 'label-font-weight',
314
+ '400'
315
+ ),
316
+ color: getStyleValue(
317
+ 'label-color',
318
+ '#030712'
319
+ ) as string
320
+ }}
321
+ >
322
+ {option.name}
323
+ </span>
324
+ </Radio>
325
+ <span
326
+ style={{
327
+ fontSize: getStyleValue('price-font-size', '12px'),
328
+ fontWeight: getStyleValue('price-font-weight', '400'),
329
+ color: getStyleValue(
330
+ 'price-color',
331
+ '#030712'
332
+ ) as string
333
+ }}
334
+ >
335
+ <Price value={option.shipping_amount} />
336
+ </span>
337
+ </div>
338
+ );
339
+ })}
340
+ </>
341
+ )}
202
342
 
203
343
  {attributeBasedShippingOptions &&
204
344
  Object.keys(attributeBasedShippingOptions).length > 0 &&
@@ -263,9 +403,74 @@ const ShippingOptions: React.FC = () => {
263
403
  ))}
264
404
 
265
405
  <Button
266
- className="mt-2 w-full"
406
+ className="mt-2"
407
+ style={{
408
+ width: getButtonStyle('button-width', 'auto') as string,
409
+ backgroundColor: getButtonStyle(
410
+ 'primary-background-color',
411
+ '#000000'
412
+ ) as string,
413
+ color: getButtonStyle('primary-text-color', '#ffffff') as string,
414
+ borderWidth: getButtonStyle('primary-border-width', 0),
415
+ borderStyle: 'solid',
416
+ borderColor: getButtonStyle(
417
+ 'primary-border-color',
418
+ '#000000'
419
+ ) as string,
420
+ borderRadius: getButtonStyle('primary-border-radius', 4),
421
+ paddingLeft: getButtonStyle('primary-padding-x', 24),
422
+ paddingRight: getButtonStyle('primary-padding-x', 24),
423
+ paddingTop: getButtonStyle('primary-padding-y', 12),
424
+ paddingBottom: getButtonStyle('primary-padding-y', 12),
425
+ fontSize: getButtonStyle('primary-font-size', 14),
426
+ fontWeight: getButtonStyle('primary-font-weight', '500'),
427
+ textTransform: getButtonStyle(
428
+ 'primary-text-transform',
429
+ 'uppercase'
430
+ ) as string as
431
+ | 'none'
432
+ | 'capitalize'
433
+ | 'uppercase'
434
+ | 'lowercase'
435
+ | 'initial'
436
+ | 'inherit',
437
+ cursor: !steps.shipping.completed ? 'not-allowed' : 'pointer',
438
+ transition: 'all 0.2s ease'
439
+ }}
267
440
  disabled={!steps.shipping.completed}
268
441
  onClick={() => dispatch(setCurrentStep(CheckoutStep.Payment))}
442
+ onMouseEnter={(e) => {
443
+ if (steps.shipping.completed) {
444
+ e.currentTarget.style.backgroundColor = getButtonStyle(
445
+ 'primary-hover-background-color',
446
+ '#1a1a1a'
447
+ ) as string;
448
+ e.currentTarget.style.color = getButtonStyle(
449
+ 'primary-hover-text-color',
450
+ '#ffffff'
451
+ ) as string;
452
+ e.currentTarget.style.borderColor = getButtonStyle(
453
+ 'primary-hover-border-color',
454
+ '#1a1a1a'
455
+ ) as string;
456
+ }
457
+ }}
458
+ onMouseLeave={(e) => {
459
+ if (steps.shipping.completed) {
460
+ e.currentTarget.style.backgroundColor = getButtonStyle(
461
+ 'primary-background-color',
462
+ '#000000'
463
+ ) as string;
464
+ e.currentTarget.style.color = getButtonStyle(
465
+ 'primary-text-color',
466
+ '#ffffff'
467
+ ) as string;
468
+ e.currentTarget.style.borderColor = getButtonStyle(
469
+ 'primary-border-color',
470
+ '#000000'
471
+ ) as string;
472
+ }
473
+ }}
269
474
  data-testid="checkout-shipping-save"
270
475
  >
271
476
  {t('checkout.address.shipping.button')}