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

Bugifx/ecd 1011 garantie sgr dublata trimisa ca articol in picking app #344

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1150,3 +1150,5 @@ Rename `large` prop to `isSizeLarge` for better description
### Added

- Publish first version of the app.

## [0.0.1] - 2024-01-08
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The Minicart is a block that displays a summary list of all items added to the s

```json
"dependencies": {
"vtex.minicart": "2.x"
"auchan.minicart": "0.x"
}
```

Expand Down
6 changes: 3 additions & 3 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"vendor": "vtex",
"vendor": "auchan",
"name": "minicart",
"title": "Mini Cart",
"version": "2.68.0",
Expand All @@ -14,6 +14,8 @@
"postreleasy": "vtex publish --verbose"
},
"dependencies": {
"auchan.product-list": "0.x",
"auchan.checkout-summary": "0.x",
"vtex.product-summary": "2.x",
"vtex.store-resources": "0.x",
"vtex.store-components": "3.x",
Expand All @@ -26,10 +28,8 @@
"vtex.css-handles": "1.x",
"vtex.order-manager": "0.x",
"vtex.order-items": "0.x",
"vtex.product-list": "0.x",
"vtex.device-detector": "0.x",
"vtex.store-drawer": "0.x",
"vtex.checkout-summary": "0.x",
"vtex.checkout-resources": "0.x",
"vtex.flex-layout": "0.x",
"vtex.rich-text": "0.x",
Expand Down
9 changes: 4 additions & 5 deletions react/ProductList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,15 @@ const ProductList: FC<Props> = ({

return (
<div
/*
/*
This prevents an interaction with the quantity selector
inside of a product in the ProductList to bubble up a
mouseleave event to the Popup component, which would result
in the minicart being closed (when openOnHover = true).
in the minicart being closed (when openOnHover = true).
*/
onMouseLeave={e => e.stopPropagation()}
className={`${handles.minicartProductListContainer} ${
renderAsChildren ? 'w-100 h-100' : ''
} overflow-y-auto ph4 ph6-l`}
className={`${handles.minicartProductListContainer} ${renderAsChildren ? 'w-100 h-100' : ''
} overflow-y-auto ph4 ph6-l`}
>
<ExtensionPoint
id="product-list"
Expand Down
133 changes: 128 additions & 5 deletions react/Summary.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,143 @@
import React, { FC } from 'react'
import React, { FC, useEffect, useMemo, useState } from 'react'
import { ExtensionPoint } from 'vtex.render-runtime'
import { OrderForm as OrderFormComponent } from 'vtex.order-manager'
import { OrderForm as OrderFormComponent, OrderQueue } from 'vtex.order-manager'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import { fetchWithRetry } from './legacy/utils/fetchWithRetry'

const CSS_HANDLES = ['minicartSummary'] as const

interface Props {
classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

const Summary: FC<Props> = ({ classes }) => {
const { useOrderForm } = OrderFormComponent
const { useOrderForm } = OrderFormComponent;
const { useOrderQueue, QueueStatus } = OrderQueue;
const orderFormContext = useOrderForm();

const {
orderForm: { totalizers, value, items, paymentData },
} = useOrderForm()
} = orderFormContext;
const { listen } = useOrderQueue();

const [finalTotalizers, setFinalTotalizers] = useState(totalizers);

const [packagesSkuIds, setPackagesSkuIds] = useState<string[]>([])
const [sgrSkuIds, setSgrSkuIds] = useState<string[]>([])

useEffect(() => {
let isSubscribed = true

fetchWithRetry('/_v/private/api/cart-bags-manager/app-settings', 3).then(
(res: PackagesSkuIds) => {
if (res && isSubscribed) {
try {
const { bagsSettings, sgrSettings } = res?.data ?? {}

setPackagesSkuIds(Object.values(bagsSettings))

const allSkuIds: string[] = []

Object.values(sgrSettings).forEach(sgrType => {
if (sgrType?.skuIds) {
allSkuIds.push(...sgrType.skuIds)
}
})

setSgrSkuIds(allSkuIds)
} catch (error) {
console.error('Error in packages feature.', error)
}
}
}
)

return () => {
isSubscribed = false
}
}, [])

const flegValue = useMemo(() => {
if (!packagesSkuIds.length) {
return
}
return items.reduce((total: number, item: OrderFormItem) => {
if (packagesSkuIds.includes(item.id)) {
return (
total + ((item?.listPrice as number) ?? 0) * (item?.quantity ?? 1)
)
}
return total
}, 0)
}, [items, packagesSkuIds])

const sgrValue = useMemo(() => {
if (!sgrSkuIds.length) {
return
}
return items.reduce((total: number, item: OrderFormItem) => {
if (sgrSkuIds.includes(item.id)) {
return (
total + ((item?.listPrice as number) ?? 0) * (item?.quantity ?? 1)
)
}
return total
}, 0)
}, [items, sgrSkuIds])

listen(QueueStatus.FULFILLED, () => {
const onlySgrOrBags = items.every(
(item: any) =>
sgrSkuIds.includes(item.id) || packagesSkuIds.includes(item.id)
)

if (onlySgrOrBags) {
computeTotalizers()
}
});

useEffect(() => {
computeTotalizers()
}, [items, flegValue, sgrValue, totalizers])

const computeTotalizers = () => {
if (!items?.length) {
setFinalTotalizers([])
return
}

let newTotalizers = JSON.parse(JSON.stringify(totalizers))

const totalizerItems = newTotalizers.find((t: { id: string }) => t.id === 'Items')

if (flegValue && typeof flegValue === 'number') {
newTotalizers.push({
id: 'Packaging',
name: 'Taxa ambalare',
value: flegValue,
__typename: 'Totalizer',
})

if (totalizerItems) {
totalizerItems.value -= flegValue ?? 0
}
}

if (sgrValue && typeof sgrValue === 'number') {
newTotalizers.push({
id: 'SGR',
name: 'Garantie',
value: sgrValue,
__typename: 'Totalizer',
})
if (totalizerItems) {
totalizerItems.value -= sgrValue ?? 0
}
}

setFinalTotalizers(newTotalizers)
}

const { handles } = useCssHandles(CSS_HANDLES, { classes })

Expand All @@ -30,7 +153,7 @@ const Summary: FC<Props> = ({ classes }) => {
<div className={`${handles.minicartSummary} ph4 ph6-l pt5`}>
<ExtensionPoint
id="checkout-summary"
totalizers={totalizers}
totalizers={finalTotalizers}
paymentData={paymentData}
total={value}
originalTotal={originalValue}
Expand Down
56 changes: 52 additions & 4 deletions react/components/MinicartIconButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import { ButtonWithIcon } from 'vtex.styleguide'
import { useOrderForm } from 'vtex.order-manager/OrderForm'
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'
Expand All @@ -7,6 +7,7 @@ import styles from '../styles.css'
import { useMinicartCssHandles } from './CssHandlesContext'
import { useMinicartDispatch, useMinicartState } from '../MinicartContext'
import useCheckout from '../modules/checkoutHook'
import { fetchWithRetry } from '../legacy/utils/fetchWithRetry'

export const CSS_HANDLES = [
'minicartIconContainer',
Expand All @@ -22,10 +23,18 @@ interface Props {

const countCartItems = (
countMode: MinicartTotalItemsType,
allItems: OrderFormItem[]
allItems: OrderFormItem[],
packagesSkuIds: string[],
sgrSkuIds: string[]
) => {
// Filter only main products, remove assembly items from the count
const items = allItems.filter(item => item.parentItemIndex === null)
const items = allItems.filter(
item =>
item.parentItemIndex === null &&
item.productId &&
!packagesSkuIds.includes(item.productId) &&
!sgrSkuIds.includes(item.productId)
)

if (countMode === 'distinctAvailable') {
return items.reduce((itemQuantity: number, item) => {
Expand Down Expand Up @@ -61,7 +70,46 @@ const MinicartIconButton: React.FC<Props> = props => {
const { handles } = useMinicartCssHandles()
const { open, openBehavior, openOnHoverProp } = useMinicartState()
const dispatch = useMinicartDispatch()
const quantity = countCartItems(itemCountMode, orderForm.items)
const [packagesSkuIds, setPackagesSkuIds] = useState<string[]>([])
const [sgrSkuIds, setSgrSkuIds] = useState<string[]>([])

useEffect(() => {
let isSubscribed = true

fetchWithRetry('/_v/private/api/cart-bags-manager/app-settings', 3).then(
(res: PackagesSkuIds) => {
if (res && isSubscribed) {
try {
const { bagsSettings, sgrSettings } = res?.data ?? {}

setPackagesSkuIds(Object.values(bagsSettings))

const allSkuIds: string[] = []

Object.values(sgrSettings).forEach(sgrType => {
if (sgrType?.skuIds) {
allSkuIds.push(...sgrType.skuIds)
}
})

setSgrSkuIds(allSkuIds)
} catch (error) {
console.error('Error in packages feature.', error)
}
}
}
)

return () => {
isSubscribed = false
}
}, [])
const quantity = countCartItems(
itemCountMode,
orderForm.items,
packagesSkuIds,
sgrSkuIds
)
const itemQuantity = loading ? 0 : quantity
const { url: checkoutUrl } = useCheckoutURL()
const goToCheckout = useCheckout()
Expand Down
18 changes: 18 additions & 0 deletions react/legacy/utils/fetchWithRetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
interface FetchWithRetry {
(url: string, retries: number): Promise<PackagesSkuIds>
}

export const fetchWithRetry: FetchWithRetry = (url: string, retries: number) =>
fetch(url)
.then(res => {
if (res.ok) {
return res.json()
}

if (retries > 0) {
return fetchWithRetry(url, retries - 1)
}

throw new Error(`Failed to fetch: ${url}`)
})
.catch(error => console.error(error.message))
22 changes: 10 additions & 12 deletions react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,26 @@
"apollo-cache-inmemory": "^1.6.5",
"babel-eslint": "^10.1.0",
"typescript": "3.9.7",
"vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].0/public/@types/vtex.checkout-graphql",
"vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].3/public/@types/vtex.checkout-graphql",
"vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.checkout-resources",
"vtex.checkout-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.checkout-summary",
"vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.css-handles",
"vtex.device-detector": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.device-detector",
"vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].0/public/@types/vtex.flex-layout",
"vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].21/public/@types/vtex.order-items",
"vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].3/public/@types/vtex.flex-layout",
"vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].23/public/@types/vtex.order-items",
"vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.order-manager",
"vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.pixel-manager",
"vtex.product-list": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.product-list",
"vtex.product-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.product-summary",
"vtex.product-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.product-summary",
"vtex.react-portal": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.react-portal",
"vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.133.0/public/@types/vtex.render-runtime",
"vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.134.2/public/@types/vtex.render-runtime",
"vtex.responsive-values": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.responsive-values",
"vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.rich-text",
"vtex.sandbox": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.sandbox",
"vtex.store-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-components@3.167.0/public/@types/vtex.store-components",
"vtex.store-drawer": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].2/public/@types/vtex.store-drawer",
"vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.161.2/public/@types/vtex.store-graphql",
"vtex.store-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-components@3.170.0/public/@types/vtex.store-components",
"vtex.store-drawer": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].3/public/@types/vtex.store-drawer",
"vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.170.1/public/@types/vtex.store-graphql",
"vtex.store-icons": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected]/public/@types/vtex.store-icons",
"vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.89.0/public/@types/vtex.store-resources",
"vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].3/public/@types/vtex.styleguide"
"vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.93.0/public/@types/vtex.store-resources",
"vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/[email protected].9/public/@types/vtex.styleguide"
},
"dependencies": {
"apollo-client": "2.6.4",
Expand Down
25 changes: 25 additions & 0 deletions react/typings/packages-sku-ids.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface PackagesSkuIds {
data: {
bagsSettings: {
bioFlegBagId: string
insulationBagId: string
plasticBagId: string
paperBagId: string
}
sgrSettings: {
aluminumCanProducts: {
label: string
skuIds: string[]
}
glassBottleProducts: {
label: string
skuIds: string[]
}
plasticBottleProducts: {
label: string
skuIds: string[]
}
}
}
error: null | string
}
Loading