mirror of
https://github.com/vercel/commerce.git
synced 2025-05-12 12:47:50 +00:00
Merge branch 'main' of github.com:Car-Part-Planet/storefront
This commit is contained in:
commit
d3774c7340
@ -3,13 +3,15 @@
|
|||||||
import { renderToBuffer } from '@react-pdf/renderer';
|
import { renderToBuffer } from '@react-pdf/renderer';
|
||||||
import OrderConfirmationPdf from 'components/orders/order-confirmation-pdf';
|
import OrderConfirmationPdf from 'components/orders/order-confirmation-pdf';
|
||||||
import { handleUploadFile } from 'components/form/file-input/actions';
|
import { handleUploadFile } from 'components/form/file-input/actions';
|
||||||
import { TAGS } from 'lib/constants';
|
import { CORE_RETURN_FIELDS, TAGS, WARRANTY_FIELDS } from 'lib/constants';
|
||||||
import { getOrderConfirmationContent, updateOrderMetafields } from 'lib/shopify';
|
import { getOrderConfirmationContent, updateOrderMetafields } from 'lib/shopify';
|
||||||
import {
|
import {
|
||||||
|
CoreReturnStatus,
|
||||||
Order,
|
Order,
|
||||||
OrderConfirmationContent,
|
OrderConfirmationContent,
|
||||||
ShopifyOrderMetafield,
|
ShopifyOrderMetafield,
|
||||||
UpdateOrderMetafieldInput
|
UpdateOrderMetafieldInput,
|
||||||
|
WarrantyStatus
|
||||||
} from 'lib/shopify/types';
|
} from 'lib/shopify/types';
|
||||||
import { revalidateTag } from 'next/cache';
|
import { revalidateTag } from 'next/cache';
|
||||||
import { cache } from 'react';
|
import { cache } from 'react';
|
||||||
@ -38,7 +40,7 @@ export const activateWarranty = async (order: Order, formData: FormData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://shopify.dev/docs/api/admin-graphql/2024-01/mutations/orderUpdate
|
// https://shopify.dev/docs/api/admin-graphql/2024-01/mutations/orderUpdate
|
||||||
const rawFormData = [
|
const metafields = [
|
||||||
getMetafieldValue(
|
getMetafieldValue(
|
||||||
'warrantyActivationOdometer',
|
'warrantyActivationOdometer',
|
||||||
{
|
{
|
||||||
@ -86,10 +88,23 @@ export const activateWarranty = async (order: Order, formData: FormData) => {
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const shouldSetWarrantyStatusToActivated = WARRANTY_FIELDS.every((field) =>
|
||||||
|
metafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shouldSetWarrantyStatusToActivated) {
|
||||||
|
metafields.push({
|
||||||
|
key: 'warranty_status',
|
||||||
|
value: WarrantyStatus.Activated,
|
||||||
|
namespace: 'custom',
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateOrderMetafields({
|
await updateOrderMetafields({
|
||||||
orderId: order.id,
|
orderId: order.id,
|
||||||
metafields: rawFormData
|
metafields
|
||||||
});
|
});
|
||||||
|
|
||||||
revalidateTag(TAGS.orderMetafields);
|
revalidateTag(TAGS.orderMetafields);
|
||||||
@ -166,21 +181,89 @@ export const confirmOrder = async ({ order, content, formData }: ConfirmOrderOpt
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function returnCore(order: Order, formData: FormData) {
|
export async function returnCore(order: Order, formData: FormData) {
|
||||||
const rawFormData = [
|
const metafields = [
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnName',
|
||||||
|
{
|
||||||
|
key: 'core_return_name',
|
||||||
|
value: formData.get('name') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnEmail',
|
||||||
|
{
|
||||||
|
key: 'core_return_email',
|
||||||
|
value: formData.get('email') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnPhone',
|
||||||
|
{
|
||||||
|
key: 'core_return_phone',
|
||||||
|
value: formData.get('phone') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnAddress',
|
||||||
|
{
|
||||||
|
key: 'core_return_address',
|
||||||
|
value: formData.get('address') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnCity',
|
||||||
|
{
|
||||||
|
key: 'core_return_city',
|
||||||
|
value: formData.get('city') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
|
getMetafieldValue(
|
||||||
|
'coreReturnState',
|
||||||
|
{
|
||||||
|
key: 'core_return_state',
|
||||||
|
value: formData.get('state[code]') as string | null,
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
},
|
||||||
|
order
|
||||||
|
),
|
||||||
getMetafieldValue(
|
getMetafieldValue(
|
||||||
'coreReturnZip',
|
'coreReturnZip',
|
||||||
{
|
{
|
||||||
key: '',
|
key: 'core_return_zip',
|
||||||
value: formData.get('name') as string | null,
|
value: formData.get('zip') as string | null,
|
||||||
type: 'file_reference'
|
type: 'single_line_text_field'
|
||||||
},
|
},
|
||||||
order
|
order
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const shouldSetCoreStatusToReturned = CORE_RETURN_FIELDS.every((field) =>
|
||||||
|
metafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shouldSetCoreStatusToReturned) {
|
||||||
|
metafields.push({
|
||||||
|
key: 'core_status',
|
||||||
|
value: CoreReturnStatus.PickupRequested,
|
||||||
|
namespace: 'custom',
|
||||||
|
type: 'single_line_text_field'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateOrderMetafields({
|
await updateOrderMetafields({
|
||||||
orderId: order.id,
|
orderId: order.id,
|
||||||
metafields: rawFormData
|
metafields
|
||||||
});
|
});
|
||||||
|
|
||||||
revalidateTag(TAGS.orderMetafields);
|
revalidateTag(TAGS.orderMetafields);
|
||||||
|
@ -18,7 +18,8 @@ export function CoreReturnModal({
|
|||||||
|
|
||||||
async function submitCoreReturn(formData: FormData) {
|
async function submitCoreReturn(formData: FormData) {
|
||||||
startTransition(async () => {
|
startTransition(async () => {
|
||||||
returnCore(order, formData);
|
await returnCore(order, formData);
|
||||||
|
onClose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,10 +78,16 @@ export function CoreReturnModal({
|
|||||||
<StatesCombobox defaultStateCode={order.shippingAddress.provinceCode} />
|
<StatesCombobox defaultStateCode={order.shippingAddress.provinceCode} />
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<Button variant="text" onClick={onClose}>
|
<Button variant="text" onClick={onClose} type="button">
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
<Button color="primary" variant="solid" disabled={submitting}>
|
<Button
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
variant="solid"
|
||||||
|
disabled={submitting}
|
||||||
|
isLoading={submitting}
|
||||||
|
>
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { Button } from 'components/ui';
|
import { Button } from 'components/ui';
|
||||||
import { Order } from 'lib/shopify/types';
|
import { CoreReturnStatus, Order } from 'lib/shopify/types';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { CoreReturnModal } from './core-return-modal';
|
import { CoreReturnModal } from './core-return-modal';
|
||||||
|
import { isBeforeToday } from 'lib/utils';
|
||||||
|
|
||||||
export function CoreReturn({ order }: { order: Order }) {
|
export function CoreReturn({ order }: { order: Order }) {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const isPassDeadline = isBeforeToday(order?.coreReturnDeadline?.value);
|
||||||
|
|
||||||
|
if (order.coreReturnStatus?.value !== CoreReturnStatus.CoreNeeded || isPassDeadline) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={() => setIsOpen(true)}>Core Return</Button>
|
<Button onClick={() => setIsOpen(true)}>Core Return</Button>
|
||||||
|
@ -141,7 +141,7 @@ const Combobox = <T extends Record<string, unknown>, TMultiple extends boolean |
|
|||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
/>
|
/>
|
||||||
<ComboboxButton className={button()}>
|
<ComboboxButton className={button()}>
|
||||||
<ChevronDownIcon className="fill-black/60 group-data-[hover]:fill-black size-5" />
|
<ChevronDownIcon className="size-5 fill-black/60 group-data-[hover]:fill-black" />
|
||||||
</ComboboxButton>
|
</ComboboxButton>
|
||||||
</div>
|
</div>
|
||||||
<ComboboxOptions anchor="bottom" className={optionsStyles()}>
|
<ComboboxOptions anchor="bottom" className={optionsStyles()}>
|
||||||
|
@ -71,6 +71,16 @@ export const WARRANTY_FIELDS = [
|
|||||||
'warranty_activation_mileage'
|
'warranty_activation_mileage'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const CORE_RETURN_FIELDS = [
|
||||||
|
'core_return_name',
|
||||||
|
'core_return_email',
|
||||||
|
'core_return_phone',
|
||||||
|
'core_return_address',
|
||||||
|
'core_return_city',
|
||||||
|
'core_return_zip',
|
||||||
|
'core_return_state'
|
||||||
|
];
|
||||||
|
|
||||||
export const URL_PREFIXES = [
|
export const URL_PREFIXES = [
|
||||||
'/transmissions',
|
'/transmissions',
|
||||||
'/engines',
|
'/engines',
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
SHOPIFY_GRAPHQL_CUSTOMER_API_ENDPOINT,
|
SHOPIFY_GRAPHQL_CUSTOMER_API_ENDPOINT,
|
||||||
TAGS,
|
TAGS,
|
||||||
VARIANT_METAFIELD_PREFIX,
|
VARIANT_METAFIELD_PREFIX,
|
||||||
WARRANTY_FIELDS,
|
|
||||||
YEAR_FILTER_ID
|
YEAR_FILTER_ID
|
||||||
} from 'lib/constants';
|
} from 'lib/constants';
|
||||||
import { isShopifyError } from 'lib/type-guards';
|
import { isShopifyError } from 'lib/type-guards';
|
||||||
@ -1191,25 +1190,13 @@ export const updateOrderMetafields = async ({
|
|||||||
const validMetafields = metafields.filter((field) => Boolean(field.value)) as Array<Metafield>;
|
const validMetafields = metafields.filter((field) => Boolean(field.value)) as Array<Metafield>;
|
||||||
|
|
||||||
if (validMetafields.length === 0) return null;
|
if (validMetafields.length === 0) return null;
|
||||||
|
console.log('Updating order metafields', { orderId, metafields: validMetafields });
|
||||||
const shouldSetWarrantyStatusToActivated = WARRANTY_FIELDS.every((field) =>
|
|
||||||
validMetafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
|
|
||||||
);
|
|
||||||
|
|
||||||
const response = await shopifyAdminFetch<ShopifyUpdateOrderMetafieldsOperation>({
|
const response = await shopifyAdminFetch<ShopifyUpdateOrderMetafieldsOperation>({
|
||||||
query: updateOrderMetafieldsMutation,
|
query: updateOrderMetafieldsMutation,
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
metafields: shouldSetWarrantyStatusToActivated
|
metafields: validMetafields,
|
||||||
? validMetafields.concat([
|
|
||||||
{
|
|
||||||
key: 'warranty_status',
|
|
||||||
value: WarrantyStatus.Activated,
|
|
||||||
namespace: 'custom',
|
|
||||||
type: 'single_line_text_field'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
: validMetafields,
|
|
||||||
id: orderId
|
id: orderId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user