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

Voucherify integration (deprecated) #1

Draft
wants to merge 14 commits into
base: feat/cart-persistance
Choose a base branch
from
1 change: 1 addition & 0 deletions composable-ui/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = () => {
transpilePackages: [
'@composable/cms-generic',
'@composable/commerce-generic',
'@composable/voucherify',
'@composable/stripe',
'@composable/types',
'@composable/ui',
Expand Down
1 change: 1 addition & 0 deletions composable-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@chakra-ui/theme-tools": "^2.0.16",
"@composable/cms-generic": "workspace:*",
"@composable/commerce-generic": "workspace:*",
"@composable/voucherify": "workspace:*",
"@composable/stripe": "workspace:*",
"@composable/types": "workspace:*",
"@composable/ui": "workspace:*",
Expand Down
12 changes: 11 additions & 1 deletion composable-ui/src/components/cart/__data__/cart-data.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { CartItemWithDiscounts } from '@composable/types'
import { CartData } from '../../../hooks'

export const cartData: CartData = {
id: '7a6dd462-24dc-11ed-861d-0242ac120002',
cartType: 'CartWithDiscounts',
redeemables: [],
items: [
{
id: '1',
cartItemType: 'CartItemWithDiscounts',
category: 'Accessories',
type: 'Bag',
name: 'Venture Daypack',
Expand All @@ -17,12 +21,18 @@ export const cartData: CartData = {
sku: 'SKU-A1-2345',
slug: 'venture-daypack',
quantity: 1,
discounts: {
subtotalAmount: '',
},
},
],
] as CartItemWithDiscounts[],
summary: {
taxes: '2.45',
totalPrice: '35.00',
shipping: 'Free',
discountAmount: '0',
totalDiscountAmount: '0',
grandPrice: '0',
},
isLoading: false,
isEmpty: false,
Expand Down
66 changes: 66 additions & 0 deletions composable-ui/src/components/cart/cart-promotions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useIntl } from 'react-intl'
import { CartItem, Redeemable } from '@composable/types'
import {
Box,
Divider,
Flex,
HStack,
Link,
StackDivider,
Tag,
TagCloseButton,
TagLabel,
Wrap,
WrapItem,
Text,
useBreakpointValue,
TagLeftIcon,
} from '@chakra-ui/react'
import { Icon } from '@chakra-ui/icons'
import { MdShoppingCart } from 'react-icons/md'
import { Price } from 'components/price'
import { QuantityPicker } from 'components/quantity-picker'
import { CartItemData, CartSummaryItem } from '.'

interface CartPromotionsProps {
promotions: Redeemable[]
}

export const CartPromotions = ({ promotions }: CartPromotionsProps) => {
const intl = useIntl()
// const isMobile = useBreakpointValue({ base: true, md: false })
if (!promotions.length) {
return null
}

return (
<>
<CartSummaryItem
label={intl.formatMessage({
id: 'cart.summary.promotions',
})}
></CartSummaryItem>
{promotions.map((redeemable) => (
<Flex key={redeemable.id} justify="space-between">
<Tag
size="md"
paddingRight={2}
paddingLeft={2}
borderRadius="sm"
variant="outline"
colorScheme="whiteAlpha"
>
<TagLeftIcon boxSize="12px" as={MdShoppingCart} />
<TagLabel>{redeemable.label}</TagLabel>
</Tag>
<Box>
<Price
rootProps={{ textStyle: 'Body-S', color: 'green' }}
price={`-${redeemable.discount}`}
/>
</Box>
</Flex>
))}
</>
)
}
42 changes: 42 additions & 0 deletions composable-ui/src/components/cart/cart-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useIntl } from 'react-intl'
import { useRouter } from 'next/router'
import { CartData, useCart } from 'hooks'
import { Price } from 'components/price'
import { CouponForm } from 'components/forms/coupon-form'
import {
Box,
Button,
Expand All @@ -12,6 +13,7 @@ import {
Text,
} from '@chakra-ui/react'
import { CartSummaryItem } from '.'
import { CartPromotions } from './cart-promotions'

interface CartSummaryProps {
rootProps?: StackProps
Expand All @@ -29,6 +31,15 @@ export const CartSummary = ({
const intl = useIntl()
const _cartData = cartData ?? cart

const vouchers =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this voucher const can be deleted from this file

_cartData.redeemables?.filter(
(redeemable) => redeemable.object === 'voucher'
) || []
const promotions =
_cartData.redeemables?.filter(
(redeemable) => redeemable.object === 'promotion_tier'
) || []

return (
<Stack spacing={{ base: '4', md: '6' }} width="full" {...rootProps}>
<Stack bg="shading.100" p={'2rem 1.5rem'}>
Expand Down Expand Up @@ -90,6 +101,37 @@ export const CartSummary = ({
</Flex>
</>
)}
<CartPromotions promotions={promotions} />
<CouponForm />
{_cartData.summary?.totalDiscountAmount && (
<CartSummaryItem
label={intl.formatMessage({
id: 'cart.summary.totalDiscountAmount',
})}
>
<Price
rootProps={{ textStyle: 'Body-S', color: 'green' }}
price={`-${_cartData.summary.totalDiscountAmount}`}
/>
</CartSummaryItem>
)}

{_cartData.summary?.grandPrice && (
<>
<Divider />
<Flex
justify="space-between"
textStyle={{ base: 'Mobile/S', md: 'Desktop/S' }}
>
<Text>
{intl.formatMessage({ id: 'cart.summary.grandPrice' })}
</Text>
<Box>
<Price price={_cartData.summary.grandPrice} />
</Box>
</Flex>
</>
)}
</Stack>
</Stack>

Expand Down
156 changes: 156 additions & 0 deletions composable-ui/src/components/forms/coupon-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import * as yup from 'yup'
import { useIntl } from 'react-intl'
import { useForm } from 'react-hook-form'
import {
Alert,
AlertIcon,
Box,
Flex,
TagLeftIcon,
Wrap,
WrapItem,
} from '@chakra-ui/react'
import { yupResolver } from '@hookform/resolvers/yup'
import { useState } from 'react'
import { IconButton, Text } from '@chakra-ui/react'
import { ArrowForwardIcon } from '@chakra-ui/icons'
import { InputField } from '@composable/ui'
import { Tag, TagLabel, TagCloseButton } from '@chakra-ui/react'
import { useCart } from 'hooks'
import { Price } from 'components/price'
import { CartSummaryItem } from 'components/cart'
import { Icon } from '@chakra-ui/react'
import { MdDiscount } from 'react-icons/md'
import { displayValue } from '@tanstack/react-query-devtools/build/lib/utils'

export const CouponForm = () => {
const intl = useIntl()
const [errorMessage, setErrorMessage] = useState<false | string>(false)
const {
register,
handleSubmit,
setError,
setValue,
formState: { errors },
} = useForm<{ coupon: string }>({
resolver: yupResolver(couponFormSchema()),
mode: 'all',
})
const { cart, addCartCoupon, deleteCartCoupon } = useCart({
onCartCouponAddError: (msg) => {
setErrorMessage(msg || 'Could not add coupon')
},
})

const content = {
input: {
coupon: {
label: intl.formatMessage({ id: 'cart.summary.label.coupon' }),
placeholder: intl.formatMessage({ id: 'cart.summary.label.coupon' }),
},
},
button: {
login: intl.formatMessage({ id: 'action.addCoupon' }),
},
}

const vouchers =
cart.redeemables?.filter((redeemable) => redeemable.object === 'voucher') ||
[]

return (
<>
<CartSummaryItem
label={intl.formatMessage({
id: 'cart.summary.couponCodes',
})}
></CartSummaryItem>
<form
role={'form'}
onSubmit={handleSubmit(async (data) => {
setErrorMessage(false)

// setError('coupon', {message: 'Could not add coupon' })
await addCartCoupon.mutate({
cartId: cart.id || '',
coupon: data.coupon,
})
setValue('coupon', '')
})}
>
<Box
display={'flex'}
flexDirection={'row'}
alignItems={'flex-start'}
justifyContent={'center'}
height={'60px'}
gap={3}
>
<InputField
inputProps={{
size: 'sm',
fontSize: 'sm',
placeholder: content.input.coupon.placeholder,
...register('coupon'),
}}
error={errors.coupon}
label={''}
/>
<IconButton
mt={2}
aria-label="Search database"
icon={<ArrowForwardIcon />}
type="submit"
size="sm"
variant={'outline'}
/>
</Box>
{errorMessage && (
<Alert mt={2} status="warning" borderRadius={'6px'}>
<AlertIcon alignSelf={'flex-start'} />
{errorMessage}
</Alert>
)}
</form>
{vouchers.map((redeemable) => (
<Flex
key={redeemable.id}
justify="space-between"
textStyle={{ base: 'Mobile/S', md: 'Desktop/S' }}
>
<Tag
size="md"
paddingRight={2}
paddingLeft={2}
borderRadius="sm"
variant="outline"
colorScheme="whiteAlpha"
>
<TagLeftIcon boxSize="12px" as={MdDiscount} />
<TagLabel>{redeemable.label}</TagLabel>
<TagCloseButton
onClick={() =>
deleteCartCoupon.mutate({
cartId: cart.id || '',
coupon: redeemable.id,
})
}
/>
</Tag>
<Box>
<Price
rootProps={{ textStyle: 'Body-S', color: 'green' }}
price={`-${redeemable.discount}`}
/>
</Box>
</Flex>
))}
</>
)
}

const couponFormSchema = () => {
return yup.object().shape({
coupon: yup.string().required(),
})
}
Loading