Skip to content

Commit

Permalink
Merge pull request Weaverse#236 from Weaverse/dev
Browse files Browse the repository at this point in the history
Use `metaobject` entries for colors swatches
  • Loading branch information
hta218 authored Dec 14, 2024
2 parents 77bcb59 + 63bcede commit 802f7d5
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ WEAVERSE_PROJECT_ID=clptu3l4p001sxfsn1u9jzqnm
#PUBLIC_GOOGLE_GTM_ID=G-R1KFYYKE48
#JUDGEME_PRIVATE_API_TOKEN="your-judgeme-private-api-token"
#ALI_REVIEWS_API_KEY="your-ali-reviews-api-key"

CUSTOM_COLLECTION_BANNER_METAFIELD="custom.collection_banner"
METAOBJECT_COLORS_TYPE="colors"
METAOBJECT_COLOR_NAME_KEY="label"
METAOBJECT_COLOR_VALUE_KEY="color"
2 changes: 1 addition & 1 deletion app/components/header/cart-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function CartDrawer() {
"group-hover/header:text-[--color-header-bg]",
)}
>
<span className="-mr-0.5">{cart?.totalQuantity}</span>
<span className="-mr-px">{cart?.totalQuantity}</span>
</div>
)}
</Dialog.Trigger>
Expand Down
16 changes: 16 additions & 0 deletions app/data/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ import {
PRODUCT_VARIANT_FRAGMENT,
} from "~/data/fragments";

export let COLORS_CONFIGS_QUERY = `#graphql
query colorsConfigs($type: String!, $nameKey: String!, $valueKey: String!) {
metaobjects(first: 100, type: $type) {
nodes {
id
name: field(key: $nameKey) {
value
}
value: field(key: $valueKey) {
value
}
}
}
}
`;

export let SHOP_QUERY = `#graphql
query shopQuery($country: CountryCode, $language: LanguageCode)
@inContext(country: $country, language: $language) {
Expand Down
16 changes: 12 additions & 4 deletions app/modules/product-form/options.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { useRouteLoaderData } from "@remix-run/react";
import { Image, type VariantOptionValue } from "@shopify/hydrogen";
import { type SwatchesConfigs, useThemeSettings } from "@weaverse/hydrogen";
import {
type ColorSwatch,
type SwatchesConfigs,
useThemeSettings,
} from "@weaverse/hydrogen";
import { cva } from "class-variance-authority";
import clsx from "clsx";
import type { ProductVariantFragmentFragment } from "storefrontapi.generated";
import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/tooltip";
import { cn } from "~/lib/cn";
import type { RootLoader } from "~/root";

export let variants = cva(
"border border-line hover:border-body cursor-pointer",
Expand Down Expand Up @@ -53,9 +59,13 @@ interface VariantOptionProps {

export function VariantOption(props: VariantOptionProps) {
let { name, values, selectedOptionValue, onSelectOptionValue } = props;
let { colorsConfigs } = useRouteLoaderData<RootLoader>("root");
let themeSettings = useThemeSettings();
let productSwatches: SwatchesConfigs = themeSettings.productSwatches;
let { options, swatches } = productSwatches;
let colorsSwatches: ColorSwatch[] = colorsConfigs?.length
? colorsConfigs
: swatches.colors;
let optionConf = options.find((opt) => {
return opt.name.toLowerCase() === name.toLowerCase();
});
Expand Down Expand Up @@ -99,9 +109,7 @@ export function VariantOption(props: VariantOptionProps) {
{type === "color" && (
<div className="flex gap-3">
{values.map(({ value, isAvailable }) => {
let swatchColor = swatches.colors.find(
({ name }) => name === value,
);
let swatchColor = colorsSwatches.find(({ name }) => name === value);
return (
<Tooltip key={value}>
<TooltipTrigger>
Expand Down
45 changes: 40 additions & 5 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,25 @@ import type {
MetaArgs,
} from "@shopify/remix-oxygen";
import { defer } from "@shopify/remix-oxygen";
import { useThemeSettings, withWeaverse } from "@weaverse/hydrogen";
import {
type ColorSwatch,
useThemeSettings,
withWeaverse,
} from "@weaverse/hydrogen";
import type { CSSProperties } from "react";
import type { LayoutQuery } from "storefrontapi.generated";
import type { ColorsConfigsQuery, LayoutQuery } from "storefrontapi.generated";
import invariant from "tiny-invariant";
import { seoPayload } from "~/lib/seo.server";
import { CustomAnalytics } from "~/modules/custom-analytics";
import { GlobalLoading } from "~/modules/global-loading";
import { Layout as PageLayout } from "~/modules/layout";
import { TooltipProvider } from "./components/tooltip";
import { COLORS_CONFIGS_QUERY } from "./data/queries";
import { DEFAULT_LOCALE, parseMenu } from "./lib/utils";
import { GenericError } from "./modules/generic-error";
import { NotFound } from "./modules/not-found";
import styles from "./styles/app.css?url";
import { GlobalStyle } from "./weaverse/style";
import { GenericError } from "./modules/generic-error";
import styles from "./styles/app.css?url";

export type RootLoader = typeof loader;

Expand Down Expand Up @@ -111,8 +116,9 @@ export async function loader(args: LoaderFunctionArgs) {
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
*/
async function loadCriticalData({ request, context }: LoaderFunctionArgs) {
let [layout] = await Promise.all([
let [layout, colorsConfigs] = await Promise.all([
getLayoutData(context),
getColorsConfigs(context),
// Add other queries here, so that they are loaded in parallel
]);

Expand All @@ -138,6 +144,7 @@ async function loadCriticalData({ request, context }: LoaderFunctionArgs) {
selectedLocale: storefront.i18n,
weaverseTheme: await context.weaverse.loadThemeSettings(),
googleGtmID: context.env.PUBLIC_GOOGLE_GTM_ID,
colorsConfigs,
};
}

Expand Down Expand Up @@ -372,3 +379,31 @@ async function getLayoutData({ storefront, env }: AppLoadContext) {

return { shop: data.shop, headerMenu, footerMenu };
}

async function getColorsConfigs(context: AppLoadContext) {
let {
METAOBJECT_COLORS_TYPE: type,
METAOBJECT_COLOR_NAME_KEY: nameKey,
METAOBJECT_COLOR_VALUE_KEY: valueKey,
} = context.env;
if (!type || !nameKey || !valueKey) {
return [];
}
let { metaobjects } = await context.storefront.query<ColorsConfigsQuery>(
COLORS_CONFIGS_QUERY,
{
variables: {
type,
nameKey,
valueKey,
},
},
);
return metaobjects.nodes.map(({ id, name, value }) => {
return {
id,
name: name.value,
value: value.value,
};
}) as ColorSwatch[];
}
20 changes: 17 additions & 3 deletions app/sections/collection-filters/filter-item.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { useLocation, useNavigate, useSearchParams } from "@remix-run/react";
import {
useLocation,
useNavigate,
useRouteLoaderData,
useSearchParams,
} from "@remix-run/react";
import type { Filter } from "@shopify/hydrogen/storefront-api-types";
import { type SwatchesConfigs, useThemeSettings } from "@weaverse/hydrogen";
import {
type ColorSwatch,
type SwatchesConfigs,
useThemeSettings,
} from "@weaverse/hydrogen";
import clsx from "clsx";
import { useState } from "react";
import { Checkbox } from "~/components/checkbox";
Expand All @@ -9,6 +18,7 @@ import { cn } from "~/lib/cn";
import type { AppliedFilter } from "~/lib/filter";
import { getAppliedFilterLink, getFilterLink } from "~/lib/filter";
import { variants as productOptionsVariants } from "~/modules/product-form/options";
import type { RootLoader } from "~/root";

export function FilterItem({
displayAs,
Expand All @@ -25,6 +35,7 @@ export function FilterItem({
let [params] = useSearchParams();
let location = useLocation();
let themeSettings = useThemeSettings();
let { colorsConfigs } = useRouteLoaderData<RootLoader>("root");
let { options, swatches }: SwatchesConfigs = themeSettings.productSwatches;

let filter = appliedFilters.find(
Expand All @@ -45,7 +56,10 @@ export function FilterItem({
}

if (displayAs === "color-swatch") {
let swatchColor = swatches.colors.find(({ name }) => name === option.label);
let colors: ColorSwatch[] = colorsConfigs?.length
? colorsConfigs
: swatches.colors;
let swatchColor = colors.find(({ name }) => name === option.label);
let optionConf = options.find(({ name }) => {
return name.toLowerCase() === option.label.toLowerCase();
});
Expand Down
4 changes: 4 additions & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ declare global {
// declare additional Env parameter use in the fetch handler and Remix loader context here
PUBLIC_GOOGLE_GTM_ID: string;
JUDGEME_PRIVATE_API_TOKEN: string;
CUSTOM_COLLECTION_BANNER_METAFIELD: string;
METAOBJECT_COLORS_TYPE: string;
METAOBJECT_COLOR_NAME_KEY: string;
METAOBJECT_COLOR_VALUE_KEY: string;
}
}

Expand Down
25 changes: 25 additions & 0 deletions storefrontapi.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,27 @@ export type CartApiQueryFragment = Pick<
>;
};

export type ColorsConfigsQueryVariables = StorefrontAPI.Exact<{
type: StorefrontAPI.Scalars['String']['input'];
nameKey: StorefrontAPI.Scalars['String']['input'];
valueKey: StorefrontAPI.Scalars['String']['input'];
}>;

export type ColorsConfigsQuery = {
metaobjects: {
nodes: Array<
Pick<StorefrontAPI.Metaobject, 'id'> & {
name?: StorefrontAPI.Maybe<
Pick<StorefrontAPI.MetaobjectField, 'value'>
>;
value?: StorefrontAPI.Maybe<
Pick<StorefrontAPI.MetaobjectField, 'value'>
>;
}
>;
};
};

export type ShopQueryQueryVariables = StorefrontAPI.Exact<{
country?: StorefrontAPI.InputMaybe<StorefrontAPI.CountryCode>;
language?: StorefrontAPI.InputMaybe<StorefrontAPI.LanguageCode>;
Expand Down Expand Up @@ -1816,6 +1837,10 @@ export type OurTeamQuery = {
};

interface GeneratedQueryTypes {
'#graphql\n query colorsConfigs($type: String!, $nameKey: String!, $valueKey: String!) {\n metaobjects(first: 100, type: $type) {\n nodes {\n id\n name: field(key: $nameKey) {\n value\n }\n value: field(key: $valueKey) {\n value\n }\n }\n }\n }\n': {
return: ColorsConfigsQuery;
variables: ColorsConfigsQueryVariables;
};
'#graphql\n query shopQuery($country: CountryCode, $language: LanguageCode)\n @inContext(country: $country, language: $language) {\n shop {\n name\n description\n }\n }\n': {
return: ShopQueryQuery;
variables: ShopQueryQueryVariables;
Expand Down

0 comments on commit 802f7d5

Please sign in to comment.