feat: implement text/image-with-text/icon-with-text content block

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe
2024-05-23 14:17:55 +07:00
parent 4684d54ac3
commit a1d65a54c1
15 changed files with 431 additions and 24 deletions

View File

@@ -29,6 +29,7 @@ import {
} from './queries/collection';
import { getMenuQuery } from './queries/menu';
import { getMetaobjectsQuery } from './queries/metaobject';
import { getImageQuery, getMetaobjectsByIdsQuery } from './queries/node';
import { getPageQuery, getPagesQuery } from './queries/page';
import {
getProductQuery,
@@ -44,8 +45,10 @@ import {
Menu,
Metaobject,
Money,
PAGE_TYPES,
Page,
PageInfo,
PageMetafield,
Product,
ProductVariant,
ShopifyAddToCartOperation,
@@ -57,8 +60,10 @@ import {
ShopifyCollectionsOperation,
ShopifyCreateCartOperation,
ShopifyFilter,
ShopifyImageOperation,
ShopifyMenuOperation,
ShopifyMetaobject,
ShopifyMetaobjectOperation,
ShopifyMetaobjectsOperation,
ShopifyPageOperation,
ShopifyPagesOperation,
@@ -490,10 +495,36 @@ export async function getMetaobjects(type: string) {
return reshapeMetaobjects(removeEdgesAndNodes(res.body.data.metaobjects));
}
export async function getMetaobjectsByIds(ids: string[]) {
if (!ids.length) return [];
const res = await shopifyFetch<ShopifyMetaobjectOperation>({
query: getMetaobjectsByIdsQuery,
variables: { ids }
});
return reshapeMetaobjects(res.body.data.nodes);
}
export async function getPageMetaObjects(metafield: PageMetafield) {
let metaobjectIds = parseMetaFieldValue<string | string[]>(metafield) || metafield.value;
if (!metaobjectIds) {
return null;
}
metaobjectIds = (Array.isArray(metaobjectIds) ? metaobjectIds : [metaobjectIds]) as string[];
const metaobjects = await getMetaobjectsByIds(metaobjectIds);
return { metaobjects, id: metafield.id, key: metafield.key };
}
export async function getPage(handle: string): Promise<Page> {
const metafieldIdentifiers = PAGE_TYPES.map((key) => ({ key, namespace: 'custom' }));
const res = await shopifyFetch<ShopifyPageOperation>({
query: getPageQuery,
variables: { handle }
variables: { handle, metafieldIdentifiers }
});
return res.body.data.pageByHandle;
@@ -604,3 +635,12 @@ export async function revalidate(req: NextRequest): Promise<NextResponse> {
return NextResponse.json({ status: 200, revalidated: true, now: Date.now() });
}
export const getImage = async (id: string): Promise<Image> => {
const res = await shopifyFetch<ShopifyImageOperation>({
query: getImageQuery,
variables: { id }
});
return res.body.data.node.image;
};

View File

@@ -0,0 +1,33 @@
export const getImageQuery = /* GraphQL */ `
query getImage($id: ID!) {
node(id: $id) {
... on MediaImage {
image {
altText
width
height
url
}
}
}
}
`;
export const getMetaobjectsByIdsQuery = /* GraphQL */ `
query getMetaobjectsByIds($ids: [ID!]!) {
nodes(ids: $ids) {
... on Metaobject {
id
fields {
reference {
... on Metaobject {
id
}
}
key
value
}
}
}
}
`;

View File

@@ -19,9 +19,14 @@ const pageFragment = /* GraphQL */ `
`;
export const getPageQuery = /* GraphQL */ `
query getPage($handle: String!) {
query getPage($handle: String!, $metafieldIdentifiers: [HasMetafieldsIdentifier!]!) {
pageByHandle(handle: $handle) {
...page
metafields(identifiers: $metafieldIdentifiers) {
value
key
id
}
}
}
${pageFragment}

View File

@@ -51,6 +51,15 @@ export type Money = {
currencyCode: string;
};
export type PageMetafield = {
id: string;
key: PageMetafieldKey;
value: string;
};
export const PAGE_TYPES = ['page_icon_section', 'page_section', 'page_image_content'] as const;
export type PageMetafieldKey = (typeof PAGE_TYPES)[number];
export type Page = {
id: string;
title: string;
@@ -60,6 +69,12 @@ export type Page = {
seo?: SEO;
createdAt: string;
updatedAt: string;
metafields: PageMetafield[];
};
export type MetafieldIdentifier = {
key: string;
namespace: string;
};
export type ShopifyMetaobject = {
@@ -282,7 +297,12 @@ export type ShopifyMenuOperation = {
export type ShopifyPageOperation = {
data: { pageByHandle: Page };
variables: { handle: string };
variables: { handle: string; metafieldIdentifiers: MetafieldIdentifier[] };
};
export type ShopifyImageOperation = {
data: { node: { image: Image } };
variables: { id: string };
};
export type ShopifyMetaobjectsOperation = {
@@ -296,6 +316,11 @@ export type ShopifyPagesOperation = {
};
};
export type ShopifyMetaobjectOperation = {
data: { nodes: ShopifyMetaobject[] };
variables: { ids: string[] };
};
export type ShopifyProductOperation = {
data: { product: ShopifyProduct };
variables: {
@@ -363,3 +388,13 @@ export type Filter = {
value: unknown;
}[];
};
export type PageContent = {
id: string;
key: PageMetafieldKey;
metaobjects: Metaobject[];
};
export const SCREEN_SIZES = ['small', 'medium', 'large', 'extra_large'] as const;
export type ScreenSize = (typeof SCREEN_SIZES)[number];