From 47a1949f5685d47b781aec493afe9d29dad69cb4 Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Mon, 7 Jan 2019 19:15:54 +0100 Subject: [PATCH 1/5] Add base quantity change controls, structure improvements --- src/components/App/routes.tsx | 3 +- src/components/CartOverlay/index.tsx | 12 +- src/components/CartPage/index.tsx | 159 ------------------ src/components/CartProvider/context.ts | 11 +- src/components/CartProvider/index.tsx | 106 ++++++++---- src/components/CheckoutApp/index.tsx | 14 +- src/components/CheckoutApp/queries.ts | 19 ++- src/components/CheckoutBilling/queries.ts | 4 +- src/components/CheckoutShipping/queries.ts | 4 +- .../CheckoutShippingOptions/queries.ts | 4 +- src/components/{CartPage => }/EmptyCart.tsx | 4 +- src/components/GoToCheckout/index.tsx | 28 ++- src/components/GoToCheckout/queries.ts | 4 +- src/components/index.ts | 1 - src/images/cart-add.svg | 5 + src/images/cart-remove.svg | 7 + src/images/cart-subtract.svg | 4 + src/views/Cart/Page.tsx | 158 +++++++++++++++++ src/views/Cart/View.tsx | 35 ++++ src/views/Cart/index.ts | 1 + .../CartPage => views/Cart}/scss/index.scss | 36 +++- 21 files changed, 383 insertions(+), 236 deletions(-) delete mode 100644 src/components/CartPage/index.tsx rename src/components/{CartPage => }/EmptyCart.tsx (86%) create mode 100644 src/images/cart-add.svg create mode 100644 src/images/cart-remove.svg create mode 100644 src/images/cart-subtract.svg create mode 100644 src/views/Cart/Page.tsx create mode 100644 src/views/Cart/View.tsx create mode 100644 src/views/Cart/index.ts rename src/{components/CartPage => views/Cart}/scss/index.scss (54%) diff --git a/src/components/App/routes.tsx b/src/components/App/routes.tsx index 422179ccee..bcb9818297 100644 --- a/src/components/App/routes.tsx +++ b/src/components/App/routes.tsx @@ -1,8 +1,9 @@ import * as React from "react"; import { Route, Switch } from "react-router-dom"; -import { CartPage, CheckoutLogin } from ".."; +import { CheckoutLogin } from ".."; import { ArticlePage } from "../../views/Article"; +import { CartPage } from "../../views/Cart"; import { CategoryPage } from "../../views/Category"; import { CollectionPage } from "../../views/Collection"; import { HomePage } from "../../views/Home"; diff --git a/src/components/CartOverlay/index.tsx b/src/components/CartOverlay/index.tsx index 942b24292a..2c7abd5685 100644 --- a/src/components/CartOverlay/index.tsx +++ b/src/components/CartOverlay/index.tsx @@ -8,21 +8,20 @@ import ReactSVG from "react-svg"; import { Button } from ".."; import { maybe, priceToString } from "../../core/utils"; import { checkoutLoginUrl } from "../App/routes"; +import CachedImage from "../CachedImage"; import { CartContext } from "../CartProvider/context"; import { Error } from "../Error"; import GoToCart from "../GoToCart"; import { GoToCheckout } from "../GoToCheckout"; import Loader from "../Loader"; +import Offline from "../Offline"; +import OfflinePlaceholder from "../OfflinePlaceholder"; +import Online from "../Online"; import { Overlay } from "../Overlay"; import { OverlayContext, OverlayType } from "../Overlay/context"; import { ShopContext } from "../ShopProvider/context"; import { UserContext } from "../User/context"; -import CachedImage from "../CachedImage"; -import Offline from "../Offline"; -import OfflinePlaceholder from "../OfflinePlaceholder"; -import Online from "../Online"; - const cartSvg = require("../../images/cart.svg"); const closeSvg = require("../../images/x.svg"); const noPhotoPng = require("../../images/nophoto.png"); @@ -46,11 +45,13 @@ export const CartOverlay: React.SFC = () => ( ); } + if (errors) { return errors.map(error => ( )); } + return (
@@ -127,6 +128,7 @@ export const CartOverlay: React.SFC = () => ( apolloClient={client} cart={cart} secondary + onClick={overlay.hide} > Go to my bag diff --git a/src/components/CartPage/index.tsx b/src/components/CartPage/index.tsx deleted file mode 100644 index f3dbfb2ec3..0000000000 --- a/src/components/CartPage/index.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import "./scss/index.scss"; - -import * as React from "react"; -import { ApolloConsumer, Query } from "react-apollo"; -import Media from "react-media"; -import { RouteComponentProps } from "react-router"; -import { Link } from "react-router-dom"; -import ReactSVG from "react-svg"; - -import { Button, Loader } from ".."; -import { maybe } from "../../core/utils"; -import { checkoutLoginUrl } from "../App/routes"; -import { smallScreen } from "../App/scss/variables.scss"; -import CachedImage from "../CachedImage"; -import { CartContext } from "../CartProvider/context"; -import { GET_CHECKOUT } from "../CheckoutApp/queries"; -import { getCheckout } from "../CheckoutApp/types/getCheckout"; -import { Error } from "../Error"; -import { GoToCheckout } from "../GoToCheckout"; -import { UserContext } from "../User/context"; -import { EmptyCart } from "./EmptyCart"; - -const noPhotoPng = require("../../images/nophoto.png"); -const removeSvg = require("../../images/garbage.svg"); - -const canDisplay = (data: getCheckout) => - data && data.checkout && data.checkout.lines && data.checkout.subtotalPrice; - -const CartPage: React.SFC> = ({ - match: { - params: { token = "" } - } -}) => { - return ( -
-

Shopping bag

- - {({ error, data }) => { - if (canDisplay(data)) { - const { checkout } = data; - const lines = checkout ? checkout.lines : []; - if (lines.length > 0) { - return ( - <> - - - - - - {matches => (matches ? : null)} - - - - - - - {lines.map(line => ( - - - - {matches => - matches ? ( - - ) : null - } - - - - - - ))} - - - - - - {matches => (matches ? - - -
ProductsPriceQuantity - - {matches => (matches ? "Total Price" : "Price")} - - -
- ( - line.variant.product.thumbnail.url, - noPhotoPng - )} - url2x={maybe( - () => line.variant.product.thumbnail2x.url - )} - /> - )} - /> - {line.variant.product.name} - {line.variant.name - ? ` (${line.variant.name})` - : null} - {line.variant.price.localized}{line.quantity}{line.totalPrice.gross.localized} - - {({ remove }) => ( - remove(line.variant.id)} - /> - )} - -
Subtotal : null)} - - - {checkout.subtotalPrice.gross.localized} -
-
- - {({ user }) => - user ? ( - - {client => ( - - Checkout{" "} - - )} - - ) : ( - - - - ) - } - -
- - ); - } else { - return ; - } - } - if (error && !data) { - return ; - } - return ; - }} -
-
- ); -}; - -export default CartPage; diff --git a/src/components/CartProvider/context.ts b/src/components/CartProvider/context.ts index e805c9489d..e2ea7f3877 100644 --- a/src/components/CartProvider/context.ts +++ b/src/components/CartProvider/context.ts @@ -10,15 +10,16 @@ export interface CartLineInterface { export interface CartInterface { errors: ApolloError[] | null; - loading: boolean; lines: CartLineInterface[]; + loading: boolean; add(variantId: string, quantity?: number): void; - remove(variantId: string): void; changeQuantity(variantId: string, quantity: number); - fetch(): void; clear(): void; + fetch(): void; getQuantity(): number; getTotal(): { currency: string; amount: number }; + remove(variantId: string): void; + subtract(variantId, quantity?: number): void; } /* tslint:disable:no-empty */ @@ -32,7 +33,7 @@ export const CartContext = createContext({ getTotal: () => ({ currency: "USD", amount: 0 }), lines: [], loading: false, - - remove: variantId => {} + remove: variantId => {}, + subtract: (variantId, quantity = 1) => {} }); /* tslint:enable:no-empty */ diff --git a/src/components/CartProvider/index.tsx b/src/components/CartProvider/index.tsx index 5355c720b7..eb19704a52 100644 --- a/src/components/CartProvider/index.tsx +++ b/src/components/CartProvider/index.tsx @@ -1,8 +1,23 @@ import * as React from "react"; -import { ApolloClient } from "apollo-client"; +import { ApolloClient, ApolloError } from "apollo-client"; import { productVariatnsQuery } from "../../views/Product/queries"; -import { GET_CHECKOUT, UPDATE_CHECKOUT_LINE } from "../CheckoutApp/queries"; +import { + VariantList, + VariantListVariables +} from "../../views/Product/types/VariantList"; +import { + getCheckoutQuery, + updateCheckoutLineQuery +} from "../CheckoutApp/queries"; +import { + getCheckout, + getCheckoutVariables +} from "../CheckoutApp/types/getCheckout"; +import { + updateCheckoutLine, + updateCheckoutLineVariables +} from "../CheckoutApp/types/updateCheckoutLine"; import { CartContext, CartInterface, CartLineInterface } from "./context"; export default class CartProvider extends React.Component< @@ -11,12 +26,14 @@ export default class CartProvider extends React.Component< > { constructor(props) { super(props); + let lines; try { lines = JSON.parse(localStorage.getItem("cart")) || []; } catch { lines = []; } + this.state = { add: this.add, changeQuantity: this.changeQuantity, @@ -27,16 +44,20 @@ export default class CartProvider extends React.Component< getTotal: this.getTotal, lines, loading: false, - remove: this.remove + remove: this.remove, + subtract: this.subtract }; } + getLine = (variantId: string): CartLineInterface => + this.state.lines.find(line => line.variantId === variantId); + changeQuantity = async (variantId, quantity) => { this.setState({ loading: true }); - const newLine: CartLineInterface = { - quantity, - variantId - }; + + const checkoutToken = localStorage.getItem("checkout"); + const newLine: CartLineInterface = { quantity, variantId }; + this.setState(prevState => { let lines = prevState.lines.filter(line => line.variantId !== variantId); if (newLine.quantity > 0) { @@ -45,22 +66,24 @@ export default class CartProvider extends React.Component< return { lines }; }); - const checkoutToken = localStorage.getItem("checkout"); if (checkoutToken) { const { apolloClient } = this.props; - let data: { [key: string]: any }; - const response = await apolloClient.query({ - query: GET_CHECKOUT, + const { + data: { checkout } + } = await apolloClient.query({ + query: getCheckoutQuery, variables: { token: checkoutToken } }); - data = response.data; - const checkoutID = data.checkout.id; - await apolloClient.mutate({ - mutation: UPDATE_CHECKOUT_LINE, + const checkoutID = checkout.id; + + const x = await apolloClient.mutate({ + mutation: updateCheckoutLineQuery, update: (cache, { data: { checkoutLinesUpdate } }) => { cache.writeQuery({ - data: { checkout: checkoutLinesUpdate.checkout }, - query: GET_CHECKOUT + data: { + checkout: checkoutLinesUpdate.checkout + }, + query: getCheckoutQuery }); }, variables: { @@ -73,34 +96,49 @@ export default class CartProvider extends React.Component< ] } }); - this.setState({ loading: false }); + + if (x) { + debugger; + } } + + this.setState({ loading: false }); }; add = (variantId, quantity = 1) => { - const line = this.state.lines.find(line => line.variantId === variantId); + const line = this.getLine(variantId); const newQuantity = line ? line.quantity + quantity : quantity; this.changeQuantity(variantId, newQuantity); }; + subtract = (variantId, quantity = 1) => { + const line = this.getLine(variantId); + const newQuantity = line ? line.quantity - quantity : quantity; + this.changeQuantity(variantId, newQuantity); + }; + clear = () => this.setState({ lines: [] }); fetch = async () => { const cart = JSON.parse(localStorage.getItem("cart")) || []; + if (cart.length) { this.setState({ loading: true }); - const { apolloClient } = this.props; - let data: { [key: string]: any }; let lines; - const response = await apolloClient.query({ + const { apolloClient } = this.props; + const { data, errors } = await apolloClient.query< + VariantList, + VariantListVariables + >({ query: productVariatnsQuery, - variables: { ids: cart.map(line => line.variantId) } + variables: { + ids: cart.map(line => line.variantId) + } }); const quantityMapping = cart.reduce((obj, line) => { obj[line.variantId] = line.quantity; return obj; }, {}); - data = response.data; lines = data.productVariants ? data.productVariants.edges.map(variant => ({ quantity: quantityMapping[variant.node.id], @@ -108,15 +146,12 @@ export default class CartProvider extends React.Component< variantId: variant.node.id })) : []; - if (data.errors) { - this.setState({ - errors: data.errors, - lines: [], - loading: false - }); - } else { - this.setState({ loading: false, lines, errors: null }); - } + + this.setState({ + errors: errors ? [new ApolloError({ graphQLErrors: errors })] : null, + lines: errors ? [] : lines, + loading: false + }); } }; @@ -142,9 +177,10 @@ export default class CartProvider extends React.Component< } render() { - const { children } = this.props; return ( - {children} + + {this.props.children} + ); } } diff --git a/src/components/CheckoutApp/index.tsx b/src/components/CheckoutApp/index.tsx index a6c35c800f..d895a29d87 100644 --- a/src/components/CheckoutApp/index.tsx +++ b/src/components/CheckoutApp/index.tsx @@ -1,3 +1,6 @@ +import { mediumScreen } from "../App/scss/variables.scss"; +import "./scss/index.scss"; + import { ApolloClient } from "apollo-client"; import * as React from "react"; import { ApolloConsumer } from "react-apollo"; @@ -8,15 +11,12 @@ import ReactSVG from "react-svg"; import { CartSummary, Loader } from ".."; import { baseUrl } from "../App/routes"; -import { CheckoutContext, CheckoutContextInterface } from "./context"; -import { GET_CHECKOUT } from "./queries"; -import { Routes } from "./routes"; - -import { mediumScreen } from "../App/scss/variables.scss"; import Offline from "../Offline"; import OfflinePlaceholder from "../OfflinePlaceholder"; import Online from "../Online"; -import "./scss/index.scss"; +import { CheckoutContext, CheckoutContextInterface } from "./context"; +import { getCheckoutQuery } from "./queries"; +import { Routes } from "./routes"; export class CheckoutProvider extends React.Component< { @@ -45,7 +45,7 @@ export class CheckoutProvider extends React.Component< getCheckout = async () => { this.setState({ loading: true }); const { data } = await this.props.apolloClient.query({ - query: GET_CHECKOUT, + query: getCheckoutQuery, variables: { token: this.props.token } }); this.setState({ ...data, loading: false }); diff --git a/src/components/CheckoutApp/queries.ts b/src/components/CheckoutApp/queries.ts index dbeedf9dbc..799240727a 100644 --- a/src/components/CheckoutApp/queries.ts +++ b/src/components/CheckoutApp/queries.ts @@ -1,6 +1,8 @@ import gql from "graphql-tag"; +import { TypedQuery } from "../../core/queries"; +import { getCheckout, getCheckoutVariables } from "./types/getCheckout"; -export const CHECKOUT_FRAGMENT = gql` +export const checkoutFragment = gql` fragment Checkout on Checkout { token id @@ -111,7 +113,7 @@ export const CHECKOUT_FRAGMENT = gql` url alt } - thumbnail2x: thumbnail(size: 510){ + thumbnail2x: thumbnail(size: 510) { url } } @@ -121,8 +123,8 @@ export const CHECKOUT_FRAGMENT = gql` } `; -export const GET_CHECKOUT = gql` - ${CHECKOUT_FRAGMENT} +export const getCheckoutQuery = gql` + ${checkoutFragment} query getCheckout($token: UUID!) { checkout(token: $token) { ...Checkout @@ -130,8 +132,8 @@ export const GET_CHECKOUT = gql` } `; -export const UPDATE_CHECKOUT_LINE = gql` - ${CHECKOUT_FRAGMENT} +export const updateCheckoutLineQuery = gql` + ${checkoutFragment} mutation updateCheckoutLine($checkoutId: ID!, $lines: [CheckoutLineInput]!) { checkoutLinesUpdate(checkoutId: $checkoutId, lines: $lines) { checkout { @@ -144,3 +146,8 @@ export const UPDATE_CHECKOUT_LINE = gql` } } `; + +export const TypedGetCheckoutQuery = TypedQuery< + getCheckout, + getCheckoutVariables +>(getCheckoutQuery); diff --git a/src/components/CheckoutBilling/queries.ts b/src/components/CheckoutBilling/queries.ts index 811917a8fc..a58ee9f42e 100644 --- a/src/components/CheckoutBilling/queries.ts +++ b/src/components/CheckoutBilling/queries.ts @@ -1,9 +1,9 @@ import gql from "graphql-tag"; -import { CHECKOUT_FRAGMENT } from "../CheckoutApp/queries"; +import { checkoutFragment } from "../CheckoutApp/queries"; export const UPDATE_CHECKOUT_BILLING_ADDRESS = gql` - ${CHECKOUT_FRAGMENT} + ${checkoutFragment} mutation updateCheckoutBillingAddress( $checkoutId: ID! $billingAddress: AddressInput! diff --git a/src/components/CheckoutShipping/queries.ts b/src/components/CheckoutShipping/queries.ts index 4a5e318c8c..1c481fbfb9 100644 --- a/src/components/CheckoutShipping/queries.ts +++ b/src/components/CheckoutShipping/queries.ts @@ -1,9 +1,9 @@ import gql from "graphql-tag"; -import { CHECKOUT_FRAGMENT } from "../CheckoutApp/queries"; +import { checkoutFragment } from "../CheckoutApp/queries"; export const UPDATE_CHECKOUT_SHIPPING_ADDRESS = gql` - ${CHECKOUT_FRAGMENT} + ${checkoutFragment} mutation updateCheckoutShippingAddress( $checkoutId: ID! $shippingAddress: AddressInput! diff --git a/src/components/CheckoutShippingOptions/queries.ts b/src/components/CheckoutShippingOptions/queries.ts index 77989459b3..d08e446afd 100644 --- a/src/components/CheckoutShippingOptions/queries.ts +++ b/src/components/CheckoutShippingOptions/queries.ts @@ -1,9 +1,9 @@ import gql from "graphql-tag"; -import { CHECKOUT_FRAGMENT } from "../CheckoutApp/queries"; +import { checkoutFragment } from "../CheckoutApp/queries"; export const UPDATE_CHECKOUT_SHIPPING_OPTION = gql` - ${CHECKOUT_FRAGMENT} + ${checkoutFragment} mutation updateCheckoutShippingOptions( $checkoutId: ID! $shippingMethodId: ID! diff --git a/src/components/CartPage/EmptyCart.tsx b/src/components/EmptyCart.tsx similarity index 86% rename from src/components/CartPage/EmptyCart.tsx rename to src/components/EmptyCart.tsx index 0ff40bd93b..e9830c3ed7 100644 --- a/src/components/CartPage/EmptyCart.tsx +++ b/src/components/EmptyCart.tsx @@ -1,8 +1,8 @@ import * as React from "react"; import { Link } from "react-router-dom"; -import { baseUrl } from "../App/routes"; -import Button from "../Button"; +import { baseUrl } from "./App/routes"; +import Button from "./Button"; export const EmptyCart: React.SFC<{}> = () => (
diff --git a/src/components/GoToCheckout/index.tsx b/src/components/GoToCheckout/index.tsx index bfb455b9ee..e2d8f3ad78 100644 --- a/src/components/GoToCheckout/index.tsx +++ b/src/components/GoToCheckout/index.tsx @@ -5,7 +5,7 @@ import { Redirect } from "react-router"; import { ButtonProps, default as Button } from "../Button"; import { CartInterface } from "../CartProvider/context"; import { CheckoutContext } from "../CheckoutApp/context"; -import { GET_CHECKOUT } from "../CheckoutApp/queries"; +import { getCheckoutQuery } from "../CheckoutApp/queries"; import { checkoutBaseUrl, checkoutBillingUrl, @@ -13,6 +13,10 @@ import { checkoutShippingOptionsUrl } from "../CheckoutApp/routes"; import { Checkout } from "../CheckoutApp/types/Checkout"; +import { + getCheckout, + getCheckoutVariables +} from "../CheckoutApp/types/getCheckout"; import { CREATE_CHECKOUT } from "./queries"; export interface GoToCheckoutState { @@ -51,15 +55,17 @@ export class GoToCheckout extends React.Component< const checkoutToken = localStorage.getItem("checkout"); if (checkoutToken) { localStorage.setItem("checkout", checkoutToken); + const { apolloClient } = this.props; - let data: { [key: string]: any }; - const response = await apolloClient.query({ - query: GET_CHECKOUT, + const { data } = await apolloClient.query< + getCheckout, + getCheckoutVariables + >({ + query: getCheckoutQuery, variables: { token: checkoutToken } }); - data = response.data; this.setState({ checkout: data.checkout, checkoutToken, @@ -96,6 +102,7 @@ export class GoToCheckout extends React.Component< getRedirection() { const { checkout } = this.state; let pathname; + if (checkout.billingAddress) { pathname = checkoutPaymentUrl(this.state.checkoutToken); } else if (checkout.shippingMethod) { @@ -105,6 +112,7 @@ export class GoToCheckout extends React.Component< } else { pathname = checkoutBaseUrl(this.state.checkoutToken); } + if (pathname) { return ( @@ -117,15 +125,23 @@ export class GoToCheckout extends React.Component< } } + componentDidUpdate() { + if (this.state.checkoutToken && this.state.redirect) { + this.setState({ redirect: false }); + } + } + render = () => { const { children, cart, apolloClient, ...buttonProps } = this.props; + if (this.state.loading) { return ; } + if (this.state.checkoutToken && this.state.redirect) { - this.setState({ redirect: false }); return this.getRedirection(); } + return ( + + ) + } + +
+ + )} + + ); + } else { + return ; + } +}; + +export default Page; diff --git a/src/views/Cart/View.tsx b/src/views/Cart/View.tsx new file mode 100644 index 0000000000..ad5d62f22a --- /dev/null +++ b/src/views/Cart/View.tsx @@ -0,0 +1,35 @@ +import "./scss/index.scss"; + +import * as React from "react"; +import { RouteComponentProps } from "react-router"; + +import { Loader } from "../../components"; +import { TypedGetCheckoutQuery } from "../../components/CheckoutApp/queries"; +import { getCheckout_checkout } from "../../components/CheckoutApp/types/getCheckout"; +import { maybe } from "../../core/utils"; +import Page from "./Page"; + +const canDisplay = (checkout: getCheckout_checkout) => + maybe(() => checkout.lines && checkout.subtotalPrice); + +const View: React.SFC> = ({ + match: { + params: { token = "" } + } +}) => { + return ( +
+

Shopping bag

+ + {({ data: { checkout } }) => { + if (canDisplay(checkout)) { + return ; + } + return ; + }} + +
+ ); +}; + +export default View; diff --git a/src/views/Cart/index.ts b/src/views/Cart/index.ts new file mode 100644 index 0000000000..9494d6f214 --- /dev/null +++ b/src/views/Cart/index.ts @@ -0,0 +1 @@ +export { default as CartPage } from "./View"; diff --git a/src/components/CartPage/scss/index.scss b/src/views/Cart/scss/index.scss similarity index 54% rename from src/components/CartPage/scss/index.scss rename to src/views/Cart/scss/index.scss index 141c883e13..b2a5c961ce 100644 --- a/src/components/CartPage/scss/index.scss +++ b/src/views/Cart/scss/index.scss @@ -1,4 +1,4 @@ -@import "../../App/scss/variables.scss"; +@import "../../../components/App/scss/variables.scss"; .cart-page { &__header { @@ -10,6 +10,40 @@ color: $gray-dark; font-weight: $bold-font-weight; } + + &__quantity { + &-header { + text-align: center; + } + + &-cell { + div { + align-items: center; + display: flex; + justify-content: space-around; + } + + & > div { + padding: 0.5rem; + } + + svg:hover { + cursor: pointer; + } + + &--processing { + svg { + &:hover { + cursor: initial; + } + + path { + stroke: $white; + } + } + } + } + } } &__thumbnail { From c85e386766c767066130e1d1c77884ee89f57408 Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Tue, 8 Jan 2019 13:00:57 +0100 Subject: [PATCH 2/5] Improve quantity change handling --- package-lock.json | 22 +-- src/components/CartProvider/index.tsx | 18 +-- .../DebounceChange.tsx} | 26 ++-- .../Debounce/DebouncedTextField.tsx | 25 ++++ src/components/Debounce/index.ts | 2 + src/components/GoToCheckout/index.tsx | 15 +- src/components/GoToCheckout/queries.ts | 2 +- .../SearchOverlay/SearchOverlay.tsx | 34 ++--- src/components/TextField/index.tsx | 3 +- src/components/index.ts | 2 +- src/core/utils.ts | 6 +- src/views/Cart/Page.tsx | 138 +++++++++--------- src/views/Cart/scss/index.scss | 34 +++-- src/views/Search/index.tsx | 6 +- 14 files changed, 178 insertions(+), 155 deletions(-) rename src/components/{Debounce.tsx => Debounce/DebounceChange.tsx} (66%) create mode 100644 src/components/Debounce/DebouncedTextField.tsx create mode 100644 src/components/Debounce/index.ts diff --git a/package-lock.json b/package-lock.json index 19ccfc1e73..0ac209941e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12554,7 +12554,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -12574,7 +12574,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -14647,7 +14647,7 @@ "dependencies": { "ansi-escapes": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -14659,7 +14659,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -14758,7 +14758,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -14769,7 +14769,7 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true } @@ -15359,7 +15359,7 @@ }, "chalk": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { @@ -16283,7 +16283,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -18808,7 +18808,7 @@ }, "mute-stream": { "version": "0.0.5", - "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", "dev": true } @@ -20808,7 +20808,7 @@ }, "temp": { "version": "0.8.3", - "resolved": "http://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "dev": true, "requires": { @@ -23078,7 +23078,7 @@ "dependencies": { "string-width": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { diff --git a/src/components/CartProvider/index.tsx b/src/components/CartProvider/index.tsx index eb19704a52..379863d53c 100644 --- a/src/components/CartProvider/index.tsx +++ b/src/components/CartProvider/index.tsx @@ -14,11 +14,11 @@ import { getCheckout, getCheckoutVariables } from "../CheckoutApp/types/getCheckout"; +import { CartContext, CartInterface, CartLineInterface } from "./context"; import { updateCheckoutLine, updateCheckoutLineVariables } from "../CheckoutApp/types/updateCheckoutLine"; -import { CartContext, CartInterface, CartLineInterface } from "./context"; export default class CartProvider extends React.Component< { children: any; apolloClient: ApolloClient }, @@ -63,20 +63,24 @@ export default class CartProvider extends React.Component< if (newLine.quantity > 0) { lines = [...lines, newLine]; } + return { lines }; }); if (checkoutToken) { const { apolloClient } = this.props; const { - data: { checkout } + data: { + checkout: { id: checkoutID } + } } = await apolloClient.query({ query: getCheckoutQuery, variables: { token: checkoutToken } }); - const checkoutID = checkout.id; - - const x = await apolloClient.mutate({ + const {} = await apolloClient.mutate< + updateCheckoutLine, + updateCheckoutLineVariables + >({ mutation: updateCheckoutLineQuery, update: (cache, { data: { checkoutLinesUpdate } }) => { cache.writeQuery({ @@ -96,10 +100,6 @@ export default class CartProvider extends React.Component< ] } }); - - if (x) { - debugger; - } } this.setState({ loading: false }); diff --git a/src/components/Debounce.tsx b/src/components/Debounce/DebounceChange.tsx similarity index 66% rename from src/components/Debounce.tsx rename to src/components/Debounce/DebounceChange.tsx index 5da7012f6c..cc9771799c 100644 --- a/src/components/Debounce.tsx +++ b/src/components/Debounce/DebounceChange.tsx @@ -1,6 +1,6 @@ import * as React from "react"; -export interface DebounceProps { +export interface DebounceChangeProps { children: (( props: { change: (event: React.ChangeEvent) => void; @@ -11,32 +11,26 @@ export interface DebounceProps { time?: number; value: TValue; } -export interface DebounceState { +export interface DebounceChangeState { timer: any | null; value: TValue; } -export class Debounce extends React.Component< - DebounceProps, - DebounceState +export class DebounceChange extends React.Component< + DebounceChangeProps, + DebounceChangeState > { static getDerivedStateFromProps( - props: DebounceProps, - state: DebounceState + props: DebounceChangeProps, + state: DebounceChangeState ) { if (props.value !== state.value && state.timer === null) { - return { - ...state, - value: props.value - }; + return { ...state, value: props.value }; } return state; } - state: DebounceState = { - timer: null, - value: this.props.value - }; + state: DebounceChangeState = { timer: null, value: this.props.value }; handleChange = (event: React.ChangeEvent) => { event.persist(); @@ -60,4 +54,4 @@ export class Debounce extends React.Component< }); } } -export default Debounce; +export default DebounceChange; diff --git a/src/components/Debounce/DebouncedTextField.tsx b/src/components/Debounce/DebouncedTextField.tsx new file mode 100644 index 0000000000..4f4a371008 --- /dev/null +++ b/src/components/Debounce/DebouncedTextField.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import TextField, { TextFieldProps } from "../TextField"; +import DebounceChange, { DebounceChangeProps } from "./DebounceChange"; + +interface DebouncedTextFieldProps extends TextFieldProps { + time?: number; +} + +const DebouncedTextField: React.SFC = props => { + const { time, value, onChange, ...textFieldProps } = props; + return ( + + {({ change, value }) => ( + + )} + + ); +}; + +DebouncedTextField.defaultProps = { + time: 500 +}; + +export default DebouncedTextField; diff --git a/src/components/Debounce/index.ts b/src/components/Debounce/index.ts new file mode 100644 index 0000000000..40c608e76c --- /dev/null +++ b/src/components/Debounce/index.ts @@ -0,0 +1,2 @@ +export { default as DebounceChange } from "./DebounceChange"; +export { default as DebouncedTextField } from "./DebouncedTextField"; diff --git a/src/components/GoToCheckout/index.tsx b/src/components/GoToCheckout/index.tsx index e2d8f3ad78..18147cf84e 100644 --- a/src/components/GoToCheckout/index.tsx +++ b/src/components/GoToCheckout/index.tsx @@ -17,7 +17,11 @@ import { getCheckout, getCheckoutVariables } from "../CheckoutApp/types/getCheckout"; -import { CREATE_CHECKOUT } from "./queries"; +import { createCheckoutQuery } from "./queries"; +import { + createCheckout, + createCheckoutVariables +} from "./types/createCheckout"; export interface GoToCheckoutState { checkout?: Checkout; @@ -78,11 +82,14 @@ export class GoToCheckout extends React.Component< cart: { lines } } = this.props; this.setState({ loading: true }); - const { data } = await apolloClient.mutate({ - mutation: CREATE_CHECKOUT, + const { data } = await apolloClient.mutate< + createCheckout, + createCheckoutVariables + >({ + mutation: createCheckoutQuery, variables: { checkoutInput: { - lines: lines.map(line => ({ + lines: lines.map((line: { quantity; variantId }) => ({ quantity: line.quantity, variantId: line.variantId })) diff --git a/src/components/GoToCheckout/queries.ts b/src/components/GoToCheckout/queries.ts index d2842f18e5..1526eba40b 100644 --- a/src/components/GoToCheckout/queries.ts +++ b/src/components/GoToCheckout/queries.ts @@ -2,7 +2,7 @@ import gql from "graphql-tag"; import { checkoutFragment } from "../CheckoutApp/queries"; -export const CREATE_CHECKOUT = gql` +export const createCheckoutQuery = gql` ${checkoutFragment} mutation createCheckout($checkoutInput: CheckoutCreateInput!) { checkoutCreate(input: $checkoutInput) { diff --git a/src/components/SearchOverlay/SearchOverlay.tsx b/src/components/SearchOverlay/SearchOverlay.tsx index f6f2165181..f2ec1bd92b 100644 --- a/src/components/SearchOverlay/SearchOverlay.tsx +++ b/src/components/SearchOverlay/SearchOverlay.tsx @@ -5,10 +5,9 @@ import * as React from "react"; import { Link, RouteComponentProps, withRouter } from "react-router-dom"; import ReactSVG from "react-svg"; -import { Button, Loader, TextField } from ".."; +import { Button, DebounceChange, Loader, TextField } from ".."; import { maybe } from "../../core/utils"; import { searchUrl } from "../App/routes"; -import Debounce from "../Debounce"; import { Error } from "../Error"; import NetworkStatus from "../NetworkStatus"; import { OfflinePlaceholder } from "../OfflinePlaceholder"; @@ -18,6 +17,7 @@ import NothingFound from "./NothingFound"; import ProductItem from "./ProductItem"; import { TypedSearchResults } from "./queries"; import { SearchResults } from "./types/SearchResults"; +import { DebouncedTextField } from "../Debounce"; const closeSvg = require("../../images/x.svg"); const searchSvg = require("../../images/search.svg"); @@ -89,26 +89,18 @@ class SearchOverlay extends React.Component< onClick={e => e.stopPropagation()} >
- this.setState({ search: evt.target.value })} + this.setState({ search: evt.target.value })} value={this.state.search} - time={500} - > - {({ change, value: query }) => ( - - } - iconRight={} - autoFocus={true} - onChange={change} - value={query} - placeholder="Search" - onKeyPress={this.handleEnterPress} - onBlur={this.handleInputBlur} - /> - )} - + iconLeft={ + + } + iconRight={} + autoFocus={true} + placeholder="Search" + onKeyPress={this.handleEnterPress} + onBlur={this.handleInputBlur} + />
{ +export interface TextFieldProps + extends React.InputHTMLAttributes { errors?: FormError[]; helpText?: string; label?: string; diff --git a/src/components/index.ts b/src/components/index.ts index 549dfe2a95..9a9f5c761c 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -28,7 +28,6 @@ export { default as AddressSummary } from "./AddressSummary"; export { default as CheckoutPayment } from "./CheckoutPayment"; export { default as ShippingAddressForm } from "./ShippingAddressForm"; export { default as CheckoutReview } from "./CheckoutReview"; -export { default as Debounce } from "./Debounce"; export { default as ProductsFeatured } from "./ProductsFeatured"; export { Filters, ProductFilters } from "./ProductFilters"; export { @@ -36,6 +35,7 @@ export { Breadcrumb, extractBreadcrumbs } from "./Breadcrumbs"; +export { DebounceChange, DebouncedTextField } from "./Debounce"; export { Footer } from "./Footer"; export { MainMenu, MainMenuNavOverlay } from "./MainMenu"; export { MobileNav } from "./MobileNav"; diff --git a/src/core/utils.ts b/src/core/utils.ts index b2eee4d17a..f745c9e69b 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -2,11 +2,7 @@ import * as H from "history"; import { Base64 } from "js-base64"; import { parse as parseQs, stringify as stringifyQs } from "query-string"; -import { - OrderDirection, - ProductOrder, - ProductOrderField -} from "../../types/globalTypes"; +import { OrderDirection, ProductOrderField } from "../../types/globalTypes"; export const slugify = (text: string | number): string => text diff --git a/src/views/Cart/Page.tsx b/src/views/Cart/Page.tsx index 46c422a609..9d929139c6 100644 --- a/src/views/Cart/Page.tsx +++ b/src/views/Cart/Page.tsx @@ -8,7 +8,7 @@ import Media from "react-media"; import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; -import { Button, Loader, TextField } from "../../components"; +import { Button, DebouncedTextField } from "../../components"; import { checkoutLoginUrl } from "../../components/App/routes"; import CachedImage from "../../components/CachedImage"; import { CartContext } from "../../components/CartProvider/context"; @@ -30,28 +30,33 @@ const Page: React.SFC<{ checkout: getCheckout_checkout }> = ({ checkout }) => { return ( {isTabletUp => ( - <> - - - - - {isTabletUp && } - - - - - - - {({ remove, add, subtract, loading, changeQuantity }) => - lines + + {({ remove, add, subtract, loading, changeQuantity }) => ( + <> +
ProductsPrice - Quantity - {isTabletUp ? "Total Price" : "Price"} -
+ + + + {isTabletUp && } + + + + + + {lines .sort((a, b) => b.id.toLowerCase().localeCompare(a.id.toLowerCase()) ) .map(line => ( - + {isTabletUp && ( )} - @@ -113,40 +112,45 @@ const Page: React.SFC<{ checkout: getCheckout_checkout }> = ({ checkout }) => { /> - )) - } - - - - - - {isTabletUp && - - -
ProductsPrice + Quantity + {isTabletUp ? "Total Price" : "Price"} +
{isTabletUp && ( = ({ checkout }) => { )} {line.variant.product.name} {line.variant.name - ? ` (${line.variant.name})` + ? `(${line.variant.name})` : null} {line.variant.price.localized} + {isTabletUp ? (
= ({ checkout }) => { />
) : ( - + changeQuantity( line.variant.id, - parseInt(evt.target.value, 10) + parseInt(value, 10) ) } + disabled={loading} + value={line.quantity} + type="number" /> )}
Subtotal} - - {checkout.subtotalPrice.gross.localized} -
-
- - {({ user }) => - user ? ( - - {client => ( - - Proceed to Checkout{" "} - - )} - - ) : ( - - - - ) - } - -
- + ))} + + + + Subtotal + {isTabletUp && } + + {checkout.subtotalPrice.gross.localized} + + + + +
+ + {({ user }) => + user ? ( + + {client => ( + + Proceed to Checkout{" "} + + )} + + ) : ( + + + + ) + } + +
+ + )} + )}
); diff --git a/src/views/Cart/scss/index.scss b/src/views/Cart/scss/index.scss index b2a5c961ce..c5018d8b52 100644 --- a/src/views/Cart/scss/index.scss +++ b/src/views/Cart/scss/index.scss @@ -6,6 +6,20 @@ } &__table { + &-row--processing td { + position: relative; + + &::after { + background-color: rgba($white, 0.65); + position: absolute; + content: ""; + width: 100%; + height: 100%; + left: 0; + top: 0; + } + } + &__subtotal { color: $gray-dark; font-weight: $bold-font-weight; @@ -26,24 +40,12 @@ & > div { padding: 0.5rem; } - - svg:hover { - cursor: pointer; - } - - &--processing { - svg { - &:hover { - cursor: initial; - } - - path { - stroke: $white; - } - } - } } } + + svg:hover { + cursor: pointer; + } } &__thumbnail { diff --git a/src/views/Search/index.tsx b/src/views/Search/index.tsx index a73e180020..27b6ba8e0a 100644 --- a/src/views/Search/index.tsx +++ b/src/views/Search/index.tsx @@ -5,7 +5,7 @@ import * as React from "react"; import { RouteComponentProps } from "react-router"; import { - Debounce, + DebounceChange, Loader, ProductsFeatured, ProductsList @@ -104,7 +104,7 @@ export const SearchView: React.SFC = ({ ); return ( - = ({ ); }} - + ); }} From a91d9016dc6820cd5c6c06de082d3b48234c972c Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Tue, 8 Jan 2019 18:43:09 +0100 Subject: [PATCH 3/5] Code improvements --- package-lock.json | 22 +-- src/components/App/index.tsx | 2 +- .../{index.tsx => CachedImage.tsx} | 9 +- .../CachedImage/CachedThumbnail.tsx | 32 ++++ src/components/CachedImage/index.ts | 2 + .../{index.tsx => CartOverlay.tsx} | 64 ++----- src/components/CartOverlay/Empty.tsx | 20 +++ src/components/CartOverlay/ProductList.tsx | 47 +++++ src/components/CartOverlay/index.ts | 1 + src/components/CartProvider/index.tsx | 38 ++-- src/components/CheckoutReview/index.tsx | 16 +- .../Debounce/DebouncedTextField.tsx | 2 +- src/components/ProductListItem/index.tsx | 17 +- src/components/SearchOverlay/ProductItem.tsx | 9 +- src/components/index.ts | 3 +- src/views/Cart/Page.tsx | 170 ++++-------------- src/views/Cart/ProductsTable.tsx | 129 +++++++++++++ src/views/Cart/scss/index.scss | 2 +- src/views/Product/Page.tsx | 5 +- 19 files changed, 338 insertions(+), 252 deletions(-) rename src/components/CachedImage/{index.tsx => CachedImage.tsx} (89%) create mode 100644 src/components/CachedImage/CachedThumbnail.tsx create mode 100644 src/components/CachedImage/index.ts rename src/components/CartOverlay/{index.tsx => CartOverlay.tsx} (65%) create mode 100644 src/components/CartOverlay/Empty.tsx create mode 100644 src/components/CartOverlay/ProductList.tsx create mode 100644 src/components/CartOverlay/index.ts create mode 100644 src/views/Cart/ProductsTable.tsx diff --git a/package-lock.json b/package-lock.json index 0ac209941e..19ccfc1e73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12554,7 +12554,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -12574,7 +12574,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -14647,7 +14647,7 @@ "dependencies": { "ansi-escapes": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -14659,7 +14659,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -14758,7 +14758,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -14769,7 +14769,7 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true } @@ -15359,7 +15359,7 @@ }, "chalk": { "version": "0.4.0", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { @@ -16283,7 +16283,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -18808,7 +18808,7 @@ }, "mute-stream": { "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", "dev": true } @@ -20808,7 +20808,7 @@ }, "temp": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "resolved": "http://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "dev": true, "requires": { @@ -23078,7 +23078,7 @@ "dependencies": { "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 9c01f15d4a..1b25d4ed1c 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { ApolloConsumer } from "react-apollo"; import { + CartOverlay, Footer, MainMenu, MainMenuNavOverlay, @@ -9,7 +10,6 @@ import { MobileNav, SearchOverlay } from ".."; -import { CartOverlay } from "../CartOverlay"; import CartProvider from "../CartProvider"; import { LoginOverlay } from "../LoginOverlay"; import { NotificationOverlay } from "../NotificationOverlay"; diff --git a/src/components/CachedImage/index.tsx b/src/components/CachedImage/CachedImage.tsx similarity index 89% rename from src/components/CachedImage/index.tsx rename to src/components/CachedImage/CachedImage.tsx index 48d4f7b6fc..a04c587113 100644 --- a/src/components/CachedImage/index.tsx +++ b/src/components/CachedImage/CachedImage.tsx @@ -3,6 +3,7 @@ import * as React from "react"; interface CachedImageProps { url: string; url2x?: string; + alt?: string; } interface CachedImageState { @@ -56,12 +57,16 @@ class CachedImage extends React.Component { } render() { - const { url, url2x } = this.props; + const { url, url2x, alt } = this.props; if (this.state.isUnavailable) { return this.props.children || null; } return ( - + {alt} ); } } diff --git a/src/components/CachedImage/CachedThumbnail.tsx b/src/components/CachedImage/CachedThumbnail.tsx new file mode 100644 index 0000000000..3b445c3eb1 --- /dev/null +++ b/src/components/CachedImage/CachedThumbnail.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; + +import { maybe } from "../../core/utils"; +import CachedImage from "./CachedImage"; + +const noPhotoPng = require("../../images/nophoto.png"); + +const CachedThumbnail: React.SFC<{ + source: { + thumbnail: { url: string; alt: string }; + thumbnail2x: { url: string }; + }; + noPhotoDefault?: boolean; + children?: React.ReactNode; +}> = ({ source, noPhotoDefault, children }) => { + const defaultImg = noPhotoDefault ? noPhotoPng : undefined; + return ( + source.thumbnail.url, defaultImg)} + url2x={maybe(() => source.thumbnail2x.url, defaultImg)} + alt={maybe(() => source.thumbnail.alt, "")} + > + {children} + + ); +}; + +CachedThumbnail.defaultProps = { + noPhotoDefault: true +}; + +export default CachedThumbnail; diff --git a/src/components/CachedImage/index.ts b/src/components/CachedImage/index.ts new file mode 100644 index 0000000000..abb3a253e4 --- /dev/null +++ b/src/components/CachedImage/index.ts @@ -0,0 +1,2 @@ +export { default as CachedImage } from "./CachedImage"; +export { default as CachedThumbnail } from "./CachedThumbnail"; diff --git a/src/components/CartOverlay/index.tsx b/src/components/CartOverlay/CartOverlay.tsx similarity index 65% rename from src/components/CartOverlay/index.tsx rename to src/components/CartOverlay/CartOverlay.tsx index 2c7abd5685..048cf3ee7a 100644 --- a/src/components/CartOverlay/index.tsx +++ b/src/components/CartOverlay/CartOverlay.tsx @@ -6,9 +6,8 @@ import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; import { Button } from ".."; -import { maybe, priceToString } from "../../core/utils"; +import { priceToString } from "../../core/utils"; import { checkoutLoginUrl } from "../App/routes"; -import CachedImage from "../CachedImage"; import { CartContext } from "../CartProvider/context"; import { Error } from "../Error"; import GoToCart from "../GoToCart"; @@ -21,13 +20,13 @@ import { Overlay } from "../Overlay"; import { OverlayContext, OverlayType } from "../Overlay/context"; import { ShopContext } from "../ShopProvider/context"; import { UserContext } from "../User/context"; +import Empty from "./Empty"; +import ProductList from "./ProductList"; const cartSvg = require("../../images/cart.svg"); const closeSvg = require("../../images/x.svg"); -const noPhotoPng = require("../../images/nophoto.png"); -const removeSvg = require("../../images/garbage.svg"); -export const CartOverlay: React.SFC = () => ( +const CartOverlay: React.SFC = () => ( {overlay => overlay.type === OverlayType.cart ? ( @@ -67,45 +66,16 @@ export const CartOverlay: React.SFC = () => (
overlay.hide()} + onClick={overlay.hide} className="overlay__header__close-icon" />
{lines.length ? ( <> -
    - {lines.map(line => ( -
  • - line.variant.product.thumbnail.url, - noPhotoPng - )} - url2x={maybe( - () => line.variant.product.thumbnail2x.url - )} - /> -
    -

    {line.variant.price.localized}

    -

    {line.variant.product.name}

    - - {line.variant.name} - {"Qty: " + line.quantity} - - - cart.remove(line.variant.id) - } - /> -
    -
  • - ))} -
+
Subtotal @@ -128,7 +98,6 @@ export const CartOverlay: React.SFC = () => ( apolloClient={client} cart={cart} secondary - onClick={overlay.hide} > Go to my bag @@ -154,18 +123,7 @@ export const CartOverlay: React.SFC = () => (
) : ( -
-

Yor bag is empty

-

- You haven’t added anything to your bag. We’re sure - you’ll find something in our store -

-
- -
-
+ )}
); @@ -184,3 +142,5 @@ export const CartOverlay: React.SFC = () => ( } ); + +export default CartOverlay; diff --git a/src/components/CartOverlay/Empty.tsx b/src/components/CartOverlay/Empty.tsx new file mode 100644 index 0000000000..eadfb4e65d --- /dev/null +++ b/src/components/CartOverlay/Empty.tsx @@ -0,0 +1,20 @@ +import * as React from "react"; + +import { Button } from ".."; + +const Empty: React.SFC<{ overlayHide(): void }> = ({ overlayHide }) => ( +
+

Yor bag is empty

+

+ You haven’t added anything to your bag. We’re sure you’ll find something + in our store +

+
+ +
+
+); + +export default Empty; diff --git a/src/components/CartOverlay/ProductList.tsx b/src/components/CartOverlay/ProductList.tsx new file mode 100644 index 0000000000..2203d34697 --- /dev/null +++ b/src/components/CartOverlay/ProductList.tsx @@ -0,0 +1,47 @@ +import * as React from "react"; +import { Link } from "react-router-dom"; +import ReactSVG from "react-svg"; + +import { CachedThumbnail } from ".."; +import { generateProductUrl } from "../../core/utils"; +import { CartLineInterface } from "../CartProvider/context"; + +const removeSvg = require("../../images/garbage.svg"); + +const ProductList: React.SFC<{ + lines: CartLineInterface[]; + removeFromCart(variantId: string): void; +}> = ({ lines, removeFromCart }) => ( +
    + {lines.map(line => { + const productUrl = generateProductUrl( + line.variant.product.id, + line.variant.product.name + ); + return ( +
  • + + + +
    +

    {line.variant.price.localized}

    + +

    {line.variant.product.name}

    + + + {line.variant.name} + {`Qty: ${line.quantity}`} + + removeFromCart(line.variant.id)} + /> +
    +
  • + ); + })} +
+); + +export default ProductList; diff --git a/src/components/CartOverlay/index.ts b/src/components/CartOverlay/index.ts new file mode 100644 index 0000000000..16984ede66 --- /dev/null +++ b/src/components/CartOverlay/index.ts @@ -0,0 +1 @@ +export { default as CartOverlay } from "./CartOverlay"; diff --git a/src/components/CartProvider/index.tsx b/src/components/CartProvider/index.tsx index 379863d53c..87b9d14e4f 100644 --- a/src/components/CartProvider/index.tsx +++ b/src/components/CartProvider/index.tsx @@ -14,11 +14,11 @@ import { getCheckout, getCheckoutVariables } from "../CheckoutApp/types/getCheckout"; -import { CartContext, CartInterface, CartLineInterface } from "./context"; import { updateCheckoutLine, updateCheckoutLineVariables } from "../CheckoutApp/types/updateCheckoutLine"; +import { CartContext, CartInterface, CartLineInterface } from "./context"; export default class CartProvider extends React.Component< { children: any; apolloClient: ApolloClient }, @@ -56,16 +56,7 @@ export default class CartProvider extends React.Component< this.setState({ loading: true }); const checkoutToken = localStorage.getItem("checkout"); - const newLine: CartLineInterface = { quantity, variantId }; - - this.setState(prevState => { - let lines = prevState.lines.filter(line => line.variantId !== variantId); - if (newLine.quantity > 0) { - lines = [...lines, newLine]; - } - - return { lines }; - }); + let apiError = false; if (checkoutToken) { const { apolloClient } = this.props; @@ -77,7 +68,11 @@ export default class CartProvider extends React.Component< query: getCheckoutQuery, variables: { token: checkoutToken } }); - const {} = await apolloClient.mutate< + const { + data: { + checkoutLinesUpdate: { errors } + } + } = await apolloClient.mutate< updateCheckoutLine, updateCheckoutLineVariables >({ @@ -100,9 +95,25 @@ export default class CartProvider extends React.Component< ] } }); + apiError = !!errors.length; + if (apiError) { + // TODO Add notificaton after https://github.com/mirumee/saleor/pull/3563 will be resolved + this.setState({ loading: false }); + } } - this.setState({ loading: false }); + if (!apiError) { + const newLine = { quantity, variantId }; + this.setState(prevState => { + let lines = prevState.lines.filter( + line => line.variantId !== variantId + ); + if (newLine.quantity > 0) { + lines = [...lines, newLine]; + } + return { lines, loading: false }; + }); + } }; add = (variantId, quantity = 1) => { @@ -175,7 +186,6 @@ export default class CartProvider extends React.Component< localStorage.setItem("cart", JSON.stringify(this.state.lines)); } } - render() { return ( diff --git a/src/components/CheckoutReview/index.tsx b/src/components/CheckoutReview/index.tsx index 2a4ffa69ad..5b94199c0f 100644 --- a/src/components/CheckoutReview/index.tsx +++ b/src/components/CheckoutReview/index.tsx @@ -6,15 +6,11 @@ import { Mutation } from "react-apollo"; import Media from "react-media"; import { RouteComponentProps } from "react-router"; -import { AddressSummary, Button } from ".."; -import { maybe } from "../../core/utils"; -import CachedImage from "../CachedImage"; +import { AddressSummary, Button, CachedThumbnail } from ".."; import { CheckoutContext } from "../CheckoutApp/context"; import { OverlayContext, OverlayType } from "../Overlay/context"; import { COMPLETE_CHECKOUT } from "./queries"; -const noPhotoPng = require("../../images/nophoto.png"); - class CheckoutReview extends React.Component, {}> { render() { return ( @@ -49,15 +45,7 @@ class CheckoutReview extends React.Component, {}> { ( - line.variant.product.thumbnail.url, - noPhotoPng - )} - url2x={maybe( - () => line.variant.product.thumbnail2x.url - )} - /> + )} /> {line.variant.product.name} diff --git a/src/components/Debounce/DebouncedTextField.tsx b/src/components/Debounce/DebouncedTextField.tsx index 4f4a371008..375472ae60 100644 --- a/src/components/Debounce/DebouncedTextField.tsx +++ b/src/components/Debounce/DebouncedTextField.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import TextField, { TextFieldProps } from "../TextField"; -import DebounceChange, { DebounceChangeProps } from "./DebounceChange"; +import DebounceChange from "./DebounceChange"; interface DebouncedTextFieldProps extends TextFieldProps { time?: number; diff --git a/src/components/ProductListItem/index.tsx b/src/components/ProductListItem/index.tsx index 481622dd74..a0f09f96fc 100644 --- a/src/components/ProductListItem/index.tsx +++ b/src/components/ProductListItem/index.tsx @@ -2,9 +2,8 @@ import "./scss/index.scss"; import * as React from "react"; -import { maybe } from "../../core/utils"; +import { CachedThumbnail } from ".."; import { BasicProductFields } from "../../views/Product/types/BasicProductFields"; -import CachedImage from "../CachedImage"; const noPhoto = require("../../images/nophoto.png"); @@ -15,23 +14,21 @@ export interface Product extends BasicProductFields { }; price: { localized: string; - } + }; } interface ProductListItemProps { product: Product; } -const ProductListItem: React.SFC = ({ - product: { name, category, price, thumbnail, thumbnail2x } -}) => { - const thumbnail2xUrl = maybe(() => thumbnail2x.url, undefined) +const ProductListItem: React.SFC = ({ product }) => { + const { price, category } = product; return (
- - {thumbnail.alt} - + + {product.thumbnail.alt} +

{name}

{category.name}

diff --git a/src/components/SearchOverlay/ProductItem.tsx b/src/components/SearchOverlay/ProductItem.tsx index fc000e90cc..54ec64cb92 100644 --- a/src/components/SearchOverlay/ProductItem.tsx +++ b/src/components/SearchOverlay/ProductItem.tsx @@ -1,21 +1,16 @@ import * as React from "react"; import { Link } from "react-router-dom"; -import { CachedImage } from ".."; +import { CachedThumbnail } from ".."; import { generateProductUrl, maybe } from "../../core/utils"; import { SearchResults_products_edges } from "./types/SearchResults"; -const noPhotoPng = require("../../images/nophoto.png"); - const ProductItem: React.SFC = ({ node: product }) => (
  • - product.thumbnail.url, noPhotoPng)} - url2x={maybe(() => product.thumbnail2x.url, noPhotoPng)} - /> +

    {product.name}

    {product.category.name}

    diff --git a/src/components/index.ts b/src/components/index.ts index 9a9f5c761c..bf8a8748e5 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,5 +1,4 @@ export { default as App } from "./App"; -export { default as CachedImage } from "./CachedImage"; export { default as ContentPage } from "./ContentPage"; export { default as Button, ButtonProps } from "./Button"; export { default as TextField } from "./TextField"; @@ -36,6 +35,7 @@ export { extractBreadcrumbs } from "./Breadcrumbs"; export { DebounceChange, DebouncedTextField } from "./Debounce"; +export { CachedImage, CachedThumbnail } from "./CachedImage"; export { Footer } from "./Footer"; export { MainMenu, MainMenuNavOverlay } from "./MainMenu"; export { MobileNav } from "./MobileNav"; @@ -47,3 +47,4 @@ export { MetaContextInterface, MetaWrapper } from "./Meta"; +export { CartOverlay } from "./CartOverlay"; diff --git a/src/views/Cart/Page.tsx b/src/views/Cart/Page.tsx index 9d929139c6..95286c376b 100644 --- a/src/views/Cart/Page.tsx +++ b/src/views/Cart/Page.tsx @@ -1,158 +1,56 @@ -import { smallScreen } from "../../components/App/scss/variables.scss"; import "./scss/index.scss"; -import classNames from "classnames"; import * as React from "react"; import { ApolloConsumer } from "react-apollo"; -import Media from "react-media"; import { Link } from "react-router-dom"; -import ReactSVG from "react-svg"; -import { Button, DebouncedTextField } from "../../components"; +import { Button } from "../../components"; import { checkoutLoginUrl } from "../../components/App/routes"; -import CachedImage from "../../components/CachedImage"; import { CartContext } from "../../components/CartProvider/context"; import { getCheckout_checkout } from "../../components/CheckoutApp/types/getCheckout"; import { EmptyCart } from "../../components/EmptyCart"; import { GoToCheckout } from "../../components/GoToCheckout"; import { UserContext } from "../../components/User/context"; -import { maybe } from "../../core/utils"; - -const noPhotoPng = require("../../images/nophoto.png"); -const cartRemoveSvg = require("../../images/cart-remove.svg"); -const cartAddSvg = require("../../images/cart-add.svg"); -const cartSubtractSvg = require("../../images/cart-subtract.svg"); +import ProductsTable from "./ProductsTable"; const Page: React.SFC<{ checkout: getCheckout_checkout }> = ({ checkout }) => { const { lines } = checkout; if (lines.length > 0) { return ( - - {isTabletUp => ( - - {({ remove, add, subtract, loading, changeQuantity }) => ( - <> - - - - - {isTabletUp && } - - - - - - {lines - .sort((a, b) => - b.id.toLowerCase().localeCompare(a.id.toLowerCase()) - ) - .map(line => ( - - - {isTabletUp && ( - - )} - - - - - ))} - - - - - {isTabletUp && - - -
    ProductsPrice - Quantity - {isTabletUp ? "Total Price" : "Price"} -
    - {isTabletUp && ( - line.variant.product.thumbnail.url, - noPhotoPng - )} - url2x={maybe( - () => line.variant.product.thumbnail2x.url - )} - /> - )} - {line.variant.product.name} - {line.variant.name - ? `(${line.variant.name})` - : null} - {line.variant.price.localized} - {isTabletUp ? ( -
    - add(line.variant.id)} - /> -

    {line.quantity}

    - subtract(line.variant.id)} - /> -
    - ) : ( - - changeQuantity( - line.variant.id, - parseInt(value, 10) - ) - } - disabled={loading} - value={line.quantity} - type="number" - /> - )} -
    {line.totalPrice.gross.localized} - remove(line.variant.id)} - /> -
    Subtotal} - - {checkout.subtotalPrice.gross.localized} -
    -
    - - {({ user }) => - user ? ( - - {client => ( - - Proceed to Checkout{" "} - - )} - - ) : ( - - - - ) - } - -
    - - )} -
    + + {({ remove, add, subtract, loading, changeQuantity }) => ( + <> + +
    + + {({ user }) => + user ? ( + + {client => ( + + Proceed to Checkout{" "} + + )} + + ) : ( + + + + ) + } + +
    + )} -
    + ); } else { return ; diff --git a/src/views/Cart/ProductsTable.tsx b/src/views/Cart/ProductsTable.tsx new file mode 100644 index 0000000000..ac0108c970 --- /dev/null +++ b/src/views/Cart/ProductsTable.tsx @@ -0,0 +1,129 @@ +import { smallScreen } from "../../components/App/scss/variables.scss"; + +import classNames from "classnames"; +import * as React from "react"; +import Media from "react-media"; +import { Link } from "react-router-dom"; +import ReactSVG from "react-svg"; + +import { CachedThumbnail, DebouncedTextField } from "../../components"; +import { getCheckout_checkout } from "../../components/CheckoutApp/types/getCheckout"; +import { generateProductUrl } from "../../core/utils"; + +const cartRemoveSvg = require("../../images/cart-remove.svg"); +const cartAddSvg = require("../../images/cart-add.svg"); +const cartSubtractSvg = require("../../images/cart-subtract.svg"); + +const ProductsTable: React.SFC<{ + checkout: getCheckout_checkout; + processing: boolean; + addToCart(variantId: string): void; + changeQuantityInCart(variantId: string, quantity: number): void; + removeFromCart(variantId: string): void; + subtractToCart(variantId: string): void; +}> = ({ + addToCart, + changeQuantityInCart, + checkout, + processing, + removeFromCart, + subtractToCart +}) => { + const { lines } = checkout; + return ( + + {isMediumScreen => ( + + + + + {isMediumScreen && } + + + + + + {lines + .sort((a, b) => + b.id.toLowerCase().localeCompare(a.id.toLowerCase()) + ) + .map(line => { + const productUrl = generateProductUrl( + line.variant.product.id, + line.variant.product.name + ); + return ( + + + {isMediumScreen && } + + + + + ); + })} + + + + + + + +
    ProductsPriceQuantity{isMediumScreen ? "Total Price" : "Price"}
    + {isMediumScreen && ( + + + + )} + + {line.variant.product.name} + {line.variant.name && ` (${line.variant.name})`} + + {line.variant.price.localized} + {isMediumScreen ? ( +
    + addToCart(line.variant.id)} + /> +

    {line.quantity}

    + subtractToCart(line.variant.id)} + /> +
    + ) : ( + + changeQuantityInCart( + line.variant.id, + parseInt(value, 10) + ) + } + disabled={processing} + value={line.quantity} + type="number" + /> + )} +
    {line.totalPrice.gross.localized} + removeFromCart(line.variant.id)} + /> +
    + Subtotal + {checkout.subtotalPrice.gross.localized}
    + )} +
    + ); +}; + +export default ProductsTable; diff --git a/src/views/Cart/scss/index.scss b/src/views/Cart/scss/index.scss index c5018d8b52..0fdaa7f622 100644 --- a/src/views/Cart/scss/index.scss +++ b/src/views/Cart/scss/index.scss @@ -57,7 +57,7 @@ &__checkout-action { text-align: right; - margin: 0 $spacer * 2 $spacer * 3; + margin: 0 $spacer * 2 $spacer * 3 0; @media (max-width: $small-screen) { text-align: center; diff --git a/src/views/Product/Page.tsx b/src/views/Product/Page.tsx index b1ce197dba..c7ad63036e 100644 --- a/src/views/Product/Page.tsx +++ b/src/views/Product/Page.tsx @@ -9,7 +9,7 @@ import { CartContext } from "../../components/CartProvider/context"; import { generateCategoryUrl, generateProductUrl } from "../../core/utils"; import GalleryCarousel from "./GalleryCarousel"; import OtherProducts from "./Other"; -import { ProductDetails, ProductDetails_product } from "./types/ProductDetails"; +import { ProductDetails_product } from "./types/ProductDetails"; const noPhoto = require("../../images/nophoto.png"); @@ -118,7 +118,8 @@ class Page extends React.PureComponent<{ product: ProductDetails_product }> {
    From 50499d8b2971e12a183371fbb4cceb84c8e33c07 Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Tue, 8 Jan 2019 20:33:49 +0100 Subject: [PATCH 4/5] Add tslint check to CI --- .circleci/config.yml | 3 +++ CHANGELOG.md | 1 + package.json | 3 ++- src/components/SearchOverlay/SearchOverlay.tsx | 4 ++-- tsconfig.json | 3 ++- tslint.json | 1 - 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index da5044df9a..aac9dacfcd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,6 +12,9 @@ jobs: - run: name: Install dependencies command: npm install + - run: + name: Run tslint + command: npm run tslint - run: name: Build application command: npm run build diff --git a/CHANGELOG.md b/CHANGELOG.md index 787700d96b..b0f71cc842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,3 +16,4 @@ Storefront UX improvements, remove signup to newsletter #182 by @piotrgrundas Fix two line titles breaking fatured carousel, product page improvements #184 by @piotrgrundas Allow numbers in product, category & collection urls #185 by @piotrgrundas Add OpenGraph and Meta tags, minor UI improvements #191 by @piotrgrundas +Add tslint check in the CI, ability to change cart quantity, fix error after removing item from the cart #194 by @piotrgrundas diff --git a/package.json b/package.json index 2b28170021..81dac6af61 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "watch": "webpack -d --watch", "storybook": "start-storybook -p 9001 -c src/storybook/ -s src/", "codegen": "apollo codegen:generate --target=typescript types", - "codegen-watch": "npm run codegen -- --watch" + "codegen-watch": "npm run codegen -- --watch", + "tslint": "tslint 'src/**/*.ts?(x)'" } } diff --git a/src/components/SearchOverlay/SearchOverlay.tsx b/src/components/SearchOverlay/SearchOverlay.tsx index f2ec1bd92b..af15201b8f 100644 --- a/src/components/SearchOverlay/SearchOverlay.tsx +++ b/src/components/SearchOverlay/SearchOverlay.tsx @@ -5,9 +5,10 @@ import * as React from "react"; import { Link, RouteComponentProps, withRouter } from "react-router-dom"; import ReactSVG from "react-svg"; -import { Button, DebounceChange, Loader, TextField } from ".."; +import { Button, Loader } from ".."; import { maybe } from "../../core/utils"; import { searchUrl } from "../App/routes"; +import { DebouncedTextField } from "../Debounce"; import { Error } from "../Error"; import NetworkStatus from "../NetworkStatus"; import { OfflinePlaceholder } from "../OfflinePlaceholder"; @@ -17,7 +18,6 @@ import NothingFound from "./NothingFound"; import ProductItem from "./ProductItem"; import { TypedSearchResults } from "./queries"; import { SearchResults } from "./types/SearchResults"; -import { DebouncedTextField } from "../Debounce"; const closeSvg = require("../../images/x.svg"); const searchSvg = require("../../images/search.svg"); diff --git a/tsconfig.json b/tsconfig.json index 6038d4d066..70a1e82d74 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "jsx": "react", "lib": ["es2017", "dom", "esnext"], "sourceMap": true, - "target": "es6" + "target": "es6", + "noUnusedLocals": false } } diff --git a/tslint.json b/tslint.json index 3cf3c2ba7f..4186e4fb88 100644 --- a/tslint.json +++ b/tslint.json @@ -8,7 +8,6 @@ "no-implicit-dependencies": [true, "dev"], "no-shadowed-variable": false, "no-submodule-imports": [true], - "no-unused-variable": true, "no-var-requires": false } } From 646af0ebe1262170bbfd46af706b6848e6e3411d Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Wed, 9 Jan 2019 10:32:36 +0100 Subject: [PATCH 5/5] Review corrections --- CHANGELOG.md | 2 +- src/components/CartProvider/context.ts | 2 +- src/views/Cart/scss/index.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0f71cc842..3a606e5534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ Add add to cart indicator #173 by @piotrgrundas Fix product page tablet view #181 by @piotrgrundas Add collection view, fix cursor pagination for categories, update storefront to use new thumbnail structure #178 by @piotrgrundas Storefront UX improvements, remove signup to newsletter #182 by @piotrgrundas -Fix two line titles breaking fatured carousel, product page improvements #184 by @piotrgrundas +Fix two line titles breaking featured carousel, product page improvements #184 by @piotrgrundas Allow numbers in product, category & collection urls #185 by @piotrgrundas Add OpenGraph and Meta tags, minor UI improvements #191 by @piotrgrundas Add tslint check in the CI, ability to change cart quantity, fix error after removing item from the cart #194 by @piotrgrundas diff --git a/src/components/CartProvider/context.ts b/src/components/CartProvider/context.ts index e2ea7f3877..fb7fa8ab8f 100644 --- a/src/components/CartProvider/context.ts +++ b/src/components/CartProvider/context.ts @@ -19,7 +19,7 @@ export interface CartInterface { getQuantity(): number; getTotal(): { currency: string; amount: number }; remove(variantId: string): void; - subtract(variantId, quantity?: number): void; + subtract(variantId: string, quantity?: number): void; } /* tslint:disable:no-empty */ diff --git a/src/views/Cart/scss/index.scss b/src/views/Cart/scss/index.scss index 0fdaa7f622..198500157f 100644 --- a/src/views/Cart/scss/index.scss +++ b/src/views/Cart/scss/index.scss @@ -38,7 +38,7 @@ } & > div { - padding: 0.5rem; + padding: $spacer / 2; } } }