@akinon/pz-theme 2.0.35-rc.0 → 2.0.35
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 +12 -28
- package/package.json +4 -3
- package/src/__tests__/theme-contract.test.ts +130 -0
- package/src/blocks/__tests__/text-block.test.tsx +8 -1
- package/src/blocks/__tests__/video-block.test.tsx +14 -7
- package/src/blocks/counter-block.tsx +44 -56
- package/src/blocks/group-block.tsx +23 -22
- package/src/blocks/hotspot-block.tsx +171 -80
- package/src/blocks/input-block.tsx +15 -17
- package/src/blocks/link-block.tsx +18 -21
- package/src/blocks/slider-block.tsx +15 -12
- package/src/components/with-designer-features.tsx +2 -0
- package/src/editor-bridge.ts +160 -0
- package/src/hooks/use-designer-features.tsx +30 -37
- package/src/placeholder-registry.ts +5 -7
- package/src/sections/__tests__/countdown-campaign-banner-section.test.tsx +8 -4
- package/src/sections/__tests__/coupon-banner-section.test.tsx +4 -2
- package/src/sections/before-after-section.tsx +189 -134
- package/src/sections/contact-form-section.tsx +185 -60
- package/src/sections/countdown-campaign-banner-section.tsx +73 -27
- package/src/sections/coupon-banner-section.tsx +152 -48
- package/src/sections/featured-product-spotlight-section.tsx +67 -66
- package/src/sections/find-in-store-section.tsx +37 -25
- package/src/sections/hover-showcase-section.tsx +221 -89
- package/src/sections/image-hotspot-section.tsx +208 -94
- package/src/sections/installment-options-section.tsx +268 -259
- package/src/sections/notification-banner-section.tsx +111 -25
- package/src/sections/order-tracking-lookup-section.tsx +272 -247
- package/src/sections/posts-slider-section.tsx +17 -16
- package/src/sections/pre-order-launch-banner-section.tsx +31 -50
- package/src/sections/section-wrapper.tsx +9 -10
- package/src/sections/shipping-threshold-progress-section.tsx +72 -29
- package/src/sections/stats-counter-section.tsx +68 -30
- package/src/sections/tabs-section.tsx +124 -147
- package/src/theme-placeholder-client.tsx +11 -14
- package/src/theme-placeholder-wrapper.tsx +42 -51
- package/src/theme-section.tsx +27 -34
- package/src/utils/__tests__/transform-styles.test.ts +97 -0
- package/src/utils/index.ts +9 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Image } from '@akinon/next/components/image';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useGetInstallmentsQuery,
|
|
6
|
+
useGetProductByPkQuery
|
|
7
|
+
} from '@akinon/next/data/client/product';
|
|
5
8
|
import { useLocalization } from '@akinon/next/hooks';
|
|
6
9
|
import clsx from 'clsx';
|
|
7
10
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
@@ -18,6 +21,8 @@ import {
|
|
|
18
21
|
resolveThemeCssVariables
|
|
19
22
|
} from '../utils';
|
|
20
23
|
|
|
24
|
+
import { postToEditor } from '../editor-bridge';
|
|
25
|
+
import { PreviewToEditorMessageType } from '@akinon/theme-contract';
|
|
21
26
|
interface InstallmentOptionsSectionProps {
|
|
22
27
|
section: Section;
|
|
23
28
|
currentBreakpoint?: string;
|
|
@@ -215,7 +220,9 @@ const parsePriceValue = (value: unknown): number | null => {
|
|
|
215
220
|
};
|
|
216
221
|
|
|
217
222
|
const normalizeCurrencyLabel = (currency: unknown): string => {
|
|
218
|
-
const raw = String(currency || '')
|
|
223
|
+
const raw = String(currency || '')
|
|
224
|
+
.trim()
|
|
225
|
+
.toUpperCase();
|
|
219
226
|
if (!raw) return 'TL';
|
|
220
227
|
|
|
221
228
|
const map: Record<string, string> = {
|
|
@@ -421,8 +428,8 @@ export default function InstallmentOptionsSection({
|
|
|
421
428
|
maxWidth === 'narrow'
|
|
422
429
|
? 'max-w-4xl'
|
|
423
430
|
: maxWidth === 'normal'
|
|
424
|
-
|
|
425
|
-
|
|
431
|
+
? 'max-w-7xl'
|
|
432
|
+
: '';
|
|
426
433
|
const hasMaxWidth = maxWidth !== 'none';
|
|
427
434
|
|
|
428
435
|
const filteredStyles = Object.fromEntries(
|
|
@@ -558,11 +565,13 @@ export default function InstallmentOptionsSection({
|
|
|
558
565
|
() => getCollectionProducts(section, isDesigner),
|
|
559
566
|
[section, isDesigner]
|
|
560
567
|
);
|
|
561
|
-
const collectionProduct =
|
|
568
|
+
const collectionProduct =
|
|
569
|
+
(sectionProducts[0] as ProductLike | undefined) || null;
|
|
562
570
|
const propertyProductPk = parseProductPk(
|
|
563
571
|
readStringProperty(section.properties, 'product-pk', '', currentBreakpoint)
|
|
564
572
|
);
|
|
565
|
-
const resolvedProductPk =
|
|
573
|
+
const resolvedProductPk =
|
|
574
|
+
parseProductPk(collectionProduct?.pk) ?? propertyProductPk;
|
|
566
575
|
|
|
567
576
|
const shouldFetchProduct = !collectionProduct && resolvedProductPk !== null;
|
|
568
577
|
// currentData (not data): data is sticky across args, so a cleared
|
|
@@ -588,15 +597,17 @@ export default function InstallmentOptionsSection({
|
|
|
588
597
|
return fetchedProduct ?? null;
|
|
589
598
|
}, [collectionProduct, productResponse]);
|
|
590
599
|
|
|
591
|
-
const usePlaceholderData =
|
|
600
|
+
const usePlaceholderData =
|
|
601
|
+
isDesigner && resolvedProductPk === null && !product;
|
|
592
602
|
|
|
593
603
|
const installmentCards = useMemo<InstallmentCard[]>(() => {
|
|
594
604
|
if (usePlaceholderData) {
|
|
595
605
|
return PLACEHOLDER_INSTALLMENTS;
|
|
596
606
|
}
|
|
597
|
-
return (
|
|
598
|
-
(
|
|
599
|
-
|
|
607
|
+
return (
|
|
608
|
+
(installmentsData as InstallmentResponse | undefined)?.results || []
|
|
609
|
+
).filter((card): card is InstallmentCard =>
|
|
610
|
+
Boolean(card && card.slug && Array.isArray(card.installments))
|
|
600
611
|
);
|
|
601
612
|
}, [installmentsData, usePlaceholderData]);
|
|
602
613
|
|
|
@@ -650,9 +661,7 @@ export default function InstallmentOptionsSection({
|
|
|
650
661
|
currentBreakpoint
|
|
651
662
|
);
|
|
652
663
|
|
|
653
|
-
const productName = String(
|
|
654
|
-
product?.name || PLACEHOLDER_PRODUCT.name
|
|
655
|
-
).trim();
|
|
664
|
+
const productName = String(product?.name || PLACEHOLDER_PRODUCT.name).trim();
|
|
656
665
|
const productUrl = String(
|
|
657
666
|
product?.absolute_url || PLACEHOLDER_PRODUCT.absolute_url
|
|
658
667
|
).trim();
|
|
@@ -672,92 +681,75 @@ export default function InstallmentOptionsSection({
|
|
|
672
681
|
currentBreakpoint={currentBreakpoint}
|
|
673
682
|
onMoveUp={() => {
|
|
674
683
|
if (window.parent) {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
},
|
|
680
|
-
'*'
|
|
681
|
-
);
|
|
684
|
+
postToEditor({
|
|
685
|
+
type: 'MOVE_BLOCK_UP',
|
|
686
|
+
data: { placeholderId, sectionId: section.id, blockId: block.id }
|
|
687
|
+
});
|
|
682
688
|
}
|
|
683
689
|
}}
|
|
684
690
|
onMoveDown={() => {
|
|
685
691
|
if (window.parent) {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
},
|
|
691
|
-
'*'
|
|
692
|
-
);
|
|
692
|
+
postToEditor({
|
|
693
|
+
type: 'MOVE_BLOCK_DOWN',
|
|
694
|
+
data: { placeholderId, sectionId: section.id, blockId: block.id }
|
|
695
|
+
});
|
|
693
696
|
}
|
|
694
697
|
}}
|
|
695
698
|
onDuplicate={() => {
|
|
696
699
|
if (window.parent) {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
},
|
|
702
|
-
'*'
|
|
703
|
-
);
|
|
700
|
+
postToEditor({
|
|
701
|
+
type: 'DUPLICATE_BLOCK',
|
|
702
|
+
data: { placeholderId, sectionId: section.id, blockId: block.id }
|
|
703
|
+
});
|
|
704
704
|
}
|
|
705
705
|
}}
|
|
706
706
|
onToggleVisibility={() => {
|
|
707
707
|
if (window.parent) {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
},
|
|
713
|
-
'*'
|
|
714
|
-
);
|
|
708
|
+
postToEditor({
|
|
709
|
+
type: 'TOGGLE_BLOCK_VISIBILITY',
|
|
710
|
+
data: { placeholderId, sectionId: section.id, blockId: block.id }
|
|
711
|
+
});
|
|
715
712
|
}
|
|
716
713
|
}}
|
|
717
714
|
onDelete={() => {
|
|
718
715
|
if (window.parent) {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
},
|
|
724
|
-
'*'
|
|
725
|
-
);
|
|
716
|
+
postToEditor({
|
|
717
|
+
type: 'DELETE_BLOCK',
|
|
718
|
+
data: { placeholderId, sectionId: section.id, blockId: block.id }
|
|
719
|
+
});
|
|
726
720
|
}
|
|
727
721
|
}}
|
|
728
722
|
onRename={(newLabel) => {
|
|
729
723
|
if (window.parent) {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
},
|
|
740
|
-
'*'
|
|
741
|
-
);
|
|
724
|
+
postToEditor({
|
|
725
|
+
type: 'RENAME_BLOCK',
|
|
726
|
+
data: {
|
|
727
|
+
placeholderId,
|
|
728
|
+
sectionId: section.id,
|
|
729
|
+
blockId: block.id,
|
|
730
|
+
label: newLabel
|
|
731
|
+
}
|
|
732
|
+
});
|
|
742
733
|
}
|
|
743
734
|
}}
|
|
744
735
|
/>
|
|
745
736
|
);
|
|
746
737
|
|
|
747
|
-
const postBlockAction = (
|
|
738
|
+
const postBlockAction = (
|
|
739
|
+
type: PreviewToEditorMessageType,
|
|
740
|
+
blockId: string,
|
|
741
|
+
label?: string
|
|
742
|
+
) => {
|
|
748
743
|
if (!window.parent) return;
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
},
|
|
759
|
-
'*'
|
|
760
|
-
);
|
|
744
|
+
postToEditor({
|
|
745
|
+
type,
|
|
746
|
+
data: {
|
|
747
|
+
placeholderId,
|
|
748
|
+
sectionId: section.id,
|
|
749
|
+
blockId,
|
|
750
|
+
...(label ? { label } : {})
|
|
751
|
+
}
|
|
752
|
+
});
|
|
761
753
|
};
|
|
762
754
|
|
|
763
755
|
const renderSelectableWrapper = (
|
|
@@ -836,67 +828,67 @@ export default function InstallmentOptionsSection({
|
|
|
836
828
|
renderSelectableWrapper(
|
|
837
829
|
productCardWrapperBlock,
|
|
838
830
|
<>
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
)}
|
|
851
|
-
</div>
|
|
852
|
-
|
|
853
|
-
<div
|
|
854
|
-
className="rounded-[14px] border bg-white p-3"
|
|
855
|
-
style={{
|
|
856
|
-
borderColor: productCardBorder
|
|
857
|
-
}}
|
|
858
|
-
>
|
|
859
|
-
<div className="relative mb-3 aspect-square w-full overflow-hidden rounded-[12px] bg-[#f8fafc]">
|
|
860
|
-
{productImage ? (
|
|
861
|
-
<Image
|
|
862
|
-
src={productImage}
|
|
863
|
-
alt={productName}
|
|
864
|
-
fill
|
|
865
|
-
sizes="280px"
|
|
866
|
-
aspectRatio={1}
|
|
867
|
-
imageClassName="object-cover"
|
|
868
|
-
/>
|
|
869
|
-
) : (
|
|
870
|
-
<div className="flex h-full w-full items-center justify-center bg-[#e2e8f0] text-sm font-semibold tracking-wide text-[#64748b]">
|
|
871
|
-
Product Preview
|
|
872
|
-
</div>
|
|
831
|
+
<div className="mb-4 flex items-center justify-between gap-3">
|
|
832
|
+
<p className="m-0 text-xs font-bold uppercase tracking-[0.16em] text-[#64748b]">
|
|
833
|
+
Selected Product
|
|
834
|
+
</p>
|
|
835
|
+
{productUrl && productUrl !== '#' && (
|
|
836
|
+
<a
|
|
837
|
+
href={productUrl}
|
|
838
|
+
className="text-xs font-semibold text-[#0f172a] underline underline-offset-4"
|
|
839
|
+
>
|
|
840
|
+
View product
|
|
841
|
+
</a>
|
|
873
842
|
)}
|
|
874
843
|
</div>
|
|
875
844
|
|
|
876
|
-
<div
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
845
|
+
<div
|
|
846
|
+
className="rounded-[14px] border bg-white p-3"
|
|
847
|
+
style={{
|
|
848
|
+
borderColor: productCardBorder
|
|
849
|
+
}}
|
|
850
|
+
>
|
|
851
|
+
<div className="relative mb-3 aspect-square w-full overflow-hidden rounded-[12px] bg-[#f8fafc]">
|
|
852
|
+
{productImage ? (
|
|
853
|
+
<Image
|
|
854
|
+
src={productImage}
|
|
855
|
+
alt={productName}
|
|
856
|
+
fill
|
|
857
|
+
sizes="280px"
|
|
858
|
+
aspectRatio={1}
|
|
859
|
+
imageClassName="object-cover"
|
|
860
|
+
/>
|
|
861
|
+
) : (
|
|
862
|
+
<div className="flex h-full w-full items-center justify-center bg-[#e2e8f0] text-sm font-semibold tracking-wide text-[#64748b]">
|
|
863
|
+
Product Preview
|
|
864
|
+
</div>
|
|
865
|
+
)}
|
|
866
|
+
</div>
|
|
887
867
|
|
|
888
|
-
<div className="flex
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
868
|
+
<div className="flex min-w-0 flex-col gap-2">
|
|
869
|
+
<p
|
|
870
|
+
className="m-0 overflow-hidden text-[15px] font-medium leading-[1.45] text-[#0f172a]"
|
|
871
|
+
style={{
|
|
872
|
+
display: '-webkit-box',
|
|
873
|
+
WebkitLineClamp: isMobile ? 3 : 2,
|
|
874
|
+
WebkitBoxOrient: 'vertical'
|
|
875
|
+
}}
|
|
876
|
+
>
|
|
877
|
+
{productName}
|
|
878
|
+
</p>
|
|
879
|
+
|
|
880
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
881
|
+
{productRetailPrice && (
|
|
882
|
+
<span className="text-sm font-normal text-[#94a3b8] line-through">
|
|
883
|
+
{productRetailPrice}
|
|
884
|
+
</span>
|
|
885
|
+
)}
|
|
886
|
+
<span className="text-[17px] font-semibold text-[#0f172a]">
|
|
887
|
+
{productPrice}
|
|
892
888
|
</span>
|
|
893
|
-
|
|
894
|
-
<span className="text-[17px] font-semibold text-[#0f172a]">
|
|
895
|
-
{productPrice}
|
|
896
|
-
</span>
|
|
889
|
+
</div>
|
|
897
890
|
</div>
|
|
898
891
|
</div>
|
|
899
|
-
</div>
|
|
900
892
|
</>,
|
|
901
893
|
{
|
|
902
894
|
className: 'min-w-0 border p-4',
|
|
@@ -912,143 +904,160 @@ export default function InstallmentOptionsSection({
|
|
|
912
904
|
{renderSelectableWrapper(
|
|
913
905
|
installmentPanelWrapperBlock,
|
|
914
906
|
<>
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
: isActive
|
|
907
|
+
{isLoading && !usePlaceholderData ? (
|
|
908
|
+
<div className="flex min-h-[220px] items-center justify-center">
|
|
909
|
+
<LoaderSpinner />
|
|
910
|
+
</div>
|
|
911
|
+
) : installmentCards.length > 0 ? (
|
|
912
|
+
<>
|
|
913
|
+
{showCardLogos && (
|
|
914
|
+
<div className="flex flex-wrap gap-2">
|
|
915
|
+
{installmentCards.map((card) => {
|
|
916
|
+
const isActive = activeCard?.slug === card.slug;
|
|
917
|
+
return renderSelectableWrapper(
|
|
918
|
+
logoCardWrapperBlock
|
|
919
|
+
? {
|
|
920
|
+
...logoCardWrapperBlock,
|
|
921
|
+
id: `${logoCardWrapperBlock.id}-clone-${card.pk}`,
|
|
922
|
+
styleSourceId:
|
|
923
|
+
logoCardWrapperBlock.styleSourceId ||
|
|
924
|
+
logoCardWrapperBlock.id
|
|
925
|
+
}
|
|
926
|
+
: null,
|
|
927
|
+
<button
|
|
928
|
+
key={card.pk}
|
|
929
|
+
type="button"
|
|
930
|
+
onClick={() => setActiveCardSlug(card.slug)}
|
|
931
|
+
className={clsx(
|
|
932
|
+
'flex min-w-[72px] flex-1 items-center justify-center px-3 py-2 transition-colors lg:min-w-[96px] lg:flex-none',
|
|
933
|
+
!logoCardWrapperBlock && 'border'
|
|
934
|
+
)}
|
|
935
|
+
style={{
|
|
936
|
+
backgroundColor: logoCardWrapperBlock
|
|
937
|
+
? 'transparent'
|
|
938
|
+
: isActive
|
|
948
939
|
? logoCardActiveBackground
|
|
949
940
|
: logoCardBackground,
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
941
|
+
borderColor: logoCardWrapperBlock
|
|
942
|
+
? 'transparent'
|
|
943
|
+
: isActive
|
|
953
944
|
? logoCardActiveBorder
|
|
954
945
|
: logoCardBorder,
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
{renderSelectableWrapper(
|
|
985
|
-
tableWrapperBlock,
|
|
986
|
-
<div
|
|
987
|
-
className={clsx(
|
|
988
|
-
'overflow-hidden rounded-[12px]',
|
|
989
|
-
!tableWrapperBlock && 'border'
|
|
990
|
-
)}
|
|
991
|
-
style={{
|
|
992
|
-
borderColor: tableRowBorderColor
|
|
993
|
-
}}
|
|
994
|
-
>
|
|
995
|
-
<div
|
|
996
|
-
className="grid grid-cols-3 gap-4 border-b px-4 py-3 text-xs font-bold uppercase tracking-[0.14em]"
|
|
997
|
-
style={{
|
|
998
|
-
borderColor: tableRowBorderColor,
|
|
999
|
-
color: tableHeaderColor,
|
|
1000
|
-
backgroundColor: '#f8fafc'
|
|
1001
|
-
}}
|
|
1002
|
-
>
|
|
1003
|
-
<span>{t('product.number_of_installments')}</span>
|
|
1004
|
-
<span className="text-right">{t('product.monthly_amount')}</span>
|
|
1005
|
-
<span className="text-right">{t('product.total_amount')}</span>
|
|
1006
|
-
</div>
|
|
946
|
+
borderRadius: logoCardWrapperBlock
|
|
947
|
+
? '0px'
|
|
948
|
+
: '12px'
|
|
949
|
+
}}
|
|
950
|
+
>
|
|
951
|
+
{card.card_type?.logo ? (
|
|
952
|
+
<Image
|
|
953
|
+
src={card.card_type.logo}
|
|
954
|
+
alt={card.name}
|
|
955
|
+
width={56}
|
|
956
|
+
height={20}
|
|
957
|
+
imageClassName={clsx(
|
|
958
|
+
'h-auto max-h-5 w-auto max-w-full object-contain',
|
|
959
|
+
!isActive && 'grayscale'
|
|
960
|
+
)}
|
|
961
|
+
/>
|
|
962
|
+
) : (
|
|
963
|
+
<span className="text-xs font-bold uppercase tracking-[0.16em] text-[#0f172a]">
|
|
964
|
+
{getFallbackCardLabel(card.name)}
|
|
965
|
+
</span>
|
|
966
|
+
)}
|
|
967
|
+
</button>,
|
|
968
|
+
{
|
|
969
|
+
keyOverride: `installment-logo-card-${card.pk}`
|
|
970
|
+
}
|
|
971
|
+
);
|
|
972
|
+
})}
|
|
973
|
+
</div>
|
|
974
|
+
)}
|
|
1007
975
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
976
|
+
{renderSelectableWrapper(
|
|
977
|
+
tableWrapperBlock,
|
|
978
|
+
<div
|
|
979
|
+
className={clsx(
|
|
980
|
+
'overflow-hidden rounded-[12px]',
|
|
981
|
+
!tableWrapperBlock && 'border'
|
|
982
|
+
)}
|
|
983
|
+
style={{
|
|
984
|
+
borderColor: tableRowBorderColor
|
|
985
|
+
}}
|
|
986
|
+
>
|
|
987
|
+
<div
|
|
988
|
+
className="grid grid-cols-3 gap-4 border-b px-4 py-3 text-xs font-bold uppercase tracking-[0.14em]"
|
|
989
|
+
style={{
|
|
990
|
+
borderColor: tableRowBorderColor,
|
|
991
|
+
color: tableHeaderColor,
|
|
992
|
+
backgroundColor: '#f8fafc'
|
|
993
|
+
}}
|
|
994
|
+
>
|
|
995
|
+
<span>{t('product.number_of_installments')}</span>
|
|
996
|
+
<span className="text-right">
|
|
997
|
+
{t('product.monthly_amount')}
|
|
998
|
+
</span>
|
|
999
|
+
<span className="text-right">
|
|
1000
|
+
{t('product.total_amount')}
|
|
1001
|
+
</span>
|
|
1002
|
+
</div>
|
|
1003
|
+
|
|
1004
|
+
<div className="overflow-x-auto">
|
|
1005
|
+
{(activeCard?.installments || []).map(
|
|
1006
|
+
(installment, index) => {
|
|
1007
|
+
const isHighlighted =
|
|
1008
|
+
highlightBestOption && index === 0;
|
|
1009
|
+
return (
|
|
1010
|
+
<div
|
|
1011
|
+
key={`${activeCard?.slug || 'card'}-${
|
|
1012
|
+
installment.installment_count
|
|
1013
|
+
}`}
|
|
1014
|
+
className="grid grid-cols-3 gap-4 border-b px-4 py-3 last:border-b-0"
|
|
1015
|
+
style={{
|
|
1016
|
+
borderColor: tableRowBorderColor,
|
|
1017
|
+
backgroundColor: isHighlighted
|
|
1018
|
+
? highlightRowBackground
|
|
1019
|
+
: panelBackground,
|
|
1020
|
+
color: isHighlighted
|
|
1021
|
+
? highlightRowText
|
|
1022
|
+
: '#0f172a'
|
|
1023
|
+
}}
|
|
1024
|
+
>
|
|
1025
|
+
<div className="min-w-0 text-sm font-semibold">
|
|
1026
|
+
{installment.installment_count === 1
|
|
1027
|
+
? t('product.cash')
|
|
1028
|
+
: `${installment.installment_count} ${t(
|
|
1029
|
+
'product.installment'
|
|
1030
|
+
)}`}
|
|
1031
|
+
</div>
|
|
1032
|
+
<div className="text-right text-sm font-semibold">
|
|
1033
|
+
<Price
|
|
1034
|
+
value={
|
|
1035
|
+
installment.single_installment_amount
|
|
1036
|
+
}
|
|
1037
|
+
/>
|
|
1038
|
+
</div>
|
|
1039
|
+
<div className="text-right text-sm font-semibold">
|
|
1040
|
+
<Price value={installment.total_amount} />
|
|
1041
|
+
</div>
|
|
1042
|
+
</div>
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
)}
|
|
1046
|
+
</div>
|
|
1047
|
+
</div>,
|
|
1048
|
+
{
|
|
1049
|
+
keyOverride: 'installment-table-wrapper'
|
|
1050
|
+
}
|
|
1051
|
+
)}
|
|
1052
|
+
</>
|
|
1053
|
+
) : (
|
|
1054
|
+
<div
|
|
1055
|
+
className="flex min-h-[220px] items-center justify-center rounded-[12px] border border-dashed px-6 text-center text-sm font-medium text-[#64748b]"
|
|
1056
|
+
style={{ borderColor: panelBorder }}
|
|
1057
|
+
>
|
|
1058
|
+
{emptyStateText}
|
|
1059
|
+
</div>
|
|
1060
|
+
)}
|
|
1052
1061
|
</>,
|
|
1053
1062
|
{
|
|
1054
1063
|
className: 'flex min-w-0 flex-col gap-4 border p-4 lg:p-5',
|