Theming @compoents folder components in purpose of future merging with updates, prepared to deploy on heroku

This commit is contained in:
Bayram Muhiyev 2021-07-22 13:51:53 +05:00
parent 33661cb30a
commit 7f02987f34
12 changed files with 395 additions and 23 deletions

View File

@ -5,6 +5,6 @@
"search": true, "search": true,
"wishlist": false, "wishlist": false,
"customerAuth": false, "customerAuth": false,
"customCheckout": false "customCheckout": true
} }
} }

View File

@ -15,6 +15,13 @@ export const getCollectionsQuery = /* GraphQL */ `
children { children {
id id
} }
assets {
id
name
source
width
height
}
} }
} }
} }

View File

@ -4,7 +4,7 @@
"scripts": { "scripts": {
"dev": "NODE_OPTIONS='--inspect' next dev -p 8000", "dev": "NODE_OPTIONS='--inspect' next dev -p 8000",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start -p $PORT",
"analyze": "BUNDLE_ANALYZE=both yarn build", "analyze": "BUNDLE_ANALYZE=both yarn build",
"prettier-fix": "prettier --write .", "prettier-fix": "prettier --write .",
"find:unused": "npx next-unused", "find:unused": "npx next-unused",

View File

@ -4,6 +4,8 @@ import { ProductCard } from '@components/product'
import { Grid, Marquee, Hero } from '@components/ui' import { Grid, Marquee, Hero } from '@components/ui'
// import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid' // import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid'
import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next' import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
import Image from 'next/image'
import Link from 'next/link'
export async function getStaticProps({ export async function getStaticProps({
preview, preview,
@ -36,23 +38,29 @@ export async function getStaticProps({
} }
export default function Home({ export default function Home({
products, products, categories
}: InferGetStaticPropsType<typeof getStaticProps>) { }: InferGetStaticPropsType<typeof getStaticProps>) {
return ( return (
<> <>
<Grid variant="filled"> <div style={{
{products.slice(0, 3).map((product: any, i: number) => ( display: 'flex',
<ProductCard justifyContent: 'center'
key={product.id} }}>
product={product} {categories.slice(0, 3).map((category: any, i: number) => (
imgProps={{ <Link href={`/search/${category.slug}`}>
width: i === 0 ? 1080 : 540, <a>
height: i === 0 ? 1080 : 540, <Image
}} quality="100"
/> src={category.assets[0].source}
))} height={category.assets[0].height}
</Grid> width={category.assets[0].width}
<Marquee variant="secondary"> layout="fixed"
/>
</a>
</Link>
))}
</div>
<Marquee variant="primary">
{products.slice(0, 3).map((product: any, i: number) => ( {products.slice(0, 3).map((product: any, i: number) => (
<ProductCard key={product.id} product={product} variant="slim" /> <ProductCard key={product.id} product={product} variant="slim" />
))} ))}
@ -61,7 +69,7 @@ export default function Home({
headline=" Dessert dragée halvah croissant." headline=" Dessert dragée halvah croissant."
description="Cupcake ipsum dolor sit amet lemon drops pastry cotton candy. Sweet carrot cake macaroon bonbon croissant fruitcake jujubes macaroon oat cake. Soufflé bonbon caramels jelly beans. Tiramisu sweet roll cheesecake pie carrot cake. " description="Cupcake ipsum dolor sit amet lemon drops pastry cotton candy. Sweet carrot cake macaroon bonbon croissant fruitcake jujubes macaroon oat cake. Soufflé bonbon caramels jelly beans. Tiramisu sweet roll cheesecake pie carrot cake. "
/> />
<Grid layout="B" variant="filled"> {/* <Grid layout="B" variant="filled">
{products.slice(0, 3).map((product: any, i: number) => ( {products.slice(0, 3).map((product: any, i: number) => (
<ProductCard <ProductCard
key={product.id} key={product.id}
@ -77,7 +85,7 @@ export default function Home({
{products.slice(3).map((product: any, i: number) => ( {products.slice(3).map((product: any, i: number) => (
<ProductCard key={product.id} product={product} variant="slim" /> <ProductCard key={product.id} product={product} variant="slim" />
))} ))}
</Marquee> </Marquee> */}
{/* <HomeAllProductsGrid {/* <HomeAllProductsGrid
newestProducts={products} newestProducts={products}
categories={categories} categories={categories}

View File

@ -1,6 +1,6 @@
import { getSearchStaticProps } from '@lib/search-props' import { getSearchStaticProps } from '@lib/search-props'
import type { GetStaticPropsContext } from 'next' import type { GetStaticPropsContext } from 'next'
import Search from '@components/search' import Search from '@theme/search'
export async function getStaticProps(context: GetStaticPropsContext) { export async function getStaticProps(context: GetStaticPropsContext) {
return getSearchStaticProps(context) return getSearchStaticProps(context)

View File

@ -1,6 +1,6 @@
import { getSearchStaticProps } from '@lib/search-props' import { getSearchStaticProps } from '@lib/search-props'
import type { GetStaticPathsResult, GetStaticPropsContext } from 'next' import type { GetStaticPathsResult, GetStaticPropsContext } from 'next'
import Search from '@components/search' import Search from '@theme/search'
export async function getStaticProps(context: GetStaticPropsContext) { export async function getStaticProps(context: GetStaticPropsContext) {
return getSearchStaticProps(context) return getSearchStaticProps(context)

View File

@ -1,6 +1,6 @@
import { getSearchStaticProps } from '@lib/search-props' import { getSearchStaticProps } from '@lib/search-props'
import type { GetStaticPathsResult, GetStaticPropsContext } from 'next' import type { GetStaticPathsResult, GetStaticPropsContext } from 'next'
import Search from '@components/search' import Search from '@theme/search'
export async function getStaticProps(context: GetStaticPropsContext) { export async function getStaticProps(context: GetStaticPropsContext) {
return getSearchStaticProps(context) return getSearchStaticProps(context)

View File

@ -1,6 +1,6 @@
import { getSearchStaticProps } from '@lib/search-props' import { getSearchStaticProps } from '@lib/search-props'
import type { GetStaticPathsResult, GetStaticPropsContext } from 'next' import type { GetStaticPathsResult, GetStaticPropsContext } from 'next'
import Search from '@components/search' import Search from '@theme/search'
export async function getStaticProps(context: GetStaticPropsContext) { export async function getStaticProps(context: GetStaticPropsContext) {
return getSearchStaticProps(context) return getSearchStaticProps(context)

View File

@ -6,6 +6,7 @@ module.exports = {
purge: { purge: {
content: [ content: [
'./pages/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}',
'./theme/dap/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}',
], ],
options: { options: {

336
theme/dap/search.tsx Normal file
View File

@ -0,0 +1,336 @@
import cn from 'classnames'
import type { SearchPropsType } from '@lib/search-props'
import Link from 'next/link'
import { useState } from 'react'
import { useRouter } from 'next/router'
import { Layout } from '@components/common'
import { ProductCard } from '@components/product'
import type { Product } from '@commerce/types/product'
import { Container, Grid, Skeleton } from '@components/ui'
import useSearch from '@framework/product/use-search'
import getSlug from '@lib/get-slug'
import rangeMap from '@lib/range-map'
const SORT = Object.entries({
'trending-desc': 'Trending',
'latest-desc': 'Latest arrivals',
'price-asc': 'Price: Low to high',
'price-desc': 'Price: High to low',
})
import {
filterQuery,
getCategoryPath,
useSearchMeta,
} from '@lib/search'
export default function Search({ categories, brands }: SearchPropsType) {
const [activeFilter, setActiveFilter] = useState('')
const [toggleFilter, setToggleFilter] = useState(false)
const router = useRouter()
const { asPath, locale } = router
const { q, sort } = router.query
// `q` can be included but because categories and designers can't be searched
// in the same way of products, it's better to ignore the search input if one
// of those is selected
const query = filterQuery({ sort })
const { pathname, category, brand } = useSearchMeta(asPath)
const activeCategory = categories.find((cat: any) => cat.slug === category)
const activeBrand = brands.find(
(b: any) => getSlug(b.node.path) === `brands/${brand}`
)?.node
const { data } = useSearch({
search: typeof q === 'string' ? q : '',
categoryId: activeCategory?.id,
brandId: (activeBrand as any)?.entityId,
sort: typeof sort === 'string' ? sort : '',
locale,
})
const handleClick = (event: any, filter: string) => {
if (filter !== activeFilter) {
setToggleFilter(true)
} else {
setToggleFilter(!toggleFilter)
}
setActiveFilter(filter)
}
return (
<Container>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-4 mt-3 mb-20">
<div className="col-span-8 lg:col-span-2 order-1 lg:order-none">
{/* Categories */}
<div className="relative inline-block w-full">
<div className="lg:hidden">
<span className="rounded-md shadow-sm">
<button
type="button"
onClick={(e) => handleClick(e, 'categories')}
className="flex justify-between w-full rounded-sm border border-accent-3 px-4 py-3 bg-accent-0 text-sm leading-5 font-medium text-accent-4 hover:text-accent-5 focus:outline-none focus:border-blue-300 focus:shadow-outline-normal active:bg-accent-1 active:text-accent-8 transition ease-in-out duration-150"
id="options-menu"
aria-haspopup="true"
aria-expanded="true"
>
{activeCategory?.name
? `Category: ${activeCategory?.name}`
: 'All Categories'}
<svg
className="-mr-1 ml-2 h-5 w-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</span>
</div>
<div
className={`origin-top-left absolute lg:relative left-0 mt-2 w-full rounded-md shadow-lg lg:shadow-none z-10 mb-10 lg:block ${
activeFilter !== 'categories' || toggleFilter !== true
? 'hidden'
: ''
}`}
>
<div className="rounded-sm bg-accent-0 shadow-xs lg:bg-none lg:shadow-none">
<div
role="menu"
aria-orientation="vertical"
aria-labelledby="options-menu"
>
<ul>
<li
className={cn(
'block text-sm leading-5 text-accent-4 lg:text-base lg:no-underline lg:font-bold lg:tracking-wide hover:bg-accent-1 lg:hover:bg-transparent hover:text-accent-8 focus:outline-none focus:bg-accent-1 focus:text-accent-8',
{
underline: !activeCategory?.name,
}
)}
>
<Link
href={{ pathname: getCategoryPath('', brand), query }}
>
<a
onClick={(e) => handleClick(e, 'categories')}
className={
'block lg:inline-block px-4 py-2 lg:p-0 lg:my-2 lg:mx-4'
}
>
All Categories
</a>
</Link>
</li>
{categories.map((cat: any) => (
<li
key={cat.path}
className={cn(
'block text-sm leading-5 text-accent-4 hover:bg-accent-1 lg:hover:bg-transparent hover:text-accent-8 focus:outline-none focus:bg-accent-1 focus:text-accent-8',
{
underline: activeCategory?.id === cat.id,
}
)}
>
<Link
href={{
pathname: getCategoryPath(cat.path, brand),
query,
}}
>
<a
onClick={(e) => handleClick(e, 'categories')}
className={
'block lg:inline-block px-4 py-2 lg:p-0 lg:my-2 lg:mx-4'
}
>
{cat.name}
</a>
</Link>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
{/* Products */}
<div className="col-span-8 order-3 lg:order-none">
{(q || activeCategory || activeBrand) && (
<div className="mb-12 transition ease-in duration-75">
{data ? (
<>
<span
className={cn('animated', {
fadeIn: data.found,
hidden: !data.found,
})}
>
Showing {data.products.length} results{' '}
{q && (
<>
for "<strong>{q}</strong>"
</>
)}
</span>
<span
className={cn('animated', {
fadeIn: !data.found,
hidden: data.found,
})}
>
{q ? (
<>
There are no products that match "<strong>{q}</strong>"
</>
) : (
<>
There are no products that match the selected category.
</>
)}
</span>
</>
) : q ? (
<>
Searching for: "<strong>{q}</strong>"
</>
) : (
<>Searching...</>
)}
</div>
)}
{data ? (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{data.products.map((product: Product) => (
<ProductCard
variant="simple"
key={product.path}
className="animated fadeIn"
product={product}
imgProps={{
width: 480,
height: 480,
}}
/>
))}
</div>
) : (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{rangeMap(12, (i) => (
<Skeleton key={i}>
<div className="w-60 h-60" />
</Skeleton>
))}
</div>
)}{' '}
</div>
{/* Sort */}
<div className="col-span-8 lg:col-span-2 order-2 lg:order-none">
<div className="relative inline-block w-full">
<div className="lg:hidden">
<span className="rounded-md shadow-sm">
<button
type="button"
onClick={(e) => handleClick(e, 'sort')}
className="flex justify-between w-full rounded-sm border border-accent-3 px-4 py-3 bg-accent-0 text-sm leading-5 font-medium text-accent-4 hover:text-accent-5 focus:outline-none focus:border-blue-300 focus:shadow-outline-normal active:bg-accent-1 active:text-accent-8 transition ease-in-out duration-150"
id="options-menu"
aria-haspopup="true"
aria-expanded="true"
>
{sort ? `Sort: ${sort}` : 'Relevance'}
<svg
className="-mr-1 ml-2 h-5 w-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</span>
</div>
<div
className={`origin-top-left absolute lg:relative left-0 mt-2 w-full rounded-md shadow-lg lg:shadow-none z-10 mb-10 lg:block ${
activeFilter !== 'sort' || toggleFilter !== true ? 'hidden' : ''
}`}
>
<div className="rounded-sm bg-accent-0 shadow-xs lg:bg-none lg:shadow-none">
<div
role="menu"
aria-orientation="vertical"
aria-labelledby="options-menu"
>
<ul>
<li
className={cn(
'block text-sm leading-5 text-accent-4 lg:text-base lg:no-underline lg:font-bold lg:tracking-wide hover:bg-accent-1 lg:hover:bg-transparent hover:text-accent-8 focus:outline-none focus:bg-accent-1 focus:text-accent-8',
{
underline: !sort,
}
)}
>
<Link href={{ pathname, query: filterQuery({ q }) }}>
<a
onClick={(e) => handleClick(e, 'sort')}
className={
'block lg:inline-block px-4 py-2 lg:p-0 lg:my-2 lg:mx-4'
}
>
Relevance
</a>
</Link>
</li>
{SORT.map(([key, text]) => (
<li
key={key}
className={cn(
'block text-sm leading-5 text-accent-4 hover:bg-accent-1 lg:hover:bg-transparent hover:text-accent-8 focus:outline-none focus:bg-accent-1 focus:text-accent-8',
{
underline: sort === key,
}
)}
>
<Link
href={{
pathname,
query: filterQuery({ q, sort: key }),
}}
>
<a
onClick={(e) => handleClick(e, 'sort')}
className={
'block lg:inline-block px-4 py-2 lg:p-0 lg:my-2 lg:mx-4'
}
>
{text}
</a>
</Link>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</Container>
)
}
Search.Layout = Layout

View File

@ -24,7 +24,9 @@
"@commerce": ["framework/commerce"], "@commerce": ["framework/commerce"],
"@commerce/*": ["framework/commerce/*"], "@commerce/*": ["framework/commerce/*"],
"@framework": ["framework/vendure"], "@framework": ["framework/vendure"],
"@framework/*": ["framework/vendure/*"] "@framework/*": ["framework/vendure/*"],
"@theme": ["theme/dap"],
"@theme/*": ["theme/dap/*"]
} }
}, },
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"], "include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],

View File

@ -1140,6 +1140,11 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==
"@types/uuid@8.3.1":
version "8.3.1"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==
"@types/websocket@1.0.2": "@types/websocket@1.0.2":
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.2.tgz#d2855c6a312b7da73ed16ba6781815bf30c6187a" resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.2.tgz#d2855c6a312b7da73ed16ba6781815bf30c6187a"
@ -6044,6 +6049,19 @@ util@^0.12.0:
safe-buffer "^5.1.2" safe-buffer "^5.1.2"
which-typed-array "^1.1.2" which-typed-array "^1.1.2"
uuid@8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
uuidv4@^6.2.10:
version "6.2.11"
resolved "https://registry.yarnpkg.com/uuidv4/-/uuidv4-6.2.11.tgz#34d5a03324eb38296b87ae523a64233b5286cc27"
integrity sha512-OTS4waH9KplrXNADKo+Q1kT9AHWr8DaC0S5F54RQzEwcUaEzBEWQQlJyDUw/u1bkRhJyqkqhLD4M4lbFbV+89g==
dependencies:
"@types/uuid" "8.3.1"
uuid "8.3.2"
valid-url@1.0.9, valid-url@^1.0.9: valid-url@1.0.9, valid-url@^1.0.9:
version "1.0.9" version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"