mirror of
https://github.com/vercel/commerce.git
synced 2025-05-15 05:56:59 +00:00
feat: add activate warranty to order details page
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
parent
d801de0cf1
commit
7f4fa09027
@ -1,5 +1,5 @@
|
|||||||
import { ArrowLeftIcon, CheckCircleIcon, TruckIcon } from '@heroicons/react/24/outline';
|
import { ArrowLeftIcon, CheckCircleIcon, TruckIcon } from '@heroicons/react/24/outline';
|
||||||
import { Button } from 'components/button';
|
import ActivateWarranty from 'components/orders/activate-warranty';
|
||||||
import OrderSummary from 'components/orders/order-summary';
|
import OrderSummary from 'components/orders/order-summary';
|
||||||
import OrderSummaryMobile from 'components/orders/order-summary-mobile';
|
import OrderSummaryMobile from 'components/orders/order-summary-mobile';
|
||||||
import Price from 'components/price';
|
import Price from 'components/price';
|
||||||
@ -8,7 +8,7 @@ import { Card } from 'components/ui/card';
|
|||||||
import Heading from 'components/ui/heading';
|
import Heading from 'components/ui/heading';
|
||||||
import Label from 'components/ui/label';
|
import Label from 'components/ui/label';
|
||||||
import Text from 'components/ui/text';
|
import Text from 'components/ui/text';
|
||||||
import { getCustomerOrder } from 'lib/shopify';
|
import { getCustomerOrder, getOrderMetafields } from 'lib/shopify';
|
||||||
import { Fulfillment, Order } from 'lib/shopify/types';
|
import { Fulfillment, Order } from 'lib/shopify/types';
|
||||||
import { toPrintDate } from 'lib/utils';
|
import { toPrintDate } from 'lib/utils';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
@ -228,7 +228,10 @@ function OrderDetails({ order }: { order: Order }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function OrderPage({ params }: { params: { id: string } }) {
|
export default async function OrderPage({ params }: { params: { id: string } }) {
|
||||||
const order = await getCustomerOrder(params.id);
|
const [order, orderMetafields] = await Promise.all([
|
||||||
|
getCustomerOrder(params.id),
|
||||||
|
getOrderMetafields(params.id)
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -244,9 +247,7 @@ export default async function OrderPage({ params }: { params: { id: string } })
|
|||||||
<Label>Confirmed {toPrintDate(order.processedAt)}</Label>
|
<Label>Confirmed {toPrintDate(order.processedAt)}</Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<ActivateWarranty order={order} orderMetafields={orderMetafields} />
|
||||||
<Button>Activate Warranty</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start gap-6">
|
<div className="flex items-start gap-6">
|
||||||
<div className="flex flex-1 flex-col gap-6">
|
<div className="flex flex-1 flex-col gap-6">
|
@ -4,7 +4,7 @@ import MobileOrderActions from 'components/orders/mobile-order-actions';
|
|||||||
import OrdersHeader from 'components/orders/orders-header';
|
import OrdersHeader from 'components/orders/orders-header';
|
||||||
import Price from 'components/price';
|
import Price from 'components/price';
|
||||||
import { getCustomerOrders, getOrdersMetafields } from 'lib/shopify';
|
import { getCustomerOrders, getOrdersMetafields } from 'lib/shopify';
|
||||||
import { isBeforeToday, toPrintDate } from 'lib/utils';
|
import { toPrintDate } from 'lib/utils';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
@ -64,12 +64,7 @@ export default async function AccountPage() {
|
|||||||
<span>View Order</span>
|
<span>View Order</span>
|
||||||
<span className="sr-only">{order.normalizedId}</span>
|
<span className="sr-only">{order.normalizedId}</span>
|
||||||
</Link>
|
</Link>
|
||||||
{!isBeforeToday(ordersMetafields[order.id]?.warrantyActivationDeadline) && (
|
<ActivateWarranty order={order} orderMetafields={ordersMetafields[order.id]} />
|
||||||
<ActivateWarranty
|
|
||||||
order={order}
|
|
||||||
orderMetafields={ordersMetafields[order.id]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Order, OrderMetafield, WarrantyStatus } from 'lib/shopify/types';
|
import { Order, OrderMetafield, WarrantyStatus } from 'lib/shopify/types';
|
||||||
|
import { isBeforeToday } from 'lib/utils';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import ActivateWarrantyModal from './activate-warranty-modal';
|
import ActivateWarrantyModal from './activate-warranty-modal';
|
||||||
import WarrantyActivatedBadge from './warranty-activated-badge';
|
import WarrantyActivatedBadge from './warranty-activated-badge';
|
||||||
@ -13,15 +14,20 @@ type ActivateWarrantyModalProps = {
|
|||||||
const ActivateWarranty = ({ order, orderMetafields }: ActivateWarrantyModalProps) => {
|
const ActivateWarranty = ({ order, orderMetafields }: ActivateWarrantyModalProps) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const isWarrantyActivated = orderMetafields?.warrantyStatus === WarrantyStatus.Activated;
|
const isWarrantyActivated = orderMetafields?.warrantyStatus === WarrantyStatus.Activated;
|
||||||
|
const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline);
|
||||||
|
|
||||||
if (isWarrantyActivated) {
|
if (isWarrantyActivated) {
|
||||||
return <WarrantyActivatedBadge />;
|
return <WarrantyActivatedBadge />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPassDeadline) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="flex items-center justify-center rounded-md border border-gray-300 bg-white px-2.5 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
className="flex h-fit items-center justify-center rounded-md border border-gray-300 bg-white px-2.5 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
||||||
onClick={() => setIsOpen(true)}
|
onClick={() => setIsOpen(true)}
|
||||||
>
|
>
|
||||||
Activate Warranty
|
Activate Warranty
|
||||||
|
@ -2,7 +2,7 @@ import { CheckCircleIcon } from '@heroicons/react/24/solid';
|
|||||||
|
|
||||||
const WarrantyActivatedBadge = () => {
|
const WarrantyActivatedBadge = () => {
|
||||||
return (
|
return (
|
||||||
<span className="inline-flex items-center gap-x-2 rounded-md bg-green-50 px-2.5 py-2 text-sm font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
|
<span className="inline-flex h-fit items-center gap-x-2 rounded-md bg-green-50 px-2.5 py-2 text-sm font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
|
||||||
<CheckCircleIcon className="h-5 w-5 text-green-500" aria-hidden="true" />
|
<CheckCircleIcon className="h-5 w-5 text-green-500" aria-hidden="true" />
|
||||||
Warranty Activated
|
Warranty Activated
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import customerAddress from './customer-address';
|
import customerAddress from './customer-address';
|
||||||
import orderCard from './order-card';
|
import orderCard from './order';
|
||||||
|
|
||||||
const customerDetailsFragment = /* GraphQL */ `
|
const customerDetailsFragment = /* GraphQL */ `
|
||||||
${customerAddress}
|
${customerAddress}
|
||||||
|
@ -28,4 +28,19 @@ const orderCard = /* GraphQL */ `
|
|||||||
${lineItemFragment}
|
${lineItemFragment}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const orderMetafields = /* GraphQL */ `
|
||||||
|
fragment OrderMetafield on Order {
|
||||||
|
id
|
||||||
|
warrantyStatus: metafield(namespace: "custom", key: "warranty_status") {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
warrantyActivationDeadline: metafield(
|
||||||
|
namespace: "custom"
|
||||||
|
key: "warranty_activation_deadline"
|
||||||
|
) {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export default orderCard;
|
export default orderCard;
|
@ -38,7 +38,7 @@ import { getCustomerQuery } from './queries/customer';
|
|||||||
import { getMenuQuery } from './queries/menu';
|
import { getMenuQuery } from './queries/menu';
|
||||||
import { getMetaobjectQuery, getMetaobjectsQuery } from './queries/metaobject';
|
import { getMetaobjectQuery, getMetaobjectsQuery } from './queries/metaobject';
|
||||||
import { getImageQuery, getMetaobjectsByIdsQuery } from './queries/node';
|
import { getImageQuery, getMetaobjectsByIdsQuery } from './queries/node';
|
||||||
import { getCustomerOrderQuery } from './queries/order';
|
import { getCustomerOrderQuery, getOrderMetafieldsQuery } from './queries/order';
|
||||||
import { getCustomerOrderMetafieldsQuery, getCustomerOrdersQuery } from './queries/orders';
|
import { getCustomerOrderMetafieldsQuery, getCustomerOrdersQuery } from './queries/orders';
|
||||||
import { getPageQuery, getPagesQuery } from './queries/page';
|
import { getPageQuery, getPagesQuery } from './queries/page';
|
||||||
import {
|
import {
|
||||||
@ -1161,3 +1161,27 @@ export const getOrdersMetafields = async (): Promise<{ [key: string]: OrderMetaf
|
|||||||
{} as { [key: string]: OrderMetafield }
|
{} as { [key: string]: OrderMetafield }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getOrderMetafields = async (orderId: string): Promise<OrderMetafield> => {
|
||||||
|
const res = await adminFetch<{
|
||||||
|
data: {
|
||||||
|
order: {
|
||||||
|
id: string;
|
||||||
|
} & ShopifyOrderMetafield;
|
||||||
|
};
|
||||||
|
variables: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
}>({
|
||||||
|
query: getOrderMetafieldsQuery,
|
||||||
|
variables: { id: `gid://shopify/Order/${orderId}` },
|
||||||
|
tags: [`${TAGS.orderMetafields}/${orderId}`]
|
||||||
|
});
|
||||||
|
|
||||||
|
const order = res.body.data.order;
|
||||||
|
|
||||||
|
return {
|
||||||
|
warrantyStatus: order.warrantyStatus?.value ?? null,
|
||||||
|
warrantyActivationDeadline: order.warrantyActivationDeadline?.value ?? null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import lineItemFragment from '../fragments/line-item';
|
import lineItemFragment from '../fragments/line-item';
|
||||||
|
import { orderMetafields } from '../fragments/order';
|
||||||
|
|
||||||
// NOTE: https://shopify.dev/docs/api/customer/latest/queries/customer
|
// NOTE: https://shopify.dev/docs/api/customer/latest/queries/customer
|
||||||
export const getCustomerOrderQuery = /* GraphQL */ `
|
export const getCustomerOrderQuery = /* GraphQL */ `
|
||||||
@ -220,3 +221,12 @@ export const getCustomerOrderQuery = /* GraphQL */ `
|
|||||||
}
|
}
|
||||||
${lineItemFragment}
|
${lineItemFragment}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const getOrderMetafieldsQuery = /* GraphQL */ `
|
||||||
|
query getOrderMetafields($id: ID!) {
|
||||||
|
order(id: $id) {
|
||||||
|
...OrderMetafield
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${orderMetafields}
|
||||||
|
`;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import customerDetailsFragment from '../fragments/customer-details';
|
import customerDetailsFragment from '../fragments/customer-details';
|
||||||
|
import { orderMetafields } from '../fragments/order';
|
||||||
|
|
||||||
const customerFragment = `#graphql
|
const customerFragment = `#graphql
|
||||||
`;
|
`;
|
||||||
@ -19,18 +20,10 @@ export const getCustomerOrderMetafieldsQuery = /* GraphQL */ `
|
|||||||
customer(id: $id) {
|
customer(id: $id) {
|
||||||
orders(first: 20, sortKey: PROCESSED_AT, reverse: true) {
|
orders(first: 20, sortKey: PROCESSED_AT, reverse: true) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
...OrderMetafield
|
||||||
warrantyStatus: metafield(namespace: "custom", key: "warranty_status") {
|
|
||||||
value
|
|
||||||
}
|
|
||||||
warrantyActivationDeadline: metafield(
|
|
||||||
namespace: "custom"
|
|
||||||
key: "warranty_activation_deadline"
|
|
||||||
) {
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
${orderMetafields}
|
||||||
`;
|
`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user