): ''}
diff --git a/src/components/checkout/PaymentModes.js b/src/components/checkout/PaymentModes.js
index 04e2e9cb..33f49afd 100644
--- a/src/components/checkout/PaymentModes.js
+++ b/src/components/checkout/PaymentModes.js
@@ -1,46 +1,49 @@
import Error from "./Error";
const PaymentModes = ( { input, handleOnChange } ) => {
+
+ const { errors, paymentMethod } = input || {}
+
return (
-
+
{/*Direct bank transfers*/}
-
+
Direct Bank Transfer
{/*Pay with Paypal*/}
-
+
Pay with Paypal
{/*Check Payments*/}
-
+
Check Payments
{/*Pay with Stripe*/}
-
+
Cash on Delivery
-
+
JCC
-
+
CC Avenue
diff --git a/src/components/checkout/StatesSelection.js b/src/components/checkout/StatesSelection.js
new file mode 100644
index 00000000..07f64508
--- /dev/null
+++ b/src/components/checkout/StatesSelection.js
@@ -0,0 +1,87 @@
+import PropTypes from 'prop-types';
+import {memo} from 'react';
+import cx from 'classnames';
+
+import Abbr from "./form-elements/Abbr";
+import Error from './Error';
+
+const StateSelection = ({handleOnChange, input, states, isFetchingStates, isShipping}) => {
+
+ const {state, errors} = input || {};
+
+ const inputId = `state-${isShipping ? 'shipping' : 'billing'}`;
+
+ if (isFetchingStates) {
+ // Show loading component.
+ return (
+
+
+ State/County
+
+
+
+
+ Loading...
+
+
+
+ )
+ }
+
+ if (!states.length) {
+ return null;
+ }
+
+ return (
+
+
+ State/County
+
+
+
+
+ Select a state...
+ {states.map((state, index) => (
+
+ {state?.stateName}
+
+ ))}
+
+
+
+
+ )
+}
+
+StateSelection.propTypes = {
+ handleOnChange: PropTypes.func,
+ input: PropTypes.object,
+ states: PropTypes.array,
+ isFetchingStates: PropTypes.bool,
+ isShipping: PropTypes.bool
+}
+
+StateSelection.defaultProps = {
+ handleOnChange: () => null,
+ input: {},
+ states: [],
+ isFetchingStates: false,
+ isShipping: true
+}
+
+export default memo(StateSelection);
diff --git a/src/components/checkout/country-list.js b/src/components/checkout/country-list.js
deleted file mode 100644
index 9fc8bf5d..00000000
--- a/src/components/checkout/country-list.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// @TODO Update Country list with their names.
-// const countryList = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas"
-// ,"Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia & Herzegovina","Botswana","Brazil","British Virgin Islands"
-// ,"Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Cayman Islands","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica"
-// ,"Cote D Ivoire","Croatia","Cruise Ship","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea"
-// ,"Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana"
-// ,"Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India"
-// ,"Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kuwait","Kyrgyz Republic","Laos","Latvia"
-// ,"Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Mauritania"
-// ,"Mauritius","Mexico","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Namibia","Nepal","Netherlands","Netherlands Antilles","New Caledonia"
-// ,"New Zealand","Nicaragua","Niger","Nigeria","Norway","Oman","Pakistan","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal"
-// ,"Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre & Miquelon","Samoa","San Marino","Satellite","Saudi Arabia","Senegal","Serbia","Seychelles"
-// ,"Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","South Korea","Spain","Sri Lanka","St Kitts & Nevis","St Lucia","St Vincent","St. Lucia","Sudan"
-// ,"Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad & Tobago","Tunisia"
-// ,"Turkey","Turkmenistan","Turks & Caicos","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","United States Minor Outlying Islands","Uruguay"
-// ,"Uzbekistan","Venezuela","Vietnam","Virgin Islands (US)","Yemen","Zambia","Zimbabwe"];
-
-const countryList = [
- { countryCode: 'ID', countryName: 'India' }
-];
-
-export default countryList;
diff --git a/src/components/checkout/form-elements/Abbr.js b/src/components/checkout/form-elements/Abbr.js
new file mode 100644
index 00000000..595f5836
--- /dev/null
+++ b/src/components/checkout/form-elements/Abbr.js
@@ -0,0 +1,19 @@
+import PropTypes from 'prop-types';
+
+const Abbr = ({required}) => {
+ if ( !required ) {
+ return null;
+ }
+
+ return
*
+}
+
+Abbr.propTypes = {
+ required: PropTypes.bool
+}
+
+Abbr.defaultProps = {
+ required: false
+}
+
+export default Abbr
diff --git a/src/components/checkout/form-elements/CheckboxField.js b/src/components/checkout/form-elements/CheckboxField.js
new file mode 100644
index 00000000..4a485263
--- /dev/null
+++ b/src/components/checkout/form-elements/CheckboxField.js
@@ -0,0 +1,42 @@
+import PropTypes from 'prop-types';
+
+const CheckboxField = ({ handleOnChange, checked, name, label, placeholder, containerClassNames }) => {
+
+ return (
+
+
+
+ { label || '' }
+
+
+ )
+}
+
+CheckboxField.propTypes = {
+ handleOnChange: PropTypes.func,
+ checked: PropTypes.bool,
+ name: PropTypes.string,
+ type: PropTypes.string,
+ label: PropTypes.string,
+ placeholder: PropTypes.string,
+ containerClassNames: PropTypes.string
+}
+
+CheckboxField.defaultProps = {
+ handleOnChange: () => null,
+ checked: false,
+ name: '',
+ label: '',
+ placeholder: '',
+ errors: {},
+ containerClassNames: ''
+}
+
+export default CheckboxField;
diff --git a/src/components/checkout/form-elements/InputField.js b/src/components/checkout/form-elements/InputField.js
new file mode 100644
index 00000000..f6f79325
--- /dev/null
+++ b/src/components/checkout/form-elements/InputField.js
@@ -0,0 +1,53 @@
+import Error from "../Error";
+import PropTypes from 'prop-types';
+import Abbr from "./Abbr";
+
+const InputField = ({ handleOnChange, inputValue, name, type, label, errors, placeholder, required, containerClassNames, isShipping }) => {
+
+ const inputId = `${name}-${isShipping ? 'shipping' : ''}`;
+
+ return (
+
+
+ { label || '' }
+
+
+
+
+
+ )
+}
+
+InputField.propTypes = {
+ handleOnChange: PropTypes.func,
+ inputValue: PropTypes.string,
+ name: PropTypes.string,
+ type: PropTypes.string,
+ label: PropTypes.string,
+ placeholder: PropTypes.string,
+ errors: PropTypes.object,
+ required: PropTypes.bool,
+ containerClassNames: PropTypes.string
+}
+
+InputField.defaultProps = {
+ handleOnChange: () => null,
+ inputValue: '',
+ name: '',
+ type: 'text',
+ label: '',
+ placeholder: '',
+ errors: {},
+ required: false,
+ containerClassNames: ''
+}
+
+export default InputField;
diff --git a/src/components/icons/ArrowDown.js b/src/components/icons/ArrowDown.js
new file mode 100644
index 00000000..50ae9844
--- /dev/null
+++ b/src/components/icons/ArrowDown.js
@@ -0,0 +1,18 @@
+import * as React from "react";
+
+function SvgArrowDown(props) {
+ return (
+
+
+
+
+ );
+}
+
+export default SvgArrowDown;
diff --git a/src/components/icons/index.js b/src/components/icons/index.js
index 633de2c0..8037dadb 100644
--- a/src/components/icons/index.js
+++ b/src/components/icons/index.js
@@ -1,3 +1,4 @@
+export { default as ArrowDown } from './ArrowDown'
export { default as Cross } from './Cross'
export { default as Facebook } from './Facebook'
export { default as Instagram } from './Instagram'
diff --git a/src/components/icons/svgs/arrow-down.svg b/src/components/icons/svgs/arrow-down.svg
new file mode 100644
index 00000000..13868822
--- /dev/null
+++ b/src/components/icons/svgs/arrow-down.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/constants/urls.js b/src/constants/urls.js
new file mode 100644
index 00000000..04c9e4f7
--- /dev/null
+++ b/src/constants/urls.js
@@ -0,0 +1,3 @@
+export const DEFAULT_IMG_URL = 'https://via.placeholder.com/400x225';
+export const DEFAULT_CATEGORY_IMG_URL = 'https://via.placeholder.com/416x224';
+export const DEFAULT_PRODUCT_HOME_IMG_URL = 'https://via.placeholder.com/308x308';
diff --git a/src/functions.js b/src/functions.js
index 2dcbaadd..72a4b27d 100644
--- a/src/functions.js
+++ b/src/functions.js
@@ -213,71 +213,81 @@ export const getFormattedCart = ( data ) => {
let totalProductsCount = 0;
for( let i = 0; i < givenProducts.length; i++ ) {
- const givenProduct = givenProducts[ i ].product;
+ const givenProduct = givenProducts?.[ i ]?.product?.node;
const product = {};
const total = getFloatVal( givenProducts[ i ].total );
- product.productId = givenProduct.productId;
- product.cartKey = givenProducts[ i ].key;
- product.name = givenProduct.name;
- product.qty = givenProducts[ i ].quantity;
- product.price = total / product.qty;
- product.totalPrice = givenProducts[ i ].total;
+ product.productId = givenProduct?.productId ?? '';
+ product.cartKey = givenProducts?.[ i ]?.key ?? '';
+ product.name = givenProduct?.name ?? '';
+ product.qty = givenProducts?.[ i ]?.quantity;
+ product.price = total / product?.qty;
+ product.totalPrice = givenProducts?.[ i ]?.total ?? '';
product.image = {
- sourceUrl: givenProduct.image.sourceUrl,
- srcSet: givenProduct.image.srcSet,
- title: givenProduct.image.title
+ sourceUrl: givenProduct?.image?.sourceUrl ?? '',
+ srcSet: givenProduct?.image?.srcSet ?? '',
+ title: givenProduct?.image?.title ?? '',
+ altText: givenProduct?.image?.altText ?? ''
};
- totalProductsCount += givenProducts[ i ].quantity;
+ totalProductsCount += givenProducts?.[ i ]?.quantity;
// Push each item into the products array.
formattedCart.products.push( product );
}
formattedCart.totalProductsCount = totalProductsCount;
- formattedCart.totalProductsPrice = data.cart.total;
+ formattedCart.totalProductsPrice = data?.cart?.total ?? '';
return formattedCart;
};
export const createCheckoutData = ( order ) => {
+
+ // Set the billing Data to shipping, if applicable.
+ const billingData = order.billingDifferentThanShipping ? order.billing : order.shipping;
+
const checkoutData = {
clientMutationId: v4(),
-
- billing: {
- firstName: order.firstName,
- lastName: order.lastName,
- address1: order.address1,
- address2: order.address2,
- city: order.city,
- country: order.country,
- state: order.state,
- postcode: order.postcode,
- email: order.email,
- phone: order.phone,
- company: order.company,
- },
shipping: {
- firstName: order.firstName,
- lastName: order.lastName,
- address1: order.address1,
- address2: order.address2,
- city: order.city,
- country: order.country,
- state: order.state,
- postcode: order.postcode,
- email: order.email,
- phone: order.phone,
- company: order.company,
+ firstName: order?.shipping?.firstName,
+ lastName: order?.shipping?.lastName,
+ address1: order?.shipping?.address1,
+ address2: order?.shipping?.address2,
+ city: order?.shipping?.city,
+ country: order?.shipping?.country,
+ state: order?.shipping?.state,
+ postcode: order?.shipping?.postcode,
+ email: order?.shipping?.email,
+ phone: order?.shipping?.phone,
+ company: order?.shipping?.company,
},
- shipToDifferentAddress: false,
+ billing: {
+ firstName: billingData?.firstName,
+ lastName: billingData?.lastName,
+ address1: billingData?.address1,
+ address2: billingData?.address2,
+ city: billingData?.city,
+ country: billingData?.country,
+ state: billingData?.state,
+ postcode: billingData?.postcode,
+ email: billingData?.email,
+ phone: billingData?.phone,
+ company: billingData?.company,
+ },
+ shipToDifferentAddress: order.billingDifferentThanShipping,
paymentMethod: order.paymentMethod,
isPaid: false,
- transactionId: "hjkhjkhsdsdiui"
};
+ if (order.createAccount) {
+ checkoutData.account = {
+ username: order.username,
+ password: order.password,
+ };
+ }
+
return checkoutData;
};
diff --git a/src/image/index.js b/src/image/index.js
new file mode 100644
index 00000000..16a073c0
--- /dev/null
+++ b/src/image/index.js
@@ -0,0 +1,78 @@
+import Img from 'next/image';
+
+import PropTypes from 'prop-types';
+import cx from 'classnames';
+import {DEFAULT_IMG_URL} from "../constants/urls";
+
+/**
+ * Image Component.
+ * We don't need to add srcSet, as Next js will generate that.
+ * @see https://nextjs.org/docs/api-reference/next/image#other-props
+ * @see https://nextjs.org/docs/basic-features/image-optimization#device-sizes
+ *
+ * @param {Object} props Component props.
+ *
+ * @return {jsx}
+ */
+const Image = ( props ) => {
+ const {altText, title, width, height, sourceUrl, className, layout, objectFit, containerClassNames, showDefault, defaultImgUrl, ...rest} = props;
+
+ if ( ! sourceUrl && ! showDefault ) {
+ return null;
+ }
+
+ /**
+ * If we use layout = fill then, width and height of the image cannot be used.
+ * and the image fills on the entire width and the height of its parent container.
+ * That's we need to wrap our image in a container and give it a height and width.
+ * Notice that in this case, the given height and width is being used for container and not img.
+ */
+ if ( 'fill' === layout ) {
+ const attributes = {
+ alt: altText || title,
+ src: sourceUrl || ( showDefault ? ( defaultImgUrl || DEFAULT_IMG_URL ) : '' ),
+ layout: 'fill',
+ className: cx( 'object-cover', className ),
+ ...rest
+ };
+
+ return (
+
+
+
+ );
+ } else {
+ const attributes = {
+ alt: altText || title,
+ src: sourceUrl || ( showDefault ? DEFAULT_IMG_URL : '' ),
+ width: width || 'auto',
+ height: height || 'auto',
+ className,
+ ...rest
+ };
+ return
;
+ }
+};
+
+Image.propTypes = {
+ altText: PropTypes.string,
+ title: PropTypes.string,
+ sourceUrl: PropTypes.string,
+ layout: PropTypes.string,
+ showDefault: PropTypes.bool,
+ defaultImgUrl: PropTypes.string,
+ containerClassName: PropTypes.string,
+ className: PropTypes.string
+};
+
+Image.defaultProps = {
+ altText: '',
+ title: '',
+ sourceUrl: '',
+ showDefault: true,
+ defaultImgUrl: '',
+ containerClassNames: '',
+ className: 'post__image',
+};
+
+export default Image;
diff --git a/src/mutations/add-to-cart.js b/src/mutations/add-to-cart.js
index c35532e9..fcd23322 100644
--- a/src/mutations/add-to-cart.js
+++ b/src/mutations/add-to-cart.js
@@ -1,64 +1,66 @@
-import gql from "graphql-tag";
+import { gql } from "@apollo/client";
const ADD_TO_CART = gql`
- mutation ($input: AddToCartInput!) {
- addToCart(input: $input) {
- cartItem {
- key
- product {
- id
- productId
- name
- description
- type
- onSale
- slug
- averageRating
- reviewCount
- image {
- id
- sourceUrl
- altText
- }
- galleryImages {
- nodes {
+ mutation ADD_TO_CART($input: AddToCartInput!) {
+ addToCart(input: $input) {
+ cartItem {
+ key
+ product {
+ node {
id
- sourceUrl
- altText
+ productId: databaseId
+ name
+ description
+ type
+ onSale
+ slug
+ averageRating
+ reviewCount
+ image {
+ id
+ sourceUrl
+ altText
+ }
+ galleryImages {
+ nodes {
+ id
+ sourceUrl
+ altText
+ }
+ }
}
}
- }
- variation {
- id
- variationId
- name
- description
- type
- onSale
- price
- regularPrice
- salePrice
- image {
- id
- sourceUrl
- altText
- }
- attributes {
- nodes {
+ variation {
+ node {
+ id
+ variationId: databaseId
+ name
+ description
+ type
+ onSale
+ price
+ regularPrice
+ salePrice
+ image {
+ id
+ sourceUrl
+ altText
+ }
+ }
+ attributes {
id
attributeId
name
value
}
}
+ quantity
+ total
+ subtotal
+ subtotalTax
}
- quantity
- total
- subtotal
- subtotalTax
}
}
- }
`;
export default ADD_TO_CART;
diff --git a/src/mutations/checkout.js b/src/mutations/checkout.js
index 340f25d0..788afecf 100644
--- a/src/mutations/checkout.js
+++ b/src/mutations/checkout.js
@@ -1,4 +1,4 @@
-import gql from "graphql-tag";
+import { gql } from "@apollo/client";
const CHECKOUT_MUTATION = gql`
mutation CHECKOUT_MUTATION( $input: CheckoutInput! ) {
@@ -7,12 +7,13 @@ mutation CHECKOUT_MUTATION( $input: CheckoutInput! ) {
order {
id
orderKey
+ orderNumber
+ status
refunds {
nodes {
amount
}
}
- status
}
result
redirect
diff --git a/src/mutations/clear-cart.js b/src/mutations/clear-cart.js
index f792f26e..5a60955f 100644
--- a/src/mutations/clear-cart.js
+++ b/src/mutations/clear-cart.js
@@ -1,4 +1,4 @@
-import gql from "graphql-tag";
+import { gql } from "@apollo/client";
const CLEAR_CART_MUTATION = gql`
mutation CLEAR_CART_MUTATION( $input: RemoveItemsFromCartInput! ) {
diff --git a/src/mutations/update-cart.js b/src/mutations/update-cart.js
index 54b4e300..2bf7dea7 100644
--- a/src/mutations/update-cart.js
+++ b/src/mutations/update-cart.js
@@ -1,4 +1,4 @@
-import gql from "graphql-tag";
+import { gql } from "@apollo/client";
/**
* Update Cart
@@ -7,13 +7,14 @@ import gql from "graphql-tag";
* When the cart item needs to be deleted, we should pass quantity as 0 in the input along with other fields.
*/
const UPDATE_CART = gql`
- mutation ($input: UpdateItemQuantitiesInput!) {
- updateItemQuantities(input: $input) {
- items {
- key
- product {
+mutation UPDATE_CART($input: UpdateItemQuantitiesInput!) {
+ updateItemQuantities(input: $input) {
+ items {
+ key
+ product {
+ node {
id
- productId
+ productId: databaseId
name
description
type
@@ -24,7 +25,7 @@ const UPDATE_CART = gql`
image {
id
sourceUrl
- altText
+ altText
}
galleryImages {
nodes {
@@ -34,9 +35,11 @@ const UPDATE_CART = gql`
}
}
}
- variation {
+ }
+ variation {
+ node {
id
- variationId
+ variationId: databaseId
name
description
type
@@ -47,46 +50,53 @@ const UPDATE_CART = gql`
image {
id
sourceUrl
- altText
+ altText
}
- attributes {
- nodes {
- id
+ }
+ attributes {
+ id
attributeId
- name
- value
- }
- }
+ name
+ value
}
- quantity
- total
- subtotal
- subtotalTax
}
- removed {
- key
- product {
+ quantity
+ total
+ subtotal
+ subtotalTax
+ }
+ removed {
+ key
+ product {
+ node {
id
- productId
+ productId: databaseId
}
- variation {
+ }
+ variation {
+ node {
id
- variationId
+ variationId: databaseId
}
}
- updated {
- key
- product {
+ }
+ updated {
+ key
+ product {
+ node {
id
- productId
+ productId: databaseId
}
- variation {
+ }
+ variation {
+ node {
id
- variationId
+ variationId: databaseId
}
}
}
}
+}
`;
export default UPDATE_CART;
diff --git a/src/queries/get-cart.js b/src/queries/get-cart.js
index 3410ff8b..632eae49 100644
--- a/src/queries/get-cart.js
+++ b/src/queries/get-cart.js
@@ -1,14 +1,15 @@
import { gql } from "@apollo/client";
const GET_CART = gql`
- query GET_CART {
- cart {
- contents {
- nodes {
- key
- product {
+query GET_CART {
+ cart {
+ contents {
+ nodes {
+ key
+ product {
+ node {
id
- productId
+ productId: databaseId
name
description
type
@@ -18,10 +19,10 @@ const GET_CART = gql`
reviewCount
image {
id
- sourceUrl
- srcSet
- altText
- title
+ sourceUrl
+ srcSet
+ altText
+ title
}
galleryImages {
nodes {
@@ -29,14 +30,15 @@ const GET_CART = gql`
sourceUrl
srcSet
altText
- title
+ title
}
}
-
}
- variation {
+ }
+ variation {
+ node {
id
- variationId
+ variationId: databaseId
name
description
type
@@ -49,53 +51,38 @@ const GET_CART = gql`
sourceUrl
srcSet
altText
- title
- }
- attributes {
- nodes {
- id
- name
- value
- }
- }
- }
- quantity
- total
- subtotal
- subtotalTax
- }
- }
- appliedCoupons {
- nodes {
- id
- couponId
- discountType
- amount
- dateExpiry
- products {
- nodes {
- id
+ title
}
}
- productCategories {
- nodes {
- id
- }
+ attributes {
+ id
+ name
+ value
}
}
+ quantity
+ total
+ subtotal
+ subtotalTax
}
- subtotal
- subtotalTax
- shippingTax
- shippingTotal
- total
- totalTax
- feeTax
- feeTotal
+ }
+ appliedCoupons {
+ code
+ discountAmount
discountTax
- discountTotal
}
+ subtotal
+ subtotalTax
+ shippingTax
+ shippingTotal
+ total
+ totalTax
+ feeTax
+ feeTotal
+ discountTax
+ discountTotal
}
+}
`;
export default GET_CART;
diff --git a/src/queries/get-categories.js b/src/queries/get-categories.js
index 6df74c44..f98d52ad 100644
--- a/src/queries/get-categories.js
+++ b/src/queries/get-categories.js
@@ -12,7 +12,7 @@ const GET_CATEGORIES_QUERY = gql`query {
slug
image {
sourceUrl
- srcSet
+ altText
}
}
}
diff --git a/src/queries/get-countries.js b/src/queries/get-countries.js
new file mode 100644
index 00000000..7e4d7483
--- /dev/null
+++ b/src/queries/get-countries.js
@@ -0,0 +1,19 @@
+import { gql } from "@apollo/client";
+
+/**
+ * GraphQL countries query.
+ */
+const GET_COUNTRIES = gql`query GET_COUNTRIES{
+ wooCountries {
+ billingCountries {
+ countryCode
+ countryName
+ }
+ shippingCountries {
+ countryCode
+ countryName
+ }
+ }
+}`;
+
+export default GET_COUNTRIES;
diff --git a/src/queries/get-states.js b/src/queries/get-states.js
new file mode 100644
index 00000000..de07dd65
--- /dev/null
+++ b/src/queries/get-states.js
@@ -0,0 +1,15 @@
+import { gql } from "@apollo/client";
+
+/**
+ * GraphQL countries query.
+ */
+const GET_STATES = gql`query GET_STATES($countryCode: String!) {
+ wooStates(countryCode: $countryCode) {
+ states {
+ stateCode
+ stateName
+ }
+ }
+}`;
+
+export default GET_STATES;
diff --git a/src/queries/product-and-categories.js b/src/queries/product-and-categories.js
index 83f16b08..683280ef 100644
--- a/src/queries/product-and-categories.js
+++ b/src/queries/product-and-categories.js
@@ -38,15 +38,13 @@ const PRODUCTS_AND_CATEGORIES_QUERY = gql`query {
products(first: 50) {
nodes {
id
- productId
+ productId: databaseId
averageRating
slug
description
image {
id
- uri
- title
- srcSet
+ altText
sourceUrl
}
name
diff --git a/src/queries/product-by-category.js b/src/queries/product-by-category.js
index a5254f01..39439213 100644
--- a/src/queries/product-by-category.js
+++ b/src/queries/product-by-category.js
@@ -7,7 +7,7 @@ export const PRODUCT_BY_CATEGORY_SLUG = gql` query PRODUCT_BY_CATEGORY_SLUG($slu
products(first: 50) {
nodes {
id
- productId
+ productId: databaseId
averageRating
slug
description
diff --git a/src/queries/product-by-slug.js b/src/queries/product-by-slug.js
index 0adf26d0..6de422c9 100644
--- a/src/queries/product-by-slug.js
+++ b/src/queries/product-by-slug.js
@@ -3,7 +3,7 @@ import { gql } from "@apollo/client";
export const PRODUCT_BY_SLUG_QUERY = gql` query Product($slug: ID!) {
product(id: $slug, idType: SLUG) {
id
- productId
+ productId: databaseId
averageRating
slug
description
diff --git a/src/styles/style.scss b/src/styles/style.scss
index 75b13cde..e93245df 100644
--- a/src/styles/style.scss
+++ b/src/styles/style.scss
@@ -82,12 +82,6 @@
height: 100%;
}
-.woo-next-checkout-form {
- label {
- display: block;
- }
-}
-
.main-title {
position: relative;
text-align: center;
diff --git a/src/utils/cart.js b/src/utils/cart.js
new file mode 100644
index 00000000..478d97f8
--- /dev/null
+++ b/src/utils/cart.js
@@ -0,0 +1,37 @@
+/**
+ * @TODO will update this in future, when required.
+ * Handles adding items to the cart.
+ *
+ * @return {void}
+ */
+// const handleAddToCartLocalStorage = () => {
+//
+// // If component is rendered client side.
+// if ( process.browser ) {
+//
+// let existingCart = localStorage.getItem( 'woo-next-cart' );
+//
+// // If cart has item(s) already, update existing or add new item.
+// if ( existingCart ) {
+//
+// existingCart = JSON.parse( existingCart );
+//
+// const qtyToBeAdded = 1;
+//
+// const updatedCart = updateCart( existingCart, product, qtyToBeAdded );
+//
+// setCart( updatedCart );
+//
+// } else {
+// /**
+// * If No Items in the cart, create an empty array and add one.
+// * @type {Array}
+// */
+// const newCart = addFirstProduct( product );
+// setCart( newCart );
+// }
+//
+// // Show View Cart Button
+// setShowViewCart( true )
+// }
+// };
diff --git a/src/utils/checkout.js b/src/utils/checkout.js
new file mode 100644
index 00000000..cbd0fd15
--- /dev/null
+++ b/src/utils/checkout.js
@@ -0,0 +1,47 @@
+import client from "../components/ApolloClient";
+import GET_STATES from "../queries/get-states";
+
+/**
+ * Get states
+ *
+ * @param {String} countryCode Country code
+ *
+ * @returns {Promise
}
+ */
+export const getStates = async ( countryCode ) => {
+ const { data } = await client.query( {
+ query: GET_STATES,
+ variables: { countryCode: countryCode || '' }
+ } )
+
+ return data?.wooStates?.states ?? [];
+}
+
+/**
+ * Set states for the country.
+ *
+ * @param {Object} target Target.
+ * @param {Function} setTheStates React useState function to set the value of the states basis country selection.
+ * @param {Function} setIsFetchingStates React useState function, to manage loading state when request is in process.
+ *
+ * @return {Promise}
+ */
+export const setStatesForCountry = async ( target, setTheStates, setIsFetchingStates ) => {
+ if ( 'country' === target.name ) {
+ setIsFetchingStates(true);
+ const countryCode = target[target.selectedIndex].getAttribute('data-countrycode')
+ const states = await getStates( countryCode );
+ setTheStates( states || [] );
+ setIsFetchingStates(false);
+ }
+}
+
+export const handleBillingDifferentThanShipping = ( input, setInput, target ) => {
+ const newState = { ...input, [target.name]: ! input.billingDifferentThanShipping };
+ setInput( newState );
+}
+
+export const handleCreateAccount = ( input, setInput, target ) => {
+ const newState = { ...input, [target.name]: ! input.createAccount };
+ setInput( newState );
+}
diff --git a/src/validator/checkout.js b/src/validator/checkout.js
index 5a1c645f..f1862d37 100644
--- a/src/validator/checkout.js
+++ b/src/validator/checkout.js
@@ -1,9 +1,8 @@
import validator from 'validator';
import isEmpty from './isEmpty';
-import config from '../../client-config';
-const validateAndSanitizeCheckoutForm = ( data ) => {
+const validateAndSanitizeCheckoutForm = ( data, hasStates = true ) => {
let errors = {};
let sanitizedData = {};
@@ -27,7 +26,7 @@ const validateAndSanitizeCheckoutForm = ( data ) => {
data.email = ( ! isEmpty( data.email ) ) ? data.email : '';
data.createAccount = ( ! isEmpty( data.createAccount ) ) ? data.createAccount : '';
data.orderNotes = ( ! isEmpty( data.orderNotes ) ) ? data.orderNotes : '';
- data.paymentMethod = ( ! isEmpty( data.paymentMethod ) ) ? data.paymentMethod : '';
+ // data.paymentMethod = ( ! isEmpty( data.paymentMethod ) ) ? data.paymentMethod : '';
/**
* Checks for error if required is true
@@ -42,7 +41,6 @@ const validateAndSanitizeCheckoutForm = ( data ) => {
*/
const addErrorAndSanitizedData = ( fieldName, errorContent, min, max, type = '', required ) => {
- const postCodeLocale = config.postCodeLocale ? config.postCodeLocale : '';
/**
* Please note that this isEmpty() belongs to validator and not our custom function defined above.
*
@@ -60,15 +58,10 @@ const validateAndSanitizeCheckoutForm = ( data ) => {
errors[ fieldName ] = `${errorContent} is not valid`;
}
- if ( 'postcode' === type && postCodeLocale && ! validator.isPostalCode( data[ fieldName ], postCodeLocale ) ) {
- errors[ fieldName ] = `${errorContent} is not valid`;
- }
-
if ( required && validator.isEmpty( data[ fieldName ] ) ) {
errors[ fieldName ] = `${errorContent} is required`;
}
-
// If no errors
if ( ! errors[ fieldName ] ) {
sanitizedData[ fieldName ] = validator.trim( data[ fieldName ] );
@@ -82,19 +75,19 @@ const validateAndSanitizeCheckoutForm = ( data ) => {
addErrorAndSanitizedData( 'lastName', 'Last name', 2, 35, 'string', true );
addErrorAndSanitizedData( 'company', 'Company Name', 0, 35, 'string', false );
addErrorAndSanitizedData( 'country', 'Country name', 2, 55, 'string', true );
- addErrorAndSanitizedData( 'address1', 'Street address line 1', 20, 100,'string',true );
+ addErrorAndSanitizedData( 'address1', 'Street address line 1', 12, 100,'string',true );
addErrorAndSanitizedData( 'address2', '', 0, 254, 'string', false );
addErrorAndSanitizedData( 'city', 'City field', 3, 25, 'string', true );
- addErrorAndSanitizedData( 'state', 'State/County', 0, 254, 'string', true );
- addErrorAndSanitizedData( 'postcode', 'Post code', 2, 9, 'postcode', true );
+ addErrorAndSanitizedData( 'state', 'State/County', 0, 254, 'string', hasStates );
+ addErrorAndSanitizedData( 'postcode', 'Post code', 2, 10, 'postcode', true );
addErrorAndSanitizedData( 'phone', 'Phone number', 10, 15, 'phone', true );
addErrorAndSanitizedData( 'email', 'Email', 11, 254, 'email', true );
// The data.createAccount is a boolean value.
sanitizedData.createAccount = data.createAccount;
addErrorAndSanitizedData( 'orderNotes', '', 0, 254, 'string', false );
- addErrorAndSanitizedData( 'paymentMethod', 'Payment mode field', 2, 50, 'string', true );
-
+ // @TODO Payment mode error to be handled later.
+ // addErrorAndSanitizedData( 'paymentMethod', 'Payment mode field', 2, 50, 'string', false );
return {
sanitizedData,
diff --git a/tailwind.config.js b/tailwind.config.js
index f77c69ef..2feeffec 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -8,7 +8,15 @@ module.exports = {
'./src/components/**/*.js',
'./pages/**/*.js'],
theme: {
- extend: {},
+ extend: {
+ height: {
+ 'almost-screen': 'calc(-16rem + 100vh)',
+ '308px': '19.25rem',
+ },
+ width: {
+ '308px': '19.25rem',
+ },
+ },
},
variants: {},
plugins: [
diff --git a/wordpress/plugins/headless-cms.zip b/wordpress/plugins/headless-cms.zip
new file mode 100644
index 00000000..1e41cd7b
Binary files /dev/null and b/wordpress/plugins/headless-cms.zip differ
diff --git a/wordpress/plugins/wp-graphql-woocommerce.zip b/wordpress/plugins/wp-graphql-woocommerce.zip
index efab8558..81c36d28 100644
Binary files a/wordpress/plugins/wp-graphql-woocommerce.zip and b/wordpress/plugins/wp-graphql-woocommerce.zip differ
diff --git a/wordpress/plugins/wp-graphql.zip b/wordpress/plugins/wp-graphql.zip
index 6081aa04..9a60c2bd 100644
Binary files a/wordpress/plugins/wp-graphql.zip and b/wordpress/plugins/wp-graphql.zip differ