From d8138673f93cee96507d261b09f6c22b79a9d9b2 Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Thu, 20 Dec 2018 09:52:12 +0100 Subject: [PATCH 1/3] [128] Extracted category stuff --- src/components/Breadcrumbs/index.tsx | 53 ++++++--- src/components/ProductFilters/index.tsx | 6 +- src/components/index.ts | 8 +- src/core/queries.tsx | 38 +++++- src/core/utils.ts | 59 +++++++--- src/views/Article/ArticlePage.tsx | 2 +- src/views/Category/CategoryPage.tsx | 43 +++---- src/views/Category/index.tsx | 110 +++++++---------- src/views/Category/queries.ts | 9 +- .../View.tsx} | 0 src/views/Collection/index.ts | 0 src/views/Collection/queries.ts | 82 +++++++++++++ src/views/Collection/types/Collection.ts | 111 ++++++++++++++++++ src/views/Search/index.tsx | 6 +- types/globalTypes.ts | 2 + 15 files changed, 388 insertions(+), 141 deletions(-) rename src/views/{Category/CategoryHeader.tsx => Collection/View.tsx} (100%) create mode 100644 src/views/Collection/index.ts create mode 100644 src/views/Collection/queries.ts create mode 100644 src/views/Collection/types/Collection.ts diff --git a/src/components/Breadcrumbs/index.tsx b/src/components/Breadcrumbs/index.tsx index 7db2f2e602..56bf2ff8f1 100644 --- a/src/components/Breadcrumbs/index.tsx +++ b/src/components/Breadcrumbs/index.tsx @@ -1,28 +1,53 @@ +import "./scss/index.scss"; + import * as React from "react"; import { Link } from "react-router-dom"; +import { getDBIdFromGraphqlId, slugify } from "../../core/utils"; +import { Category_category } from "../../views/Category/types/Category"; import { baseUrl } from "../App/routes"; -import "./scss/index.scss"; - export interface Breadcrumb { value: string; link: string; } +export const extractBreadcrumbs = ( + iterable: Category_category, + type: "Category" +) => { + const constructLink = item => ({ + link: [ + `/${type.toLowerCase()}`, + `/${slugify(item.name)}`, + `/${getDBIdFromGraphqlId(item.id, type)}/` + ].join(""), + value: item.name + }); + + let breadcrumbs = [constructLink(iterable)]; + + if (iterable.ancestors.edges.length) { + const ancestorsList = iterable.ancestors.edges.map(constructLink); + breadcrumbs = ancestorsList.concat(breadcrumbs); + } + return breadcrumbs; +}; + const Breadcrumbs: React.SFC<{ breadcrumbs: Breadcrumb[]; -}> = ({ breadcrumbs }) => ( - + ); +}; export default Breadcrumbs; diff --git a/src/components/ProductFilters/index.tsx b/src/components/ProductFilters/index.tsx index c45c354454..dd938c066e 100644 --- a/src/components/ProductFilters/index.tsx +++ b/src/components/ProductFilters/index.tsx @@ -2,10 +2,8 @@ import "./scss/index.scss"; import * as React from "react"; -import { - Category_attributes_edges_node, - SearchProducts_attributes_edges_node -} from "../../core/types/saleor"; +import { Category_attributes_edges_node } from "../../views/Category/types/Category"; +import { SearchProducts_attributes_edges_node } from "../../views/Search/types/SearchProducts"; import PriceRangeFilter from "../PriceRangeFilter"; import SelectField, { SelectValue } from "../SelectField"; diff --git a/src/components/index.ts b/src/components/index.ts index fa60ac4cd7..4f1ed5521e 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -10,7 +10,6 @@ export { default as SelectField } from "./SelectField"; export { default as Message } from "./Message"; export { default as ProductListItem } from "./ProductListItem"; export { default as SearchOverlay } from "./SearchOverlay"; -export { default as Breadcrumbs } from "./Breadcrumbs"; export { default as Dropdown } from "./Dropdown"; export { default as Carousel } from "./Carousel"; export { default as SocialMediaIcon } from "./SocialMediaIcon"; @@ -35,7 +34,12 @@ 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 { + default as Breadcrumbs, + Breadcrumb, + extractBreadcrumbs +} from "./Breadcrumbs"; export { Footer } from "./Footer"; export { MainMenu, MainMenuNavOverlay } from "./MainMenu"; export { MobileNav } from "./MobileNav"; -export { NavLink } from './NavLink'; +export { NavLink } from "./NavLink"; diff --git a/src/core/queries.tsx b/src/core/queries.tsx index 43b55029b3..1d66d1061f 100644 --- a/src/core/queries.tsx +++ b/src/core/queries.tsx @@ -1,4 +1,4 @@ -import { FetchPolicy } from "apollo-client"; +import { ApolloQueryResult, ErrorPolicy, FetchPolicy } from "apollo-client"; import { DocumentNode } from "graphql"; import * as React from "react"; import { Query, QueryResult } from "react-apollo"; @@ -7,8 +7,18 @@ import { Error } from "../components/Error"; import Loader from "../components/Loader"; import { maybe } from "./utils"; +interface LoadMore { + loadMore: ( + mergeFunc: (prev: TData, next: TData) => TData, + endCursor: string, + endCursorKey?: string + ) => Promise>; +} + interface TypedQueryInnerProps { - children: (result: QueryResult) => React.ReactNode; + children: ( + result: QueryResult & LoadMore + ) => React.ReactNode; displayError?: boolean; displayLoader?: boolean; fetchPolicy?: FetchPolicy; @@ -16,6 +26,7 @@ interface TypedQueryInnerProps { renderOnError?: boolean; skip?: boolean; variables?: TVariables; + errorPolicy?: ErrorPolicy; } export function TypedQuery(query: DocumentNode) { @@ -27,6 +38,7 @@ export function TypedQuery(query: DocumentNode) { displayLoader = true, renderOnError = false, fetchPolicy = "cache-and-network", + errorPolicy, loaderFull, skip, variables @@ -36,12 +48,28 @@ export function TypedQuery(query: DocumentNode) { variables={variables} skip={skip} fetchPolicy={fetchPolicy} + errorPolicy={errorPolicy} > {queryData => { - const { error, loading, data } = queryData; + const { error, loading, data, fetchMore } = queryData; const hasData = maybe(() => !!Object.keys(data).length, false); + const loadMore = ( + mergeFunc: (previousResults: TData, fetchMoreResult: TData) => TData, + endCursor: string, + endCursorKey: string = "after" + ) => + fetchMore({ + query, + updateQuery: (previousResults, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return previousResults; + } + return mergeFunc(previousResults, fetchMoreResult); + }, + variables: { ...variables, [endCursorKey]: endCursor } + }); - if (displayError && error) { + if (displayError && error && !hasData) { return ; } @@ -50,7 +78,7 @@ export function TypedQuery(query: DocumentNode) { } if (hasData || (renderOnError && error)) { - return children(queryData); + return children({ ...queryData, loadMore }); } return null; diff --git a/src/core/utils.ts b/src/core/utils.ts index c525831da3..b2eee4d17a 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -1,5 +1,12 @@ +import * as H from "history"; import { Base64 } from "js-base64"; -import { OrderDirection, ProductOrderField } from "../core/types/saleor"; +import { parse as parseQs, stringify as stringifyQs } from "query-string"; + +import { + OrderDirection, + ProductOrder, + ProductOrderField +} from "../../types/globalTypes"; export const slugify = (text: string | number): string => text @@ -60,16 +67,8 @@ interface AttributeDict { } export const convertToAttributeScalar = (attributes: AttributeDict) => Object.entries(attributes) - .map(([key, value]) => - typeof value === "string" - ? key + ":" + value - : value.map(attribute => key + ":" + attribute) - ) - .reduce( - (prev, curr) => - typeof curr === "string" ? [...prev, curr] : [...prev, ...curr], - [] - ); + .map(([key, value]) => value.map(attribute => `${key}:${attribute}`)) + .reduce((prev, curr) => [...prev, ...curr], []); interface QueryString { [key: string]: string[] | string | null | undefined; @@ -95,13 +94,19 @@ export const convertSortByFromString = (sortBy: string) => { ? OrderDirection.DESC : OrderDirection.ASC; - let field = sortBy.replace(/^-/, ""); - field = - field === "name" - ? ProductOrderField.NAME - : field === "price" - ? ProductOrderField.PRICE - : undefined; + let field; + switch (sortBy.replace(/^-/, "")) { + case "name": + field = ProductOrderField.NAME; + break; + + case "price": + field = ProductOrderField.PRICE; + break; + + default: + return null; + } return { field, direction }; }; @@ -113,3 +118,21 @@ export function maybe(exp: () => T, d?: T) { return d; } } + +export const parseQueryString = (location: H.LocationState) => + parseQs(location.search.substr(1)); + +export const updateQueryString = ( + location: H.LocationState, + history: H.History +) => { + const querystring = parseQueryString(location); + return (key: string, value?) => { + if (value === "") { + delete querystring[key]; + } else { + querystring[key] = value || key; + } + history.replace("?" + stringifyQs(querystring)); + }; +}; diff --git a/src/views/Article/ArticlePage.tsx b/src/views/Article/ArticlePage.tsx index 7a3723e8e5..18a00d3767 100644 --- a/src/views/Article/ArticlePage.tsx +++ b/src/views/Article/ArticlePage.tsx @@ -2,7 +2,7 @@ import classNames from "classnames"; import * as React from "react"; import { Link } from "react-router-dom"; -import Breadcrumbs, { Breadcrumb } from "../../components/Breadcrumbs"; +import { Breadcrumb, Breadcrumbs } from "../../components"; interface PageNavigationElement { active: boolean; diff --git a/src/views/Category/CategoryPage.tsx b/src/views/Category/CategoryPage.tsx index db125d48a4..7d86986ded 100644 --- a/src/views/Category/CategoryPage.tsx +++ b/src/views/Category/CategoryPage.tsx @@ -2,14 +2,20 @@ import "./scss/index.scss"; import * as React from "react"; -import { Breadcrumbs, ProductsFeatured, ProductsList } from "../../components"; +import { + Breadcrumbs, + extractBreadcrumbs, + ProductsFeatured, + ProductsList +} from "../../components"; import { Filters, ProductFilters } from "../../components/ProductFilters"; + +import { maybe } from "../../core/utils"; import { Category_attributes_edges_node, Category_category, Category_products -} from "../../core/types/saleor"; -import { getDBIdFromGraphqlId, maybe, slugify } from "../../core/utils"; +} from "./types/Category"; interface CategoryPageProps { attributes: Category_attributes_edges_node[]; @@ -24,31 +30,6 @@ interface CategoryPageProps { onOrder: (order: string) => void; } -const formatBreadcrumbs = (category: Category_category) => { - let breadcrumbs = [ - { - link: `/category/${slugify(category.name)}/${getDBIdFromGraphqlId( - category.id, - "Category" - )}/`, - value: category.name - } - ]; - if (category.ancestors.edges.length > 0) { - const ancestorsList = category.ancestors.edges.map( - ({ node: ancestor }) => ({ - link: `/category/${slugify(ancestor.name)}/${getDBIdFromGraphqlId( - ancestor.id, - "Category" - )}/`, - value: ancestor.name - }) - ); - breadcrumbs = ancestorsList.concat(breadcrumbs); - } - return breadcrumbs; -}; - export const CategoryPage: React.SFC = ({ attributes, category, @@ -66,6 +47,7 @@ export const CategoryPage: React.SFC = ({ false ); const hasProducts = canDisplayProducts && !!products.totalCount; + return (
= ({

{category.name}

+
- +
+ {hasProducts && ( = ({ onPriceChange={onPriceChange} /> )} + {canDisplayProducts && ( = ({ location, history }) => { - const qs = parseQs(location.search.substr(1)); - const attributes: AttributeList = getAttributesFromQs(qs); + const querystring = parseQueryString(location); + const updateQs = updateQueryString(location, history); + const attributes: AttributeList = getAttributesFromQs(querystring); + const filters: Filters = { attributes, pageSize: PRODUCTS_PER_PAGE, - priceGte: qs.priceGte || null, - priceLte: qs.priceLte || null, - sortBy: qs.sortBy || null + priceGte: querystring.priceGte || null, + priceLte: querystring.priceLte || null, + sortBy: querystring.sortBy || null + }; + const variables = { + ...filters, + attributes: convertToAttributeScalar(filters.attributes), + id: getGraphqlIdFromDBId(match.params.id, "Category"), + sortBy: convertSortByFromString(filters.sortBy) }; + return ( {isOnline => ( - - {({ loading, error, data, fetchMore }) => { + {({ loading, data, loadMore }) => { const canDisplayFilters = maybe( - () => data.attributes.edges && data.category.name, + () => !!data.attributes.edges && !!data.category.name, false ); + if (canDisplayFilters) { - const handleLoadMore = () => - fetchMore({ - query: GET_CATEGORY_AND_ATTRIBUTES, - updateQuery: (prev: Category, { fetchMoreResult }) => { - if (!fetchMoreResult) { - return prev; - } - return { - ...prev, - products: { - ...prev.products, - edges: [ - ...prev.products.edges, - ...fetchMoreResult.products.edges - ], - pageInfo: fetchMoreResult.products.pageInfo - } - }; - }, - variables: { - ...filters, - after: data.products.pageInfo.endCursor, - attributes: convertToAttributeScalar(filters.attributes), - id: getGraphqlIdFromDBId(match.params.id, "Category"), - sortBy: convertSortByFromString(filters.sortBy) + const handleLoadMore = () => loadMore( + (prev, next) => ({ + ...prev, + products: { + ...prev.products, + edges: [ + ...prev.products.edges, + ...next.products.edges + ], + pageInfo: next.products.pageInfo } - }); + }), + data.products.pageInfo.endCursor + ) + return ( edge.node)} @@ -97,34 +86,23 @@ export const CategoryView: React.SFC = ({ )} filters={filters} products={data.products} - onAttributeFiltersChange={(attribute, values) => { - qs[attribute] = values; - history.replace("?" + stringifyQs(qs)); - }} + onAttributeFiltersChange={updateQs} onLoadMore={handleLoadMore} - onOrder={sortBy => { - qs.sortBy = sortBy; - history.replace("?" + stringifyQs(qs)); - }} - onPriceChange={(field, value) => { - qs[field] = value; - history.replace("?" + stringifyQs(qs)); - }} + onOrder={(value) => updateQs("sortBy", value)} + onPriceChange={updateQs} /> ); } + if (data && data.category === null) { return ; } + if (!isOnline) { return ; } - if (error && !data) { - return ; - } - return ; }} - + )} ); diff --git a/src/views/Category/queries.ts b/src/views/Category/queries.ts index d676bdd4f4..82c725afb8 100644 --- a/src/views/Category/queries.ts +++ b/src/views/Category/queries.ts @@ -1,6 +1,9 @@ import gql from "graphql-tag"; -export const GET_CATEGORY_AND_ATTRIBUTES = gql` +import { TypedQuery } from "../../core/queries"; +import { Category, CategoryVariables } from "./types/Category"; + +export const categoryProductsQuery = gql` query Category( $id: ID! $attributes: [AttributeScalar] @@ -75,3 +78,7 @@ export const GET_CATEGORY_AND_ATTRIBUTES = gql` } } `; + +export const TypedCategoryProductsQuery = TypedQuery( + categoryProductsQuery +); diff --git a/src/views/Category/CategoryHeader.tsx b/src/views/Collection/View.tsx similarity index 100% rename from src/views/Category/CategoryHeader.tsx rename to src/views/Collection/View.tsx diff --git a/src/views/Collection/index.ts b/src/views/Collection/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/views/Collection/queries.ts b/src/views/Collection/queries.ts new file mode 100644 index 0000000000..498f2bde7b --- /dev/null +++ b/src/views/Collection/queries.ts @@ -0,0 +1,82 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../../core/queries"; +import { Collection, CollectionVariables } from "./types/Collection"; + +export const callectionPoroductsQuery = gql` + query Collection( + $id: ID! + $attributes: [AttributeScalar] + $after: String + $pageSize: Int + $sortBy: ProductOrder + $priceLte: Float + $priceGte: Float + ) { + collection(id: $id) { + id + slug + name + backgroundImage { + url + } + } + products( + collections: [$id] + after: $after + attributes: $attributes + categories: [$id] + first: $pageSize + sortBy: $sortBy + priceLte: $priceLte + priceGte: $priceGte + ) { + totalCount + edges { + node { + id + name + thumbnailUrl + thumbnailUrl2x: thumbnailUrl(size: 510) + thumbnail { + url + } + collections { + id + name + } + price { + amount + currency + localized + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + attributes(inCategory: $id, first: 100) { + edges { + node { + id + name + slug + values { + id + name + slug + } + } + } + } + } +`; + +export const TypedCollectionProductsQuery = TypedQuery< + Collection, + CollectionVariables +>(callectionPoroductsQuery); diff --git a/src/views/Collection/types/Collection.ts b/src/views/Collection/types/Collection.ts new file mode 100644 index 0000000000..fb8fd3b785 --- /dev/null +++ b/src/views/Collection/types/Collection.ts @@ -0,0 +1,111 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +import { ProductOrder } from "./../../../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: Collection +// ==================================================== + +export interface Collection_collection_backgroundImage { + __typename: "Image"; + url: string; +} + +export interface Collection_collection { + __typename: "Collection"; + id: string; + slug: string; + name: string; + backgroundImage: Collection_collection_backgroundImage | null; +} + +export interface Collection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface Collection_products_edges_node_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface Collection_products_edges_node_price { + __typename: "Money"; + amount: number; + currency: string; + localized: string; +} + +export interface Collection_products_edges_node { + __typename: "Product"; + id: string; + name: string; + thumbnailUrl: string | null; + thumbnailUrl2x: string | null; + thumbnail: Collection_products_edges_node_thumbnail | null; + collections: (Collection_products_edges_node_collections | null)[] | null; + price: Collection_products_edges_node_price | null; +} + +export interface Collection_products_edges { + __typename: "ProductCountableEdge"; + node: Collection_products_edges_node; +} + +export interface Collection_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface Collection_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; + edges: Collection_products_edges[]; + pageInfo: Collection_products_pageInfo; +} + +export interface Collection_attributes_edges_node_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface Collection_attributes_edges_node { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (Collection_attributes_edges_node_values | null)[] | null; +} + +export interface Collection_attributes_edges { + __typename: "AttributeCountableEdge"; + node: Collection_attributes_edges_node; +} + +export interface Collection_attributes { + __typename: "AttributeCountableConnection"; + edges: Collection_attributes_edges[]; +} + +export interface Collection { + collection: Collection_collection | null; + products: Collection_products | null; + attributes: Collection_attributes | null; +} + +export interface CollectionVariables { + id: string; + attributes?: (any | null)[] | null; + after?: string | null; + pageSize?: number | null; + sortBy?: ProductOrder | null; + priceLte?: number | null; + priceGte?: number | null; +} diff --git a/src/views/Search/index.tsx b/src/views/Search/index.tsx index 72729906d2..81ad4d255a 100644 --- a/src/views/Search/index.tsx +++ b/src/views/Search/index.tsx @@ -112,7 +112,11 @@ export const SearchView: React.SFC = ({ const hasProducts = canDisplayProducts && !!data.products.totalCount; const updateQueryString = (key: string, value?) => { - qs[key] = value || key; + if (value === "") { + delete qs[key] + } else { + qs[key] = value || key; + } history.replace("?" + stringifyQs(qs)); }; diff --git a/types/globalTypes.ts b/types/globalTypes.ts index 083322b535..935e44238a 100644 --- a/types/globalTypes.ts +++ b/types/globalTypes.ts @@ -9,6 +9,7 @@ export enum GatewaysEnum { BRAINTREE = "BRAINTREE", DUMMY = "DUMMY", RAZORPAY = "RAZORPAY", + STRIPE = "STRIPE", } export enum OrderDirection { @@ -17,6 +18,7 @@ export enum OrderDirection { } export enum ProductOrderField { + DATE = "DATE", NAME = "NAME", PRICE = "PRICE", } From 13fe7c2f28de596e97181c87d1a06c54d631870b Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Fri, 21 Dec 2018 14:08:45 +0100 Subject: [PATCH 2/3] [128] Collection view --- src/components/App/routes.tsx | 3 + src/components/Carousel/index.tsx | 6 +- src/components/ProductFilters/index.tsx | 2 + src/components/ProductListItem/index.tsx | 48 +++++--- src/components/ProductListItem/queries.ts | 15 +++ .../types/ProductNodeFragment.ts | 22 ++++ src/components/ProductPage/queries.ts | 8 +- .../ProductPage/types/BasicProductFields.ts | 9 +- .../ProductPage/types/ProductDetails.ts | 18 ++- .../ProductPage/types/VariantList.ts | 9 +- src/components/ProductsFeatured/index.tsx | 12 +- src/components/ProductsFeatured/queries.tsx | 21 ++-- .../ProductsFeatured/types/ProductsList.ts | 16 +-- src/components/ProductsList/index.tsx | 23 ++-- src/components/SearchOverlay/queries.ts | 6 +- .../SearchOverlay/types/SearchResults.ts | 9 +- src/components/index.ts | 1 + src/core/queries.tsx | 2 +- src/views/Category/CategoryPage.tsx | 3 +- src/views/Category/queries.ts | 20 ++-- src/views/Category/types/Category.ts | 14 +-- src/views/Collection/Page.tsx | 103 +++++++++++++++++ src/views/Collection/View.tsx | 106 ++++++++++++++++++ src/views/Collection/index.ts | 1 + src/views/Collection/queries.ts | 18 +-- src/views/Collection/types/Collection.ts | 18 +-- src/views/Search/index.tsx | 7 +- 27 files changed, 403 insertions(+), 117 deletions(-) create mode 100644 src/components/ProductListItem/queries.ts create mode 100644 src/components/ProductListItem/types/ProductNodeFragment.ts create mode 100644 src/views/Collection/Page.tsx diff --git a/src/components/App/routes.tsx b/src/components/App/routes.tsx index 4eff5c6ad4..dd4fb0a08c 100644 --- a/src/components/App/routes.tsx +++ b/src/components/App/routes.tsx @@ -4,12 +4,14 @@ import { Route, Switch } from "react-router-dom"; import { CartPage, CheckoutLogin, HomePage, ProductPage } from ".."; import ArticlePage from "../../views/Article"; import CategoryPage from "../../views/Category"; +import { CollectionPage } from "../../views/Collection"; import SearchPage from "../../views/Search"; import { NotFound } from "../NotFound"; export const baseUrl = "/"; export const searchUrl = `${baseUrl}search/`; export const categoryUrl = `${baseUrl}category/:slug([a-z-]+)/:id([0-9]+)/`; +export const collectionUrl = `${baseUrl}collection/:slug([a-z-]+)/:id([0-9]+)/`; export const productUrl = `${baseUrl}product/:slug([a-z-]+)/:id([0-9]+)/`; export const cartUrl = `${baseUrl}cart/:token/`; export const checkoutLoginUrl = `${baseUrl}login/`; @@ -20,6 +22,7 @@ export const Routes: React.SFC = () => ( + diff --git a/src/components/Carousel/index.tsx b/src/components/Carousel/index.tsx index f044d300ad..b156692bd8 100644 --- a/src/components/Carousel/index.tsx +++ b/src/components/Carousel/index.tsx @@ -6,6 +6,8 @@ import ReactSVG from "react-svg"; import { mediumScreen, smallScreen } from "../App/scss/variables.scss"; import "./scss/index.scss"; +const arrowSvg = require("../../images/carousel-arrow.svg"); + interface CarouselType extends CarouselProps { children: React.ReactNode; } @@ -20,7 +22,7 @@ const Carousel: React.SFC = ({ children, ...rest }) => { onClick={previousSlide} className="carousel__control carousel__control--left" > - +
) : null, renderCenterRightControls: ({ @@ -34,7 +36,7 @@ const Carousel: React.SFC = ({ children, ...rest }) => { onClick={nextSlide} className="carousel__control carousel__control--right" > - + ) : null, ...rest diff --git a/src/components/ProductFilters/index.tsx b/src/components/ProductFilters/index.tsx index dd938c066e..ab40a0b935 100644 --- a/src/components/ProductFilters/index.tsx +++ b/src/components/ProductFilters/index.tsx @@ -3,6 +3,7 @@ import "./scss/index.scss"; import * as React from "react"; import { Category_attributes_edges_node } from "../../views/Category/types/Category"; +import { Collection_attributes_edges_node } from "../../views/Collection/types/Collection"; import { SearchProducts_attributes_edges_node } from "../../views/Search/types/SearchProducts"; import PriceRangeFilter from "../PriceRangeFilter"; import SelectField, { SelectValue } from "../SelectField"; @@ -22,6 +23,7 @@ export interface Filters { export interface ProductFiltersProps { attributes: | Category_attributes_edges_node[] + | Collection_attributes_edges_node[] | SearchProducts_attributes_edges_node[]; filters: Filters; onPriceChange: (field: "priceLte" | "priceGte", value: number) => void; diff --git a/src/components/ProductListItem/index.tsx b/src/components/ProductListItem/index.tsx index 9ec38be910..b99ee1533e 100644 --- a/src/components/ProductListItem/index.tsx +++ b/src/components/ProductListItem/index.tsx @@ -1,27 +1,45 @@ +import "./scss/index.scss"; + import * as React from "react"; -import { ProductListItemInterface } from "../../core/types"; +import { maybe } from "../../core/utils"; import CachedImage from "../CachedImage"; +import { ProductNodeFragment } from "./types/ProductNodeFragment"; -import "./scss/index.scss"; +interface Product extends ProductNodeFragment { + category?: { + id: string; + name: string; + }; + collections?: Array<{ + id: string; + name: string; + }>; +} interface ProductListItemProps { - product: ProductListItemInterface; + product: Product; } const ProductListItem: React.SFC = ({ - product: { name, category, price, thumbnailUrl, thumbnailUrl2x } -}) => ( -
-
- - - + product: { name, collections, category, price, thumbnailUrl, thumbnailUrl2x } +}) => { + const categoryOrCollecton = maybe(() => collections[0].name || category.name); + + return ( +
+
+ + + +
+

{name}

+

+ {categoryOrCollecton} +

+

{price.localized}

-

{name}

-

{category.name}

-

{price.localized}

-
-); + ); +}; export default ProductListItem; diff --git a/src/components/ProductListItem/queries.ts b/src/components/ProductListItem/queries.ts new file mode 100644 index 0000000000..7af62f4920 --- /dev/null +++ b/src/components/ProductListItem/queries.ts @@ -0,0 +1,15 @@ +import gql from "graphql-tag"; + +export const productNodeFragment = gql` + fragment ProductNodeFragment on Product { + id + name + thumbnailUrl + thumbnailUrl2x: thumbnailUrl(size: 510) + price { + amount + currency + localized + } + } +`; diff --git a/src/components/ProductListItem/types/ProductNodeFragment.ts b/src/components/ProductListItem/types/ProductNodeFragment.ts new file mode 100644 index 0000000000..a07f1db23e --- /dev/null +++ b/src/components/ProductListItem/types/ProductNodeFragment.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ProductNodeFragment +// ==================================================== + +export interface ProductNodeFragment_price { + __typename: "Money"; + amount: number; + currency: string; + localized: string; +} + +export interface ProductNodeFragment { + __typename: "Product"; + id: string; + name: string; + thumbnailUrl: string | null; + thumbnailUrl2x: string | null; + price: ProductNodeFragment_price | null; +} diff --git a/src/components/ProductPage/queries.ts b/src/components/ProductPage/queries.ts index 7e0502a456..8d6c323357 100644 --- a/src/components/ProductPage/queries.ts +++ b/src/components/ProductPage/queries.ts @@ -4,8 +4,10 @@ export const BASIC_PRODUCT_FRAGMENT = gql` fragment BasicProductFields on Product { id name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) + thumbnail(size: 510) { + url + alt + } } `; @@ -76,7 +78,7 @@ export const GET_PRODUCT_DETAILS = gql` } `; -// FIXME: Check how to handle pagination of `productVariants` in the UI. +// FIXME: Check how to handle pagination of `productVariants` in the UI. // We need allow the user view all cart items regardless of pagination. export const GET_PRODUCTS_VARIANTS = gql` ${BASIC_PRODUCT_FRAGMENT} diff --git a/src/components/ProductPage/types/BasicProductFields.ts b/src/components/ProductPage/types/BasicProductFields.ts index 3badfd736c..26479f807a 100644 --- a/src/components/ProductPage/types/BasicProductFields.ts +++ b/src/components/ProductPage/types/BasicProductFields.ts @@ -5,10 +5,15 @@ // GraphQL fragment: BasicProductFields // ==================================================== +export interface BasicProductFields_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + export interface BasicProductFields { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: BasicProductFields_thumbnail | null; } diff --git a/src/components/ProductPage/types/ProductDetails.ts b/src/components/ProductPage/types/ProductDetails.ts index 0a38bfc3af..4ddce7fdbf 100644 --- a/src/components/ProductPage/types/ProductDetails.ts +++ b/src/components/ProductPage/types/ProductDetails.ts @@ -5,6 +5,18 @@ // GraphQL query operation: ProductDetails // ==================================================== +export interface ProductDetails_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface ProductDetails_product_category_products_edges_node_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + export interface ProductDetails_product_category_products_edges_node_category { __typename: "Category"; id: string; @@ -22,8 +34,7 @@ export interface ProductDetails_product_category_products_edges_node { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: ProductDetails_product_category_products_edges_node_thumbnail | null; category: ProductDetails_product_category_products_edges_node_category; price: ProductDetails_product_category_products_edges_node_price | null; } @@ -97,8 +108,7 @@ export interface ProductDetails_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: ProductDetails_product_thumbnail | null; description: string; category: ProductDetails_product_category; price: ProductDetails_product_price | null; diff --git a/src/components/ProductPage/types/VariantList.ts b/src/components/ProductPage/types/VariantList.ts index 0b183819b8..b12bfab5bd 100644 --- a/src/components/ProductPage/types/VariantList.ts +++ b/src/components/ProductPage/types/VariantList.ts @@ -31,12 +31,17 @@ export interface VariantList_productVariants_edges_node_attributes { value: VariantList_productVariants_edges_node_attributes_value; } +export interface VariantList_productVariants_edges_node_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + export interface VariantList_productVariants_edges_node_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: VariantList_productVariants_edges_node_product_thumbnail | null; } export interface VariantList_productVariants_edges_node { diff --git a/src/components/ProductsFeatured/index.tsx b/src/components/ProductsFeatured/index.tsx index 7cd20eb45e..9cd2b22e47 100644 --- a/src/components/ProductsFeatured/index.tsx +++ b/src/components/ProductsFeatured/index.tsx @@ -4,7 +4,7 @@ import { Link } from "react-router-dom"; import { Carousel, Loader, ProductListItem } from ".."; import { generateProductUrl, maybe } from "../../core/utils"; -import { GET_FEATURED_PRODUCTS } from "./queries"; +import { TypedFeaturedProductsQuery } from "./queries"; import "./scss/index.scss"; @@ -14,8 +14,8 @@ interface ProductsFeaturedProps { const ProductsFeatured: React.SFC = ({ title }) => { return ( - - {({ error, data, loading }) => { + + {({ data }) => { const products = maybe( () => data.shop.homepageCollection.products.edges, [] @@ -40,12 +40,8 @@ const ProductsFeatured: React.SFC = ({ title }) => {
); } - if (loading) { - return ; - } - return null; }} - + ); }; diff --git a/src/components/ProductsFeatured/queries.tsx b/src/components/ProductsFeatured/queries.tsx index b312356bc6..87e21b2f8d 100644 --- a/src/components/ProductsFeatured/queries.tsx +++ b/src/components/ProductsFeatured/queries.tsx @@ -1,6 +1,11 @@ import gql from "graphql-tag"; -export const GET_FEATURED_PRODUCTS = gql` +import { TypedQuery } from "../../core/queries"; +import { productNodeFragment } from "../ProductListItem/queries"; +import { ProductsList } from "./types/ProductsList"; + +export const featuredProducts = gql` + ${productNodeFragment} query ProductsList { shop { homepageCollection { @@ -8,19 +13,11 @@ export const GET_FEATURED_PRODUCTS = gql` products(first: 20) { edges { node { - id - name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) + ...ProductNodeFragment category { id name } - price { - currency - amount - localized - } } } } @@ -28,3 +25,7 @@ export const GET_FEATURED_PRODUCTS = gql` } } `; + +export const TypedFeaturedProductsQuery = TypedQuery( + featuredProducts +); diff --git a/src/components/ProductsFeatured/types/ProductsList.ts b/src/components/ProductsFeatured/types/ProductsList.ts index 33456d9919..9d4dbdfa09 100644 --- a/src/components/ProductsFeatured/types/ProductsList.ts +++ b/src/components/ProductsFeatured/types/ProductsList.ts @@ -5,27 +5,27 @@ // GraphQL query operation: ProductsList // ==================================================== -export interface ProductsList_shop_homepageCollection_products_edges_node_category { - __typename: "Category"; - id: string; - name: string; -} - export interface ProductsList_shop_homepageCollection_products_edges_node_price { __typename: "Money"; - currency: string; amount: number; + currency: string; localized: string; } +export interface ProductsList_shop_homepageCollection_products_edges_node_category { + __typename: "Category"; + id: string; + name: string; +} + export interface ProductsList_shop_homepageCollection_products_edges_node { __typename: "Product"; id: string; name: string; thumbnailUrl: string | null; thumbnailUrl2x: string | null; - category: ProductsList_shop_homepageCollection_products_edges_node_category; price: ProductsList_shop_homepageCollection_products_edges_node_price | null; + category: ProductsList_shop_homepageCollection_products_edges_node_category; } export interface ProductsList_shop_homepageCollection_products_edges { diff --git a/src/components/ProductsList/index.tsx b/src/components/ProductsList/index.tsx index 069b4ef9a7..f414e236e6 100644 --- a/src/components/ProductsList/index.tsx +++ b/src/components/ProductsList/index.tsx @@ -1,34 +1,37 @@ +import "./scss/index.scss"; + import * as React from "react"; -import Media from "react-media"; import { Link } from "react-router-dom"; import { Button, Dropdown, ProductListItem } from ".."; -import { CategoryProductInterface } from "../../core/types"; import { generateProductUrl } from "../../core/utils"; import Loader from "../Loader"; import { Filters } from "../ProductFilters"; -import "./scss/index.scss"; -import { mediumScreen, smallScreen } from "../App/scss/variables.scss"; +import { Category_products } from "../../views/Category/types/Category"; +import { Collection_products } from "../../views/Collection/types/Collection"; +import { ProductNodeFragment } from "../ProductListItem/types/ProductNodeFragment"; interface ProductsListProps { + products: ProductNodeFragment[]; displayLoader: boolean; hasNextPage: boolean; filters: Filters; onLoadMore: () => void; - products: CategoryProductInterface; onOrder: (order: string) => void; notFoundPhrase?: string; + totalCount: number; } export const ProductList: React.SFC = ({ displayLoader, filters, hasNextPage, + notFoundPhrase, onLoadMore, - products, onOrder, - notFoundPhrase + products, + totalCount }) => { const filterOptions = [ { value: "price", label: "Price Low-High" }, @@ -39,14 +42,14 @@ export const ProductList: React.SFC = ({ const sortValues = filterOptions.find( option => option.value === filters.sortBy ); - const hasProducts = !!products.totalCount; + const hasProducts = !!totalCount; return (
- {products.totalCount} Products + {totalCount} Products {displayLoader && (
@@ -70,7 +73,7 @@ export const ProductList: React.SFC = ({ {hasProducts ? ( <>
- {products.edges.map(({ node: product }) => ( + {products.map(product => ( (query: DocumentNode) { variables: { ...variables, [endCursorKey]: endCursor } }); - if (displayError && error && !hasData) { + if (displayError && error && !hasData) { return ; } diff --git a/src/views/Category/CategoryPage.tsx b/src/views/Category/CategoryPage.tsx index 7d86986ded..aa2f8d12a5 100644 --- a/src/views/Category/CategoryPage.tsx +++ b/src/views/Category/CategoryPage.tsx @@ -83,7 +83,8 @@ export const CategoryPage: React.SFC = ({ hasNextPage={hasNextPage} onLoadMore={onLoadMore} onOrder={onOrder} - products={products} + products={products.edges.map(edge => edge.node)} + totalCount={products.totalCount} /> )} {!hasProducts && } diff --git a/src/views/Category/queries.ts b/src/views/Category/queries.ts index 82c725afb8..650873d755 100644 --- a/src/views/Category/queries.ts +++ b/src/views/Category/queries.ts @@ -1,9 +1,12 @@ import gql from "graphql-tag"; +import { productNodeFragment } from "../../components/ProductListItem/queries"; import { TypedQuery } from "../../core/queries"; import { Category, CategoryVariables } from "./types/Category"; + export const categoryProductsQuery = gql` + ${productNodeFragment} query Category( $id: ID! $attributes: [AttributeScalar] @@ -25,19 +28,11 @@ export const categoryProductsQuery = gql` totalCount edges { node { - id - name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) + ...ProductNodeFragment category { id name } - price { - amount - currency - localized - } } } pageInfo { @@ -79,6 +74,7 @@ export const categoryProductsQuery = gql` } `; -export const TypedCategoryProductsQuery = TypedQuery( - categoryProductsQuery -); +export const TypedCategoryProductsQuery = TypedQuery< + Category, + CategoryVariables +>(categoryProductsQuery); diff --git a/src/views/Category/types/Category.ts b/src/views/Category/types/Category.ts index 7dc6eee220..8f35366d41 100644 --- a/src/views/Category/types/Category.ts +++ b/src/views/Category/types/Category.ts @@ -7,12 +7,6 @@ import { ProductOrder } from "./../../../../types/globalTypes"; // GraphQL query operation: Category // ==================================================== -export interface Category_products_edges_node_category { - __typename: "Category"; - id: string; - name: string; -} - export interface Category_products_edges_node_price { __typename: "Money"; amount: number; @@ -20,14 +14,20 @@ export interface Category_products_edges_node_price { localized: string; } +export interface Category_products_edges_node_category { + __typename: "Category"; + id: string; + name: string; +} + export interface Category_products_edges_node { __typename: "Product"; id: string; name: string; thumbnailUrl: string | null; thumbnailUrl2x: string | null; - category: Category_products_edges_node_category; price: Category_products_edges_node_price | null; + category: Category_products_edges_node_category; } export interface Category_products_edges { diff --git a/src/views/Collection/Page.tsx b/src/views/Collection/Page.tsx new file mode 100644 index 0000000000..e4398a2eac --- /dev/null +++ b/src/views/Collection/Page.tsx @@ -0,0 +1,103 @@ +import "../Category/scss/index.scss"; + +import * as React from "react"; + +import { + Breadcrumbs, + Filters, + ProductFilters, + ProductsFeatured, + ProductsList +} from "../../components"; + +import { getDBIdFromGraphqlId, maybe } from "../../core/utils"; +import { + Collection_attributes_edges_node, + Collection_collection, + Collection_products +} from "./types/Collection"; + +interface PageProps { + attributes: Collection_attributes_edges_node[]; + collection: Collection_collection; + displayLoader: boolean; + filters: Filters; + hasNextPage: boolean; + products: Collection_products; + onLoadMore: () => void; + onPriceChange: (field: "priceLte" | "priceGte", value: number) => void; + onAttributeFiltersChange: (attributeSlug: string, values: string[]) => void; + onOrder: (order: string) => void; +} + +export const Page: React.SFC = ({ + attributes, + collection, + displayLoader, + filters, + hasNextPage, + onLoadMore, + products, + onAttributeFiltersChange, + onPriceChange, + onOrder +}) => { + const canDisplayProducts = maybe( + () => products.edges && products.totalCount !== undefined, + false + ); + const hasProducts = canDisplayProducts && !!products.totalCount; + const breadcrumbs = [ + { + link: [ + `/collection`, + `/${collection.slug}`, + `/${getDBIdFromGraphqlId(collection.id, "Collection")}/` + ].join(""), + value: collection.name + } + ]; + + return ( +
+
+ +

{collection.name}

+
+
+ +
+ +
+ + {hasProducts && ( + + )} + + {canDisplayProducts && ( + edge.node)} + totalCount={products.totalCount} + /> + )} + {!hasProducts && } +
+ ); +}; diff --git a/src/views/Collection/View.tsx b/src/views/Collection/View.tsx index e69de29bb2..59ea0206c1 100644 --- a/src/views/Collection/View.tsx +++ b/src/views/Collection/View.tsx @@ -0,0 +1,106 @@ +import * as React from "react"; +import { RouteComponentProps } from "react-router"; + +import NetworkStatus from "../../components/NetworkStatus"; +import { NotFound } from "../../components/NotFound"; +import { OfflinePlaceholder } from "../../components/OfflinePlaceholder"; +import { AttributeList, Filters } from "../../components/ProductFilters"; +import { PRODUCTS_PER_PAGE } from "../../core/config"; +import { + convertSortByFromString, + convertToAttributeScalar, + getAttributesFromQs, + getGraphqlIdFromDBId, + maybe, + parseQueryString, + updateQueryString +} from "../../core/utils"; +import { Page } from "./Page"; +import { TypedCollectionProductsQuery } from "./queries"; + +type ViewProps = RouteComponentProps<{ + id: string; +}>; + +export const View: React.SFC = ({ match, location, history }) => { + const querystring = parseQueryString(location); + const updateQs = updateQueryString(location, history); + const attributes: AttributeList = getAttributesFromQs(querystring); + + const filters: Filters = { + attributes, + pageSize: PRODUCTS_PER_PAGE, + priceGte: querystring.priceGte || null, + priceLte: querystring.priceLte || null, + sortBy: querystring.sortBy || null + }; + const variables = { + ...filters, + attributes: convertToAttributeScalar(filters.attributes), + id: getGraphqlIdFromDBId(match.params.id, "Collection"), + sortBy: convertSortByFromString(filters.sortBy) + }; + + return ( + + {isOnline => ( + + {({ loading, data, loadMore }) => { + const canDisplayFilters = maybe( + () => !!data.collection.name, + false + ); + + if (canDisplayFilters) { + const handleLoadMore = () => + loadMore( + (prev, next) => ({ + ...prev, + products: { + ...prev.products, + edges: [...prev.products.edges, ...next.products.edges], + pageInfo: next.products.pageInfo + } + }), + data.products.pageInfo.endCursor + ); + + return ( + edge.node)} + attributes={[]} + collection={data.collection} + displayLoader={loading} + hasNextPage={maybe( + () => data.products.pageInfo.hasNextPage, + false + )} + filters={filters} + products={data.products} + onAttributeFiltersChange={updateQs} + onLoadMore={handleLoadMore} + onOrder={value => updateQs("sortBy", value)} + onPriceChange={updateQs} + /> + ); + } + + if (data && data.collection === null) { + return ; + } + + if (!isOnline) { + return ; + } + + return null; + }} + + )} + + ); +}; diff --git a/src/views/Collection/index.ts b/src/views/Collection/index.ts index e69de29bb2..af284cd938 100644 --- a/src/views/Collection/index.ts +++ b/src/views/Collection/index.ts @@ -0,0 +1 @@ +export { View as CollectionPage } from "./View"; diff --git a/src/views/Collection/queries.ts b/src/views/Collection/queries.ts index 498f2bde7b..11fbac187e 100644 --- a/src/views/Collection/queries.ts +++ b/src/views/Collection/queries.ts @@ -1,9 +1,11 @@ import gql from "graphql-tag"; +import { productNodeFragment } from "../../components/ProductListItem/queries"; import { TypedQuery } from "../../core/queries"; import { Collection, CollectionVariables } from "./types/Collection"; export const callectionPoroductsQuery = gql` + ${productNodeFragment} query Collection( $id: ID! $attributes: [AttributeScalar] @@ -25,7 +27,6 @@ export const callectionPoroductsQuery = gql` collections: [$id] after: $after attributes: $attributes - categories: [$id] first: $pageSize sortBy: $sortBy priceLte: $priceLte @@ -34,22 +35,11 @@ export const callectionPoroductsQuery = gql` totalCount edges { node { - id - name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) - thumbnail { - url - } + ...ProductNodeFragment collections { id name } - price { - amount - currency - localized - } } } pageInfo { @@ -59,6 +49,8 @@ export const callectionPoroductsQuery = gql` startCursor } } + # attributes(inCollection: $id, first: 100) { + # TODO change after merge attributes(inCategory: $id, first: 100) { edges { node { diff --git a/src/views/Collection/types/Collection.ts b/src/views/Collection/types/Collection.ts index fb8fd3b785..496f486253 100644 --- a/src/views/Collection/types/Collection.ts +++ b/src/views/Collection/types/Collection.ts @@ -20,9 +20,11 @@ export interface Collection_collection { backgroundImage: Collection_collection_backgroundImage | null; } -export interface Collection_products_edges_node_thumbnail { - __typename: "Image"; - url: string; +export interface Collection_products_edges_node_price { + __typename: "Money"; + amount: number; + currency: string; + localized: string; } export interface Collection_products_edges_node_collections { @@ -31,22 +33,14 @@ export interface Collection_products_edges_node_collections { name: string; } -export interface Collection_products_edges_node_price { - __typename: "Money"; - amount: number; - currency: string; - localized: string; -} - export interface Collection_products_edges_node { __typename: "Product"; id: string; name: string; thumbnailUrl: string | null; thumbnailUrl2x: string | null; - thumbnail: Collection_products_edges_node_thumbnail | null; - collections: (Collection_products_edges_node_collections | null)[] | null; price: Collection_products_edges_node_price | null; + collections: (Collection_products_edges_node_collections | null)[] | null; } export interface Collection_products_edges { diff --git a/src/views/Search/index.tsx b/src/views/Search/index.tsx index 81ad4d255a..f20cfd3a0f 100644 --- a/src/views/Search/index.tsx +++ b/src/views/Search/index.tsx @@ -143,12 +143,13 @@ export const SearchView: React.SFC = ({ {canDisplayProducts && ( edge.node)} + totalCount={data.products.totalCount} /> )} {!hasProducts && ( From 6157fa75957c84d8307fbbda23a7eb8c4bd5a3b8 Mon Sep 17 00:00:00 2001 From: Piotr Grundas Date: Thu, 27 Dec 2018 13:06:38 +0100 Subject: [PATCH 3/3] [128] New thumbnail structure --- src/components/Breadcrumbs/index.tsx | 15 +-- src/components/CartOverlay/index.tsx | 32 ++--- src/components/CartPage/index.tsx | 28 +++-- src/components/CartProvider/index.tsx | 4 +- src/components/CartSummary/index.tsx | 15 ++- src/components/CheckoutApp/context.ts | 4 +- src/components/CheckoutApp/queries.ts | 9 +- src/components/CheckoutApp/types/Checkout.ts | 15 ++- .../CheckoutApp/types/getCheckout.ts | 15 ++- .../CheckoutApp/types/updateCheckoutLine.ts | 17 ++- .../types/updateCheckoutBillingAddress.ts | 17 ++- .../CheckoutPayment/types/createPayment.ts | 2 +- src/components/CheckoutReview/index.tsx | 21 ++-- .../CheckoutReview/types/completeCheckout.ts | 2 +- .../types/updateCheckoutShippingAddress.ts | 19 ++- .../types/updateCheckoutShippingOptions.ts | 17 ++- src/components/GoToCheckout/index.tsx | 4 +- .../GoToCheckout/types/createCheckout.ts | 17 ++- .../LoginOverlay/types/RegisterCutomer.ts | 2 +- .../PasswordResetForm/types/ResetPassword.ts | 2 +- src/components/ProductListItem/index.tsx | 26 ++-- src/components/ProductListItem/queries.ts | 15 --- .../types/ProductNodeFragment.ts | 22 ---- src/components/ProductPage/index.tsx | 112 ++++++++---------- src/components/ProductPage/queries.ts | 32 +++-- .../ProductPage/types/BasicProductFields.ts | 6 + .../ProductPage/types/ProductDetails.ts | 12 ++ .../ProductPage/types/VariantList.ts | 6 + src/components/ProductsFeatured/queries.tsx | 11 +- .../ProductsFeatured/types/ProductsList.ts | 15 ++- src/components/ProductsList/index.tsx | 6 +- src/components/SearchOverlay/index.tsx | 50 ++++---- src/components/SearchOverlay/queries.ts | 15 ++- .../SearchOverlay/types/SearchResults.ts | 6 + src/core/queries.tsx | 12 +- src/storybook/stories/components.js | 4 +- src/views/Category/CategoryPage.tsx | 2 +- src/views/Category/queries.ts | 12 +- src/views/Category/types/Category.ts | 15 ++- src/views/Collection/Page.tsx | 1 - src/views/Collection/View.tsx | 3 +- src/views/Collection/queries.ts | 21 ++-- src/views/Collection/types/Collection.ts | 21 +++- src/views/Search/queries.ts | 9 +- src/views/Search/types/SearchProducts.ts | 15 ++- 45 files changed, 429 insertions(+), 277 deletions(-) delete mode 100644 src/components/ProductListItem/queries.ts delete mode 100644 src/components/ProductListItem/types/ProductNodeFragment.ts diff --git a/src/components/Breadcrumbs/index.tsx b/src/components/Breadcrumbs/index.tsx index 56bf2ff8f1..dbe3fb7b6d 100644 --- a/src/components/Breadcrumbs/index.tsx +++ b/src/components/Breadcrumbs/index.tsx @@ -12,23 +12,20 @@ export interface Breadcrumb { link: string; } -export const extractBreadcrumbs = ( - iterable: Category_category, - type: "Category" -) => { +export const extractBreadcrumbs = (category: Category_category) => { const constructLink = item => ({ link: [ - `/${type.toLowerCase()}`, + `/category`, `/${slugify(item.name)}`, - `/${getDBIdFromGraphqlId(item.id, type)}/` + `/${getDBIdFromGraphqlId(item.id, "Category")}/` ].join(""), value: item.name }); - let breadcrumbs = [constructLink(iterable)]; + let breadcrumbs = [constructLink(category)]; - if (iterable.ancestors.edges.length) { - const ancestorsList = iterable.ancestors.edges.map(constructLink); + if (category.ancestors.edges.length) { + const ancestorsList = category.ancestors.edges.map(constructLink); breadcrumbs = ancestorsList.concat(breadcrumbs); } return breadcrumbs; diff --git a/src/components/CartOverlay/index.tsx b/src/components/CartOverlay/index.tsx index 1f8219f6cb..66ed7f4537 100644 --- a/src/components/CartOverlay/index.tsx +++ b/src/components/CartOverlay/index.tsx @@ -1,10 +1,12 @@ +import "./scss/index.scss"; + import * as React from "react"; import { ApolloConsumer } from "react-apollo"; import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; import { Button } from ".."; -import { priceToString } from "../../core/utils"; +import { maybe, priceToString } from "../../core/utils"; import { checkoutLoginUrl } from "../App/routes"; import { CartContext } from "../CartProvider/context"; import { Error } from "../Error"; @@ -21,7 +23,10 @@ import Offline from "../Offline"; import OfflinePlaceholder from "../OfflinePlaceholder"; import Online from "../Online"; -import "./scss/index.scss"; +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 = () => ( @@ -50,7 +55,7 @@ export const CartOverlay: React.SFC = () => (
@@ -60,7 +65,7 @@ export const CartOverlay: React.SFC = () => (
overlay.hide()} className="overlay__header__close-icon" /> @@ -74,24 +79,23 @@ export const CartOverlay: React.SFC = () => ( className="cart__list__item" > 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} - + {"Qty: " + line.quantity} cart.remove(line.variant.id) diff --git a/src/components/CartPage/index.tsx b/src/components/CartPage/index.tsx index 5548ec74c0..76e5d25769 100644 --- a/src/components/CartPage/index.tsx +++ b/src/components/CartPage/index.tsx @@ -1,3 +1,5 @@ +import "./scss/index.scss"; + import * as React from "react"; import { ApolloConsumer, Query } from "react-apollo"; import Media from "react-media"; @@ -6,18 +8,20 @@ import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; import { Button, Loader } from ".."; -import { getCheckout } from "../../core/types/saleor"; +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"; -import { smallScreen } from "../App/scss/variables.scss"; -import CachedImage from "../CachedImage"; -import "./scss/index.scss"; +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; @@ -67,11 +71,13 @@ const CartPage: React.SFC> = ({ query={{ minWidth: smallScreen }} render={() => ( line.variant.product.thumbnail.url, + noPhotoPng + )} + url2x={maybe( + () => line.variant.product.thumbnail2x.url + )} /> )} /> @@ -93,7 +99,7 @@ const CartPage: React.SFC> = ({ {({ remove }) => ( remove(line.variant.id)} /> @@ -122,7 +128,7 @@ const CartPage: React.SFC> = ({ {client => ( - Checkout + Checkout{" "} )} diff --git a/src/components/CartProvider/index.tsx b/src/components/CartProvider/index.tsx index 318ae964e6..8c3a15c201 100644 --- a/src/components/CartProvider/index.tsx +++ b/src/components/CartProvider/index.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { ApolloClient } from "apollo-client"; import { GET_CHECKOUT, UPDATE_CHECKOUT_LINE } from "../CheckoutApp/queries"; -import { GET_PRODUCTS_VARIANTS } from "../ProductPage/queries"; +import { productVariatnsQuery } from "../ProductPage/queries"; import { CartContext, CartInterface, CartLineInterface } from "./context"; export default class CartProvider extends React.Component< @@ -93,7 +93,7 @@ export default class CartProvider extends React.Component< let data: { [key: string]: any }; let lines; const response = await apolloClient.query({ - query: GET_PRODUCTS_VARIANTS, + query: productVariatnsQuery, variables: { ids: cart.map(line => line.variantId) } }); const quantityMapping = cart.reduce((obj, line) => { diff --git a/src/components/CartSummary/index.tsx b/src/components/CartSummary/index.tsx index 8882118852..d22596df4a 100644 --- a/src/components/CartSummary/index.tsx +++ b/src/components/CartSummary/index.tsx @@ -1,10 +1,13 @@ +import "./scss/index.scss"; + import * as React from "react"; +import { maybe } from "../../core/utils"; import { CheckoutContext } from "../CheckoutApp/context"; -import "./scss/index.scss"; +const noPhotoPng = require("../../images/nophoto.png"); -const CartSummary: React.SFC<{}> = () => ( +const CartSummary: React.SFC = () => ( {({ checkout }) => checkout ? ( @@ -13,10 +16,10 @@ const CartSummary: React.SFC<{}> = () => ( {checkout.lines.map(product => (
product.variant.product.thumbnail.url, + noPhotoPng + )} />

{product.variant.price.localized}

diff --git a/src/components/CheckoutApp/context.ts b/src/components/CheckoutApp/context.ts index 0056ac0443..8a147d9f97 100644 --- a/src/components/CheckoutApp/context.ts +++ b/src/components/CheckoutApp/context.ts @@ -1,6 +1,6 @@ import { createContext } from "react"; -import { CheckoutInterface } from "../../core/types"; +import { Checkout } from "./types/Checkout"; export interface CheckoutContextInterface { cardData?: { @@ -8,7 +8,7 @@ export interface CheckoutContextInterface { ccType: string; token: string; }; - checkout?: CheckoutInterface; + checkout?: Checkout; loading?: boolean; shippingAsBilling?: boolean; updateCheckout?(chekcoutData: CheckoutContextInterface): void; diff --git a/src/components/CheckoutApp/queries.ts b/src/components/CheckoutApp/queries.ts index ce8c53fe00..dbeedf9dbc 100644 --- a/src/components/CheckoutApp/queries.ts +++ b/src/components/CheckoutApp/queries.ts @@ -107,8 +107,13 @@ export const CHECKOUT_FRAGMENT = gql` product { id name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) + thumbnail { + url + alt + } + thumbnail2x: thumbnail(size: 510){ + url + } } } quantity diff --git a/src/components/CheckoutApp/types/Checkout.ts b/src/components/CheckoutApp/types/Checkout.ts index 1cfa9ea7ab..f97ff9b225 100644 --- a/src/components/CheckoutApp/types/Checkout.ts +++ b/src/components/CheckoutApp/types/Checkout.ts @@ -152,12 +152,23 @@ export interface Checkout_lines_variant_price { localized: string; } +export interface Checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface Checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface Checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: Checkout_lines_variant_product_thumbnail | null; + thumbnail2x: Checkout_lines_variant_product_thumbnail2x | null; } export interface Checkout_lines_variant { diff --git a/src/components/CheckoutApp/types/getCheckout.ts b/src/components/CheckoutApp/types/getCheckout.ts index 2606c71506..22c8a8ba73 100644 --- a/src/components/CheckoutApp/types/getCheckout.ts +++ b/src/components/CheckoutApp/types/getCheckout.ts @@ -152,12 +152,23 @@ export interface getCheckout_checkout_lines_variant_price { localized: string; } +export interface getCheckout_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface getCheckout_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface getCheckout_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: getCheckout_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: getCheckout_checkout_lines_variant_product_thumbnail2x | null; } export interface getCheckout_checkout_lines_variant { diff --git a/src/components/CheckoutApp/types/updateCheckoutLine.ts b/src/components/CheckoutApp/types/updateCheckoutLine.ts index b7b5b1e78b..0dae7ac80b 100644 --- a/src/components/CheckoutApp/types/updateCheckoutLine.ts +++ b/src/components/CheckoutApp/types/updateCheckoutLine.ts @@ -154,12 +154,23 @@ export interface updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_p localized: string; } +export interface updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant_product_thumbnail2x | null; } export interface updateCheckoutLine_checkoutLinesUpdate_checkout_lines_variant { @@ -202,7 +213,7 @@ export interface updateCheckoutLine_checkoutLinesUpdate_errors { export interface updateCheckoutLine_checkoutLinesUpdate { __typename: "CheckoutLinesUpdate"; checkout: updateCheckoutLine_checkoutLinesUpdate_checkout | null; - errors: (updateCheckoutLine_checkoutLinesUpdate_errors | null)[] | null; + errors: updateCheckoutLine_checkoutLinesUpdate_errors[] | null; } export interface updateCheckoutLine { diff --git a/src/components/CheckoutBilling/types/updateCheckoutBillingAddress.ts b/src/components/CheckoutBilling/types/updateCheckoutBillingAddress.ts index fecbf6c3ed..25532697d9 100644 --- a/src/components/CheckoutBilling/types/updateCheckoutBillingAddress.ts +++ b/src/components/CheckoutBilling/types/updateCheckoutBillingAddress.ts @@ -160,12 +160,23 @@ export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_check localized: string; } +export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant_product_thumbnail2x | null; } export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines_variant { @@ -201,7 +212,7 @@ export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_check export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate { __typename: "CheckoutBillingAddressUpdate"; - errors: (updateCheckoutBillingAddress_checkoutBillingAddressUpdate_errors | null)[] | null; + errors: updateCheckoutBillingAddress_checkoutBillingAddressUpdate_errors[] | null; checkout: updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout | null; } diff --git a/src/components/CheckoutPayment/types/createPayment.ts b/src/components/CheckoutPayment/types/createPayment.ts index 5f51c10293..0aa78957bc 100644 --- a/src/components/CheckoutPayment/types/createPayment.ts +++ b/src/components/CheckoutPayment/types/createPayment.ts @@ -15,7 +15,7 @@ export interface createPayment_checkoutPaymentCreate_errors { export interface createPayment_checkoutPaymentCreate { __typename: "CheckoutPaymentCreate"; - errors: (createPayment_checkoutPaymentCreate_errors | null)[] | null; + errors: createPayment_checkoutPaymentCreate_errors[] | null; } export interface createPayment { diff --git a/src/components/CheckoutReview/index.tsx b/src/components/CheckoutReview/index.tsx index d88d1a406d..2a4ffa69ad 100644 --- a/src/components/CheckoutReview/index.tsx +++ b/src/components/CheckoutReview/index.tsx @@ -1,16 +1,19 @@ +import { smallScreen } from "../App/scss/variables.scss"; +import "./scss/index.scss"; + import * as React from "react"; 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 { CheckoutContext } from "../CheckoutApp/context"; import { OverlayContext, OverlayType } from "../Overlay/context"; import { COMPLETE_CHECKOUT } from "./queries"; -import { smallScreen } from "../App/scss/variables.scss"; -import CachedImage from "../CachedImage"; -import "./scss/index.scss"; +const noPhotoPng = require("../../images/nophoto.png"); class CheckoutReview extends React.Component, {}> { render() { @@ -47,11 +50,13 @@ class CheckoutReview extends React.Component, {}> { query={{ minWidth: smallScreen }} render={() => ( line.variant.product.thumbnail.url, + noPhotoPng + )} + url2x={maybe( + () => line.variant.product.thumbnail2x.url + )} /> )} /> diff --git a/src/components/CheckoutReview/types/completeCheckout.ts b/src/components/CheckoutReview/types/completeCheckout.ts index 8b9cfb9a24..d8effe84f8 100644 --- a/src/components/CheckoutReview/types/completeCheckout.ts +++ b/src/components/CheckoutReview/types/completeCheckout.ts @@ -18,7 +18,7 @@ export interface completeCheckout_checkoutComplete_order { export interface completeCheckout_checkoutComplete { __typename: "CheckoutComplete"; - errors: (completeCheckout_checkoutComplete_errors | null)[] | null; + errors: completeCheckout_checkoutComplete_errors[] | null; order: completeCheckout_checkoutComplete_order | null; } diff --git a/src/components/CheckoutShipping/types/updateCheckoutShippingAddress.ts b/src/components/CheckoutShipping/types/updateCheckoutShippingAddress.ts index 3a26252437..eec0e969b2 100644 --- a/src/components/CheckoutShipping/types/updateCheckoutShippingAddress.ts +++ b/src/components/CheckoutShipping/types/updateCheckoutShippingAddress.ts @@ -15,7 +15,7 @@ export interface updateCheckoutShippingAddress_checkoutShippingAddressUpdate_err export interface updateCheckoutShippingAddress_checkoutShippingAddressUpdate { __typename: "CheckoutShippingAddressUpdate"; - errors: (updateCheckoutShippingAddress_checkoutShippingAddressUpdate_errors | null)[] | null; + errors: updateCheckoutShippingAddress_checkoutShippingAddressUpdate_errors[] | null; } export interface updateCheckoutShippingAddress_checkoutEmailUpdate_errors { @@ -171,12 +171,23 @@ export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_line localized: string; } +export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant_product_thumbnail2x | null; } export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines_variant { @@ -212,7 +223,7 @@ export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout { export interface updateCheckoutShippingAddress_checkoutEmailUpdate { __typename: "CheckoutEmailUpdate"; - errors: (updateCheckoutShippingAddress_checkoutEmailUpdate_errors | null)[] | null; + errors: updateCheckoutShippingAddress_checkoutEmailUpdate_errors[] | null; checkout: updateCheckoutShippingAddress_checkoutEmailUpdate_checkout | null; } diff --git a/src/components/CheckoutShippingOptions/types/updateCheckoutShippingOptions.ts b/src/components/CheckoutShippingOptions/types/updateCheckoutShippingOptions.ts index 543e8d7654..a0c94512a9 100644 --- a/src/components/CheckoutShippingOptions/types/updateCheckoutShippingOptions.ts +++ b/src/components/CheckoutShippingOptions/types/updateCheckoutShippingOptions.ts @@ -158,12 +158,23 @@ export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_chec localized: string; } +export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant_product_thumbnail2x | null; } export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines_variant { @@ -199,7 +210,7 @@ export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_chec export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate { __typename: "CheckoutShippingMethodUpdate"; - errors: (updateCheckoutShippingOptions_checkoutShippingMethodUpdate_errors | null)[] | null; + errors: updateCheckoutShippingOptions_checkoutShippingMethodUpdate_errors[] | null; checkout: updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout | null; } diff --git a/src/components/GoToCheckout/index.tsx b/src/components/GoToCheckout/index.tsx index b06ec75b01..bfb455b9ee 100644 --- a/src/components/GoToCheckout/index.tsx +++ b/src/components/GoToCheckout/index.tsx @@ -2,7 +2,6 @@ import { ApolloClient } from "apollo-client"; import * as React from "react"; import { Redirect } from "react-router"; -import { CheckoutInterface } from "../../core/types"; import { ButtonProps, default as Button } from "../Button"; import { CartInterface } from "../CartProvider/context"; import { CheckoutContext } from "../CheckoutApp/context"; @@ -13,10 +12,11 @@ import { checkoutPaymentUrl, checkoutShippingOptionsUrl } from "../CheckoutApp/routes"; +import { Checkout } from "../CheckoutApp/types/Checkout"; import { CREATE_CHECKOUT } from "./queries"; export interface GoToCheckoutState { - checkout?: CheckoutInterface; + checkout?: Checkout; checkoutToken: string; loading: boolean; redirect: boolean; diff --git a/src/components/GoToCheckout/types/createCheckout.ts b/src/components/GoToCheckout/types/createCheckout.ts index 08287a65d1..49b8aa57bd 100644 --- a/src/components/GoToCheckout/types/createCheckout.ts +++ b/src/components/GoToCheckout/types/createCheckout.ts @@ -160,12 +160,23 @@ export interface createCheckout_checkoutCreate_checkout_lines_variant_price { localized: string; } +export interface createCheckout_checkoutCreate_checkout_lines_variant_product_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface createCheckout_checkoutCreate_checkout_lines_variant_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface createCheckout_checkoutCreate_checkout_lines_variant_product { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: createCheckout_checkoutCreate_checkout_lines_variant_product_thumbnail | null; + thumbnail2x: createCheckout_checkoutCreate_checkout_lines_variant_product_thumbnail2x | null; } export interface createCheckout_checkoutCreate_checkout_lines_variant { @@ -201,7 +212,7 @@ export interface createCheckout_checkoutCreate_checkout { export interface createCheckout_checkoutCreate { __typename: "CheckoutCreate"; - errors: (createCheckout_checkoutCreate_errors | null)[] | null; + errors: createCheckout_checkoutCreate_errors[] | null; checkout: createCheckout_checkoutCreate_checkout | null; } diff --git a/src/components/LoginOverlay/types/RegisterCutomer.ts b/src/components/LoginOverlay/types/RegisterCutomer.ts index b4fe0c55d3..a851df949c 100644 --- a/src/components/LoginOverlay/types/RegisterCutomer.ts +++ b/src/components/LoginOverlay/types/RegisterCutomer.ts @@ -13,7 +13,7 @@ export interface RegisterCutomer_customerRegister_errors { export interface RegisterCutomer_customerRegister { __typename: "CustomerRegister"; - errors: (RegisterCutomer_customerRegister_errors | null)[] | null; + errors: RegisterCutomer_customerRegister_errors[] | null; } export interface RegisterCutomer { diff --git a/src/components/PasswordResetForm/types/ResetPassword.ts b/src/components/PasswordResetForm/types/ResetPassword.ts index 9c07615549..c8d2a50e48 100644 --- a/src/components/PasswordResetForm/types/ResetPassword.ts +++ b/src/components/PasswordResetForm/types/ResetPassword.ts @@ -13,7 +13,7 @@ export interface ResetPassword_customerPasswordReset_errors { export interface ResetPassword_customerPasswordReset { __typename: "CustomerPasswordReset"; - errors: (ResetPassword_customerPasswordReset_errors | null)[] | null; + errors: ResetPassword_customerPasswordReset_errors[] | null; } export interface ResetPassword { diff --git a/src/components/ProductListItem/index.tsx b/src/components/ProductListItem/index.tsx index b99ee1533e..311c04b2df 100644 --- a/src/components/ProductListItem/index.tsx +++ b/src/components/ProductListItem/index.tsx @@ -4,17 +4,18 @@ import * as React from "react"; import { maybe } from "../../core/utils"; import CachedImage from "../CachedImage"; -import { ProductNodeFragment } from "./types/ProductNodeFragment"; +import { BasicProductFields } from "../ProductPage/types/BasicProductFields"; -interface Product extends ProductNodeFragment { +const noPhoto = require("../../images/nophoto.png"); + +export interface Product extends BasicProductFields { category?: { id: string; name: string; }; - collections?: Array<{ - id: string; - name: string; - }>; + price: { + localized: string; + } } interface ProductListItemProps { @@ -22,21 +23,18 @@ interface ProductListItemProps { } const ProductListItem: React.SFC = ({ - product: { name, collections, category, price, thumbnailUrl, thumbnailUrl2x } + product: { name, category, price, thumbnail, thumbnail2x } }) => { - const categoryOrCollecton = maybe(() => collections[0].name || category.name); - + const thumbnail2xUrl = maybe(() => thumbnail2x.url, undefined) return (
- - + + {thumbnail.alt}

{name}

-

- {categoryOrCollecton} -

+

{category.name}

{price.localized}

); diff --git a/src/components/ProductListItem/queries.ts b/src/components/ProductListItem/queries.ts deleted file mode 100644 index 7af62f4920..0000000000 --- a/src/components/ProductListItem/queries.ts +++ /dev/null @@ -1,15 +0,0 @@ -import gql from "graphql-tag"; - -export const productNodeFragment = gql` - fragment ProductNodeFragment on Product { - id - name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) - price { - amount - currency - localized - } - } -`; diff --git a/src/components/ProductListItem/types/ProductNodeFragment.ts b/src/components/ProductListItem/types/ProductNodeFragment.ts deleted file mode 100644 index a07f1db23e..0000000000 --- a/src/components/ProductListItem/types/ProductNodeFragment.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: ProductNodeFragment -// ==================================================== - -export interface ProductNodeFragment_price { - __typename: "Money"; - amount: number; - currency: string; - localized: string; -} - -export interface ProductNodeFragment { - __typename: "Product"; - id: string; - name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; - price: ProductNodeFragment_price | null; -} diff --git a/src/components/ProductPage/index.tsx b/src/components/ProductPage/index.tsx index cbc6c91e4e..354b2ac0f8 100644 --- a/src/components/ProductPage/index.tsx +++ b/src/components/ProductPage/index.tsx @@ -1,6 +1,5 @@ import classNames from "classnames"; import * as React from "react"; -import { Query } from "react-apollo"; import Media from "react-media"; import { RouteComponentProps } from "react-router"; import { Link } from "react-router-dom"; @@ -13,29 +12,31 @@ import { ProductDescription, ProductListItem } from ".."; -import { ProductDetails } from "../../core/types/saleor"; import { generateCategoryUrl, generateProductUrl, - getGraphqlIdFromDBId + getGraphqlIdFromDBId, + maybe } from "../../core/utils"; import { smallScreen } from "../App/scss/variables.scss"; import { CartContext } from "../CartProvider/context"; -import { Error } from "../Error"; import NetworkStatus from "../NetworkStatus"; import { NotFound } from "../NotFound"; import { OfflinePlaceholder } from "../OfflinePlaceholder"; -import { GET_PRODUCT_DETAILS } from "./queries"; +import { TypedProductDetailsQuery } from "./queries"; import "./scss/index.scss"; +import { ProductDetails } from "./types/ProductDetails"; +const noPhoto = require("../../images/nophoto.png"); const canDisplay = (data: ProductDetails) => - data && - data.product && - data.product.description && - data.product.name && - data.product.price && - data.product.variants; + maybe( + () => + !!data.product.description && + !!data.product.name && + !!data.product.price && + !!data.product.variants + ); class ProductPage extends React.Component, {}> { fixedElement: React.RefObject = React.createRef(); @@ -73,38 +74,37 @@ class ProductPage extends React.Component, {}> { render() { return ( - - {({ error, data }) => ( + {({ data }) => ( {isOnline => { if (canDisplay(data)) { const { product } = data; + const breadcrumbs = [ + { + link: generateCategoryUrl( + product.category.id, + product.category.name + ), + value: product.category.name + }, + { + link: generateProductUrl(product.id, product.name), + value: product.name + } + ]; + return (
- +
@@ -149,21 +149,14 @@ class ProductPage extends React.Component, {}> { ); }} > - {product.images.map( - image => ( - - - - ) - )} + {product.images.map(image => ( + + + + ))}
@@ -190,21 +183,14 @@ class ProductPage extends React.Component, {}> { className="product-page__product__gallery" ref={this.productGallery} > - {product.images.map( - image => ( - - - - ) - )} + {product.images.map(image => ( + + + + ))}
, {}> { if (!isOnline) { return ; } - if (error) { - return ; - } - return ; }} )} - + ); } } diff --git a/src/components/ProductPage/queries.ts b/src/components/ProductPage/queries.ts index 8d6c323357..bc93e80616 100644 --- a/src/components/ProductPage/queries.ts +++ b/src/components/ProductPage/queries.ts @@ -1,17 +1,26 @@ import gql from "graphql-tag"; -export const BASIC_PRODUCT_FRAGMENT = gql` +import { TypedQuery } from "../../core/queries"; +import { + ProductDetails, + ProductDetailsVariables +} from "./types/ProductDetails"; + +export const basicProductFragment = gql` fragment BasicProductFields on Product { id name - thumbnail(size: 510) { + thumbnail { url alt } + thumbnail2x: thumbnail(size: 510) { + url + } } `; -export const PRODUCT_VARIANT_FRAGMENT = gql` +export const productVariantFragment = gql` fragment ProductVariantFields on ProductVariant { id name @@ -35,9 +44,9 @@ export const PRODUCT_VARIANT_FRAGMENT = gql` } `; -export const GET_PRODUCT_DETAILS = gql` - ${BASIC_PRODUCT_FRAGMENT} - ${PRODUCT_VARIANT_FRAGMENT} +export const productDetailsQuery = gql` + ${basicProductFragment} + ${productVariantFragment} query ProductDetails($id: ID!) { product(id: $id) { ...BasicProductFields @@ -80,9 +89,9 @@ export const GET_PRODUCT_DETAILS = gql` // FIXME: Check how to handle pagination of `productVariants` in the UI. // We need allow the user view all cart items regardless of pagination. -export const GET_PRODUCTS_VARIANTS = gql` - ${BASIC_PRODUCT_FRAGMENT} - ${PRODUCT_VARIANT_FRAGMENT} +export const productVariatnsQuery = gql` + ${basicProductFragment} + ${productVariantFragment} query VariantList($ids: [ID!]) { productVariants(ids: $ids, first: 100) { edges { @@ -96,3 +105,8 @@ export const GET_PRODUCTS_VARIANTS = gql` } } `; + +export const TypedProductDetailsQuery = TypedQuery< + ProductDetails, + ProductDetailsVariables +>(productDetailsQuery); diff --git a/src/components/ProductPage/types/BasicProductFields.ts b/src/components/ProductPage/types/BasicProductFields.ts index 26479f807a..3871dec11c 100644 --- a/src/components/ProductPage/types/BasicProductFields.ts +++ b/src/components/ProductPage/types/BasicProductFields.ts @@ -11,9 +11,15 @@ export interface BasicProductFields_thumbnail { alt: string | null; } +export interface BasicProductFields_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface BasicProductFields { __typename: "Product"; id: string; name: string; thumbnail: BasicProductFields_thumbnail | null; + thumbnail2x: BasicProductFields_thumbnail2x | null; } diff --git a/src/components/ProductPage/types/ProductDetails.ts b/src/components/ProductPage/types/ProductDetails.ts index 4ddce7fdbf..677b38c7ec 100644 --- a/src/components/ProductPage/types/ProductDetails.ts +++ b/src/components/ProductPage/types/ProductDetails.ts @@ -11,12 +11,22 @@ export interface ProductDetails_product_thumbnail { alt: string | null; } +export interface ProductDetails_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface ProductDetails_product_category_products_edges_node_thumbnail { __typename: "Image"; url: string; alt: string | null; } +export interface ProductDetails_product_category_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface ProductDetails_product_category_products_edges_node_category { __typename: "Category"; id: string; @@ -35,6 +45,7 @@ export interface ProductDetails_product_category_products_edges_node { id: string; name: string; thumbnail: ProductDetails_product_category_products_edges_node_thumbnail | null; + thumbnail2x: ProductDetails_product_category_products_edges_node_thumbnail2x | null; category: ProductDetails_product_category_products_edges_node_category; price: ProductDetails_product_category_products_edges_node_price | null; } @@ -109,6 +120,7 @@ export interface ProductDetails_product { id: string; name: string; thumbnail: ProductDetails_product_thumbnail | null; + thumbnail2x: ProductDetails_product_thumbnail2x | null; description: string; category: ProductDetails_product_category; price: ProductDetails_product_price | null; diff --git a/src/components/ProductPage/types/VariantList.ts b/src/components/ProductPage/types/VariantList.ts index b12bfab5bd..6d519de626 100644 --- a/src/components/ProductPage/types/VariantList.ts +++ b/src/components/ProductPage/types/VariantList.ts @@ -37,11 +37,17 @@ export interface VariantList_productVariants_edges_node_product_thumbnail { alt: string | null; } +export interface VariantList_productVariants_edges_node_product_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface VariantList_productVariants_edges_node_product { __typename: "Product"; id: string; name: string; thumbnail: VariantList_productVariants_edges_node_product_thumbnail | null; + thumbnail2x: VariantList_productVariants_edges_node_product_thumbnail2x | null; } export interface VariantList_productVariants_edges_node { diff --git a/src/components/ProductsFeatured/queries.tsx b/src/components/ProductsFeatured/queries.tsx index 87e21b2f8d..128119e9e4 100644 --- a/src/components/ProductsFeatured/queries.tsx +++ b/src/components/ProductsFeatured/queries.tsx @@ -1,11 +1,11 @@ import gql from "graphql-tag"; import { TypedQuery } from "../../core/queries"; -import { productNodeFragment } from "../ProductListItem/queries"; +import { basicProductFragment } from "../ProductPage/queries"; import { ProductsList } from "./types/ProductsList"; export const featuredProducts = gql` - ${productNodeFragment} + ${basicProductFragment} query ProductsList { shop { homepageCollection { @@ -13,7 +13,12 @@ export const featuredProducts = gql` products(first: 20) { edges { node { - ...ProductNodeFragment + ...BasicProductFields + price { + amount + currency + localized + } category { id name diff --git a/src/components/ProductsFeatured/types/ProductsList.ts b/src/components/ProductsFeatured/types/ProductsList.ts index 9d4dbdfa09..0b183308ae 100644 --- a/src/components/ProductsFeatured/types/ProductsList.ts +++ b/src/components/ProductsFeatured/types/ProductsList.ts @@ -5,6 +5,17 @@ // GraphQL query operation: ProductsList // ==================================================== +export interface ProductsList_shop_homepageCollection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface ProductsList_shop_homepageCollection_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface ProductsList_shop_homepageCollection_products_edges_node_price { __typename: "Money"; amount: number; @@ -22,8 +33,8 @@ export interface ProductsList_shop_homepageCollection_products_edges_node { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: ProductsList_shop_homepageCollection_products_edges_node_thumbnail | null; + thumbnail2x: ProductsList_shop_homepageCollection_products_edges_node_thumbnail2x | null; price: ProductsList_shop_homepageCollection_products_edges_node_price | null; category: ProductsList_shop_homepageCollection_products_edges_node_category; } diff --git a/src/components/ProductsList/index.tsx b/src/components/ProductsList/index.tsx index f414e236e6..5bb03cccce 100644 --- a/src/components/ProductsList/index.tsx +++ b/src/components/ProductsList/index.tsx @@ -8,12 +8,10 @@ import { generateProductUrl } from "../../core/utils"; import Loader from "../Loader"; import { Filters } from "../ProductFilters"; -import { Category_products } from "../../views/Category/types/Category"; -import { Collection_products } from "../../views/Collection/types/Collection"; -import { ProductNodeFragment } from "../ProductListItem/types/ProductNodeFragment"; +import { Product } from "../ProductListItem"; interface ProductsListProps { - products: ProductNodeFragment[]; + products: Product[]; displayLoader: boolean; hasNextPage: boolean; filters: Filters; diff --git a/src/components/SearchOverlay/index.tsx b/src/components/SearchOverlay/index.tsx index 7e073168bc..89b59e8ce5 100644 --- a/src/components/SearchOverlay/index.tsx +++ b/src/components/SearchOverlay/index.tsx @@ -3,14 +3,12 @@ import "./scss/index.scss"; import classNames from "classnames"; import * as React from "react"; -import { Query } from "react-apollo"; import Media from "react-media"; import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; import { Button, Loader, TextField } from ".."; -import { SearchResults } from "../../core/types/saleor"; -import { generateProductUrl } from "../../core/utils"; +import { generateProductUrl, maybe } from "../../core/utils"; import { searchUrl } from "../App/routes"; import CachedImage from "../CachedImage"; import Debounce from "../Debounce"; @@ -19,7 +17,12 @@ import NetworkStatus from "../NetworkStatus"; import { OfflinePlaceholder } from "../OfflinePlaceholder"; import { Overlay } from "../Overlay"; import { OverlayContext, OverlayType } from "../Overlay/context"; -import { GET_SEARCH_RESULTS } from "./queries"; +import { TypedSearchResults } from "./queries"; +import { SearchResults } from "./types/SearchResults"; + +const closeSvg = require("../../images/x.svg"); +const noPhotoPng = require("../../images/nophoto.png"); +const searcgSvg = require("../../images/search.svg"); const canDisplay = (data: SearchResults) => data && data.products && data.products.edges; @@ -64,26 +67,18 @@ class SearchOverlay extends React.Component<{}, { search: string }> { } - iconRight={ - - } + iconRight={} autoFocus={true} onChange={change} value={query} /> ) : ( - } + iconRight={} autoFocus={true} onChange={change} value={query} @@ -103,11 +98,11 @@ class SearchOverlay extends React.Component<{}, { search: string }> { > {isOnline => ( - {({ data, error, loading }) => { if (canDisplay(data)) { @@ -126,11 +121,14 @@ class SearchOverlay extends React.Component<{}, { search: string }> { )} > item.node.thumbnail.url, + noPhotoPng + )} + url2x={maybe( + () => item.node.thumbnail2x.url, + noPhotoPng + )} />

{item.node.name}

@@ -157,15 +155,15 @@ class SearchOverlay extends React.Component<{}, { search: string }> { ); } + if (error) { if (!isOnline) { return ; } return ; } - return ; }} -
+ )}
diff --git a/src/components/SearchOverlay/queries.ts b/src/components/SearchOverlay/queries.ts index 1748249cbe..3e27a98d63 100644 --- a/src/components/SearchOverlay/queries.ts +++ b/src/components/SearchOverlay/queries.ts @@ -1,16 +1,22 @@ import gql from "graphql-tag"; -export const GET_SEARCH_RESULTS = gql` +import { TypedQuery } from "../../core/queries"; +import { SearchResults, SearchResultsVariables } from "./types/SearchResults"; + +const searchResultsQuery = gql` query SearchResults($query: String!) { products(query: $query, first: 20) { edges { node { id name - thumbnail(size: 510){ + thumbnail { url alt } + thumbnail2x: thumbnail(size: 510) { + url + } url category { id @@ -27,3 +33,8 @@ export const GET_SEARCH_RESULTS = gql` } } `; + +export const TypedSearchResults = TypedQuery< + SearchResults, + SearchResultsVariables +>(searchResultsQuery); diff --git a/src/components/SearchOverlay/types/SearchResults.ts b/src/components/SearchOverlay/types/SearchResults.ts index 13d8f9f135..92a8df8eed 100644 --- a/src/components/SearchOverlay/types/SearchResults.ts +++ b/src/components/SearchOverlay/types/SearchResults.ts @@ -11,6 +11,11 @@ export interface SearchResults_products_edges_node_thumbnail { alt: string | null; } +export interface SearchResults_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface SearchResults_products_edges_node_category { __typename: "Category"; id: string; @@ -22,6 +27,7 @@ export interface SearchResults_products_edges_node { id: string; name: string; thumbnail: SearchResults_products_edges_node_thumbnail | null; + thumbnail2x: SearchResults_products_edges_node_thumbnail2x | null; url: string; category: SearchResults_products_edges_node_category; } diff --git a/src/core/queries.tsx b/src/core/queries.tsx index 16246ba15a..f67b5f7be6 100644 --- a/src/core/queries.tsx +++ b/src/core/queries.tsx @@ -10,8 +10,8 @@ import { maybe } from "./utils"; interface LoadMore { loadMore: ( mergeFunc: (prev: TData, next: TData) => TData, - endCursor: string, - endCursorKey?: string + cursor: string, + cursorKey?: string ) => Promise>; } @@ -55,8 +55,8 @@ export function TypedQuery(query: DocumentNode) { const hasData = maybe(() => !!Object.keys(data).length, false); const loadMore = ( mergeFunc: (previousResults: TData, fetchMoreResult: TData) => TData, - endCursor: string, - endCursorKey: string = "after" + cursor: string, + cursorKey: string = "after" ) => fetchMore({ query, @@ -66,10 +66,10 @@ export function TypedQuery(query: DocumentNode) { } return mergeFunc(previousResults, fetchMoreResult); }, - variables: { ...variables, [endCursorKey]: endCursor } + variables: { ...variables, [cursorKey]: cursor } }); - if (displayError && error && !hasData) { + if (displayError && error && !hasData) { return ; } diff --git a/src/storybook/stories/components.js b/src/storybook/stories/components.js index 1a2ae28e00..6732b0150c 100644 --- a/src/storybook/stories/components.js +++ b/src/storybook/stories/components.js @@ -76,7 +76,9 @@ storiesOf("Components", module) = ({
- +
{hasProducts && ( diff --git a/src/views/Category/queries.ts b/src/views/Category/queries.ts index 650873d755..17081096ed 100644 --- a/src/views/Category/queries.ts +++ b/src/views/Category/queries.ts @@ -1,12 +1,11 @@ import gql from "graphql-tag"; -import { productNodeFragment } from "../../components/ProductListItem/queries"; +import { basicProductFragment } from "../../components/ProductPage/queries"; import { TypedQuery } from "../../core/queries"; import { Category, CategoryVariables } from "./types/Category"; - export const categoryProductsQuery = gql` - ${productNodeFragment} + ${basicProductFragment} query Category( $id: ID! $attributes: [AttributeScalar] @@ -28,7 +27,12 @@ export const categoryProductsQuery = gql` totalCount edges { node { - ...ProductNodeFragment + ...BasicProductFields + price { + amount + currency + localized + } category { id name diff --git a/src/views/Category/types/Category.ts b/src/views/Category/types/Category.ts index 8f35366d41..1d3ca3588b 100644 --- a/src/views/Category/types/Category.ts +++ b/src/views/Category/types/Category.ts @@ -7,6 +7,17 @@ import { ProductOrder } from "./../../../../types/globalTypes"; // GraphQL query operation: Category // ==================================================== +export interface Category_products_edges_node_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface Category_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface Category_products_edges_node_price { __typename: "Money"; amount: number; @@ -24,8 +35,8 @@ export interface Category_products_edges_node { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: Category_products_edges_node_thumbnail | null; + thumbnail2x: Category_products_edges_node_thumbnail2x | null; price: Category_products_edges_node_price | null; category: Category_products_edges_node_category; } diff --git a/src/views/Collection/Page.tsx b/src/views/Collection/Page.tsx index e4398a2eac..4cf40b3903 100644 --- a/src/views/Collection/Page.tsx +++ b/src/views/Collection/Page.tsx @@ -9,7 +9,6 @@ import { ProductsFeatured, ProductsList } from "../../components"; - import { getDBIdFromGraphqlId, maybe } from "../../core/utils"; import { Collection_attributes_edges_node, diff --git a/src/views/Collection/View.tsx b/src/views/Collection/View.tsx index 59ea0206c1..3a02f9020b 100644 --- a/src/views/Collection/View.tsx +++ b/src/views/Collection/View.tsx @@ -71,8 +71,7 @@ export const View: React.SFC = ({ match, location, history }) => { return ( edge.node)} - attributes={[]} + attributes={data.attributes.edges.map(edge => edge.node)} collection={data.collection} displayLoader={loading} hasNextPage={maybe( diff --git a/src/views/Collection/queries.ts b/src/views/Collection/queries.ts index 11fbac187e..a5a276bc46 100644 --- a/src/views/Collection/queries.ts +++ b/src/views/Collection/queries.ts @@ -1,11 +1,11 @@ import gql from "graphql-tag"; -import { productNodeFragment } from "../../components/ProductListItem/queries"; +import { basicProductFragment } from "../../components/ProductPage/queries"; import { TypedQuery } from "../../core/queries"; import { Collection, CollectionVariables } from "./types/Collection"; -export const callectionPoroductsQuery = gql` - ${productNodeFragment} +export const collectionProductsQuery = gql` + ${basicProductFragment} query Collection( $id: ID! $attributes: [AttributeScalar] @@ -35,8 +35,13 @@ export const callectionPoroductsQuery = gql` totalCount edges { node { - ...ProductNodeFragment - collections { + ...BasicProductFields + price { + amount + currency + localized + } + category { id name } @@ -49,9 +54,7 @@ export const callectionPoroductsQuery = gql` startCursor } } - # attributes(inCollection: $id, first: 100) { - # TODO change after merge - attributes(inCategory: $id, first: 100) { + attributes(inCollection: $id, first: 100) { edges { node { id @@ -71,4 +74,4 @@ export const callectionPoroductsQuery = gql` export const TypedCollectionProductsQuery = TypedQuery< Collection, CollectionVariables ->(callectionPoroductsQuery); +>(collectionProductsQuery); diff --git a/src/views/Collection/types/Collection.ts b/src/views/Collection/types/Collection.ts index 496f486253..53d7b1c47f 100644 --- a/src/views/Collection/types/Collection.ts +++ b/src/views/Collection/types/Collection.ts @@ -20,6 +20,17 @@ export interface Collection_collection { backgroundImage: Collection_collection_backgroundImage | null; } +export interface Collection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface Collection_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface Collection_products_edges_node_price { __typename: "Money"; amount: number; @@ -27,8 +38,8 @@ export interface Collection_products_edges_node_price { localized: string; } -export interface Collection_products_edges_node_collections { - __typename: "Collection"; +export interface Collection_products_edges_node_category { + __typename: "Category"; id: string; name: string; } @@ -37,10 +48,10 @@ export interface Collection_products_edges_node { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: Collection_products_edges_node_thumbnail | null; + thumbnail2x: Collection_products_edges_node_thumbnail2x | null; price: Collection_products_edges_node_price | null; - collections: (Collection_products_edges_node_collections | null)[] | null; + category: Collection_products_edges_node_category; } export interface Collection_products_edges { diff --git a/src/views/Search/queries.ts b/src/views/Search/queries.ts index 14ebf5a1f5..d9195fc970 100644 --- a/src/views/Search/queries.ts +++ b/src/views/Search/queries.ts @@ -20,8 +20,13 @@ export const GET_SEARCH_PRODUCTS = gql` node { id name - thumbnailUrl - thumbnailUrl2x: thumbnailUrl(size: 510) + thumbnail { + url + alt + } + thumbnail2x: thumbnail(size: 510) { + url + } category { id name diff --git a/src/views/Search/types/SearchProducts.ts b/src/views/Search/types/SearchProducts.ts index 3c9af6cd61..6c77859ee7 100644 --- a/src/views/Search/types/SearchProducts.ts +++ b/src/views/Search/types/SearchProducts.ts @@ -7,6 +7,17 @@ import { ProductOrder } from "./../../../../types/globalTypes"; // GraphQL query operation: SearchProducts // ==================================================== +export interface SearchProducts_products_edges_node_thumbnail { + __typename: "Image"; + url: string; + alt: string | null; +} + +export interface SearchProducts_products_edges_node_thumbnail2x { + __typename: "Image"; + url: string; +} + export interface SearchProducts_products_edges_node_category { __typename: "Category"; id: string; @@ -24,8 +35,8 @@ export interface SearchProducts_products_edges_node { __typename: "Product"; id: string; name: string; - thumbnailUrl: string | null; - thumbnailUrl2x: string | null; + thumbnail: SearchProducts_products_edges_node_thumbnail | null; + thumbnail2x: SearchProducts_products_edges_node_thumbnail2x | null; category: SearchProducts_products_edges_node_category; price: SearchProducts_products_edges_node_price | null; }