@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
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { signIn } from 'next-auth/react';
4
- import { useSearchParams } from 'next/navigation';
5
- import { useState } from 'react';
4
+ import { usePathname, useSearchParams } from 'next/navigation';
5
+ import { useEffect, useState } from 'react';
6
6
  import { ROUTES } from '@theme/routes';
7
7
  import { LoginFormType, FormType, PzSignInOptions } from '@theme/types';
8
8
  import { Button, Input, Link } from '@theme/components';
@@ -15,6 +15,7 @@ import { useCaptcha, useLocalization } from '@akinon/next/hooks';
15
15
  import { AuthError } from '@akinon/next/types';
16
16
  import { Image } from '@akinon/next/components/image';
17
17
  import PluginModule, { Component } from '@akinon/next/components/plugin-module';
18
+ import { twMerge } from 'tailwind-merge';
18
19
 
19
20
  const oauthProviders: Array<{
20
21
  key: string;
@@ -24,18 +25,15 @@ const oauthProviders: Array<{
24
25
  }> = [
25
26
  {
26
27
  key: 'google',
27
- label: 'Google',
28
- image: '/google.svg'
28
+ label: 'Google'
29
29
  },
30
30
  {
31
31
  key: 'facebook',
32
- label: 'Facebook',
33
- image: '/facebook.svg'
32
+ label: 'Facebook'
34
33
  },
35
34
  {
36
35
  key: 'apple',
37
- label: 'Apple',
38
- image: '/apple.svg'
36
+ label: 'Apple'
39
37
  }
40
38
  ];
41
39
 
@@ -48,7 +46,11 @@ const loginFormSchema = (t) =>
48
46
  password: yup.string().required(t('auth.login.form.error.required'))
49
47
  });
50
48
 
51
- export const Login = () => {
49
+ export const Login = ({
50
+ setActiveTab
51
+ }: {
52
+ setActiveTab?: (tab: string) => void;
53
+ }) => {
52
54
  const { t, locale } = useLocalization();
53
55
 
54
56
  const { refetch: refetchBasketData } = useGetBasketQuery();
@@ -62,8 +64,10 @@ export const Login = () => {
62
64
  resolver: yupResolver(loginFormSchema(t))
63
65
  });
64
66
 
67
+ const pathname = usePathname();
65
68
  const searchParams = useSearchParams();
66
69
  const [formError, setFormError] = useState(null);
70
+ const [isCheckout, setIsCheckout] = useState<boolean>(false);
67
71
 
68
72
  const {
69
73
  CaptchaView,
@@ -147,16 +151,14 @@ export const Login = () => {
147
151
  }
148
152
  };
149
153
 
150
- return (
151
- <section
152
- className={clsx([
153
- 'w-full py-10 px-5 md:py-0 md:px-8 md:mx-auto lg:px-16'
154
- ])}
155
- >
156
- <h2 className="mb-3 text-lg text-start text-black-800 font-light md:mb-9 md:text-2xl">
157
- {t('auth.login.title')}
158
- </h2>
154
+ useEffect(() => {
155
+ if (pathname.includes('/orders/checkout')) {
156
+ setIsCheckout(true);
157
+ }
158
+ }, [pathname]);
159
159
 
160
+ return (
161
+ <section className="w-full mt-6 lg:mt-8">
160
162
  <form
161
163
  action="/api/auth/signin/credentials"
162
164
  method="post"
@@ -165,11 +167,11 @@ export const Login = () => {
165
167
  <input type="hidden" value={FormType.login} {...register('formType')} />
166
168
  <input type="hidden" value={locale} {...register('locale')} />
167
169
 
168
- <div className={clsx(errors.email ? 'mb-8' : 'mb-4')}>
170
+ <div>
169
171
  <Input
170
172
  labelStyle="floating"
171
173
  label={t('auth.login.form.email.placeholder')}
172
- className="h-14"
174
+ className="h-12"
173
175
  {...register('email')}
174
176
  error={errors.email}
175
177
  data-testid="login-email"
@@ -177,11 +179,11 @@ export const Login = () => {
177
179
  />
178
180
  </div>
179
181
 
180
- <div className={clsx(errors.password ? 'mb-8' : 'mb-4')}>
182
+ <div className="mt-4">
181
183
  <Input
182
184
  labelStyle="floating"
183
185
  label={t('auth.login.form.password.placeholder')}
184
- className="h-14"
186
+ className="h-12"
185
187
  type="password"
186
188
  {...register('password')}
187
189
  error={errors.password}
@@ -192,7 +194,7 @@ export const Login = () => {
192
194
 
193
195
  <Link
194
196
  href={ROUTES.FORGOT_PASSWORD}
195
- className="block text-sm underline mb-8"
197
+ className="block text-black-750/75 text-sm underline mt-4"
196
198
  data-testid="login-forgot-password"
197
199
  >
198
200
  {t('auth.login.form.forgot_password')}
@@ -200,7 +202,7 @@ export const Login = () => {
200
202
 
201
203
  {formError && (
202
204
  <p
203
- className="text-error text-xs my-5"
205
+ className="text-error text-xs my-2"
204
206
  data-testid="login-error-field"
205
207
  >
206
208
  {formError}
@@ -208,11 +210,11 @@ export const Login = () => {
208
210
  )}
209
211
 
210
212
  <div className="flex justify-center">
211
- <CaptchaView className="mb-5" data-testid="login-captcha" />
213
+ <CaptchaView className="mt-8" data-testid="login-captcha" />
212
214
  </div>
213
215
 
214
216
  <Button
215
- className="w-full h-12 uppercase text-xs font-semibold"
217
+ className="w-full h-12 text-sm font-normal mt-6 lg:mt-8"
216
218
  type="submit"
217
219
  disabled={isCaptchaVisible && !captchaValidated}
218
220
  data-testid="login-submit"
@@ -220,22 +222,23 @@ export const Login = () => {
220
222
  {t('auth.login.form.submit')}
221
223
  </Button>
222
224
 
223
- <p className="relative text-gray-600 text-center my-4 before:absolute before:h-[1px] before:w-5/12 before:bg-gray-600 before:bg-opacity-25 before:top-1/2 before:left-0 after:absolute after:h-[1px] after:w-5/12 after:bg-gray-600 after:bg-opacity-25 after:top-1/2 after:right-0">
224
- {t('auth.login.form.or')}
225
+ <p
226
+ className={clsx(
227
+ twMerge(
228
+ 'relative block text-center mt-3 lg:mt-8 text-black-750 text-sm',
229
+ 'before:absolute before:left-0 before:top-1/2 before:w-full before:h-px before:bg-[#d2d2d2] before:-z-10'
230
+ )
231
+ )}
232
+ >
233
+ <span className="bg-white px-4">{t('auth.login.form.or')}</span>
225
234
  </p>
226
-
227
- <div className="social-login">
228
- <p className="mb-3 text-lg text-start font-light md:mb-9 md:text-2xl">
229
- {t('auth.login.form.sign_in_with')}
230
- </p>
231
- </div>
232
235
  </form>
233
236
 
234
- <div className="grid grid-cols-2 gap-4 lg:grid-cols-3">
237
+ <div className="grid gap-4 mt-2">
235
238
  {oauthProviders.map((provider) => (
236
239
  <Button
237
240
  key={provider.key}
238
- className="w-full h-14 uppercase text-xs font-semibold flex items-center justify-center gap-2 hover:bg-transparent hover:border hover:border-primary-800 hover:text-primary"
241
+ className="text-base text-black-750 h-auto py-4 border border-gray-650 leading-[0.94]"
239
242
  type="submit"
240
243
  appearance="outlined"
241
244
  disabled={isCaptchaVisible && !captchaValidated}
@@ -243,19 +246,24 @@ export const Login = () => {
243
246
  location.href = `/${provider.key}/login/`;
244
247
  }}
245
248
  >
246
- {provider.image && (
247
- <Image
248
- src={provider.image}
249
- alt={provider.label}
250
- width={provider.label === 'Facebook' ? 10 : 18}
251
- height={18}
252
- className="flex-shrink-0"
253
- />
249
+ {t('auth.login.form.continue_with_provider').replace(
250
+ '{provider}',
251
+ provider.localeKey ? t(provider.localeKey) : provider.label
254
252
  )}
255
-
256
- {provider.localeKey ? t(provider.localeKey) : provider.label}
257
253
  </Button>
258
254
  ))}
255
+ {isCheckout && (
256
+ <Button
257
+ className="text-base text-black-750 h-auto py-4 border border-gray-650 leading-[0.94]"
258
+ type="submit"
259
+ appearance="outlined"
260
+ onClick={() => {
261
+ setActiveTab?.('guest');
262
+ }}
263
+ >
264
+ {t('checkout.auth.continue_as_guest_checkout')}
265
+ </Button>
266
+ )}
259
267
  <PluginModule
260
268
  component={Component.AkifastQuickLoginButton}
261
269
  props={{
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Accordion Section Wrapper
5
+ *
6
+ * Wraps accordion components with Theme Editor styling support.
7
+ * Applies CSS variables for customization via Theme Editor.
8
+ */
9
+
10
+ import { PropsWithChildren, CSSProperties, useMemo } from 'react';
11
+ import clsx from 'clsx';
12
+ import {
13
+ useProductDetail,
14
+ ACCORDION_SECTION_ID
15
+ } from '@theme/views/product-detail';
16
+
17
+ export default function AccordionSection({ children }: PropsWithChildren) {
18
+ const { isDesigner, selectedSectionId, accordionStyles } = useProductDetail();
19
+
20
+ const isSelected = isDesigner && selectedSectionId === ACCORDION_SECTION_ID;
21
+
22
+ const cssVariables = useMemo((): CSSProperties => {
23
+ if (!accordionStyles) return {};
24
+
25
+ const vars: Record<string, string> = {};
26
+ Object.entries(accordionStyles).forEach(([key, value]) => {
27
+ if (value) {
28
+ vars[`--accordion-${key}`] = value;
29
+ }
30
+ });
31
+ return vars as CSSProperties;
32
+ }, [accordionStyles]);
33
+
34
+ const handleClick = (e: React.MouseEvent) => {
35
+ if (isDesigner) {
36
+ e.stopPropagation();
37
+ window.parent?.postMessage(
38
+ {
39
+ type: 'SELECT_SECTION',
40
+ data: {
41
+ placeholderId: 'product-detail',
42
+ sectionId: ACCORDION_SECTION_ID
43
+ }
44
+ },
45
+ '*'
46
+ );
47
+ }
48
+ };
49
+
50
+ return (
51
+ <div
52
+ className={clsx('accordion-section-wrapper', {
53
+ 'ring-2 ring-blue-500 ring-offset-2': isSelected
54
+ })}
55
+ style={cssVariables}
56
+ onClick={handleClick}
57
+ >
58
+ {children}
59
+ </div>
60
+ );
61
+ }
@@ -1,59 +1,151 @@
1
1
  'use client';
2
2
 
3
3
  import { useLocalization } from '@akinon/next/hooks';
4
- import React from 'react';
4
+ import React, { useMemo, CSSProperties } from 'react';
5
5
  import { Accordion } from '@theme/components';
6
6
  import InstallmentOptions from '@theme/views/installment-options';
7
+ import AccordionSection from './accordion-section';
8
+ import { useProductDetail } from '@theme/views/product-detail';
7
9
 
8
10
  export default function AccordionWrapper({ data, deliveryReturn }) {
9
11
  const { t } = useLocalization();
12
+ const { accordionStyles } = useProductDetail();
13
+
14
+ const iconSize = useMemo(() => {
15
+ const size = accordionStyles['icon-size'];
16
+ const parsed = parseInt(size);
17
+ return !isNaN(parsed) ? parsed : 15;
18
+ }, [accordionStyles]);
19
+
20
+ const iconColor = useMemo(
21
+ () => accordionStyles['icon-color'] || '#6b7280',
22
+ [accordionStyles]
23
+ );
24
+
25
+ const containerStyle = useMemo(
26
+ (): CSSProperties => ({
27
+ width: '100%',
28
+ marginTop: accordionStyles['container-spacing'] || '1rem',
29
+ borderColor: accordionStyles['container-border-color'] || 'transparent',
30
+ borderWidth: accordionStyles['container-border-width'] || '0',
31
+ borderRadius: accordionStyles['container-border-radius'] || '0',
32
+ borderStyle: 'solid'
33
+ }),
34
+ [accordionStyles]
35
+ );
36
+
37
+ const headerStyle = useMemo(
38
+ (): CSSProperties => ({
39
+ fontSize: accordionStyles['title-font-size'] || '1rem',
40
+ fontWeight: accordionStyles['title-font-weight'] || '600',
41
+ color: accordionStyles['title-color'] || '#111827',
42
+ backgroundColor:
43
+ accordionStyles['title-background-color'] || 'transparent',
44
+ paddingLeft: accordionStyles['title-padding-x'] || '1rem',
45
+ paddingRight: accordionStyles['title-padding-x'] || '1rem',
46
+ paddingTop: accordionStyles['title-padding-y'] || '0.75rem',
47
+ paddingBottom: accordionStyles['title-padding-y'] || '0.75rem',
48
+ borderBottom: `1px solid ${
49
+ accordionStyles['container-border-color'] || '#e5e7eb'
50
+ }`
51
+ }),
52
+ [accordionStyles]
53
+ );
54
+
55
+ const contentStyle = useMemo(
56
+ (): CSSProperties => ({
57
+ fontSize: accordionStyles['content-font-size'] || '0.875rem',
58
+ fontWeight: accordionStyles['content-font-weight'] || '400',
59
+ color: accordionStyles['content-color'] || '#6b7280',
60
+ backgroundColor:
61
+ accordionStyles['content-background-color'] || 'transparent',
62
+ paddingLeft: accordionStyles['content-padding-x'] || '1rem',
63
+ paddingRight: accordionStyles['content-padding-x'] || '1rem',
64
+ paddingTop: accordionStyles['content-padding-y'] || '0.75rem',
65
+ paddingBottom: accordionStyles['content-padding-y'] || '0.75rem'
66
+ }),
67
+ [accordionStyles]
68
+ );
10
69
 
11
70
  const generateHtml = (data: string) => {
12
71
  return { __html: data };
13
72
  };
14
73
 
15
74
  return (
16
- <div className="w-full">
17
- <Accordion
18
- title={t('product.details_care')}
19
- icons={['minus', 'plus']}
20
- iconSize={15}
21
- >
22
- {t('product.product_code')}: {data.product.sku} -{' '}
23
- {data.product.base_code}
24
- {data.product.attributes.integration_ProductAtt03Desc &&
25
- data.product.attributes.integration_ProductAtt03Desc}
26
- {data.product.attributes.integration_kumas_icerik &&
27
- data.product.attributes.integration_kumas_icerik}
28
- {data.product.attributes.model_olculeri &&
29
- data.product.attributes.model_olculeri}
30
- {data.product.attributes.aciklama && (
31
- <div
32
- dangerouslySetInnerHTML={generateHtml(
33
- data.product.attributes.aciklama
34
- )}
35
- />
36
- )}
37
- </Accordion>
38
- <Accordion
39
- title={t('product.delivery_collections')}
40
- icons={['minus', 'plus']}
41
- iconSize={15}
42
- >
43
- <div
44
- dangerouslySetInnerHTML={generateHtml(
45
- deliveryReturn?.product_delivery_returns?.value
46
- )}
47
- />
48
- </Accordion>
49
-
50
- <Accordion
51
- title={t('product.installment_options')}
52
- icons={['minus', 'plus']}
53
- iconSize={15}
54
- >
55
- <InstallmentOptions productPk={data.product.pk} />
56
- </Accordion>
57
- </div>
75
+ <AccordionSection>
76
+ <div style={containerStyle}>
77
+ <div style={headerStyle} className="accordion-header">
78
+ <Accordion
79
+ title={t('product.details_care')}
80
+ icons={['minus', 'plus']}
81
+ iconSize={iconSize}
82
+ iconColor={iconColor}
83
+ isCollapse={false}
84
+ className="border-none"
85
+ >
86
+ <div style={contentStyle}>
87
+ {t('product.product_code')}: {data.product.sku} -{' '}
88
+ {data.product.base_code}
89
+ {data.product.attributes.integration_ProductAtt03Desc &&
90
+ data.product.attributes.integration_ProductAtt03Desc}
91
+ {data.product.attributes.integration_kumas_icerik &&
92
+ data.product.attributes.integration_kumas_icerik}
93
+ {data.product.attributes.model_olculeri &&
94
+ data.product.attributes.model_olculeri}
95
+ {data.product.attributes.aciklama && (
96
+ <div
97
+ dangerouslySetInnerHTML={generateHtml(
98
+ data.product.attributes.aciklama
99
+ )}
100
+ />
101
+ )}
102
+ </div>
103
+ </Accordion>
104
+ </div>
105
+
106
+ <div style={headerStyle} className="accordion-header">
107
+ <Accordion
108
+ title={t('product.delivery_collections')}
109
+ icons={['minus', 'plus']}
110
+ iconSize={iconSize}
111
+ iconColor={iconColor}
112
+ isCollapse={false}
113
+ className="border-none"
114
+ >
115
+ <div style={contentStyle}>
116
+ <div
117
+ dangerouslySetInnerHTML={generateHtml(
118
+ deliveryReturn?.product_delivery_returns?.value
119
+ )}
120
+ />
121
+ </div>
122
+ </Accordion>
123
+ </div>
124
+
125
+ <div style={headerStyle} className="accordion-header">
126
+ <Accordion
127
+ title={t('product.installment_options')}
128
+ icons={['minus', 'plus']}
129
+ iconSize={iconSize}
130
+ iconColor={iconColor}
131
+ isCollapse={false}
132
+ className="border-none"
133
+ >
134
+ <div style={contentStyle}>
135
+ <InstallmentOptions productPk={data.product.pk} />
136
+ </div>
137
+ </Accordion>
138
+ </div>
139
+ </div>
140
+ <style jsx global>{`
141
+ .accordion-header:hover {
142
+ background-color: ${accordionStyles['hover-background-color'] ||
143
+ '#f9fafb'};
144
+ color: ${accordionStyles['hover-title-color'] ||
145
+ accordionStyles['title-color'] ||
146
+ '#111827'};
147
+ }
148
+ `}</style>
149
+ </AccordionSection>
58
150
  );
59
151
  }
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+
3
+ import { Icon, Button } from '@theme/components';
4
+
5
+ type CustomButtonGroupProps = {
6
+ carouselState?: {
7
+ currentSlide: number;
8
+ totalItems: number;
9
+ };
10
+ previous?: () => void;
11
+ next?: () => void;
12
+ goToSlide?: (slide: number) => void;
13
+ };
14
+
15
+ export default function CustomButtonGroup({
16
+ carouselState,
17
+ previous,
18
+ next
19
+ }: CustomButtonGroupProps) {
20
+ const currentSlide = carouselState?.currentSlide ?? 0;
21
+ const totalItems = carouselState?.totalItems ?? 0;
22
+
23
+ if (!totalItems) return null;
24
+
25
+ const isFirstSlide = currentSlide === 0;
26
+ const isLastSlide = currentSlide >= totalItems - 1;
27
+
28
+ const handlePrevClick = () => {
29
+ if (isFirstSlide) return;
30
+ previous?.();
31
+ };
32
+
33
+ const handleNextClick = () => {
34
+ if (isLastSlide) return;
35
+ next?.();
36
+ };
37
+
38
+ return (
39
+ <div className="relative mt-3 w-full">
40
+ <div className="flex items-center justify-center gap-2 text-[13px] font-medium text-gray-650">
41
+ <Button
42
+ type="button"
43
+ aria-label="Previous image"
44
+ aria-disabled={isFirstSlide}
45
+ disabled={isFirstSlide}
46
+ onClick={handlePrevClick}
47
+ className="bg-transparent text-primary border-none"
48
+ >
49
+ <Icon name="chevron-start" size={12} />
50
+ </Button>
51
+
52
+ <span>
53
+ {currentSlide + 1}/{totalItems}
54
+ </span>
55
+
56
+ <Button
57
+ type="button"
58
+ aria-label="Next image"
59
+ aria-disabled={isLastSlide}
60
+ disabled={isLastSlide}
61
+ onClick={handleNextClick}
62
+ className="bg-transparent text-primary border-none"
63
+ >
64
+ <Icon name="chevron-end" size={12} className="text-gray-900" />
65
+ </Button>
66
+ </div>
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Favorites Button Section Wrapper
5
+ *
6
+ * Wraps favorites button with Theme Editor styling support.
7
+ * Applies CSS variables for customization via Theme Editor.
8
+ */
9
+
10
+ import { PropsWithChildren, CSSProperties, useMemo } from 'react';
11
+ import clsx from 'clsx';
12
+ import {
13
+ useProductDetail,
14
+ FAVORITES_BUTTON_SECTION_ID
15
+ } from '@theme/views/product-detail';
16
+
17
+ export default function FavoritesButtonSection({
18
+ children
19
+ }: PropsWithChildren) {
20
+ const { isDesigner, selectedSectionId, favoritesButtonStyles } =
21
+ useProductDetail();
22
+
23
+ // Check if this section is selected in designer mode
24
+ const isSelected =
25
+ isDesigner && selectedSectionId === FAVORITES_BUTTON_SECTION_ID;
26
+
27
+ // Build CSS variables from favoritesButtonStyles
28
+ const cssVariables = useMemo((): CSSProperties => {
29
+ if (!favoritesButtonStyles) return {};
30
+
31
+ const vars: Record<string, string> = {};
32
+ Object.entries(favoritesButtonStyles).forEach(([key, value]) => {
33
+ if (value) {
34
+ vars[`--favorites-button-${key}`] = value;
35
+ }
36
+ });
37
+ return vars as CSSProperties;
38
+ }, [favoritesButtonStyles]);
39
+
40
+ const handleClick = (e: React.MouseEvent) => {
41
+ if (isDesigner) {
42
+ e.stopPropagation();
43
+ window.parent?.postMessage(
44
+ {
45
+ type: 'SELECT_SECTION',
46
+ data: {
47
+ placeholderId: 'product-detail',
48
+ sectionId: FAVORITES_BUTTON_SECTION_ID
49
+ }
50
+ },
51
+ '*'
52
+ );
53
+ }
54
+ };
55
+
56
+ return (
57
+ <div
58
+ className={clsx(
59
+ 'favorites-button-section',
60
+ isDesigner && 'cursor-pointer',
61
+ isSelected && 'ring-2 ring-blue-500 ring-offset-2'
62
+ )}
63
+ style={cssVariables}
64
+ onClick={handleClick}
65
+ >
66
+ {children}
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ import React, { CSSProperties, useMemo } from 'react';
4
+ import { useDesignerFeatures } from '@akinon/next/components/theme-editor/hooks/use-designer-features';
5
+ import {
6
+ useProductDetail,
7
+ PRODUCT_DETAIL_PLACEHOLDER_ID,
8
+ FIND_IN_STORE_SECTION_ID
9
+ } from '@theme/views/product-detail';
10
+
11
+ interface FindInStoreSectionProps {
12
+ children: React.ReactNode;
13
+ }
14
+
15
+ export default function FindInStoreSection({
16
+ children
17
+ }: FindInStoreSectionProps) {
18
+ const { isDesigner, selectedSectionId, findInStoreStyles } =
19
+ useProductDetail();
20
+
21
+ const { handleClick } = useDesignerFeatures({
22
+ sectionId: FIND_IN_STORE_SECTION_ID,
23
+ placeholderId: PRODUCT_DETAIL_PLACEHOLDER_ID,
24
+ blockId: '',
25
+ isDesigner
26
+ });
27
+
28
+ const isSelected = selectedSectionId === FIND_IN_STORE_SECTION_ID;
29
+
30
+ const cssVariables = useMemo((): CSSProperties => {
31
+ if (!findInStoreStyles) return {};
32
+
33
+ const vars: Record<string, string> = {};
34
+ Object.entries(findInStoreStyles).forEach(([key, value]) => {
35
+ if (value) {
36
+ vars[`--find-in-store-${key}`] = value;
37
+ }
38
+ });
39
+ return vars as CSSProperties;
40
+ }, [findInStoreStyles]);
41
+
42
+ if (!isDesigner) {
43
+ return <>{children}</>;
44
+ }
45
+
46
+ return (
47
+ <div
48
+ onClick={handleClick}
49
+ style={{
50
+ ...cssVariables,
51
+ cursor: 'pointer',
52
+ outline: isSelected ? '2px solid #3b82f6' : 'none',
53
+ outlineOffset: '2px'
54
+ }}
55
+ data-section-id={FIND_IN_STORE_SECTION_ID}
56
+ >
57
+ {children}
58
+ </div>
59
+ );
60
+ }
@@ -1,6 +1,7 @@
1
1
  export { default as PriceWrapper } from './price-wrapper';
2
2
  export { default as Variant } from './variant';
3
3
  export { default as ProductInfo } from './product-info';
4
+ export { default as ProductShare } from './product-share';
4
5
  export { default as ProductGroupInfo } from './product-group-info';
5
6
  export { default as MiscButtons } from './misc-buttons';
6
7
  export { default as ProductInfoSlider } from './slider';