From c0432eb30b90f0a2e7b93e827bcdfb62b8b9728c Mon Sep 17 00:00:00 2001 From: hta218 Date: Sat, 14 Dec 2024 08:21:56 +0700 Subject: [PATCH 1/7] Remove unused sort filter component --- app/lib/collections.ts | 2 +- app/modules/sort-filter.tsx | 374 ------------------ ...$locale).collections.$collectionHandle.tsx | 10 +- app/sections/product-list.tsx | 2 +- 4 files changed, 5 insertions(+), 383 deletions(-) delete mode 100644 app/modules/sort-filter.tsx diff --git a/app/lib/collections.ts b/app/lib/collections.ts index 9ce69223..8c04c7ae 100644 --- a/app/lib/collections.ts +++ b/app/lib/collections.ts @@ -1,5 +1,5 @@ import type { ProductCollectionSortKeys } from "@shopify/hydrogen/storefront-api-types"; -import type { SortParam } from "~/modules/sort-filter"; +import type { SortParam } from "./filter"; export let getSortValuesFromParam = ( sortParam: SortParam | null, diff --git a/app/modules/sort-filter.tsx b/app/modules/sort-filter.tsx deleted file mode 100644 index 4820c88c..00000000 --- a/app/modules/sort-filter.tsx +++ /dev/null @@ -1,374 +0,0 @@ -import { - Disclosure, - Menu, - MenuButton, - MenuItem, - MenuItems, -} from "@headlessui/react"; -import type { Location } from "@remix-run/react"; -import { - Link, - useLocation, - useNavigate, - useSearchParams, -} from "@remix-run/react"; -import type { - Filter, - ProductFilter, -} from "@shopify/hydrogen/storefront-api-types"; -import type { SyntheticEvent } from "react"; -import { useMemo, useState } from "react"; -import useDebounce from "react-use/esm/useDebounce"; -import { IconCaret, IconFilters, IconXMark } from "~/modules/icon"; -import { Heading, Text } from "~/modules/text"; - -export type AppliedFilter = { - label: string; - filter: ProductFilter; -}; - -export type SortParam = - | "price-low-high" - | "price-high-low" - | "best-selling" - | "newest" - | "featured"; - -type Props = { - filters: Filter[]; - appliedFilters?: AppliedFilter[]; - children: React.ReactNode; - collections?: Array<{ handle: string; title: string }>; -}; -export const FILTER_URL_PREFIX = "filter."; - -export function SortFilter({ - filters, - appliedFilters = [], - children, - collections = [], -}: Props) { - const [isOpen, setIsOpen] = useState(false); - return ( - <> -
- - -
-
-
- -
-
{children}
-
- - ); -} - -export function FiltersDrawer({ - filters = [], - appliedFilters = [], -}: Omit) { - const [params] = useSearchParams(); - const location = useLocation(); - - const filterMarkup = (filter: Filter, option: Filter["values"][0]) => { - switch (filter.type) { - case "PRICE_RANGE": { - const priceFilter = params.get(`${FILTER_URL_PREFIX}price`); - const price = priceFilter - ? (JSON.parse(priceFilter) as ProductFilter["price"]) - : undefined; - const min = Number.isNaN(Number(price?.min)) - ? undefined - : Number(price?.min); - const max = Number.isNaN(Number(price?.max)) - ? undefined - : Number(price?.max); - - return ; - } - - default: { - const to = getFilterLink(option.input as string, params, location); - return ( - - {option.label} - - ); - } - } - }; - - return ( - <> - - - ); -} - -function AppliedFilters({ filters = [] }: { filters: AppliedFilter[] }) { - const [params] = useSearchParams(); - const location = useLocation(); - return ( - <> - - Applied filters - -
- {filters.map((filter: AppliedFilter) => { - return ( - - {filter.label} - - - - - ); - })} -
- - ); -} - -function getAppliedFilterLink( - filter: AppliedFilter, - params: URLSearchParams, - location: Location, -) { - let paramsClone = new URLSearchParams(params); - for (let [key, value] of Object.entries(filter.filter)) { - let fullKey = FILTER_URL_PREFIX + key; - paramsClone.delete(fullKey, JSON.stringify(value)); - } - return `${location.pathname}?${paramsClone.toString()}`; -} - -function getSortLink( - sort: SortParam, - params: URLSearchParams, - location: Location, -) { - params.set("sort", sort); - return `${location.pathname}?${params.toString()}`; -} - -function getFilterLink( - rawInput: string | ProductFilter, - params: URLSearchParams, - location: ReturnType, -) { - const paramsClone = new URLSearchParams(params); - const newParams = filterInputToParams(rawInput, paramsClone); - return `${location.pathname}?${newParams.toString()}`; -} - -const PRICE_RANGE_FILTER_DEBOUNCE = 500; - -function PriceRangeFilter({ max, min }: { max?: number; min?: number }) { - const location = useLocation(); - const params = useMemo( - () => new URLSearchParams(location.search), - [location.search], - ); - const navigate = useNavigate(); - - const [minPrice, setMinPrice] = useState(min); - const [maxPrice, setMaxPrice] = useState(max); - - useDebounce( - () => { - if (minPrice === undefined && maxPrice === undefined) { - params.delete(`${FILTER_URL_PREFIX}price`); - navigate(`${location.pathname}?${params.toString()}`); - return; - } - - const price = { - ...(minPrice === undefined ? {} : { min: minPrice }), - ...(maxPrice === undefined ? {} : { max: maxPrice }), - }; - const newParams = filterInputToParams({ price }, params); - navigate(`${location.pathname}?${newParams.toString()}`); - }, - PRICE_RANGE_FILTER_DEBOUNCE, - [minPrice, maxPrice], - ); - - const onChangeMax = (event: SyntheticEvent) => { - const value = (event.target as HTMLInputElement).value; - const newMaxPrice = Number.isNaN(Number.parseFloat(value)) - ? undefined - : Number.parseFloat(value); - setMaxPrice(newMaxPrice); - }; - - const onChangeMin = (event: SyntheticEvent) => { - const value = (event.target as HTMLInputElement).value; - const newMinPrice = Number.isNaN(Number.parseFloat(value)) - ? undefined - : Number.parseFloat(value); - setMinPrice(newMinPrice); - }; - - return ( -
- - -
- ); -} - -function filterInputToParams( - rawInput: string | ProductFilter, - params: URLSearchParams, -) { - let input = - typeof rawInput === "string" - ? (JSON.parse(rawInput) as ProductFilter) - : rawInput; - - for (let [key, value] of Object.entries(input)) { - if (params.has(`${FILTER_URL_PREFIX}${key}`, JSON.stringify(value))) { - continue; - } - if (key === "price") { - // For price, we want to overwrite - params.set(`${FILTER_URL_PREFIX}${key}`, JSON.stringify(value)); - } else { - params.append(`${FILTER_URL_PREFIX}${key}`, JSON.stringify(value)); - } - } - - return params; -} - -export default function SortMenu() { - const items: { label: string; key: SortParam }[] = [ - { label: "Featured", key: "featured" }, - { - label: "Price: Low - High", - key: "price-low-high", - }, - { - label: "Price: High - Low", - key: "price-high-low", - }, - { - label: "Best Selling", - key: "best-selling", - }, - { - label: "Newest", - key: "newest", - }, - ]; - const [params] = useSearchParams(); - const location = useLocation(); - const activeItem = items.find((item) => item.key === params.get("sort")); - - return ( - - - - Sort by: - {(activeItem || items[0]).label} - - - - - {items.map((item) => ( - - {() => ( - - {item.label} - - )} - - ))} - - - ); -} diff --git a/app/routes/($locale).collections.$collectionHandle.tsx b/app/routes/($locale).collections.$collectionHandle.tsx index 5557b7ce..7acff115 100644 --- a/app/routes/($locale).collections.$collectionHandle.tsx +++ b/app/routes/($locale).collections.$collectionHandle.tsx @@ -5,10 +5,7 @@ import { getPaginationVariables, getSeoMeta, } from "@shopify/hydrogen"; -import type { - ProductCollectionSortKeys, - ProductFilter, -} from "@shopify/hydrogen/storefront-api-types"; +import type { ProductFilter } from "@shopify/hydrogen/storefront-api-types"; import { type LoaderFunctionArgs, type MetaArgs, @@ -20,11 +17,10 @@ import invariant from "tiny-invariant"; import { routeHeaders } from "~/data/cache"; import { COLLECTION_QUERY } from "~/data/queries"; import { getSortValuesFromParam } from "~/lib/collections"; -import { PAGINATION_SIZE } from "~/lib/const"; +import { FILTER_URL_PREFIX, PAGINATION_SIZE } from "~/lib/const"; +import type { SortParam } from "~/lib/filter"; import { seoPayload } from "~/lib/seo.server"; import { parseAsCurrency } from "~/lib/utils"; -import type { SortParam } from "~/modules/sort-filter"; -import { FILTER_URL_PREFIX } from "~/modules/sort-filter"; import { WeaverseContent } from "~/weaverse"; export let headers = routeHeaders; diff --git a/app/sections/product-list.tsx b/app/sections/product-list.tsx index 195c63ce..f1a18f41 100644 --- a/app/sections/product-list.tsx +++ b/app/sections/product-list.tsx @@ -8,8 +8,8 @@ import { forwardRef } from "react"; import { COLLECTION_QUERY } from "~/data/queries"; import { getSortValuesFromParam } from "~/lib/collections"; import { PAGINATION_SIZE } from "~/lib/const"; +import type { SortParam } from "~/lib/filter"; import { ProductSwimlane } from "~/modules/product-swimlane"; -import type { SortParam } from "~/modules/sort-filter"; interface ProductListProps extends HydrogenComponentProps>> { From 3876e440a9848f4974db6ba9ffe6eeb69a7a2f8f Mon Sep 17 00:00:00 2001 From: hta218 Date: Sat, 14 Dec 2024 08:29:01 +0700 Subject: [PATCH 2/7] Fix logo object fit --- app/components/logo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/logo.tsx b/app/components/logo.tsx index 896960b3..f92a91cc 100644 --- a/app/components/logo.tsx +++ b/app/components/logo.tsx @@ -25,7 +25,7 @@ export function Logo() { sizes="auto" className={clsx( "main-logo", - "max-w-full h-full object-cover mx-auto", + "max-w-full h-full object-contain mx-auto", "transition-opacity duration-300 ease-in group-hover/header:opacity-100", )} style={{ width: "auto" }} @@ -36,7 +36,7 @@ export function Logo() { sizes="auto" className={clsx( "transparent-logo", - "absolute top-0 left-0 max-w-full h-full object-cover mx-auto", + "absolute top-0 left-0 max-w-full h-full object-contain mx-auto", "transition-opacity duration-300 ease-in group-hover/header:opacity-0", )} style={{ width: "auto" }} From bd44c44ae013945604272a2664d67d33c6f87c52 Mon Sep 17 00:00:00 2001 From: hta218 Date: Sat, 14 Dec 2024 08:29:09 +0700 Subject: [PATCH 3/7] Fix sort filter on mobile --- app/sections/collection-filters/sort.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/sections/collection-filters/sort.tsx b/app/sections/collection-filters/sort.tsx index fc24429f..3a0a7ec7 100644 --- a/app/sections/collection-filters/sort.tsx +++ b/app/sections/collection-filters/sort.tsx @@ -40,9 +40,10 @@ export function Sort() { return ( - + Sort by: {currentSort.label} + Sort From 3a479e07829a2866a287151f2780da1878aebdc6 Mon Sep 17 00:00:00 2001 From: hta218 Date: Sat, 14 Dec 2024 09:37:49 +0700 Subject: [PATCH 4/7] Fix cart count button styke --- app/components/header/cart-drawer.tsx | 10 +++++----- tailwind.config.js | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/components/header/cart-drawer.tsx b/app/components/header/cart-drawer.tsx index d4eefa74..21d119e5 100644 --- a/app/components/header/cart-drawer.tsx +++ b/app/components/header/cart-drawer.tsx @@ -48,15 +48,15 @@ export function CartDrawer() {
- {cart?.totalQuantity} + {cart?.totalQuantity}
)} @@ -74,8 +74,8 @@ export function CartDrawer() { >
- - Cart + + Cart