diff --git a/packages/nextjs/components/Button.tsx b/packages/nextjs/components/Button.tsx index f20b0439..ab8eba79 100644 --- a/packages/nextjs/components/Button.tsx +++ b/packages/nextjs/components/Button.tsx @@ -28,12 +28,12 @@ function ButtonComponent( "py-4", "px-8", "text-body-reg", - "font-bold", { "bg-blue text-white hover:text-sky": variant === "primary", - "bg-white text-blue hover:bg-blue hover:text-sky border border-blue": variant === "secondary", + "bg-[transparent] text-blue hover:bg-blue hover:text-sky border border-blue": variant === "secondary", "bg-white text-yellow hover:bg-yellow hover:text-blue": variant === "tertiary", "bg-thunder-cloud text-dark-thunder-cloud hover:text-dark-thunder-cloud": disabled, + "cursor-pointer": as === "a", }, className ); diff --git a/packages/nextjs/components/Card.tsx b/packages/nextjs/components/Card.tsx index 703b51e5..0206d5fc 100644 --- a/packages/nextjs/components/Card.tsx +++ b/packages/nextjs/components/Card.tsx @@ -3,22 +3,34 @@ import Link from "next/link"; import { Image } from "./Image"; -interface Props { - children: React.ReactNode; +export interface CardProps { + title: string; + price?: string | number; + subTitle?: string; to: string; className?: string; imageProps: { src: SanityImageSource; alt: string; + width?: number; + height?: number; }; } -export const Card: React.FC = ({ to, children, imageProps, className = "" }) => { +export const Card: React.FC = ({ to, subTitle, title, price, imageProps, className = "" }) => { return ( - - {imageProps.alt} -

{children}

+
+ {imageProps.alt} +

{title}

+ {price && ${price}} + {subTitle && {subTitle}}
); diff --git a/packages/nextjs/components/CategoryList.tsx b/packages/nextjs/components/CategoryList.tsx index 37220340..4bf4806f 100644 --- a/packages/nextjs/components/CategoryList.tsx +++ b/packages/nextjs/components/CategoryList.tsx @@ -18,9 +18,9 @@ export const CategoryList = ({ items }: CategoryListProps) => { src: category.images?.[0]?.images ?? "", alt: category.images?.[0]?.name ?? "", }} - > - {category.name} - + title={category.name ?? ""} + subTitle={category.description ?? ""} + /> ))} diff --git a/packages/nextjs/components/FeaturedList.tsx b/packages/nextjs/components/FeaturedList.tsx new file mode 100644 index 00000000..acb59158 --- /dev/null +++ b/packages/nextjs/components/FeaturedList.tsx @@ -0,0 +1,57 @@ +import classNames from "classnames"; +import { Card, CardProps } from "components/Card"; +import { GetProductsAndCategoriesQuery } from "utils/generated/graphql"; + +type Props = { + items?: GetProductsAndCategoriesQuery["allProduct"] | GetProductsAndCategoriesQuery["allCategory"]; +}; + +export const FeaturedList = ({ items }: Props) => { + if (!items) return null; + + return ( + + ); +}; diff --git a/packages/nextjs/components/FeaturedQuote.tsx b/packages/nextjs/components/FeaturedQuote.tsx new file mode 100644 index 00000000..685eeae3 --- /dev/null +++ b/packages/nextjs/components/FeaturedQuote.tsx @@ -0,0 +1,7 @@ +export const FeaturedQuote = () => { + return ( +
+

"Game-changing bread service."

+
+ ); +}; diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx index 1546347b..b83d9a09 100644 --- a/packages/nextjs/components/Footer.tsx +++ b/packages/nextjs/components/Footer.tsx @@ -1,3 +1,7 @@ export const Footer = () => { - return
© MMXXII Formidable Labs, LLC.
; + return ( +
+ © MMXXII Formidable Labs, LLC. +
+ ); }; diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index 7b3450ca..9dbefe5c 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -1,6 +1,8 @@ +import classNames from "classnames"; import Link from "next/link"; -import React from "react"; -import { MdShoppingCart } from "react-icons/md"; +import React, { useState } from "react"; +import { FiMenu, FiShoppingCart } from "react-icons/fi"; +import { MdClose } from "react-icons/md"; import { useCart } from "./CartContext"; import { Search } from "./Search"; @@ -17,32 +19,78 @@ const NAV_ITEMS = [ ]; export const Header = () => { + const [navOpen, setNavOpen] = useState(false); const { cartTotal } = useCart(); + const onMobileNavClick = () => setNavOpen((prev) => !prev); + + const onMobileNavClose = () => setNavOpen(false); + return ( -
-
-

+ <> +

- -
-
- - - - {cartTotal} - - -
-
+ + +
+ + + + Cart + + {cartTotal} + + + + {/* Mobile Nav */} +
+ +
+
+ + + ); }; diff --git a/packages/nextjs/components/Input.tsx b/packages/nextjs/components/Input.tsx index a7c4e692..b2c55763 100644 --- a/packages/nextjs/components/Input.tsx +++ b/packages/nextjs/components/Input.tsx @@ -1,21 +1,24 @@ import classNames from "classnames"; -import { InputHTMLAttributes, useId } from "react"; +import { ForwardedRef, forwardRef, InputHTMLAttributes, useId } from "react"; interface Props extends InputHTMLAttributes { - label: string; + label?: string; placeholder: string; disabled?: boolean; } -export const Input: React.FC = ({ label, disabled, ...props }) => { +const InputComponent = ({ label, disabled, ...props }: Props, ref: ForwardedRef) => { const id = useId(); return (
- + {label && ( + + )} = ({ label, disabled, ...props }) => {
); }; + +export const Input = forwardRef(InputComponent); diff --git a/packages/nextjs/components/Layout.tsx b/packages/nextjs/components/Layout.tsx index e50567ee..c106101a 100644 --- a/packages/nextjs/components/Layout.tsx +++ b/packages/nextjs/components/Layout.tsx @@ -1,3 +1,4 @@ +import Head from "next/head"; import React from "react"; import { Footer } from "./Footer"; import { Header } from "./Header"; @@ -8,10 +9,15 @@ interface Props { export const Layout: React.FC = ({ children }) => { return ( -
-
-
{children}
-
-
+ <> + + Formidable Boulangerie + +
+
+
{children}
+
+
+ ); }; diff --git a/packages/nextjs/components/ProductList.tsx b/packages/nextjs/components/ProductList.tsx deleted file mode 100644 index bacf9a83..00000000 --- a/packages/nextjs/components/ProductList.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Card } from "components/Card"; -import { GetProductsAndCategoriesQuery } from "utils/generated/graphql"; - -type Props = { - items?: GetProductsAndCategoriesQuery["allProduct"]; -}; - -export const ProductList = ({ items }: Props) => { - if (!items) return null; - - return ( -
    - {items.map((product) => ( -
  • - - {product.name} - -
  • - ))} -
- ); -}; diff --git a/packages/nextjs/components/Search.tsx b/packages/nextjs/components/Search.tsx index 91f72ef7..21e4145c 100644 --- a/packages/nextjs/components/Search.tsx +++ b/packages/nextjs/components/Search.tsx @@ -6,6 +6,7 @@ import debounce from "lodash.debounce"; import { ProductSearch } from "utils/groqTypes/ProductSearch"; import Link from "next/link"; import { Image } from "./Image"; +import { Input } from "./Input"; const SEARCH_QUERY = groq`*[_type == 'product'] | score( @@ -74,10 +75,9 @@ export const Search: React.FC = () => { }, [closeMenu]); return ( -
+
- { {...getMenuProps({ "aria-labelledby": "search-label", })} - className={`absolute bg-white w-72 mt-2 border rounded z-10 p-5 ${!isOpen ? "hidden" : ""}`} + className={`absolute w-72 bg-yellow mt-2 border rounded z-10 p-5 ${!isOpen ? "hidden" : ""}`} > {isOpen && products.length ? ( products.map((product) => ( diff --git a/packages/nextjs/pages/index.tsx b/packages/nextjs/pages/index.tsx index 0101fd2e..02bc084a 100644 --- a/packages/nextjs/pages/index.tsx +++ b/packages/nextjs/pages/index.tsx @@ -2,31 +2,57 @@ import { GetServerSideProps, NextPage } from "next"; import { withUrqlClient } from "next-urql"; import { GetProductsAndCategoriesDocument, useGetProductsAndCategoriesQuery } from "utils/generated/graphql"; import { initializeUrql, urqlOptions, withUrqlOptions } from "utils/urql"; -import { CategoryList } from "components/CategoryList"; import { setCachingHeaders } from "utils/setCachingHeaders"; -import { ProductList } from "components/ProductList"; -import { ImageCarousel } from "components/ImageCarousel"; import { SanityType } from "utils/consts"; +import { Button } from "components/Button"; +import { FiArrowRight } from "react-icons/fi"; +import { FeaturedList } from "components/FeaturedList"; +import { FeaturedQuote } from "components/FeaturedQuote"; +import { Image } from "components/Image"; +import Link from "next/link"; const Home: NextPage = () => { const [{ data }] = useGetProductsAndCategoriesQuery(); return ( -
-
-
- + <> +
+
+

Formidable breads for your daily life.

+ + +
+ + + {data?.allProductImage[0].name +
-
-

Top Products

- +

Our bestsellers

+ + +
+ + +
-

Top Categories

- -
+ + +

Top categories

+ + ); }; diff --git a/packages/nextjs/public/Logo.svg b/packages/nextjs/public/Logo.svg new file mode 100644 index 00000000..9dbdb5e5 --- /dev/null +++ b/packages/nextjs/public/Logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/nextjs/utils/generated/graphql.ts b/packages/nextjs/utils/generated/graphql.ts index 84f8e1d1..d684c9ef 100644 --- a/packages/nextjs/utils/generated/graphql.ts +++ b/packages/nextjs/utils/generated/graphql.ts @@ -1099,7 +1099,7 @@ export type GetBlogsSlugsQuery = { __typename?: 'RootQuery', allBlog: Array<{ __ export type GetCategoriesQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCategoriesQuery = { __typename?: 'RootQuery', allCategory: Array<{ __typename?: 'Category', _id?: string | null, name?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, images?: Array<{ __typename?: 'CategoryImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null }> }; +export type GetCategoriesQuery = { __typename?: 'RootQuery', allCategory: Array<{ __typename?: 'Category', _id?: string | null, name?: string | null, description?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, images?: Array<{ __typename?: 'CategoryImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null }> }; export type GetCategoriesSlugsQueryVariables = Exact<{ [key: string]: never; }>; @@ -1116,7 +1116,7 @@ export type GetProductQuery = { __typename?: 'RootQuery', allProduct: Array<{ __ export type GetProductsAndCategoriesQueryVariables = Exact<{ [key: string]: never; }>; -export type GetProductsAndCategoriesQuery = { __typename?: 'RootQuery', allCategory: Array<{ __typename?: 'Category', _id?: string | null, name?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, images?: Array<{ __typename?: 'CategoryImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null }>, allProduct: Array<{ __typename?: 'Product', _id?: string | null, name?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, variants?: Array<{ __typename?: 'Variant', images?: Array<{ __typename?: 'ProductImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null } | null> | null }>, allProductImage: Array<{ __typename?: 'ProductImage', _id?: string | null, name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', _id?: string | null, url?: string | null } | null } | null }> }; +export type GetProductsAndCategoriesQuery = { __typename?: 'RootQuery', allCategory: Array<{ __typename?: 'Category', _id?: string | null, name?: string | null, description?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, images?: Array<{ __typename?: 'CategoryImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null }>, allProduct: Array<{ __typename?: 'Product', _id?: string | null, name?: string | null, slug?: { __typename?: 'Slug', current?: string | null } | null, variants?: Array<{ __typename?: 'Variant', price?: number | null, images?: Array<{ __typename?: 'ProductImage', name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', url?: string | null } | null } | null } | null> | null } | null> | null }>, allProductImage: Array<{ __typename?: 'ProductImage', _id?: string | null, name?: string | null, images?: { __typename?: 'Image', asset?: { __typename?: 'SanityImageAsset', _id?: string | null, url?: string | null } | null } | null }> }; export type GetProductsQueryVariables = Exact<{ [key: string]: never; }>; @@ -1163,6 +1163,7 @@ export const GetCategoriesDocument = gql` allCategory { _id name + description slug { current } @@ -1237,6 +1238,7 @@ export const GetProductsAndCategoriesDocument = gql` allCategory(limit: 3, sort: {_updatedAt: ASC}) { _id name + description slug { current } @@ -1256,6 +1258,7 @@ export const GetProductsAndCategoriesDocument = gql` current } variants { + price images { name images { @@ -1266,7 +1269,7 @@ export const GetProductsAndCategoriesDocument = gql` } } } - allProductImage(limit: 5, sort: {_updatedAt: ASC}) { + allProductImage(limit: 1, sort: {_updatedAt: ASC}) { _id name images { diff --git a/packages/nextjs/utils/graphql/getCategories.graphql b/packages/nextjs/utils/graphql/getCategories.graphql index 4906f343..74b3b42f 100644 --- a/packages/nextjs/utils/graphql/getCategories.graphql +++ b/packages/nextjs/utils/graphql/getCategories.graphql @@ -2,6 +2,7 @@ query getCategories { allCategory { _id name + description slug { current } diff --git a/packages/nextjs/utils/graphql/getProductAndCategories.graphql b/packages/nextjs/utils/graphql/getProductAndCategories.graphql index 39eb0b79..d6b39b3d 100644 --- a/packages/nextjs/utils/graphql/getProductAndCategories.graphql +++ b/packages/nextjs/utils/graphql/getProductAndCategories.graphql @@ -2,6 +2,7 @@ query getProductsAndCategories { allCategory(limit: 3, sort: { _updatedAt: ASC }) { _id name + description slug { current } @@ -21,6 +22,7 @@ query getProductsAndCategories { current } variants { + price images { name images { @@ -31,7 +33,7 @@ query getProductsAndCategories { } } } - allProductImage(limit: 5, sort: { _updatedAt: ASC }) { + allProductImage(limit: 1, sort: { _updatedAt: ASC }) { _id name images {