From 112d51303f996367fdaf51f11730288f8cf9054c Mon Sep 17 00:00:00 2001 From: Michal Miszczyszyn Date: Mon, 1 May 2023 19:29:46 +0200 Subject: [PATCH] Make types independent of Sh --- app/product/[handle]/page.tsx | 2 +- components/cart/button.tsx | 2 +- components/cart/delete-item-button.tsx | 2 +- components/cart/edit-item-quantity-button.tsx | 2 +- components/cart/modal.tsx | 2 +- components/grid/three-items.tsx | 2 +- components/layout/footer.tsx | 2 +- components/layout/navbar/index.tsx | 2 +- components/layout/navbar/mobile-menu.tsx | 2 +- components/layout/product-grid-items.tsx | 2 +- components/product/add-to-cart.tsx | 2 +- components/product/variant-selector.tsx | 2 +- .../fragments/FeaturedProductFragment.graphql | 20 ++ lib/saleor/fragments/MenuFragment.graphql | 21 ++ lib/saleor/queries/GetCollections.graphql | 11 + .../queries/GetFeaturedProducts.graphql | 9 + lib/saleor/queries/GetMenu.graphql | 5 + lib/saleor/queries/SearchProducts.graphql | 18 ++ lib/saleor/queries/test.graphql | 9 + lib/types.ts | 263 ++++++++++++++++++ 20 files changed, 368 insertions(+), 12 deletions(-) create mode 100644 lib/saleor/fragments/FeaturedProductFragment.graphql create mode 100644 lib/saleor/fragments/MenuFragment.graphql create mode 100644 lib/saleor/queries/GetCollections.graphql create mode 100644 lib/saleor/queries/GetFeaturedProducts.graphql create mode 100644 lib/saleor/queries/GetMenu.graphql create mode 100644 lib/saleor/queries/SearchProducts.graphql create mode 100644 lib/saleor/queries/test.graphql create mode 100644 lib/types.ts diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx index 612cd0236..acca9ef51 100644 --- a/app/product/[handle]/page.tsx +++ b/app/product/[handle]/page.tsx @@ -11,7 +11,7 @@ import { VariantSelector } from 'components/product/variant-selector'; import Prose from 'components/prose'; import { HIDDEN_PRODUCT_TAG } from 'lib/constants'; import { getProduct, getProductRecommendations } from 'lib/shopify'; -import { Image } from 'lib/shopify/types'; +import { Image } from 'lib/types'; export const runtime = 'edge'; diff --git a/components/cart/button.tsx b/components/cart/button.tsx index aed87ee7a..4ef6dd0f9 100644 --- a/components/cart/button.tsx +++ b/components/cart/button.tsx @@ -6,7 +6,7 @@ import { useCookies } from 'react-cookie'; import CartIcon from 'components/icons/cart'; import CartModal from './modal'; -import type { Cart } from 'lib/shopify/types'; +import type { Cart } from 'lib/types'; export default function CartButton({ cart, diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx index 789a87754..fe1011d79 100644 --- a/components/cart/delete-item-button.tsx +++ b/components/cart/delete-item-button.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/navigation'; import { startTransition, useState } from 'react'; import clsx from 'clsx'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/types'; export default function DeleteItemButton({ item }: { item: CartItem }) { const router = useRouter(); diff --git a/components/cart/edit-item-quantity-button.tsx b/components/cart/edit-item-quantity-button.tsx index 2249bd1aa..a20c5c06a 100644 --- a/components/cart/edit-item-quantity-button.tsx +++ b/components/cart/edit-item-quantity-button.tsx @@ -4,7 +4,7 @@ import { startTransition, useState } from 'react'; import clsx from 'clsx'; import MinusIcon from 'components/icons/minus'; import PlusIcon from 'components/icons/plus'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/types'; import LoadingDots from '../loading-dots'; export default function EditItemQuantityButton({ diff --git a/components/cart/modal.tsx b/components/cart/modal.tsx index 4220cfe94..7f507bd60 100644 --- a/components/cart/modal.tsx +++ b/components/cart/modal.tsx @@ -7,7 +7,7 @@ import CloseIcon from 'components/icons/close'; import ShoppingBagIcon from 'components/icons/shopping-bag'; import Price from 'components/price'; import { DEFAULT_OPTION } from 'lib/constants'; -import type { Cart } from 'lib/shopify/types'; +import type { Cart } from 'lib/types'; import { createUrl } from 'lib/utils'; import DeleteItemButton from './delete-item-button'; import EditItemQuantityButton from './edit-item-quantity-button'; diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index 6814a171a..2f337edb2 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -1,6 +1,6 @@ import { GridTileImage } from 'components/grid/tile'; import { getCollectionProducts } from 'lib/shopify'; -import type { Product } from 'lib/shopify/types'; +import type { Product } from 'lib/types'; import Link from 'next/link'; function ThreeItemGridItem({ diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index 72e9e03fc..42b8deb0e 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -4,7 +4,7 @@ import GitHubIcon from 'components/icons/github'; import LogoIcon from 'components/icons/logo'; import VercelIcon from 'components/icons/vercel'; import { getMenu } from 'lib/shopify'; -import { Menu } from 'lib/shopify/types'; +import { Menu } from 'lib/types'; const { SITE_NAME } = process.env; diff --git a/components/layout/navbar/index.tsx b/components/layout/navbar/index.tsx index 537c450a1..8924b7d9e 100644 --- a/components/layout/navbar/index.tsx +++ b/components/layout/navbar/index.tsx @@ -5,7 +5,7 @@ import Cart from 'components/cart'; import CartIcon from 'components/icons/cart'; import LogoIcon from 'components/icons/logo'; import { getMenu } from 'lib/shopify'; -import { Menu } from 'lib/shopify/types'; +import { Menu } from 'lib/types'; import MobileMenu from './mobile-menu'; import Search from './search'; diff --git a/components/layout/navbar/mobile-menu.tsx b/components/layout/navbar/mobile-menu.tsx index c960d5218..bf6be9452 100644 --- a/components/layout/navbar/mobile-menu.tsx +++ b/components/layout/navbar/mobile-menu.tsx @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'; import CloseIcon from 'components/icons/close'; import MenuIcon from 'components/icons/menu'; -import { Menu } from 'lib/shopify/types'; +import { Menu } from 'lib/types'; import Search from './search'; export default function MobileMenu({ menu }: { menu: Menu[] }) { diff --git a/components/layout/product-grid-items.tsx b/components/layout/product-grid-items.tsx index 0c0e907ed..d2ace926d 100644 --- a/components/layout/product-grid-items.tsx +++ b/components/layout/product-grid-items.tsx @@ -1,6 +1,6 @@ import Grid from 'components/grid'; import { GridTileImage } from 'components/grid/tile'; -import { Product } from 'lib/shopify/types'; +import { Product } from 'lib/types'; import Link from 'next/link'; export default function ProductGridItems({ products }: { products: Product[] }) { diff --git a/components/product/add-to-cart.tsx b/components/product/add-to-cart.tsx index 9da11bafa..5339c9c12 100644 --- a/components/product/add-to-cart.tsx +++ b/components/product/add-to-cart.tsx @@ -5,7 +5,7 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { useEffect, useState, useTransition } from 'react'; import LoadingDots from 'components/loading-dots'; -import { ProductVariant } from 'lib/shopify/types'; +import { ProductVariant } from 'lib/types'; export function AddToCart({ variants, diff --git a/components/product/variant-selector.tsx b/components/product/variant-selector.tsx index 520818516..71426836d 100644 --- a/components/product/variant-selector.tsx +++ b/components/product/variant-selector.tsx @@ -1,7 +1,7 @@ 'use client'; import clsx from 'clsx'; -import { ProductOption, ProductVariant } from 'lib/shopify/types'; +import { ProductOption, ProductVariant } from 'lib/types'; import { createUrl } from 'lib/utils'; import Link from 'next/link'; import { usePathname, useRouter, useSearchParams } from 'next/navigation'; diff --git a/lib/saleor/fragments/FeaturedProductFragment.graphql b/lib/saleor/fragments/FeaturedProductFragment.graphql new file mode 100644 index 000000000..8a9c20486 --- /dev/null +++ b/lib/saleor/fragments/FeaturedProductFragment.graphql @@ -0,0 +1,20 @@ +fragment FeaturedProduct on Product { + id + slug + name + pricing { + priceRange { + stop { + gross { + currency + amount + } + } + } + } + media { + url(size: 2160) + type + alt + } +} diff --git a/lib/saleor/fragments/MenuFragment.graphql b/lib/saleor/fragments/MenuFragment.graphql new file mode 100644 index 000000000..cfc40b112 --- /dev/null +++ b/lib/saleor/fragments/MenuFragment.graphql @@ -0,0 +1,21 @@ +fragment Menu on Menu { + id + name + items { + ...MenuItem + } +} +fragment MenuItem on MenuItem { + id + name + url + collection { + slug + } + children { + id + collection { + slug + } + } +} diff --git a/lib/saleor/queries/GetCollections.graphql b/lib/saleor/queries/GetCollections.graphql new file mode 100644 index 000000000..18cf45795 --- /dev/null +++ b/lib/saleor/queries/GetCollections.graphql @@ -0,0 +1,11 @@ +query GetCollections { + collections(channel: "default-channel", first: 100) { + edges { + node { + id + name + slug + } + } + } +} diff --git a/lib/saleor/queries/GetFeaturedProducts.graphql b/lib/saleor/queries/GetFeaturedProducts.graphql new file mode 100644 index 000000000..8054117a4 --- /dev/null +++ b/lib/saleor/queries/GetFeaturedProducts.graphql @@ -0,0 +1,9 @@ +query GetFeaturedProducts($first: Int!) { + products(first: $first, channel: "default-channel") { + edges { + node { + ...FeaturedProduct + } + } + } +} diff --git a/lib/saleor/queries/GetMenu.graphql b/lib/saleor/queries/GetMenu.graphql new file mode 100644 index 000000000..f39a309ba --- /dev/null +++ b/lib/saleor/queries/GetMenu.graphql @@ -0,0 +1,5 @@ +query GetMenu($name: String!) { + menu(name: $name, channel: "default-channel") { + ...Menu + } +} diff --git a/lib/saleor/queries/SearchProducts.graphql b/lib/saleor/queries/SearchProducts.graphql new file mode 100644 index 000000000..ce7d2b7fa --- /dev/null +++ b/lib/saleor/queries/SearchProducts.graphql @@ -0,0 +1,18 @@ +query SearchProducts( + $search: String! + $sortBy: ProductOrderField! + $sortDirection: OrderDirection! +) { + products( + first: 100 + channel: "default-channel" + sortBy: { field: $sortBy, direction: $sortDirection } + filter: { search: $search } + ) { + edges { + node { + ...FeaturedProduct + } + } + } +} diff --git a/lib/saleor/queries/test.graphql b/lib/saleor/queries/test.graphql new file mode 100644 index 000000000..d06ad6502 --- /dev/null +++ b/lib/saleor/queries/test.graphql @@ -0,0 +1,9 @@ +query GetProducts { + products(first: 10, channel: "default-channel") { + edges { + node { + name + } + } + } +} diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 000000000..f2acf60b5 --- /dev/null +++ b/lib/types.ts @@ -0,0 +1,263 @@ +export type Maybe = T | null; + +export type Connection = { + edges: Array>; +}; + +export type Edge = { + node: T; +}; + +export type Cart = Omit & { + lines: CartItem[]; +}; + +export type CartItem = { + id: string; + quantity: number; + cost: { + totalAmount: Money; + }; + merchandise: { + id: string; + title: string; + selectedOptions: { + name: string; + value: string; + }[]; + product: Product; + }; +}; + +export type Collection = VercelCommerceCollection & { + path: string; +}; + +export type Image = { + url: string; + altText: string; + width: number; + height: number; +}; + +export type Menu = { + title: string; + path: string; +}; + +export type Money = { + amount: string; + currencyCode: string; +}; + +export type Page = { + id: string; + title: string; + handle: string; + body: string; + bodySummary: string; + seo?: SEO; + createdAt: string; + updatedAt: string; +}; + +export type Product = Omit & { + variants: ProductVariant[]; + images: Image[]; +}; + +export type ProductOption = { + id: string; + name: string; + values: string[]; +}; + +export type ProductVariant = { + id: string; + title: string; + availableForSale: boolean; + selectedOptions: { + name: string; + value: string; + }[]; + price: Money; +}; + +export type SEO = { + title: string; + description: string; +}; + +export type VercelCommerceCart = { + id: string; + checkoutUrl: string; + cost: { + subtotalAmount: Money; + totalAmount: Money; + totalTaxAmount: Money; + }; + lines: Connection; + totalQuantity: number; +}; + +export type VercelCommerceCollection = { + handle: string; + title: string; + description: string; + seo: SEO; + updatedAt: string; +}; + +export type VercelCommerceProduct = { + id: string; + handle: string; + availableForSale: boolean; + title: string; + description: string; + descriptionHtml: string; + options: ProductOption[]; + priceRange: { + maxVariantPrice: Money; + minVariantPrice: Money; + }; + variants: Connection; + featuredImage: Image; + images: Connection; + seo: SEO; + tags: string[]; + updatedAt: string; +}; + +export type VercelCommerceCartOperation = { + data: { + cart: VercelCommerceCart; + }; + variables: { + cartId: string; + }; +}; + +export type VercelCommerceCreateCartOperation = { + data: { cartCreate: { cart: VercelCommerceCart } }; +}; + +export type VercelCommerceAddToCartOperation = { + data: { + cartLinesAdd: { + cart: VercelCommerceCart; + }; + }; + variables: { + cartId: string; + lines: { + merchandiseId: string; + quantity: number; + }[]; + }; +}; + +export type VercelCommerceRemoveFromCartOperation = { + data: { + cartLinesRemove: { + cart: VercelCommerceCart; + }; + }; + variables: { + cartId: string; + lineIds: string[]; + }; +}; + +export type VercelCommerceUpdateCartOperation = { + data: { + cartLinesUpdate: { + cart: VercelCommerceCart; + }; + }; + variables: { + cartId: string; + lines: { + id: string; + merchandiseId: string; + quantity: number; + }[]; + }; +}; + +export type VercelCommerceCollectionOperation = { + data: { + collection: VercelCommerceCollection; + }; + variables: { + handle: string; + }; +}; + +export type VercelCommerceCollectionProductsOperation = { + data: { + collection: { + products: Connection; + }; + }; + variables: { + handle: string; + }; +}; + +export type VercelCommerceCollectionsOperation = { + data: { + collections: Connection; + }; +}; + +export type VercelCommerceMenuOperation = { + data: { + menu?: { + items: { + title: string; + url: string; + }[]; + }; + }; + variables: { + handle: string; + }; +}; + +export type VercelCommercePageOperation = { + data: { pageByHandle: Page }; + variables: { handle: string }; +}; + +export type VercelCommercePagesOperation = { + data: { + pages: Connection; + }; +}; + +export type VercelCommerceProductOperation = { + data: { product: VercelCommerceProduct }; + variables: { + handle: string; + }; +}; + +export type VercelCommerceProductRecommendationsOperation = { + data: { + productRecommendations: VercelCommerceProduct[]; + }; + variables: { + productId: string; + }; +}; + +export type VercelCommerceProductsOperation = { + data: { + products: Connection; + }; + variables: { + query?: string; + reverse?: boolean; + sortKey?: string; + }; +};