@akinon/projectzero 2.0.0-beta.9 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -17
- package/app-template/.env.example +3 -0
- package/app-template/.github/instructions/account.instructions.md +749 -0
- package/app-template/.github/instructions/checkout.instructions.md +678 -0
- package/app-template/.github/instructions/default.instructions.md +279 -0
- package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
- package/app-template/.github/instructions/routing.instructions.md +603 -0
- package/app-template/.github/instructions/settings.instructions.md +338 -0
- package/app-template/.gitignore +3 -0
- package/app-template/AGENTS.md +7 -0
- package/app-template/CHANGELOG.md +2065 -232
- package/app-template/Procfile +1 -1
- package/app-template/akinon.json +1 -4
- package/app-template/build.sh +10 -0
- package/app-template/docs/advanced-usage.md +111 -0
- package/app-template/docs/plugins.md +60 -25
- package/app-template/docs/sentry-usage.md +35 -0
- package/app-template/jest.config.ts +2 -2
- package/app-template/next-env.d.ts +1 -0
- package/app-template/{next.config.ts → next.config.mjs} +6 -7
- package/app-template/package.json +58 -50
- package/app-template/postcss.config.mjs +1 -4
- package/app-template/public/amex.svg +12 -0
- package/app-template/public/apple-pay.svg +16 -0
- package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
- package/app-template/public/google-pay.svg +16 -0
- package/app-template/public/locales/en/account.json +9 -4
- package/app-template/public/locales/en/auth.json +6 -7
- package/app-template/public/locales/en/basket.json +6 -6
- package/app-template/public/locales/en/blog.json +7 -0
- package/app-template/public/locales/en/category.json +3 -1
- package/app-template/public/locales/en/checkout.json +17 -4
- package/app-template/public/locales/en/common.json +61 -3
- package/app-template/public/locales/en/forgot_password.json +6 -7
- package/app-template/public/locales/en/product.json +84 -4
- package/app-template/public/locales/tr/account.json +9 -4
- package/app-template/public/locales/tr/auth.json +16 -17
- package/app-template/public/locales/tr/basket.json +4 -4
- package/app-template/public/locales/tr/blog.json +7 -0
- package/app-template/public/locales/tr/category.json +3 -1
- package/app-template/public/locales/tr/checkout.json +48 -36
- package/app-template/public/locales/tr/common.json +60 -2
- package/app-template/public/locales/tr/forgot_password.json +12 -13
- package/app-template/public/locales/tr/product.json +82 -0
- package/app-template/public/logo.svg +3 -27
- package/app-template/public/mastercard.svg +14 -0
- package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
- package/app-template/public/promotion-banner.jpg +0 -0
- package/app-template/public/shop-pay.svg +12 -0
- package/app-template/public/visa.svg +12 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +11 -11
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +4 -3
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +13 -10
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +73 -51
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +2 -2
- package/app-template/src/app/[pz]/blog/[slug]/page.tsx +120 -0
- package/app-template/src/app/[pz]/category/[pk]/page.tsx +37 -0
- package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +2 -3
- package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +6 -11
- package/app-template/src/app/[pz]/list/page.tsx +26 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/not-found.tsx +5 -7
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
- package/app-template/src/app/[pz]/page.tsx +28 -0
- package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
- package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
- package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +41 -5
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/[node]/route.ts +8 -6
- package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
- package/app-template/src/app/api/barcode-search/route.ts +1 -0
- package/app-template/src/app/api/cache/route.ts +1 -1
- package/app-template/src/app/api/form/[...id]/route.ts +1 -7
- package/app-template/src/app/api/image-proxy/route.ts +1 -0
- package/app-template/src/app/api/logout/route.ts +1 -1
- package/app-template/src/app/api/product-categories/route.ts +1 -0
- package/app-template/src/app/api/similar-product-list/route.ts +1 -0
- package/app-template/src/app/api/similar-products/route.ts +1 -0
- package/app-template/src/app/api/theme-settings/route.ts +12 -0
- package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
- package/app-template/src/app/api/web-vitals/route.ts +1 -1
- package/app-template/src/assets/fonts/pz-icon.css +211 -49
- package/app-template/src/assets/fonts/pz-icon.eot +0 -0
- package/app-template/src/assets/fonts/pz-icon.html +486 -0
- package/app-template/src/assets/fonts/pz-icon.scss +373 -49
- package/app-template/src/assets/fonts/pz-icon.svg +215 -53
- package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
- package/app-template/src/assets/globals.scss +8 -133
- package/app-template/src/assets/icons/arrow-right.svg +3 -0
- package/app-template/src/assets/icons/cart.svg +4 -12
- package/app-template/src/assets/icons/check.svg +2 -18
- package/app-template/src/assets/icons/chevron-down.svg +2 -7
- package/app-template/src/assets/icons/delete.svg +3 -0
- package/app-template/src/assets/icons/facebook.svg +2 -8
- package/app-template/src/assets/icons/fav-off.svg +5 -0
- package/app-template/src/assets/icons/fav-on.svg +5 -0
- package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
- package/app-template/src/assets/icons/heart.svg +3 -0
- package/app-template/src/assets/icons/instagram.svg +2 -13
- package/app-template/src/assets/icons/materials.svg +3 -0
- package/app-template/src/assets/icons/person.svg +4 -0
- package/app-template/src/assets/icons/pinterest.svg +5 -11
- package/app-template/src/assets/icons/ruler.svg +3 -0
- package/app-template/src/assets/icons/search.svg +8 -11
- package/app-template/src/assets/icons/share.svg +2 -9
- package/app-template/src/assets/icons/snapchat.svg +3 -0
- package/app-template/src/assets/icons/tiktok.svg +3 -0
- package/app-template/src/assets/icons/tumblr.svg +6 -0
- package/app-template/src/assets/icons/twitter.svg +2 -10
- package/app-template/src/assets/icons/vimeo.svg +3 -0
- package/app-template/src/assets/icons/youtube.svg +3 -0
- package/app-template/src/assets/icons/zoom.svg +8 -0
- package/app-template/src/auth.ts +3 -0
- package/app-template/src/components/__tests__/badge.test.tsx +2 -2
- package/app-template/src/components/__tests__/link.test.tsx +2 -0
- package/app-template/src/components/accordion.tsx +48 -23
- package/app-template/src/components/action-tooltip.tsx +160 -0
- package/app-template/src/components/button.tsx +1 -1
- package/app-template/src/components/carousel-core.tsx +4 -11
- package/app-template/src/components/checkbox.tsx +2 -1
- package/app-template/src/components/currency-select.tsx +150 -4
- package/app-template/src/components/file-input.tsx +27 -7
- package/app-template/src/components/generate-form-fields.tsx +49 -10
- package/app-template/src/components/icon.tsx +5 -6
- package/app-template/src/components/index.ts +4 -1
- package/app-template/src/components/input.tsx +11 -5
- package/app-template/src/components/language-select.tsx +88 -2
- package/app-template/src/components/modal.tsx +34 -16
- package/app-template/src/components/pagination.tsx +133 -20
- package/app-template/src/components/price.tsx +1 -1
- package/app-template/src/components/pwa-tags.tsx +1 -0
- package/app-template/src/components/quantity-input.tsx +63 -0
- package/app-template/src/components/quantity-selector.tsx +215 -0
- package/app-template/src/components/route-handler.tsx +50 -0
- package/app-template/src/components/select.tsx +86 -54
- package/app-template/src/components/shimmer.tsx +1 -1
- package/app-template/src/components/types/index.ts +51 -1
- package/app-template/src/components/widget-content.tsx +323 -0
- package/app-template/src/data/server/theme.ts +70 -0
- package/app-template/src/hooks/use-fav-button.tsx +9 -10
- package/app-template/src/hooks/use-product-cart.ts +80 -0
- package/app-template/src/hooks/use-stock-alert.ts +74 -0
- package/app-template/src/hooks/use-theme-settings.ts +42 -0
- package/app-template/src/lib/fonts.ts +149 -0
- package/app-template/src/plugins.js +12 -2
- package/app-template/src/{middleware.ts → proxy.ts} +3 -3
- package/app-template/src/redux/middlewares/category.ts +5 -4
- package/app-template/src/redux/store.ts +21 -1
- package/app-template/src/routes/index.ts +8 -7
- package/app-template/src/settings.js +6 -3
- package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
- package/app-template/src/types/index.ts +74 -3
- package/app-template/src/types/next-auth.d.ts +2 -2
- package/app-template/src/types/widget.ts +169 -0
- package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
- package/app-template/src/utils/formatDate.ts +48 -0
- package/app-template/src/utils/styles.ts +71 -0
- package/app-template/src/utils/theme-page-context.ts +309 -0
- package/app-template/src/utils/variant-validation.ts +41 -0
- package/app-template/src/views/account/address-form.tsx +8 -4
- package/app-template/src/views/account/contact-form.tsx +148 -131
- package/app-template/src/views/account/content-header.tsx +4 -3
- package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
- package/app-template/src/views/account/favorite-item.tsx +1 -1
- package/app-template/src/views/account/order.tsx +11 -9
- package/app-template/src/views/account/orders/order-cancellation-item.tsx +1 -1
- package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
- package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +45 -38
- package/app-template/src/views/basket/basket-item.tsx +6 -1
- package/app-template/src/views/basket/summary.tsx +16 -0
- package/app-template/src/views/breadcrumb.tsx +2 -2
- package/app-template/src/views/category/category-banner.tsx +4 -23
- package/app-template/src/views/category/category-info.tsx +2 -1
- package/app-template/src/views/category/filters/filter-item.tsx +138 -42
- package/app-template/src/views/category/filters/index.tsx +1 -1
- package/app-template/src/views/category/layout.tsx +1 -0
- package/app-template/src/views/checkout/auth.tsx +64 -40
- package/app-template/src/views/checkout/layout/header.tsx +10 -6
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +22 -6
- package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
- package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
- package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
- package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +33 -20
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +2 -2
- package/app-template/src/views/checkout/summary.tsx +12 -2
- package/app-template/src/views/find-in-store/index.tsx +2 -2
- package/app-template/src/views/guest-login/index.tsx +62 -58
- package/app-template/src/views/header/action-menu.tsx +1 -1
- package/app-template/src/views/header/band.tsx +2 -2
- package/app-template/src/views/header/index.tsx +1 -1
- package/app-template/src/views/header/mini-basket.tsx +3 -3
- package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
- package/app-template/src/views/header/mobile-menu.tsx +18 -6
- package/app-template/src/views/header/navbar.tsx +1 -1
- package/app-template/src/views/header/pwa-back-button.tsx +1 -1
- package/app-template/src/views/header/search/index.tsx +13 -3
- package/app-template/src/views/header/search/results.tsx +1 -1
- package/app-template/src/views/header/user-menu.tsx +1 -3
- package/app-template/src/views/login/index.tsx +66 -57
- package/app-template/src/views/otp-login/index.tsx +11 -6
- package/app-template/src/views/product/index.ts +1 -0
- package/app-template/src/views/product/layout.tsx +26 -6
- package/app-template/src/views/product/price-wrapper.tsx +3 -24
- package/app-template/src/views/product/product-actions.tsx +165 -0
- package/app-template/src/views/product/product-info.tsx +76 -238
- package/app-template/src/views/product/product-share.tsx +58 -0
- package/app-template/src/views/product/product-variants.tsx +26 -0
- package/app-template/src/views/product/slider.tsx +22 -1
- package/app-template/src/views/product/variant.tsx +69 -41
- package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
- package/app-template/src/views/register/index.tsx +31 -46
- package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
- package/app-template/src/views/share/index.tsx +9 -6
- package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
- package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
- package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
- package/app-template/src/widgets/footer-info.tsx +1 -1
- package/app-template/src/widgets/footer-menu.tsx +7 -3
- package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
- package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
- package/app-template/src/widgets/home-stories-eng.tsx +43 -35
- package/app-template/src/widgets/index.ts +7 -0
- package/app-template/src/widgets/schemas/about-us.json +46 -0
- package/app-template/src/widgets/schemas/blog-list.json +37 -0
- package/app-template/src/widgets/schemas/blog.json +29 -0
- package/app-template/tailwind.config.js +155 -7
- package/app-template/tsconfig.json +29 -11
- package/codemods/migrate-auth-v5/index.js +339 -0
- package/codemods/migrate-auth-v5/transform.js +86 -0
- package/codemods/migrate-segments/index.js +591 -0
- package/codemods/update-tailwind-config/index.js +30 -0
- package/codemods/update-tailwind-config/transform.js +102 -0
- package/codemods/upgrade-to-2/index.js +549 -0
- package/commands/codemod.ts +0 -1
- package/commands/plugins.ts +111 -46
- package/dist/commands/codemod.js +0 -1
- package/dist/commands/plugins.js +104 -36
- package/package.json +3 -2
- package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
- package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
- package/app-template/src/app/[commerce]/[locale]/[currency]/list/page.tsx +0 -18
- package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -50
- package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
- package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
- package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/error.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
|
|
5
|
+
interface ActionTooltipProps {
|
|
6
|
+
widgetData: {
|
|
7
|
+
attributes: Record<string, any>;
|
|
8
|
+
name: string;
|
|
9
|
+
template: string;
|
|
10
|
+
slug: string;
|
|
11
|
+
};
|
|
12
|
+
selectedWidget: any;
|
|
13
|
+
designMode: boolean;
|
|
14
|
+
onDelete?: () => void;
|
|
15
|
+
onMoveUp?: () => void;
|
|
16
|
+
onMoveDown?: () => void;
|
|
17
|
+
onCopy?: () => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ActionTooltip({
|
|
21
|
+
widgetData,
|
|
22
|
+
selectedWidget,
|
|
23
|
+
designMode,
|
|
24
|
+
onDelete,
|
|
25
|
+
onMoveUp,
|
|
26
|
+
onMoveDown,
|
|
27
|
+
onCopy
|
|
28
|
+
}: ActionTooltipProps) {
|
|
29
|
+
if (!widgetData?.attributes) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const componentId = Object.keys(widgetData.attributes)[0];
|
|
34
|
+
const attributes = widgetData.attributes[componentId];
|
|
35
|
+
|
|
36
|
+
if (!attributes) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const isRootContainer = !attributes.parentId;
|
|
41
|
+
|
|
42
|
+
if (isRootContainer) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isContainer = ['container'].includes(attributes.type);
|
|
47
|
+
const isCollectionItem = selectedWidget?.id?.includes('-');
|
|
48
|
+
|
|
49
|
+
const isSelected = isCollectionItem
|
|
50
|
+
? selectedWidget?.id === componentId
|
|
51
|
+
: selectedWidget?.id?.split('-')[0] === componentId?.split('-')[0];
|
|
52
|
+
|
|
53
|
+
if (!designMode || !selectedWidget || !isSelected) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<section className="flex absolute justify-center right-[29px] mr-[4px] bottom-[-1px] z-[51] w-[73px] h-[21px] bg-[#292b2c] overflow-hidden gap-[9px]">
|
|
59
|
+
<button
|
|
60
|
+
className={clsx('bg-[#292b2c] text-white hover:opacity-80')}
|
|
61
|
+
onClick={onMoveUp}
|
|
62
|
+
>
|
|
63
|
+
<svg
|
|
64
|
+
width="9"
|
|
65
|
+
height="9"
|
|
66
|
+
viewBox="0 0 9 9"
|
|
67
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
68
|
+
>
|
|
69
|
+
<path
|
|
70
|
+
d="M3.94 2.33 2.557 3.715a.546.546 0 0 1-.771-.772L4.1.628a.546.546 0 0 1 .771 0l2.315 2.314a.546.546 0 0 1-.772.772L5.031 2.33v5.626a.546.546 0 0 1-1.09 0V2.33z"
|
|
71
|
+
fill="#FFF"
|
|
72
|
+
fillRule="evenodd"
|
|
73
|
+
/>
|
|
74
|
+
</svg>
|
|
75
|
+
</button>
|
|
76
|
+
|
|
77
|
+
<button
|
|
78
|
+
className={clsx(
|
|
79
|
+
'bg-[#292b2c] text-white hover:opacity-80',
|
|
80
|
+
isContainer && 'disabled'
|
|
81
|
+
)}
|
|
82
|
+
onClick={onMoveDown}
|
|
83
|
+
>
|
|
84
|
+
<svg
|
|
85
|
+
width="9"
|
|
86
|
+
height="9"
|
|
87
|
+
viewBox="0 0 9 9"
|
|
88
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
89
|
+
>
|
|
90
|
+
<path
|
|
91
|
+
d="M3.697 6.64 2.314 5.257a.546.546 0 0 0-.771.771l2.314 2.315a.546.546 0 0 0 .772 0l2.314-2.315a.546.546 0 0 0-.772-.771L4.788 6.64V1.014a.546.546 0 0 0-1.09 0V6.64z"
|
|
92
|
+
fill="#FFF"
|
|
93
|
+
fillRule="evenodd"
|
|
94
|
+
/>
|
|
95
|
+
</svg>
|
|
96
|
+
</button>
|
|
97
|
+
|
|
98
|
+
<button
|
|
99
|
+
className="bg-[#292b2c] text-white hover:opacity-80"
|
|
100
|
+
onClick={onDelete}
|
|
101
|
+
>
|
|
102
|
+
<svg
|
|
103
|
+
width="8"
|
|
104
|
+
height="8"
|
|
105
|
+
viewBox="0 0 8 8"
|
|
106
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
107
|
+
>
|
|
108
|
+
<path
|
|
109
|
+
d="M6.8986356,1.49777209 L5.4463047,1.49777209 L5.4463047,1.089312 C5.4463047,0.499342458 4.94696224,0 4.3569927,0 L2.9046618,0 C2.31469226,0 1.8153498,0.499342458 1.8153498,1.089312 L1.8153498,1.49777209 L0.363018903,1.49777209 C0.181509452,1.49777209 0,1.63384035 0,1.86079099 C0,2.08774162 0.181509452,2.17836871 0.363018903,2.17836871 L0.771478991,2.17836871 L0.771478991,6.9438215 C0.771478991,7.53379103 1.27082145,7.98769231 1.86079099,7.98769231 L5.4914906,7.98769231 C6.08146013,7.98769231 6.53536141,7.48834985 6.53536141,6.9438215 L6.53536141,2.17836871 L6.9438215,2.17836871 C7.12533095,2.17836871 7.3068404,2.04230044 7.3068404,1.8153498 C7.3068404,1.58839917 7.07988976,1.49777209 6.89838031,1.49777209 L6.8986356,1.49777209 Z M2.5416429,1.089312 C2.5416429,0.862361361 2.72315235,0.680851909 2.95010299,0.680851909 L4.40243389,0.680851909 C4.62938452,0.680851909 4.81089397,0.862361361 4.81089397,1.089312 L4.81089397,1.49777209 L2.5416429,1.49777209 L2.5416429,1.089312 L2.5416429,1.089312 Z M5.8093236,6.8986356 C5.8093236,7.12558623 5.62781415,7.2616545 5.4463047,7.2616545 L1.81560509,7.2616545 C1.58865445,7.2616545 1.407145,7.08014505 1.407145,6.8986356 L1.407145,2.17862399 L5.8093236,2.17862399 L5.8093236,6.8986356 Z M2.9046618,3.31312189 C2.72315235,3.31312189 2.5416429,3.44919016 2.5416429,3.67614079 L2.5416429,5.8093236 C2.5416429,5.99083305 2.67771116,6.1723425 2.9046618,6.1723425 C3.13161244,6.1723425 3.2676807,6.03627424 3.2676807,5.8093236 L3.2676807,3.63095489 C3.2676807,3.44944544 3.08617125,3.31337718 2.9046618,3.31337718 L2.9046618,3.31312189 Z M4.3569927,3.31312189 C4.17548325,3.31312189 3.9939738,3.44919016 3.9939738,3.63069961 L3.9939738,5.80906831 C3.9939738,5.99057777 4.13004206,6.17208722 4.3569927,6.17208722 C4.58394334,6.17208722 4.7200116,6.03601895 4.7200116,5.80906831 L4.7200116,3.63069961 C4.67457042,3.44919016 4.53850215,3.31312189 4.3569927,3.31312189 Z"
|
|
110
|
+
fill="#FFF"
|
|
111
|
+
fillRule="evenodd"
|
|
112
|
+
/>
|
|
113
|
+
</svg>
|
|
114
|
+
</button>
|
|
115
|
+
|
|
116
|
+
<button
|
|
117
|
+
className="bg-[#292b2c] text-white hover:opacity-80"
|
|
118
|
+
onClick={onCopy}
|
|
119
|
+
>
|
|
120
|
+
<svg
|
|
121
|
+
width="8px"
|
|
122
|
+
height="10px"
|
|
123
|
+
viewBox="0 0 8 10"
|
|
124
|
+
version="1.1"
|
|
125
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
126
|
+
>
|
|
127
|
+
<g
|
|
128
|
+
id="dynamic-widget"
|
|
129
|
+
stroke="none"
|
|
130
|
+
strokeWidth="1"
|
|
131
|
+
fill="none"
|
|
132
|
+
fillRule="evenodd"
|
|
133
|
+
>
|
|
134
|
+
<g
|
|
135
|
+
id="dynamic-widget---02"
|
|
136
|
+
transform="translate(-543, -615)"
|
|
137
|
+
fill="#FFFFFF"
|
|
138
|
+
fillRule="nonzero"
|
|
139
|
+
stroke="#FFFFFF"
|
|
140
|
+
strokeWidth="0.307692308"
|
|
141
|
+
>
|
|
142
|
+
<g id="Grou5" transform="translate(484, 610)">
|
|
143
|
+
<g id="Group-5" transform="translate(59.6154, 6)">
|
|
144
|
+
<path
|
|
145
|
+
d="M4.35136402,1.39920627 L0.632480235,1.39920627 C0.283491141,1.39920627 0,1.68269742 0,2.03168651 L0,7.36751977 C0,7.71650886 0.283491141,8 0.632480235,8 L4.35136402,8 C4.70035311,8 4.98384425,7.71650886 4.98384425,7.36751977 L4.98384425,2.03168651 C4.98209431,1.68269742 4.69885316,1.39920627 4.35136402,1.39920627 Z M4.53985813,7.36576982 C4.53985813,7.47051655 4.45461079,7.55576388 4.34986407,7.55576388 L0.630980282,7.55576388 C0.526233555,7.55576388 0.440986219,7.47051655 0.440986219,7.36576982 L0.440986219,2.03143652 C0.440986219,1.92668979 0.526233555,1.84144245 0.630980282,1.84144245 L4.34986407,1.84144245 C4.45461079,1.84144245 4.53985813,1.92668979 4.53985813,2.03143652 L4.53985813,7.36576982 Z"
|
|
146
|
+
id="Shape"
|
|
147
|
+
></path>
|
|
148
|
+
<path
|
|
149
|
+
d="M5.77331958,0 L2.0544358,0 C1.7054467,0 1.42195556,0.283491141 1.42195556,0.632480235 C1.42195556,0.755226399 1.52020249,0.853723321 1.64319865,0.853723321 C1.76619481,0.853723321 1.86444174,0.755476391 1.86444174,0.632480235 C1.86444174,0.527733508 1.94968907,0.442486172 2.0544358,0.442486172 L5.77331958,0.442486172 C5.87806631,0.442486172 5.96331365,0.527733508 5.96331365,0.632480235 L5.96331365,5.96831349 C5.96331365,6.07306022 5.87806631,6.15830755 5.77331958,6.15830755 C5.65057342,6.15830755 5.5520765,6.25655448 5.5520765,6.37955064 C5.5520765,6.5025468 5.65032343,6.60079373 5.77331958,6.60079373 C6.12230868,6.60079373 6.40579982,6.31730258 6.40579982,5.96831349 L6.40579982,0.632480235 C6.40579982,0.283491141 6.12230868,0 5.77331958,0 Z"
|
|
150
|
+
id="Path"
|
|
151
|
+
></path>
|
|
152
|
+
</g>
|
|
153
|
+
</g>
|
|
154
|
+
</g>
|
|
155
|
+
</g>
|
|
156
|
+
</svg>
|
|
157
|
+
</button>
|
|
158
|
+
</section>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
4
|
import 'react-multi-carousel/lib/styles.css';
|
|
5
5
|
import Carousel, {
|
|
6
6
|
CarouselProps as BaseCarouselProps
|
|
7
7
|
} from 'react-multi-carousel';
|
|
8
|
-
import { forwardRef } from 'react';
|
|
9
8
|
import { useMediaQuery } from '@akinon/next/hooks';
|
|
10
9
|
|
|
11
10
|
type ContainerAspectRatioType = {
|
|
@@ -20,15 +19,9 @@ interface CarouselProps extends BaseCarouselProps {
|
|
|
20
19
|
const CarouselCore = forwardRef<Carousel, CarouselProps>((props, ref) => {
|
|
21
20
|
const { containerAspectRatio } = props;
|
|
22
21
|
const matches = useMediaQuery('(min-width: 768px)');
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (matches) {
|
|
27
|
-
setAspectRatio(containerAspectRatio.desktop);
|
|
28
|
-
} else {
|
|
29
|
-
setAspectRatio(containerAspectRatio.mobile);
|
|
30
|
-
}
|
|
31
|
-
}, [matches, containerAspectRatio]);
|
|
22
|
+
const aspectRatio = matches
|
|
23
|
+
? containerAspectRatio.desktop
|
|
24
|
+
: containerAspectRatio.mobile;
|
|
32
25
|
|
|
33
26
|
return (
|
|
34
27
|
<div className="w-full" style={{ aspectRatio }}>
|
|
@@ -9,6 +9,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
|
|
9
9
|
<label className={twMerge('flex flex-col text-xs', props.className)}>
|
|
10
10
|
<div className="flex items-center">
|
|
11
11
|
<input
|
|
12
|
+
data-testid="checkbox"
|
|
12
13
|
type="checkbox"
|
|
13
14
|
{...rest}
|
|
14
15
|
ref={ref}
|
|
@@ -18,7 +19,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
|
|
18
19
|
{children && <span className="ml-2">{children}</span>}
|
|
19
20
|
</div>
|
|
20
21
|
{error && (
|
|
21
|
-
<span className="mt-1 text-sm text-error">{error.message}</span>
|
|
22
|
+
<span className="mt-1 text-sm text-error">{String(error.message)}</span>
|
|
22
23
|
)}
|
|
23
24
|
</label>
|
|
24
25
|
);
|
|
@@ -9,6 +9,11 @@ import { Select } from './select';
|
|
|
9
9
|
|
|
10
10
|
interface CurrencySelectProps {
|
|
11
11
|
className?: string;
|
|
12
|
+
showIcon?: boolean;
|
|
13
|
+
/** Custom SVG icon content */
|
|
14
|
+
customIcon?: string;
|
|
15
|
+
/** Label format: 'full' (US Dollar), 'symbol' ($), 'code' (USD) */
|
|
16
|
+
labelFormat?: 'full' | 'symbol' | 'code';
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
export const CurrencySelect = (props: CurrencySelectProps) => {
|
|
@@ -17,6 +22,98 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
|
|
|
17
22
|
const { t, currency, setCurrency } = useLocalization();
|
|
18
23
|
const { currencies } = settings.localization;
|
|
19
24
|
|
|
25
|
+
// Currency symbol map for common currencies
|
|
26
|
+
const currencySymbolMap: Record<string, string> = {
|
|
27
|
+
usd: '$',
|
|
28
|
+
eur: '€',
|
|
29
|
+
gbp: '£',
|
|
30
|
+
try: '₺',
|
|
31
|
+
jpy: '¥',
|
|
32
|
+
cny: '¥',
|
|
33
|
+
krw: '₩',
|
|
34
|
+
inr: '₹',
|
|
35
|
+
rub: '₽',
|
|
36
|
+
brl: 'R$',
|
|
37
|
+
aud: 'A$',
|
|
38
|
+
cad: 'C$',
|
|
39
|
+
chf: 'CHF',
|
|
40
|
+
sek: 'kr',
|
|
41
|
+
nok: 'kr',
|
|
42
|
+
dkk: 'kr',
|
|
43
|
+
pln: 'zł',
|
|
44
|
+
mxn: '$',
|
|
45
|
+
sgd: 'S$',
|
|
46
|
+
hkd: 'HK$',
|
|
47
|
+
nzd: 'NZ$',
|
|
48
|
+
zar: 'R',
|
|
49
|
+
aed: 'د.إ',
|
|
50
|
+
sar: '﷼',
|
|
51
|
+
thb: '฿',
|
|
52
|
+
myr: 'RM',
|
|
53
|
+
php: '₱',
|
|
54
|
+
idr: 'Rp',
|
|
55
|
+
vnd: '₫',
|
|
56
|
+
egp: 'E£',
|
|
57
|
+
ngn: '₦',
|
|
58
|
+
pkr: '₨',
|
|
59
|
+
bdt: '৳',
|
|
60
|
+
cop: '$',
|
|
61
|
+
ars: '$',
|
|
62
|
+
clp: '$',
|
|
63
|
+
pen: 'S/',
|
|
64
|
+
ils: '₪',
|
|
65
|
+
kwd: 'د.ك',
|
|
66
|
+
qar: '﷼',
|
|
67
|
+
bhd: '.د.ب',
|
|
68
|
+
omr: '﷼'
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Currency full name map for common currencies
|
|
72
|
+
const currencyNameMap: Record<string, string> = {
|
|
73
|
+
usd: 'US Dollar',
|
|
74
|
+
eur: 'Euro',
|
|
75
|
+
gbp: 'British Pound',
|
|
76
|
+
try: 'Turkish Lira',
|
|
77
|
+
jpy: 'Japanese Yen',
|
|
78
|
+
cny: 'Chinese Yuan',
|
|
79
|
+
krw: 'South Korean Won',
|
|
80
|
+
inr: 'Indian Rupee',
|
|
81
|
+
rub: 'Russian Ruble',
|
|
82
|
+
brl: 'Brazilian Real',
|
|
83
|
+
aud: 'Australian Dollar',
|
|
84
|
+
cad: 'Canadian Dollar',
|
|
85
|
+
chf: 'Swiss Franc',
|
|
86
|
+
sek: 'Swedish Krona',
|
|
87
|
+
nok: 'Norwegian Krone',
|
|
88
|
+
dkk: 'Danish Krone',
|
|
89
|
+
pln: 'Polish Zloty',
|
|
90
|
+
mxn: 'Mexican Peso',
|
|
91
|
+
sgd: 'Singapore Dollar',
|
|
92
|
+
hkd: 'Hong Kong Dollar',
|
|
93
|
+
nzd: 'New Zealand Dollar',
|
|
94
|
+
zar: 'South African Rand',
|
|
95
|
+
aed: 'UAE Dirham',
|
|
96
|
+
sar: 'Saudi Riyal',
|
|
97
|
+
thb: 'Thai Baht',
|
|
98
|
+
myr: 'Malaysian Ringgit',
|
|
99
|
+
php: 'Philippine Peso',
|
|
100
|
+
idr: 'Indonesian Rupiah',
|
|
101
|
+
vnd: 'Vietnamese Dong',
|
|
102
|
+
egp: 'Egyptian Pound',
|
|
103
|
+
ngn: 'Nigerian Naira',
|
|
104
|
+
pkr: 'Pakistani Rupee',
|
|
105
|
+
bdt: 'Bangladeshi Taka',
|
|
106
|
+
cop: 'Colombian Peso',
|
|
107
|
+
ars: 'Argentine Peso',
|
|
108
|
+
clp: 'Chilean Peso',
|
|
109
|
+
pen: 'Peruvian Sol',
|
|
110
|
+
ils: 'Israeli Shekel',
|
|
111
|
+
kwd: 'Kuwaiti Dinar',
|
|
112
|
+
qar: 'Qatari Riyal',
|
|
113
|
+
bhd: 'Bahraini Dinar',
|
|
114
|
+
omr: 'Omani Rial'
|
|
115
|
+
};
|
|
116
|
+
|
|
20
117
|
const handleChange = async (e) => {
|
|
21
118
|
setSelectedCurrency(e.currentTarget.value);
|
|
22
119
|
setIsModalOpen(true);
|
|
@@ -26,16 +123,64 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
|
|
|
26
123
|
setCurrency(selectedCurrency);
|
|
27
124
|
};
|
|
28
125
|
|
|
126
|
+
// Get currency symbol from map or use provided symbol
|
|
127
|
+
const getCurrencySymbol = (curr: { code: string; symbol?: string }) => {
|
|
128
|
+
if (curr.symbol) return curr.symbol;
|
|
129
|
+
return (
|
|
130
|
+
currencySymbolMap[curr.code.toLowerCase()] || curr.code.toUpperCase()
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Get currency full name from map or use provided label
|
|
135
|
+
const getCurrencyName = (curr: { code: string; label: string }) => {
|
|
136
|
+
const name = currencyNameMap[curr.code.toLowerCase()];
|
|
137
|
+
// If name exists in map, use it. Otherwise check if label looks like a full name (not just code)
|
|
138
|
+
if (name) return name;
|
|
139
|
+
// If label is different from code, assume it's a proper name
|
|
140
|
+
if (curr.label.toLowerCase() !== curr.code.toLowerCase()) return curr.label;
|
|
141
|
+
// Fallback to code uppercase
|
|
142
|
+
return curr.code.toUpperCase();
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Format label based on labelFormat prop
|
|
146
|
+
const formatLabel = (curr: {
|
|
147
|
+
code: string;
|
|
148
|
+
label: string;
|
|
149
|
+
symbol?: string;
|
|
150
|
+
}) => {
|
|
151
|
+
switch (props.labelFormat) {
|
|
152
|
+
case 'symbol':
|
|
153
|
+
// Return currency symbol ($, €, etc.)
|
|
154
|
+
return getCurrencySymbol(curr);
|
|
155
|
+
case 'code':
|
|
156
|
+
// Return currency code (USD, EUR, etc.)
|
|
157
|
+
return curr.code.toUpperCase();
|
|
158
|
+
case 'full':
|
|
159
|
+
default:
|
|
160
|
+
// Return full label (US Dollar, Euro, etc.)
|
|
161
|
+
return getCurrencyName(curr);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Check if customIcon has actual SVG content
|
|
166
|
+
const hasValidCustomIcon =
|
|
167
|
+
props.customIcon &&
|
|
168
|
+
typeof props.customIcon === 'string' &&
|
|
169
|
+
props.customIcon.includes('<svg');
|
|
170
|
+
|
|
29
171
|
return (
|
|
30
172
|
<>
|
|
31
173
|
<Select
|
|
32
174
|
onChange={handleChange}
|
|
33
|
-
options={currencies.map((
|
|
34
|
-
value:
|
|
35
|
-
label:
|
|
175
|
+
options={currencies.map((curr) => ({
|
|
176
|
+
value: curr.code,
|
|
177
|
+
label: formatLabel(curr)
|
|
36
178
|
}))}
|
|
37
179
|
value={currency}
|
|
38
|
-
icon=
|
|
180
|
+
icon={
|
|
181
|
+
props.showIcon !== false && !hasValidCustomIcon ? 'money' : undefined
|
|
182
|
+
}
|
|
183
|
+
customIcon={props.showIcon !== false ? props.customIcon : undefined}
|
|
39
184
|
data-testid="currency"
|
|
40
185
|
borderless
|
|
41
186
|
className={props.className}
|
|
@@ -70,6 +215,7 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
|
|
|
70
215
|
onClick={confirmModalHandleClick}
|
|
71
216
|
appearance="filled"
|
|
72
217
|
className="font-medium px-10 py-4 h-12"
|
|
218
|
+
data-testid="currency-modal-confirm"
|
|
73
219
|
>
|
|
74
220
|
{t('common.currency_modal.continue')}
|
|
75
221
|
</Button>
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { forwardRef } from 'react';
|
|
3
3
|
import { FileInputProps } from '@theme/components/types';
|
|
4
|
-
import clsx from 'clsx';
|
|
5
4
|
import { useLocalization } from '@akinon/next/hooks';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
|
|
7
7
|
export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
|
|
8
|
-
function FileInput(
|
|
8
|
+
function FileInput(
|
|
9
|
+
{
|
|
10
|
+
buttonClassName,
|
|
11
|
+
onChange,
|
|
12
|
+
fileClassName,
|
|
13
|
+
fileNameWrapperClassName,
|
|
14
|
+
fileInputClassName,
|
|
15
|
+
...props
|
|
16
|
+
},
|
|
17
|
+
ref
|
|
18
|
+
) {
|
|
9
19
|
const { t } = useLocalization();
|
|
10
20
|
const [fileNames, setFileNames] = useState<string[]>([]);
|
|
11
21
|
|
|
@@ -24,24 +34,34 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
|
|
|
24
34
|
type="file"
|
|
25
35
|
{...props}
|
|
26
36
|
ref={ref}
|
|
27
|
-
className=
|
|
37
|
+
className={twMerge(
|
|
38
|
+
'absolute inset-0 w-full h-full opacity-0 cursor-pointer',
|
|
39
|
+
fileInputClassName
|
|
40
|
+
)}
|
|
28
41
|
onChange={handleFileChange}
|
|
29
42
|
/>
|
|
30
43
|
<button
|
|
31
44
|
type="button"
|
|
32
|
-
className={
|
|
45
|
+
className={twMerge(
|
|
46
|
+
'bg-primary text-white py-2 px-4 text-sm',
|
|
47
|
+
buttonClassName
|
|
48
|
+
)}
|
|
33
49
|
>
|
|
34
50
|
{t('common.file_input.select_file')}
|
|
35
51
|
</button>
|
|
36
|
-
<div
|
|
52
|
+
<div
|
|
53
|
+
className={twMerge('mt-1 text-gray-500', fileNameWrapperClassName)}
|
|
54
|
+
>
|
|
37
55
|
{fileNames.length > 0 ? (
|
|
38
|
-
<ul className=
|
|
56
|
+
<ul className={twMerge('list-disc pl-4 text-xs', fileClassName)}>
|
|
39
57
|
{fileNames.map((name, index) => (
|
|
40
58
|
<li key={index}>{name}</li>
|
|
41
59
|
))}
|
|
42
60
|
</ul>
|
|
43
61
|
) : (
|
|
44
|
-
<span className=
|
|
62
|
+
<span className={twMerge('text-xs', fileClassName)}>
|
|
63
|
+
{t('common.file_input.no_file')}
|
|
64
|
+
</span>
|
|
45
65
|
)}
|
|
46
66
|
</div>
|
|
47
67
|
</div>
|
|
@@ -7,6 +7,7 @@ import { useForm } from 'react-hook-form';
|
|
|
7
7
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
8
8
|
import * as yup from 'yup';
|
|
9
9
|
import DynamicForm from './dynamic-form';
|
|
10
|
+
|
|
10
11
|
import {
|
|
11
12
|
AllFieldClassesType,
|
|
12
13
|
FieldPropertiesType,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
FormPropertiesType,
|
|
15
16
|
Schema
|
|
16
17
|
} from '@akinon/next/types';
|
|
18
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
17
19
|
|
|
18
20
|
export function GenerateFormFields({
|
|
19
21
|
schema,
|
|
@@ -28,8 +30,14 @@ export function GenerateFormFields({
|
|
|
28
30
|
formProperties: FormPropertiesType;
|
|
29
31
|
submitButtonText: string;
|
|
30
32
|
}) {
|
|
33
|
+
const { t } = useLocalization();
|
|
31
34
|
const [fields, setFields] = useState([]);
|
|
32
35
|
const [loading, setIsLoading] = useState(true);
|
|
36
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
37
|
+
const [submitStatus, setSubmitStatus] = useState<
|
|
38
|
+
'idle' | 'success' | 'error'
|
|
39
|
+
>('idle');
|
|
40
|
+
const [submitMessage, setSubmitMessage] = useState('');
|
|
33
41
|
|
|
34
42
|
const generateValidationSchema = () => {
|
|
35
43
|
const schemaObject = {};
|
|
@@ -80,6 +88,7 @@ export function GenerateFormFields({
|
|
|
80
88
|
const {
|
|
81
89
|
handleSubmit,
|
|
82
90
|
register,
|
|
91
|
+
reset,
|
|
83
92
|
formState: { errors }
|
|
84
93
|
} = useForm<FormField>({
|
|
85
94
|
resolver: yupResolver(generateValidationSchema())
|
|
@@ -108,6 +117,10 @@ export function GenerateFormFields({
|
|
|
108
117
|
}, [schema, fieldProperties]);
|
|
109
118
|
|
|
110
119
|
const onSubmit = async (data) => {
|
|
120
|
+
setIsSubmitting(true);
|
|
121
|
+
setSubmitStatus('idle');
|
|
122
|
+
setSubmitMessage('');
|
|
123
|
+
|
|
111
124
|
try {
|
|
112
125
|
const formData = new FormData();
|
|
113
126
|
|
|
@@ -115,12 +128,25 @@ export function GenerateFormFields({
|
|
|
115
128
|
formData.append(key, data[key]);
|
|
116
129
|
});
|
|
117
130
|
|
|
118
|
-
fetch(formProperties.actionUrl, {
|
|
131
|
+
const response = await fetch(formProperties.actionUrl, {
|
|
119
132
|
method: 'POST',
|
|
120
133
|
body: formData
|
|
121
134
|
});
|
|
135
|
+
|
|
136
|
+
if (response.ok) {
|
|
137
|
+
setSubmitStatus('success');
|
|
138
|
+
setSubmitMessage(t('common.forms.success'));
|
|
139
|
+
reset();
|
|
140
|
+
} else {
|
|
141
|
+
setSubmitStatus('error');
|
|
142
|
+
setSubmitMessage(t('common.forms.error'));
|
|
143
|
+
}
|
|
122
144
|
} catch (error) {
|
|
123
|
-
console.error('
|
|
145
|
+
console.error(t('common.forms.submit_error'), error);
|
|
146
|
+
setSubmitStatus('error');
|
|
147
|
+
setSubmitMessage(t('common.forms.error'));
|
|
148
|
+
} finally {
|
|
149
|
+
setIsSubmitting(false);
|
|
124
150
|
}
|
|
125
151
|
};
|
|
126
152
|
|
|
@@ -157,7 +183,7 @@ export function GenerateFormFields({
|
|
|
157
183
|
className={twMerge(allFieldClasses?.className, field.class)}
|
|
158
184
|
name={field.key}
|
|
159
185
|
{...field.attributes}
|
|
160
|
-
error={errors[field.key]}
|
|
186
|
+
error={errors[field.key] as any}
|
|
161
187
|
{...register(field.key)}
|
|
162
188
|
/>
|
|
163
189
|
</div>
|
|
@@ -187,7 +213,7 @@ export function GenerateFormFields({
|
|
|
187
213
|
className={twMerge(allFieldClasses?.className, field?.class)}
|
|
188
214
|
name={field.key}
|
|
189
215
|
{...field.attributes}
|
|
190
|
-
error={errors[field.key]}
|
|
216
|
+
error={errors[field.key] as any}
|
|
191
217
|
{...register(field.key, { valueAsNumber: true })}
|
|
192
218
|
/>
|
|
193
219
|
</div>
|
|
@@ -220,7 +246,7 @@ export function GenerateFormFields({
|
|
|
220
246
|
/>
|
|
221
247
|
{errors[field.key] && (
|
|
222
248
|
<span className="mt-1 text-sm text-error">
|
|
223
|
-
{errors[field.key].message}
|
|
249
|
+
{String(errors[field.key].message)}
|
|
224
250
|
</span>
|
|
225
251
|
)}
|
|
226
252
|
</div>
|
|
@@ -251,7 +277,7 @@ export function GenerateFormFields({
|
|
|
251
277
|
className={twMerge(allFieldClasses?.className, field?.class)}
|
|
252
278
|
name={field.key}
|
|
253
279
|
{...field.attributes}
|
|
254
|
-
error={errors[field.key]}
|
|
280
|
+
error={errors[field.key] as any}
|
|
255
281
|
{...register(field.key)}
|
|
256
282
|
/>
|
|
257
283
|
</div>
|
|
@@ -285,7 +311,7 @@ export function GenerateFormFields({
|
|
|
285
311
|
label: choice
|
|
286
312
|
}))}
|
|
287
313
|
{...field.attributes}
|
|
288
|
-
error={errors[field.key]}
|
|
314
|
+
error={errors[field.key] as any}
|
|
289
315
|
{...register(field.key)}
|
|
290
316
|
/>
|
|
291
317
|
</div>
|
|
@@ -316,7 +342,7 @@ export function GenerateFormFields({
|
|
|
316
342
|
className={twMerge(allFieldClasses?.className, field?.class)}
|
|
317
343
|
name={field.key}
|
|
318
344
|
{...field.attributes}
|
|
319
|
-
error={errors[field.key]}
|
|
345
|
+
error={errors[field.key] as any}
|
|
320
346
|
{...register(field.key)}
|
|
321
347
|
/>
|
|
322
348
|
</div>
|
|
@@ -337,9 +363,22 @@ export function GenerateFormFields({
|
|
|
337
363
|
<LoaderSpinner />
|
|
338
364
|
) : (
|
|
339
365
|
<>
|
|
366
|
+
{submitStatus === 'success' && (
|
|
367
|
+
<div className="mb-4 p-3 bg-green-100 border border-green-400 text-green-700 rounded">
|
|
368
|
+
{submitMessage}
|
|
369
|
+
</div>
|
|
370
|
+
)}
|
|
371
|
+
|
|
372
|
+
{submitStatus === 'error' && (
|
|
373
|
+
<div className="mb-4 p-3 bg-red-100 border border-red-400 text-red-700 rounded">
|
|
374
|
+
{submitMessage}
|
|
375
|
+
</div>
|
|
376
|
+
)}
|
|
377
|
+
|
|
340
378
|
{fields.map((field: FormField) => generateField(field))}
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
|
|
380
|
+
<Button type="submit" className="w-full" disabled={isSubmitting}>
|
|
381
|
+
{isSubmitting ? t('common.forms.sending') : submitButtonText}
|
|
343
382
|
</Button>
|
|
344
383
|
</>
|
|
345
384
|
)}
|
|
@@ -2,17 +2,16 @@ import { IconProps } from '@theme/components/types';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
|
|
4
4
|
export const Icon = (props: IconProps) => {
|
|
5
|
-
const { name, size, className, ...rest } = props;
|
|
5
|
+
const { name, size, className, style, ...rest } = props;
|
|
6
6
|
|
|
7
7
|
return (
|
|
8
8
|
<i
|
|
9
9
|
className={clsx(`flex pz-icon-${name}`, className)}
|
|
10
10
|
{...rest}
|
|
11
|
-
style={
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
11
|
+
style={{
|
|
12
|
+
...style,
|
|
13
|
+
...(size && { fontSize: `${size}px` })
|
|
14
|
+
}}
|
|
16
15
|
/>
|
|
17
16
|
);
|
|
18
17
|
};
|
|
@@ -18,7 +18,8 @@ export * from './select';
|
|
|
18
18
|
export * from './radio';
|
|
19
19
|
export * from './checkbox';
|
|
20
20
|
export * from './file-input';
|
|
21
|
-
|
|
21
|
+
export * from './widget-content';
|
|
22
|
+
export * from './action-tooltip';
|
|
22
23
|
// Loaders
|
|
23
24
|
export * from './loader-spinner';
|
|
24
25
|
export * from './custom-loader';
|
|
@@ -39,3 +40,5 @@ export * from './skeleton-wrapper';
|
|
|
39
40
|
// Head
|
|
40
41
|
export * from './canonical-url';
|
|
41
42
|
export * from './pwa-tags';
|
|
43
|
+
export * from './quantity-input';
|
|
44
|
+
export * from './quantity-selector';
|