Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sku matrix packages core #2505

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions packages/core/cms/faststore/sections.json
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,90 @@
"default": "Tax included"
}
}
},
"skuMatrix": {
"title": "SKUMatrix Configuration",
"type": "object",
"properties": {
"shouldDisplaySKUMatrix": {
"title": "Should display SKUMatrix?",
"type": "boolean",
"default": false
},
"triggerButtonLabel": {
"title": "SKU Matrix Trigger label to be displayed",
"type": "string",
"default": "Select multiple"
},
"separatorButtonsText": {
"title": "Separator text",
"description": "Text that separates the add to cart button from the SKU Matrix Trigger button.",
"type": "string",
"default": "Or"
},
"columns": {
"title": "Columns",
"type": "object",
"properties": {
"name": {
"title": "SKU name column label",
"type": "string",
"default": "Name"
},
"additionalColumns": {
"title": "Additional columns",
"type": "array",
"items": {
"title": "Column",
"type": "object",
"required": ["label", "value"],
"properties": {
"label": {
"title": "Label",
"type": "string"
},
"value": {
"title": "Value",
"type": "string"
}
}
}
},
"availability": {
"title": "Availability column label",
"type": "object",
"properties": {
"label": {
"title": "Label",
"type": "string",
"default": "Availability"
},
"stockDisplaySettings": {
"title": "Stock display settings",
"description": "Control how the stock status of your products is displayed to customers on your online store.",
"type": "string",
"enum": ["showAvailability", "showStockQuantity"],
"enumNames": [
"Show availability (Available/Out of Stock)",
"Show stock quantity"
],
"default": "showAvailability"
}
}
},
"price": {
"title": "Price column label",
"type": "string",
"default": "Price"
},
"quantitySelector": {
"title": "Quantity selector column label",
"type": "string",
"default": "Quantity"
}
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import {
QuantitySelector as UIQuantitySelector,
ImageGalleryViewer as UIImageGalleryViewer,
ImageGallery as UIImageGallery,
SKUMatrix as UISKUMatrix,
SKUMatrixSidebar as UISKUMatrixSidebar,
SKUMatrixTrigger as UISKUMatrixTrigger,
} from '@faststore/ui'

import LocalImageGallery from 'src/components/ui/ImageGallery'
import LocalShippingSimulation from 'src/components/ui/ShippingSimulation/ShippingSimulation'
import { Image } from 'src/components/ui/Image'
import LocalNotAvailableButton from 'src/components/product/NotAvailableButton'
import LocalProductDescription from 'src/components/ui/ProductDescription'
import LocalSKUMatrixSidebar from 'src/components/ui/SKUMatrix/SKUMatrixSidebar'
import LocalProductDescription from 'src/components/ui/ProductDescription/ProductDescription'
import { ProductDetailsSettings as LocalProductDetailsSettings } from 'src/components/ui/ProductDetails'

export const ProductDetailsDefaultComponents = {
Expand All @@ -29,9 +33,13 @@ export const ProductDetailsDefaultComponents = {
ShippingSimulation: UIShippingSimulation,
ImageGallery: UIImageGallery,
ImageGalleryViewer: UIImageGalleryViewer,
SKUMatrix: UISKUMatrix,
SKUMatrixTrigger: UISKUMatrixTrigger,
SKUMatrixSidebar: UISKUMatrixSidebar,
__experimentalImageGalleryImage: Image,
__experimentalImageGallery: LocalImageGallery,
__experimentalShippingSimulation: LocalShippingSimulation,
__experimentalSKUMatrixSidebar: LocalSKUMatrixSidebar,
__experimentalNotAvailableButton: LocalNotAvailableButton,
__experimentalProductDescription: LocalProductDescription,
__experimentalProductDetailsSettings: LocalProductDetailsSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ export interface ProductDetailsProps {
usePriceWithTaxes?: boolean
taxesLabel?: string
}
skuMatrix?: {
shouldDisplaySKUMatrix?: boolean
triggerButtonLabel: string
separatorButtonsText: string
columns: {
name: string
additionalColumns: Array<{ label: string; value: string }>
availability: {
label: string
stockDisplaySettings: 'showAvailability' | 'showStockQuantity'
}
price: number
quantitySelector: number
}
}
}

function ProductDetails({
Expand All @@ -74,24 +89,27 @@ function ProductDetails({
initiallyExpanded: productDescriptionInitiallyExpanded,
displayDescription: shouldDisplayProductDescription,
},
skuMatrix,
notAvailableButton: { title: notAvailableButtonTitle },
quantitySelector,
taxesConfiguration,
}: ProductDetailsProps) {
const {
DiscountBadge,
ProductTitle,
SKUMatrix,
SKUMatrixTrigger,
__experimentalImageGallery: ImageGallery,
__experimentalShippingSimulation: ShippingSimulation,
__experimentalNotAvailableButton: NotAvailableButton,
__experimentalProductDescription: ProductDescription,
__experimentalProductDetailsSettings: ProductDetailsSettings,
__experimentalSKUMatrixSidebar: SKUMatrixSidebar,
} = useOverrideComponents<'ProductDetails'>()
const { currency } = useSession()
const context = usePDP()
const { product, isValidating } = context?.data
const [quantity, setQuantity] = useState(1)

if (!product) {
throw new Error('NotFound')
}
Expand All @@ -104,7 +122,11 @@ function ProductDetails({
brand,
isVariantOf,
description,
isVariantOf: { name, productGroupID: productId },
isVariantOf: {
name,
productGroupID: productId,
skuVariants: { slugsMap },
},
image: productImages,
offers: {
offers: [{ availability, price, listPrice, listPriceWithTaxes, seller }],
Expand Down Expand Up @@ -213,6 +235,27 @@ function ProductDetails({
isValidating={isValidating}
taxesConfiguration={taxesConfiguration}
/>

{skuMatrix?.shouldDisplaySKUMatrix &&
Object.keys(slugsMap).length > 1 && (
<>
<div data-fs-product-details-settings-separator>
{skuMatrix.separatorButtonsText}
</div>

<SKUMatrix.Component>
<SKUMatrixTrigger.Component disabled={isValidating}>
{skuMatrix.triggerButtonLabel}
</SKUMatrixTrigger.Component>

<SKUMatrixSidebar.Component
formatter={useFormattedPrice}
columns={skuMatrix.columns}
overlayProps={{ className: styles.section }}
/>
</SKUMatrix.Component>
</>
)}
</section>

{!outOfStock && (
Expand Down Expand Up @@ -277,7 +320,7 @@ export const fragment = gql(`
isVariantOf {
name
productGroupID
skuVariants {
skuVariants {
activeVariations
slugsMap
availableVariations
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
@layer components {
.section {
// Taxes label
--fs-product-details-taxes-label-color : var(--fs-color-info-text);
--fs-product-details-taxes-text-size : var(--fs-text-size-tiny);
--fs-product-details-taxes-text-weight : var(--fs-text-weight-regular);
--fs-product-details-taxes-label-color : var(--fs-color-info-text);
--fs-product-details-taxes-text-size : var(--fs-text-size-tiny);
--fs-product-details-taxes-text-weight : var(--fs-text-weight-regular);

// Separator colors
--fs-product-details-separator-color : var(--fs-color-neutral-2);
--fs-product-details-separator-color-text : var(--fs-color-text-light);

margin-top: 0;

Expand All @@ -29,11 +33,43 @@
@import "@faststore/ui/src/components/organisms/ShippingSimulation/styles.scss";
@import "@faststore/ui/src/components/organisms/ImageGallery/styles.scss";
@import "@faststore/ui/src/components/organisms/ProductDetails/styles.scss";
@import "@faststore/ui/src/components/organisms/SlideOver/styles.scss";
@import "@faststore/ui/src/components/organisms/SKUMatrix/styles.scss";

[data-fs-product-details-taxes-label] {
font-size: var(--fs-product-details-taxes-text-size);
font-weight: var(--fs-product-details-taxes-text-weight);
color: var(--fs-product-details-taxes-label-color);
}

[data-fs-product-details-settings-separator] {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--fs-product-details-separator-color-text);

&::after {
display: inline-block;
width: 45%;
height: 1px;
content: "";
background-color: var(--fs-product-details-separator-color);
}

&::before {
display: inline-block;
width: 45%;
height: 1px;
content: "";
background-color: var(--fs-product-details-separator-color);
}
}

[data-fs-sku-matrix] {
> [data-fs-button] {
width: 100%;
}
}
}
}
Loading