diff --git a/.env.template b/.env.template index c5543e4b1..b24458b80 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,4 @@ -# Available providers: bigcommerce, shopify, swell +# Available providers: local, bigcommerce, shopify, swell, saleor COMMERCE_PROVIDER= BIGCOMMERCE_STOREFRONT_API_URL= @@ -7,6 +7,10 @@ BIGCOMMERCE_STORE_API_URL= BIGCOMMERCE_STORE_API_TOKEN= BIGCOMMERCE_STORE_API_CLIENT_ID= BIGCOMMERCE_CHANNEL_ID= +BIGCOMMERCE_STORE_URL= +BIGCOMMERCE_STORE_API_STORE_HASH= +BIGCOMMERCE_STORE_API_CLIENT_SECRET= + NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN= NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN= @@ -16,3 +20,6 @@ NEXT_PUBLIC_SWELL_PUBLIC_KEY= NEXT_PUBLIC_SALEOR_API_URL= NEXT_PUBLIC_SALEOR_CHANNEL= + +NEXT_PUBLIC_VENDURE_SHOP_API_URL= +NEXT_PUBLIC_VENDURE_LOCAL_URL= diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..96856ac29 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": ["next", "prettier"], + "rules": { + "react/no-unescaped-entities": "off" + } +} diff --git a/README.md b/README.md index 8204b3445..2eeea375b 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ For example: Turning `cart` off will disable Cart capabilities. > NOTE: The selected provider should support the feature that you are toggling. (This means that you can't turn wishlist on if the provider doesn't support this functionality out the box) -- Open `commerce.config.json` +- Open `commerce.config.json` - You'll see a config file like this: ```json { @@ -151,5 +151,5 @@ Next, you're free to customize the starter. More updates coming soon. Stay tuned After Email confirmation, Checkout should be manually enabled through BigCommerce platform. Look for "Review & test your store" section through BigCommerce's dashboard.

-BigCommerce team has been notified and they plan to add more detailed about this subject. +BigCommerce team has been notified and they plan to add more details about this subject. diff --git a/assets/base.css b/assets/base.css index 00081f459..05a234a73 100644 --- a/assets/base.css +++ b/assets/base.css @@ -77,7 +77,6 @@ html { height: 100%; box-sizing: border-box; touch-action: manipulation; - font-feature-settings: 'case' 1, 'rlig' 1, 'calt' 0; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/components/auth/LoginView.tsx b/components/auth/LoginView.tsx index 35ff98f66..5e513deb9 100644 --- a/components/auth/LoginView.tsx +++ b/components/auth/LoginView.tsx @@ -38,6 +38,7 @@ const LoginView: FC = () => { } catch ({ errors }) { setMessage(errors[0].message) setLoading(false) + setDisabled(false) } } diff --git a/components/cart/CartItem/CartItem.tsx b/components/cart/CartItem/CartItem.tsx index a59024e06..4453e0c08 100644 --- a/components/cart/CartItem/CartItem.tsx +++ b/components/cart/CartItem/CartItem.tsx @@ -70,6 +70,9 @@ const CartItem = ({ if (item.quantity !== Number(quantity)) { setQuantity(item.quantity) } + // TODO: currently not including quantity in deps is intended, but we should + // do this differently as it could break easily + // eslint-disable-next-line react-hooks/exhaustive-deps }, [item.quantity]) return ( diff --git a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx index fb562e7af..13a523288 100644 --- a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx +++ b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx @@ -1,30 +1,39 @@ -import cn from 'classnames' import Link from 'next/link' import { FC } from 'react' import CartItem from '@components/cart/CartItem' import { Button, Text } from '@components/ui' import { useUI } from '@components/ui/context' +import SidebarLayout from '@components/common/SidebarLayout' import useCart from '@framework/cart/use-cart' import usePrice from '@framework/product/use-price' +import useCheckout from '@framework/checkout/use-checkout' import ShippingWidget from '../ShippingWidget' import PaymentWidget from '../PaymentWidget' -import SidebarLayout from '@components/common/SidebarLayout' import s from './CheckoutSidebarView.module.css' const CheckoutSidebarView: FC = () => { - const { setSidebarView } = useUI() - const { data } = useCart() + const { setSidebarView, closeSidebar } = useUI() + const { data: cartData } = useCart() + const { data: checkoutData, submit: onCheckout } = useCheckout() + + async function handleSubmit(event: React.ChangeEvent) { + event.preventDefault() + + await onCheckout() + + closeSidebar() + } const { price: subTotal } = usePrice( - data && { - amount: Number(data.subtotalPrice), - currencyCode: data.currency.code, + cartData && { + amount: Number(cartData.subtotalPrice), + currencyCode: cartData.currency.code, } ) const { price: total } = usePrice( - data && { - amount: Number(data.totalPrice), - currencyCode: data.currency.code, + cartData && { + amount: Number(cartData.totalPrice), + currencyCode: cartData.currency.code, } ) @@ -38,22 +47,31 @@ const CheckoutSidebarView: FC = () => { Checkout - setSidebarView('PAYMENT_VIEW')} /> - setSidebarView('SHIPPING_VIEW')} /> + setSidebarView('PAYMENT_VIEW')} + /> + setSidebarView('SHIPPING_VIEW')} + />
    - {data!.lineItems.map((item: any) => ( + {cartData!.lineItems.map((item: any) => ( ))}
-
+
  • Subtotal @@ -74,14 +92,15 @@ const CheckoutSidebarView: FC = () => {
{/* Once data is correcly filled */} - {/* */} -
- + ) } diff --git a/components/checkout/PaymentMethodView/PaymentMethodView.tsx b/components/checkout/PaymentMethodView/PaymentMethodView.tsx index a5f6f4b51..972073756 100644 --- a/components/checkout/PaymentMethodView/PaymentMethodView.tsx +++ b/components/checkout/PaymentMethodView/PaymentMethodView.tsx @@ -1,83 +1,129 @@ import { FC } from 'react' import cn from 'classnames' + +import useAddCard from '@framework/customer/card/use-add-item' import { Button, Text } from '@components/ui' import { useUI } from '@components/ui/context' -import s from './PaymentMethodView.module.css' import SidebarLayout from '@components/common/SidebarLayout' +import s from './PaymentMethodView.module.css' + +interface Form extends HTMLFormElement { + cardHolder: HTMLInputElement + cardNumber: HTMLInputElement + cardExpireDate: HTMLInputElement + cardCvc: HTMLInputElement + firstName: HTMLInputElement + lastName: HTMLInputElement + company: HTMLInputElement + streetNumber: HTMLInputElement + zipCode: HTMLInputElement + city: HTMLInputElement + country: HTMLSelectElement +} + const PaymentMethodView: FC = () => { const { setSidebarView } = useUI() + const addCard = useAddCard() + + async function handleSubmit(event: React.ChangeEvent
) { + event.preventDefault() + + await addCard({ + cardHolder: event.target.cardHolder.value, + cardNumber: event.target.cardNumber.value, + cardExpireDate: event.target.cardExpireDate.value, + cardCvc: event.target.cardCvc.value, + firstName: event.target.firstName.value, + lastName: event.target.lastName.value, + company: event.target.company.value, + streetNumber: event.target.streetNumber.value, + zipCode: event.target.zipCode.value, + city: event.target.city.value, + country: event.target.country.value, + }) + + setSidebarView('CHECKOUT_VIEW') + } return ( - setSidebarView('CHECKOUT_VIEW')}> -
- Payment Method -
-
- - -
-
-
- - + + setSidebarView('CHECKOUT_VIEW')}> +
+ Payment Method +
+
+ +
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - +
+
+
+ + +
+
+ + +
-
-
-
-
- - +
+ +
-
- - +
+ +
-
-
- - -
-
- - -
-
- - -
-
-
- - +
+ +
-
- - +
+
+ + +
+
+ + +
+
+
+ +
-
-
- -
-
-
- -
- +
+ +
+ + ) } diff --git a/components/checkout/PaymentWidget/PaymentWidget.tsx b/components/checkout/PaymentWidget/PaymentWidget.tsx index e1892934e..9b496bb44 100644 --- a/components/checkout/PaymentWidget/PaymentWidget.tsx +++ b/components/checkout/PaymentWidget/PaymentWidget.tsx @@ -1,14 +1,15 @@ import { FC } from 'react' import s from './PaymentWidget.module.css' -import { ChevronRight, CreditCard } from '@components/icons' +import { ChevronRight, CreditCard, Check } from '@components/icons' interface ComponentProps { onClick?: () => any + isValid?: boolean } -const PaymentWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - +const PaymentWidget: FC = ({ onClick, isValid }) => { + /* Shipping Address + Only available with checkout set to true - This means that the provider does offer checkout functionality. */ return (
@@ -19,9 +20,7 @@ const PaymentWidget: FC = ({ onClick }) => { {/* VISA #### #### #### 2345 */}
-
- -
+
{isValid ? : }
) } diff --git a/components/checkout/ShippingView/ShippingView.tsx b/components/checkout/ShippingView/ShippingView.tsx index 1d03a2aac..ed82bc8a2 100644 --- a/components/checkout/ShippingView/ShippingView.tsx +++ b/components/checkout/ShippingView/ShippingView.tsx @@ -1,77 +1,117 @@ import { FC } from 'react' import cn from 'classnames' -import s from './ShippingView.module.css' + import Button from '@components/ui/Button' import { useUI } from '@components/ui/context' import SidebarLayout from '@components/common/SidebarLayout' +import useAddAddress from '@framework/customer/address/use-add-item' + +import s from './ShippingView.module.css' + +interface Form extends HTMLFormElement { + cardHolder: HTMLInputElement + cardNumber: HTMLInputElement + cardExpireDate: HTMLInputElement + cardCvc: HTMLInputElement + firstName: HTMLInputElement + lastName: HTMLInputElement + company: HTMLInputElement + streetNumber: HTMLInputElement + zipCode: HTMLInputElement + city: HTMLInputElement + country: HTMLSelectElement +} const PaymentMethodView: FC = () => { const { setSidebarView } = useUI() + const addAddress = useAddAddress() + + async function handleSubmit(event: React.ChangeEvent
) { + event.preventDefault() + + await addAddress({ + type: event.target.type.value, + firstName: event.target.firstName.value, + lastName: event.target.lastName.value, + company: event.target.company.value, + streetNumber: event.target.streetNumber.value, + apartments: event.target.streetNumber.value, + zipCode: event.target.zipCode.value, + city: event.target.city.value, + country: event.target.country.value, + }) + + setSidebarView('CHECKOUT_VIEW') + } return ( - setSidebarView('CHECKOUT_VIEW')}> -
-

- Shipping -

-
-
- - Same as billing address -
-
- - - Use a different shipping address - -
-
-
-
- - + + setSidebarView('CHECKOUT_VIEW')}> +
+

+ Shipping +

+
+
+ + Same as billing address
-
- - +
+ + + Use a different shipping address +
-
-
- - -
-
- - -
-
- - -
-
-
- - +
+
+
+ + +
+
+ + +
-
- - +
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
-
-
- -
-
-
- -
- +
+ +
+ + ) } diff --git a/components/checkout/ShippingWidget/ShippingWidget.tsx b/components/checkout/ShippingWidget/ShippingWidget.tsx index b072178b0..557a69a8b 100644 --- a/components/checkout/ShippingWidget/ShippingWidget.tsx +++ b/components/checkout/ShippingWidget/ShippingWidget.tsx @@ -1,15 +1,16 @@ import { FC } from 'react' import s from './ShippingWidget.module.css' -import { ChevronRight, MapPin } from '@components/icons' +import { ChevronRight, MapPin, Check } from '@components/icons' import cn from 'classnames' interface ComponentProps { onClick?: () => any + isValid?: boolean } -const ShippingWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - +const ShippingWidget: FC = ({ onClick, isValid }) => { + /* Shipping Address + Only available with checkout set to true - This means that the provider does offer checkout functionality. */ return (
@@ -23,9 +24,7 @@ const ShippingWidget: FC = ({ onClick }) => { San Franssisco, California */}
-
- -
+
{isValid ? : }
) } diff --git a/components/common/Footer/Footer.tsx b/components/common/Footer/Footer.tsx index 04b80404e..8cfcc9666 100644 --- a/components/common/Footer/Footer.tsx +++ b/components/common/Footer/Footer.tsx @@ -73,7 +73,7 @@ const Footer: FC = ({ className, pages }) => {
Created by ( ) const dynamicProps = { - loading: () => , + loading: Loading, } const SignUpView = dynamic( diff --git a/components/common/Searchbar/Searchbar.tsx b/components/common/Searchbar/Searchbar.tsx index 0fc276d02..ee20a3ade 100644 --- a/components/common/Searchbar/Searchbar.tsx +++ b/components/common/Searchbar/Searchbar.tsx @@ -1,4 +1,4 @@ -import { FC, InputHTMLAttributes, useEffect, useMemo } from 'react' +import { FC, memo, useEffect } from 'react' import cn from 'classnames' import s from './Searchbar.module.css' import { useRouter } from 'next/router' @@ -13,7 +13,7 @@ const Searchbar: FC = ({ className, id = 'search' }) => { useEffect(() => { router.prefetch('/search') - }, []) + }, [router]) const handleKeyUp = (e: React.KeyboardEvent) => { e.preventDefault() @@ -32,32 +32,29 @@ const Searchbar: FC = ({ className, id = 'search' }) => { } } - return useMemo( - () => ( -
- - -
- - - -
+ return ( +
+ + +
+ + +
- ), - [] +
) } -export default Searchbar +export default memo(Searchbar) diff --git a/components/common/UserNav/UserNav.tsx b/components/common/UserNav/UserNav.tsx index 5d7d28df3..92df48fc2 100644 --- a/components/common/UserNav/UserNav.tsx +++ b/components/common/UserNav/UserNav.tsx @@ -7,6 +7,7 @@ import useCustomer from '@framework/customer/use-customer' import { Avatar } from '@components/common' import { Heart, Bag } from '@components/icons' import { useUI } from '@components/ui/context' +import Button from '@components/ui/Button' import DropdownMenu from './DropdownMenu' import s from './UserNav.module.css' @@ -26,9 +27,11 @@ const UserNav: FC = ({ className }) => {