mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 23:46:58 +00:00
Add : discount api fetching
This commit is contained in:
parent
11b8711fca
commit
de958dcdf3
@ -4,7 +4,7 @@ import { GridTileImage } from './grid/tile';
|
|||||||
|
|
||||||
export async function Carousel() {
|
export async function Carousel() {
|
||||||
// Collections that start with `hidden-*` are hidden from the search page.
|
// Collections that start with `hidden-*` are hidden from the search page.
|
||||||
const products = await getCollectionProducts({ collection: 'boxes' });
|
const products = await getCollectionProducts({ collection: 'all' });
|
||||||
|
|
||||||
if (!products?.length) return null;
|
if (!products?.length) return null;
|
||||||
|
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { TAGS } from 'lib/constants';
|
import { TAGS } from 'lib/constants';
|
||||||
import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
|
import {
|
||||||
|
addToCart,
|
||||||
|
createCart,
|
||||||
|
getCart,
|
||||||
|
getDiscountMetaobjects,
|
||||||
|
removeFromCart,
|
||||||
|
updateCart
|
||||||
|
} from 'lib/shopify';
|
||||||
|
import { formatDiscounts } from 'lib/utils';
|
||||||
import { revalidateTag } from 'next/cache';
|
import { revalidateTag } from 'next/cache';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
@ -83,22 +91,13 @@ export async function updateItemQuantity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function calculateDiscounts(cart: any) {
|
export async function calculateDiscounts(cart: any) {
|
||||||
const discountGroups = [
|
const metaobjects = await getDiscountMetaobjects('dynamic_discount');
|
||||||
{
|
|
||||||
name: 'Tier 2',
|
const discountGroups = formatDiscounts(metaobjects);
|
||||||
discount: {
|
|
||||||
amount: 0.1,
|
if (discountGroups === undefined) {
|
||||||
minimumSpent: 150
|
return;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Tier 1',
|
|
||||||
discount: {
|
|
||||||
amount: 0.05,
|
|
||||||
minimumSpent: 120
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const subTotal = cart?.cost.subtotalAmount.amount;
|
const subTotal = cart?.cost.subtotalAmount.amount;
|
||||||
const currencyCode = cart?.cost.subtotalAmount.currencyCode;
|
const currencyCode = cart?.cost.subtotalAmount.currencyCode;
|
||||||
@ -122,12 +121,15 @@ export async function calculateDiscounts(cart: any) {
|
|||||||
: 0;
|
: 0;
|
||||||
const nextDiscount = closestNextTier?.discount.amount;
|
const nextDiscount = closestNextTier?.discount.amount;
|
||||||
const discountAmount = finalDiscount ? finalDiscount * 100 : 0;
|
const discountAmount = finalDiscount ? finalDiscount * 100 : 0;
|
||||||
|
// get discount code from the final discount group
|
||||||
|
const discountCode = eligibleDiscount.length ? eligibleDiscount[0]?.code : '';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
discountAmount,
|
discountAmount,
|
||||||
spentToNextDiscount,
|
spentToNextDiscount,
|
||||||
nextDiscount,
|
nextDiscount,
|
||||||
discountGroups: discountGroupsSorted,
|
discountGroups: discountGroupsSorted,
|
||||||
|
discountCode,
|
||||||
minSpent,
|
minSpent,
|
||||||
subTotal,
|
subTotal,
|
||||||
currencyCode
|
currencyCode
|
||||||
|
@ -182,7 +182,7 @@ export default function CartModal({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
href={cart.checkoutUrl}
|
href={`${cart.checkoutUrl}&discount=${tieredDiscount?.discountCode || ''}`}
|
||||||
className="block w-full rounded-full bg-blue-600 p-3 text-center text-sm font-medium text-white opacity-90 hover:opacity-100"
|
className="block w-full rounded-full bg-blue-600 p-3 text-center text-sm font-medium text-white opacity-90 hover:opacity-100"
|
||||||
>
|
>
|
||||||
Proceed to Checkout
|
Proceed to Checkout
|
||||||
|
@ -40,7 +40,7 @@ function ThreeItemGridItem({
|
|||||||
export async function ThreeItemGrid() {
|
export async function ThreeItemGrid() {
|
||||||
// Collections that start with `hidden-*` are hidden from the search page.
|
// Collections that start with `hidden-*` are hidden from the search page.
|
||||||
const homepageItems = await getCollectionProducts({
|
const homepageItems = await getCollectionProducts({
|
||||||
collection: 'sale'
|
collection: 'all'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null;
|
if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import FooterMenu from 'components/layout/footer-menu';
|
|
||||||
import LogoSquare from 'components/logo-square';
|
import LogoSquare from 'components/logo-square';
|
||||||
import { getMenu } from 'lib/shopify';
|
import { getMenu } from 'lib/shopify';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
|
import FooterMenu from './footer-menu';
|
||||||
|
|
||||||
const { COMPANY_NAME, SITE_NAME } = process.env;
|
const { COMPANY_NAME, SITE_NAME } = process.env;
|
||||||
|
|
||||||
@ -16,9 +16,9 @@ export default async function Footer() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="text-sm text-neutral-500 dark:text-neutral-400">
|
<footer className="text-sm text-neutral-500 dark:text-neutral-400">
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6 border-t border-neutral-200 px-6 py-12 text-sm dark:border-neutral-700 md:flex-row md:gap-12 md:px-4 min-[1320px]:px-0">
|
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6 border-t border-neutral-200 px-6 py-12 text-sm md:flex-row md:gap-12 md:px-4 min-[1320px]:px-0 dark:border-neutral-700">
|
||||||
<div>
|
<div>
|
||||||
<Link className="flex items-center gap-2 text-black dark:text-white md:pt-1" href="/">
|
<Link className="flex items-center gap-2 text-black md:pt-1 dark:text-white" href="/">
|
||||||
<LogoSquare size="sm" />
|
<LogoSquare size="sm" />
|
||||||
<span className="uppercase">{SITE_NAME}</span>
|
<span className="uppercase">{SITE_NAME}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -10,7 +10,7 @@ import Search from './search';
|
|||||||
const { SITE_NAME } = process.env;
|
const { SITE_NAME } = process.env;
|
||||||
|
|
||||||
export default async function Navbar() {
|
export default async function Navbar() {
|
||||||
const menu = await getMenu('next-js-frontend-header-menu');
|
const menu = await getMenu('main-menu');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="relative flex items-center justify-between p-4 lg:px-6">
|
<nav className="relative flex items-center justify-between p-4 lg:px-6">
|
||||||
|
@ -451,11 +451,13 @@ export async function revalidate(req: NextRequest): Promise<NextResponse> {
|
|||||||
return NextResponse.json({ status: 200, revalidated: true, now: Date.now() });
|
return NextResponse.json({ status: 200, revalidated: true, now: Date.now() });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getDiscountMetaobjects() {
|
export async function getDiscountMetaobjects(type: string) {
|
||||||
const res = await shopifyFetch<ShopifyDiscountMetaobjectsOperation>({
|
const res = await shopifyFetch<ShopifyDiscountMetaobjectsOperation>({
|
||||||
query: getDiscountMetaobjectsQuery,
|
query: getDiscountMetaobjectsQuery,
|
||||||
cache: 'no-store'
|
cache: 'no-store',
|
||||||
|
tags: ['metaobjects'],
|
||||||
|
variables: { type }
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.body.data.metaobjects;
|
return removeEdgesAndNodes(res.body.data.metaobjects);
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ import discountMetaobject from '../fragments/discount-metaobject';
|
|||||||
export const getDiscountMetaobjectsQuery = /* GraphQL */ `
|
export const getDiscountMetaobjectsQuery = /* GraphQL */ `
|
||||||
query getDiscountMetaobjects {
|
query getDiscountMetaobjects {
|
||||||
metaobjects(type: "dynamic_discount", first: 10) {
|
metaobjects(type: "dynamic_discount", first: 10) {
|
||||||
nodes {
|
edges {
|
||||||
...metaobject
|
node {
|
||||||
|
...metaobject
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ export type Page = {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Field = {
|
export type Field = {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
@ -282,8 +282,6 @@ export type ShopifyDiscountMetaobjectsOperation = {
|
|||||||
metaobjects: Connection<DiscountMetaobject>;
|
metaobjects: Connection<DiscountMetaobject>;
|
||||||
};
|
};
|
||||||
variables: {
|
variables: {
|
||||||
query?: string;
|
type: string;
|
||||||
reverse?: boolean;
|
|
||||||
sortKey?: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
23
lib/utils.ts
23
lib/utils.ts
@ -1,4 +1,5 @@
|
|||||||
import { ReadonlyURLSearchParams } from 'next/navigation';
|
import { ReadonlyURLSearchParams } from 'next/navigation';
|
||||||
|
import { DiscountMetaobject, Field } from './shopify/types';
|
||||||
|
|
||||||
export const createUrl = (pathname: string, params: URLSearchParams | ReadonlyURLSearchParams) => {
|
export const createUrl = (pathname: string, params: URLSearchParams | ReadonlyURLSearchParams) => {
|
||||||
const paramsString = params.toString();
|
const paramsString = params.toString();
|
||||||
@ -37,3 +38,25 @@ export const validateEnvironmentVariables = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatDiscounts = (data: DiscountMetaobject[]) => {
|
||||||
|
const formattedData = data.map((item) => {
|
||||||
|
const fields = item.fields.reduce(
|
||||||
|
(acc, field: Field) => {
|
||||||
|
acc[field.key as string] = field.value;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, any>
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: fields.name,
|
||||||
|
code: fields.discount_code,
|
||||||
|
discount: {
|
||||||
|
amount: parseFloat(fields.amount) / 100,
|
||||||
|
minimumSpent: parseFloat(fields.minimum_spent)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return formattedData;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user