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

Add validation components to cart/checkout, add redemption #5

Open
wants to merge 50 commits into
base: feat/cart-persistance
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
0461d97
commerce wrapper - POC - WIP
Oct 16, 2023
c56b763
wrap commerce-generic and validate cart
Oct 17, 2023
5ca245b
PoC coupon on frontend side
Oct 18, 2023
be8b4e4
PoC handling coupon errors on frontend
Oct 18, 2023
0f512b6
refactoring
Oct 25, 2023
0d936a4
Merge branch 'feat/cart-persistance' into commerce-wrapper
Oct 31, 2023
310b634
reafactoring round one
Oct 31, 2023
1ac1568
refactoring round two
Oct 31, 2023
0b079e6
upload products to Voucherify
Oct 31, 2023
0726e9c
PoC Promotions
Nov 2, 2023
7fc7458
fix build error
Nov 2, 2023
d35191c
- display vouchers and promotions seperatelly
Nov 3, 2023
d026c93
fix naming
weronika-kurczyna Nov 7, 2023
6c9b235
add discount info to sidebar and checkout
weronika-kurczyna Nov 8, 2023
af42452
wrapped order with discount
weronika-kurczyna Nov 8, 2023
aef8301
Order With Discounts
weronika-kurczyna Nov 8, 2023
abb973b
send grandPrice to Stripe
weronika-kurczyna Nov 8, 2023
e7f33d1
Display discounts properly
weronika-kurczyna Nov 9, 2023
5244d40
Add redemption to checkout
weronika-kurczyna Nov 9, 2023
b2ada4c
use checkout - redeem
weronika-kurczyna Nov 13, 2023
dc61635
Check whether the redemptions were successful
weronika-kurczyna Nov 13, 2023
08b27c6
Filter out the promotions from redeemables
weronika-kurczyna Nov 13, 2023
9c59e22
Update order-with-discount.ts
weronika-kurczyna Nov 13, 2023
787299d
Redeem promotions
weronika-kurczyna Nov 13, 2023
a52a8f2
If there's no grandPrice, use totalPrice
weronika-kurczyna Nov 13, 2023
b231e84
Add information about applied discount to the mobile view of cart sum…
weronika-kurczyna Nov 13, 2023
1e527fe
Fix naming
weronika-kurczyna Nov 14, 2023
dd6ac49
Update create-order.ts
weronika-kurczyna Nov 14, 2023
a92d629
Remove unused imports
weronika-kurczyna Nov 14, 2023
ae6f8fd
Refactor
weronika-kurczyna Nov 14, 2023
f22a60f
Remove required from coupon form
weronika-kurczyna Nov 14, 2023
26730b6
Update persit.ts
weronika-kurczyna Nov 14, 2023
1a598e3
Unused imports
weronika-kurczyna Nov 14, 2023
ab40080
Fix localStorage name
weronika-kurczyna Nov 15, 2023
81c3aa4
Prevent value from being reset when an invalid coupon has been used
weronika-kurczyna Nov 15, 2023
23f4107
Unused imports in cart promotions
weronika-kurczyna Nov 17, 2023
b6c896a
Add Dividers to cart summary
weronika-kurczyna Nov 21, 2023
ecdd7a4
Add grey stacks for promotions and pass green colour for discounts
weronika-kurczyna Nov 21, 2023
e9faea6
Wrapper for addOrder - add discount info to final step
weronika-kurczyna Nov 21, 2023
fcfa832
Display promotion stack condionally
weronika-kurczyna Nov 21, 2023
5c98f57
Better cart drawer
weronika-kurczyna Nov 21, 2023
66a7492
Fix naming in checkout
weronika-kurczyna Nov 21, 2023
709d06c
Remove additional button "proceed to checkout"
weronika-kurczyna Nov 22, 2023
40e2e0c
Use cart instead of _cartData
weronika-kurczyna Nov 22, 2023
ff7ef22
Styling of cart drawer
weronika-kurczyna Nov 22, 2023
738ac78
Update warning appearance
weronika-kurczyna Nov 22, 2023
941ba18
Change the font size in cart
weronika-kurczyna Nov 22, 2023
7aab5cc
Fix - type of data returned onCartCouponAddSuccess
weronika-kurczyna Nov 22, 2023
02713cd
Restore previous CartSummary
weronika-kurczyna Nov 22, 2023
a88bb63
Fix type name
weronika-kurczyna Nov 22, 2023
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
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export const CartDrawerFooter = () => {
color={'text-muted'}
textStyle={{ base: 'Mobile/Eyebrow', md: 'Desktop/Body-XS' }}
>
{intl.formatMessage({ id: 'cart.summary.estimatedTotal' })}
{intl.formatMessage({ id: 'cart.summary.grandPrice' })}
</Text>
</Box>
<Box>
<Price
rootProps={{ textStyle: { base: 'Mobile/XS', md: 'Desktop/M' } }}
price={cart.summary?.totalPrice ?? ''}
price={cart.summary?.grandPrice ?? ''}
/>
</Box>
</VStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,43 @@ export const CartDrawerSummary = () => {
<Divider m={'10px 0'} />

{cart.summary?.totalPrice && (
<CartDrawerSummaryItem
label={intl.formatMessage({ id: 'cart.summary.orderTotal' })}
>
<Box>
<Price
rootProps={{ textStyle: 'Desktop/XS' }}
price={cart.summary.totalPrice}
/>
</Box>
</CartDrawerSummaryItem>
)}

{cart.summary?.totalDiscountAmount && (
<CartDrawerSummaryItem
label={intl.formatMessage({ id: 'cart.summary.totalDiscountAmount' })}
>
<Box>
<Price
rootProps={{
textStyle: 'Body-XS',
color: 'green',
}}
price={`-${cart.summary.totalDiscountAmount}`}
/>
</Box>
</CartDrawerSummaryItem>
)}
<Divider m={'10px 0'} />
{cart.summary?.grandPrice && (
<>
<Flex
justify="space-between"
textStyle={{ base: 'Mobile/S', md: 'Desktop/S' }}
>
<Text>
{intl.formatMessage({ id: 'cart.summary.estimatedTotal' })}
</Text>
<Text>{intl.formatMessage({ id: 'cart.summary.grandPrice' })}</Text>
<Box>
<Price
rootProps={{ textStyle: 'Desktop/S' }}
price={cart.summary.totalPrice}
/>
<Price price={cart.summary.grandPrice} />
</Box>
</Flex>
</>
Expand Down
15 changes: 15 additions & 0 deletions composable-ui/src/components/cart/cart-drawer/cart-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { CartDrawerFooter } from './cart-drawer-footer'
import { CartDrawerSummary } from './cart-drawer-summary'
import { CartDrawerEmptyState } from './cart-drawer-empty-state'
import { HorizontalProductCard } from '@composable/ui'
import { CouponForm } from '../../forms/coupon-form'
import { CartPromotions } from '../cart-promotions'

export const CartDrawer = () => {
const intl = useIntl()
Expand All @@ -47,6 +49,11 @@ export const CartDrawer = () => {
style: 'currency',
}

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

useEffect(() => {
router.events.on('routeChangeStart', cartDrawer.onClose)
return () => {
Expand Down Expand Up @@ -148,6 +155,14 @@ export const CartDrawer = () => {
)
})}
</Stack>
{promotions.length > 0 && (
<Stack bg="shading.100" p={'0.7rem 1.5rem'} mb={'-5'}>
<CartPromotions promotions={promotions} />
</Stack>
)}
<Stack bg="shading.100" p={'0.7rem 1.5rem'} mb={'-5'}>
<CouponForm />
</Stack>
<CartDrawerSummary />
</Stack>
)}
Expand Down
48 changes: 48 additions & 0 deletions composable-ui/src/components/cart/cart-promotions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useIntl } from 'react-intl'
import { Redeemable } from '@composable/types'
import { Box, Flex, Tag, TagLabel, TagLeftIcon } from '@chakra-ui/react'
import { MdShoppingCart } from 'react-icons/md'
import { Price } from 'components/price'
import { CartSummaryItem } from '.'

interface CartPromotionsProps {
promotions: Redeemable[]
}

export const CartPromotions = ({ promotions }: CartPromotionsProps) => {
const intl = useIntl()
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>
))}
</>
)
}
40 changes: 39 additions & 1 deletion 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,12 +31,17 @@ export const CartSummary = ({
const intl = useIntl()
const _cartData = cartData ?? cart

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'}>
<Text
as={'h2'}
textStyle={{ base: 'Mobile/XS', md: 'Desktop/M' }}
textStyle={{ base: 'Mobile/M', md: 'Desktop/M' }}
fontWeight={900}
mb="sm"
>
Expand Down Expand Up @@ -90,6 +97,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
25 changes: 5 additions & 20 deletions composable-ui/src/components/cart/cart-total.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { useIntl } from 'react-intl'
import { useRouter } from 'next/router'
import { CartData, useCart } from 'hooks'
import { useCart } from 'hooks'
import { Price } from 'components/price'
import { Button, Flex, Text, FlexProps } from '@chakra-ui/react'
import { Flex, Text, FlexProps } from '@chakra-ui/react'

interface CartTotalProps {
rootProps?: FlexProps
cartData?: CartData
}

export const CartTotal = ({ cartData, rootProps }: CartTotalProps) => {
const router = useRouter()
export const CartTotal = ({ rootProps }: CartTotalProps) => {
const { cart } = useCart()
const intl = useIntl()
const _cartData = cartData ?? cart

return (
<>
Expand All @@ -23,20 +19,9 @@ export const CartTotal = ({ cartData, rootProps }: CartTotalProps) => {
mb={'1rem'}
{...rootProps}
>
<Text>{intl.formatMessage({ id: 'cart.summary.estimatedTotal' })}</Text>
<Price price={_cartData.summary?.totalPrice ?? ''} />
<Text>{intl.formatMessage({ id: 'cart.summary.orderTotal' })}</Text>
<Price price={cart.summary?.totalPrice ?? ''} />
</Flex>
<Button
onClick={() => {
router.push('/checkout')
}}
w={{ base: 'full' }}
maxW={{ base: 'full' }}
variant={'solid'}
size={'lg'}
>
{intl.formatMessage({ id: 'action.proceedToCheckout' })}
</Button>
</>
)
}
Loading
Loading