allow customer to check on self installed field

This commit is contained in:
Chloe 2024-06-27 15:05:59 +07:00
parent 7f4fa09027
commit 6c01d8825d
No known key found for this signature in database
GPG Key ID: CFD53CE570D42DF5
16 changed files with 288 additions and 96 deletions

View File

@ -5,5 +5,6 @@
"source.fixAll": "explicit", "source.fixAll": "explicit",
"source.organizeImports": "explicit", "source.organizeImports": "explicit",
"source.sortMembers": "explicit" "source.sortMembers": "explicit"
} },
"cSpell.words": ["Metafield", "Metafields"]
} }

View File

@ -1,28 +0,0 @@
'use client';
import { CheckIcon } from '@heroicons/react/24/outline';
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import { cn } from 'lib/utils';
import { forwardRef } from 'react';
const Checkbox = forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
'ring-offset-background focus-visible:ring-ring peer h-4 w-4 shrink-0 rounded-sm border border-dark focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-dark data-[state=checked]:text-white',
className
)}
{...props}
>
<CheckboxPrimitive.Indicator className={cn('flex items-center justify-center text-current')}>
<CheckIcon className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
export { Checkbox };

View File

@ -0,0 +1,25 @@
import { Checkbox, CheckboxProps, Field, Label } from '@headlessui/react';
import { CheckIcon } from '@heroicons/react/24/solid';
type CheckboxFieldProps = CheckboxProps & {
label: string;
name: string;
};
const CheckboxField = ({ label, name, ...props }: CheckboxFieldProps) => {
return (
<Field className="flex items-center gap-2">
<Checkbox
name={name}
className="group size-5 rounded bg-white p-1 ring-1 ring-inset ring-gray-300 data-[checked]:bg-primary data-[checked]:ring-primary"
{...props}
>
{/* Checkmark icon */}
<CheckIcon className="hidden size-3 fill-white group-data-[checked]:block" />
</Checkbox>
<Label className="block text-sm font-medium leading-6 text-gray-900">{label}</Label>
</Field>
);
};
export default CheckboxField;

View File

@ -1,7 +1,7 @@
'use server'; 'use server';
import { createFile, stageUploadFile, uploadFile } from 'lib/shopify'; import { createFile, getFile, stageUploadFile, uploadFile } from 'lib/shopify';
import { StagedUploadsCreatePayload, UploadInput } from 'lib/shopify/types'; import { File as ShopifyFile, StagedUploadsCreatePayload, UploadInput } from 'lib/shopify/types';
const prepareFilePayload = ({ const prepareFilePayload = ({
stagedFileUpload, stagedFileUpload,
@ -84,3 +84,13 @@ export const handleUploadFile = async ({ file }: { file: File }) => {
console.log('handleUploadFile action', error); console.log('handleUploadFile action', error);
} }
}; };
export const getFileDetails = async (fileId?: string | null): Promise<ShopifyFile | undefined> => {
if (!fileId) return undefined;
try {
const file = await getFile(fileId);
return file;
} catch (error) {
console.log('getFileDetails action', error);
}
};

View File

@ -1,14 +1,23 @@
'use client';
import { PhotoIcon } from '@heroicons/react/24/outline'; import { PhotoIcon } from '@heroicons/react/24/outline';
import { ChangeEvent, useId, useState } from 'react'; import LoadingDots from 'components/loading-dots';
import { File as ShopifyFile } from 'lib/shopify/types';
import { ChangeEvent, useEffect, useId, useState, useTransition } from 'react';
import { getFileDetails } from './actions';
type FileInputProps = { type FileInputProps = {
name: string; name: string;
label: string; label: string;
fileId?: string | null;
}; };
const FileInput = ({ name, label }: FileInputProps) => { const FileInput = ({ name, label, fileId }: FileInputProps) => {
const id = useId(); const id = useId();
const [file, setFile] = useState<File | undefined>(); const [file, setFile] = useState<File | undefined>();
const [defaultFileDetails, setDefaultFileDetails] = useState<ShopifyFile | undefined>();
const [loading, startTransition] = useTransition();
const onFileChange = (e: ChangeEvent<HTMLInputElement>) => { const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) { if (e.target.files && e.target.files.length > 0) {
@ -16,6 +25,15 @@ const FileInput = ({ name, label }: FileInputProps) => {
} }
}; };
useEffect(() => {
if (!fileId) return;
startTransition(async () => {
const fileResponse = await getFileDetails(fileId);
setDefaultFileDetails(fileResponse);
});
}, [fileId]);
return ( return (
<div> <div>
<label className="block text-sm font-medium leading-6 text-gray-900">{label}</label> <label className="block text-sm font-medium leading-6 text-gray-900">{label}</label>
@ -34,7 +52,9 @@ const FileInput = ({ name, label }: FileInputProps) => {
</div> </div>
</div> </div>
</div> </div>
{file && <p className="mt-2 text-sm text-gray-500">{file.name}</p>} <p className="mt-2 text-sm text-gray-500">
{loading ? <LoadingDots className="bg-dark" /> : file?.name || defaultFileDetails?.alt}
</p>
</div> </div>
); );
}; };

View File

@ -1,3 +1,5 @@
'use client';
import { Field, Input as HeadlessInput, Label } from '@headlessui/react'; import { Field, Input as HeadlessInput, Label } from '@headlessui/react';
import { InputHTMLAttributes } from 'react'; import { InputHTMLAttributes } from 'react';

View File

@ -3,9 +3,24 @@
import { handleUploadFile } from 'components/form/file-input/actions'; import { handleUploadFile } from 'components/form/file-input/actions';
import { TAGS } from 'lib/constants'; import { TAGS } from 'lib/constants';
import { updateOrderMetafields } from 'lib/shopify'; import { updateOrderMetafields } from 'lib/shopify';
import { ShopifyOrderMetafield, UpdateOrderMetafieldInput } from 'lib/shopify/types';
import { revalidateTag } from 'next/cache'; import { revalidateTag } from 'next/cache';
export const activateWarranty = async (orderId: string, formData: FormData) => { const getMetafieldValue = (
key: keyof ShopifyOrderMetafield,
newValue: { value?: string | null; type: string; key: string },
orderMetafields?: ShopifyOrderMetafield
): UpdateOrderMetafieldInput => {
return orderMetafields?.[key]?.id
? { id: orderMetafields[key]?.id!, value: newValue.value, key: newValue.key }
: { ...newValue, namespace: 'custom' };
};
export const activateWarranty = async (
orderId: string,
formData: FormData,
orderMetafields?: ShopifyOrderMetafield
) => {
let odometerFileId = null; let odometerFileId = null;
let installationFileId = null; let installationFileId = null;
const odometerFile = formData.get('warranty_activation_odometer'); const odometerFile = formData.get('warranty_activation_odometer');
@ -17,20 +32,54 @@ export const activateWarranty = async (orderId: string, formData: FormData) => {
if (installationFile) { if (installationFile) {
installationFileId = await handleUploadFile({ file: installationFile as File }); installationFileId = await handleUploadFile({ file: installationFile as File });
} }
console.log(formData.get('warranty_activation_self_install'));
// https://shopify.dev/docs/api/admin-graphql/2024-01/mutations/orderUpdate
const rawFormData = [ const rawFormData = [
{ key: 'warranty_activation_odometer', value: odometerFileId, type: 'file_reference' }, getMetafieldValue(
{ key: 'warranty_activation_installation', value: installationFileId, type: 'file_reference' }, 'warrantyActivationOdometer',
{ {
key: 'warranty_activation_mileage', key: 'warranty_activation_odometer',
value: formData.get('warranty_activation_mileage') as string | null, value: odometerFileId,
type: 'number_integer' type: 'file_reference'
}, },
{ orderMetafields
key: 'warranty_activation_vin', ),
value: formData.get('warranty_activation_vin') as string | null, getMetafieldValue(
type: 'single_line_text_field' 'warrantyActivationInstallation',
} {
key: 'warranty_activation_installation',
value: installationFileId,
type: 'file_reference'
},
orderMetafields
),
getMetafieldValue(
'warrantyActivationSelfInstall',
{
key: 'warranty_activation_self_install',
value: formData.get('warranty_activation_self_install') === 'on' ? 'true' : 'false',
type: 'boolean'
},
orderMetafields
),
getMetafieldValue(
'warrantyActivationMileage',
{
key: 'warranty_activation_mileage',
value: formData.get('warranty_activation_mileage') as string | null,
type: 'number_integer'
},
orderMetafields
),
getMetafieldValue(
'warrantyActivationVIN',
{
key: 'warranty_activation_vin',
value: formData.get('warranty_activation_vin') as string | null,
type: 'single_line_text_field'
},
orderMetafields
)
]; ];
try { try {

View File

@ -2,9 +2,11 @@
import { Button, Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'; import { Button, Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
import clsx from 'clsx'; import clsx from 'clsx';
import CheckboxField from 'components/form/checkbox-field';
import FileInput from 'components/form/file-input'; import FileInput from 'components/form/file-input';
import Input from 'components/form/input'; import Input from 'components/form/input-field';
import LoadingDots from 'components/loading-dots'; import LoadingDots from 'components/loading-dots';
import { ShopifyOrderMetafield } from 'lib/shopify/types';
import { FormEventHandler, useRef, useTransition } from 'react'; import { FormEventHandler, useRef, useTransition } from 'react';
import { activateWarranty } from './actions'; import { activateWarranty } from './actions';
@ -12,9 +14,15 @@ type ActivateWarrantyModalProps = {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
orderId: string; orderId: string;
orderMetafields?: ShopifyOrderMetafield;
}; };
function ActivateWarrantyModal({ onClose, isOpen, orderId }: ActivateWarrantyModalProps) { function ActivateWarrantyModal({
onClose,
isOpen,
orderId,
orderMetafields
}: ActivateWarrantyModalProps) {
const [pending, startTransition] = useTransition(); const [pending, startTransition] = useTransition();
const formRef = useRef<HTMLFormElement>(null); const formRef = useRef<HTMLFormElement>(null);
@ -25,7 +33,7 @@ function ActivateWarrantyModal({ onClose, isOpen, orderId }: ActivateWarrantyMod
const formData = new FormData(form); const formData = new FormData(form);
startTransition(async () => { startTransition(async () => {
await activateWarranty(orderId, formData); await activateWarranty(orderId, formData, orderMetafields);
form.reset(); form.reset();
onClose(); onClose();
}); });
@ -48,10 +56,32 @@ function ActivateWarrantyModal({ onClose, isOpen, orderId }: ActivateWarrantyMod
<DialogTitle className="mb-2 font-bold">Activate Warranty</DialogTitle> <DialogTitle className="mb-2 font-bold">Activate Warranty</DialogTitle>
<form onSubmit={handleSubmit} ref={formRef}> <form onSubmit={handleSubmit} ref={formRef}>
<div className="flex w-full flex-col gap-4"> <div className="flex w-full flex-col gap-4">
<FileInput label="Odometer" name="warranty_activation_odometer" /> <FileInput
<FileInput label="Installation Receipt" name="warranty_activation_installation" /> label="Odometer"
<Input label="Customer Mileage" name="warranty_activation_mileage" type="number" /> name="warranty_activation_odometer"
<Input label="Customer VIN" name="warranty_activation_vin" /> fileId={orderMetafields?.warrantyActivationOdometer?.value}
/>
<FileInput
label="Installation Receipt"
name="warranty_activation_installation"
fileId={orderMetafields?.warrantyActivationInstallation?.value}
/>
<CheckboxField
label="Self Installed"
name="warranty_activation_self_install"
defaultChecked={orderMetafields?.warrantyActivationSelfInstall?.value === 'true'}
/>
<Input
label="Customer Mileage"
name="warranty_activation_mileage"
type="number"
defaultValue={orderMetafields?.warrantyActivationMileage?.value}
/>
<Input
label="Customer VIN"
name="warranty_activation_vin"
defaultValue={orderMetafields?.warrantyActivationVIN?.value}
/>
</div> </div>
<div className="mt-4 flex w-full justify-end gap-4"> <div className="mt-4 flex w-full justify-end gap-4">
<button <button
@ -71,7 +101,7 @@ function ActivateWarrantyModal({ onClose, isOpen, orderId }: ActivateWarrantyMod
disabled={pending} disabled={pending}
> >
{pending && <LoadingDots className="bg-white" />} {pending && <LoadingDots className="bg-white" />}
Activate Submit
</Button> </Button>
</div> </div>
</form> </form>

View File

@ -1,6 +1,6 @@
'use client'; 'use client';
import { Order, OrderMetafield, WarrantyStatus } from 'lib/shopify/types'; import { Order, ShopifyOrderMetafield, WarrantyStatus } from 'lib/shopify/types';
import { isBeforeToday } from 'lib/utils'; 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';
@ -8,13 +8,13 @@ import WarrantyActivatedBadge from './warranty-activated-badge';
type ActivateWarrantyModalProps = { type ActivateWarrantyModalProps = {
order: Order; order: Order;
orderMetafields?: OrderMetafield; orderMetafields?: ShopifyOrderMetafield;
}; };
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?.value === WarrantyStatus.Activated;
const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline); const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline?.value);
if (isWarrantyActivated) { if (isWarrantyActivated) {
return <WarrantyActivatedBadge />; return <WarrantyActivatedBadge />;
@ -32,7 +32,12 @@ const ActivateWarranty = ({ order, orderMetafields }: ActivateWarrantyModalProps
> >
Activate Warranty Activate Warranty
</button> </button>
<ActivateWarrantyModal isOpen={isOpen} onClose={() => setIsOpen(false)} orderId={order.id} /> <ActivateWarrantyModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
orderId={order.id}
orderMetafields={orderMetafields}
/>
</> </>
); );
}; };

View File

@ -3,7 +3,7 @@
import { Button, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'; import { Button, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react';
import { EllipsisVerticalIcon } from '@heroicons/react/24/solid'; import { EllipsisVerticalIcon } from '@heroicons/react/24/solid';
import clsx from 'clsx'; import clsx from 'clsx';
import { Order, OrderMetafield, WarrantyStatus } from 'lib/shopify/types'; import { Order, ShopifyOrderMetafield, WarrantyStatus } from 'lib/shopify/types';
import { isBeforeToday } from 'lib/utils'; import { isBeforeToday } from 'lib/utils';
import Link from 'next/link'; import Link from 'next/link';
import { useState } from 'react'; import { useState } from 'react';
@ -14,11 +14,11 @@ const MobileOrderActions = ({
orderMetafields orderMetafields
}: { }: {
order: Order; order: Order;
orderMetafields?: OrderMetafield; orderMetafields?: ShopifyOrderMetafield;
}) => { }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const isWarrantyActivated = orderMetafields?.warrantyStatus === WarrantyStatus.Activated; const isWarrantyActivated = orderMetafields?.warrantyStatus?.value === WarrantyStatus.Activated;
const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline); const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline?.value);
return ( return (
<> <>
@ -66,7 +66,12 @@ const MobileOrderActions = ({
</div> </div>
</MenuItems> </MenuItems>
</Menu> </Menu>
<ActivateWarrantyModal isOpen={isOpen} onClose={() => setIsOpen(false)} orderId={order.id} /> <ActivateWarrantyModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
orderId={order.id}
orderMetafields={orderMetafields}
/>
</> </>
); );
}; };

View File

@ -64,7 +64,7 @@ export const ADD_ON_PRODUCT_TYPES = {
export const WARRANTY_FIELDS = [ export const WARRANTY_FIELDS = [
'warranty_activation_odometer', 'warranty_activation_odometer',
'warranty_activation_installation', ['warranty_activation_installation', 'warranty_activation_self_install'],
'warranty_activation_vin', 'warranty_activation_vin',
'warranty_activation_mileage' 'warranty_activation_mileage'
]; ];

View File

@ -33,12 +33,50 @@ export const orderMetafields = /* GraphQL */ `
id id
warrantyStatus: metafield(namespace: "custom", key: "warranty_status") { warrantyStatus: metafield(namespace: "custom", key: "warranty_status") {
value value
id
key
} }
warrantyActivationDeadline: metafield( warrantyActivationDeadline: metafield(
namespace: "custom" namespace: "custom"
key: "warranty_activation_deadline" key: "warranty_activation_deadline"
) { ) {
value value
id
key
}
warrantyActivationOdometer: metafield(
namespace: "custom"
key: "warranty_activation_odometer"
) {
value
id
key
}
warrantyActivationInstallation: metafield(
namespace: "custom"
key: "warranty_activation_installation"
) {
value
id
key
}
warrantyActivationSelfInstall: metafield(
namespace: "custom"
key: "warranty_activation_self_install"
) {
value
id
key
}
warrantyActivationVIN: metafield(namespace: "custom", key: "warranty_activation_vin") {
value
id
key
}
warrantyActivationMileage: metafield(namespace: "custom", key: "warranty_activation_mileage") {
value
id
key
} }
} }
`; `;

View File

@ -37,7 +37,7 @@ import {
import { getCustomerQuery } from './queries/customer'; 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 { getFileQuery, getImageQuery, getMetaobjectsByIdsQuery } from './queries/node';
import { getCustomerOrderQuery, getOrderMetafieldsQuery } 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';
@ -53,6 +53,7 @@ import {
Collection, Collection,
Connection, Connection,
Customer, Customer,
File,
FileCreateInput, FileCreateInput,
Filter, Filter,
Fulfillment, Fulfillment,
@ -63,7 +64,6 @@ import {
Metaobject, Metaobject,
Money, Money,
Order, Order,
OrderMetafield,
Page, Page,
PageInfo, PageInfo,
Product, Product,
@ -105,6 +105,7 @@ import {
ShopifyUpdateOrderMetafieldsOperation, ShopifyUpdateOrderMetafieldsOperation,
Transaction, Transaction,
TransmissionType, TransmissionType,
UpdateOrderMetafieldInput,
UploadInput, UploadInput,
WarrantyStatus WarrantyStatus
} from './types'; } from './types';
@ -1092,17 +1093,14 @@ export const updateOrderMetafields = async ({
metafields metafields
}: { }: {
orderId: string; orderId: string;
metafields: { key: string; value: string | undefined | null; type: string }[]; metafields: Array<UpdateOrderMetafieldInput>;
}) => { }) => {
const validMetafields = ( const validMetafields = metafields.filter((field) => Boolean(field.value)) as Array<Metafield>;
metafields.filter((field) => Boolean(field)) as Array<Omit<Metafield, 'namespace'>>
).map((field) => ({ if (validMetafields.length === 0) return null;
...field,
namespace: 'custom'
}));
const shouldSetWarrantyStatusToActivated = WARRANTY_FIELDS.every((field) => const shouldSetWarrantyStatusToActivated = WARRANTY_FIELDS.every((field) =>
validMetafields.find(({ key }) => key === field) validMetafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
); );
const response = await adminFetch<ShopifyUpdateOrderMetafieldsOperation>({ const response = await adminFetch<ShopifyUpdateOrderMetafieldsOperation>({
@ -1127,7 +1125,7 @@ export const updateOrderMetafields = async ({
return response.body.data.orderUpdate.order.id; return response.body.data.orderUpdate.order.id;
}; };
export const getOrdersMetafields = async (): Promise<{ [key: string]: OrderMetafield }> => { export const getOrdersMetafields = async (): Promise<{ [key: string]: ShopifyOrderMetafield }> => {
const customer = await getCustomer(); const customer = await getCustomer();
const res = await adminFetch<{ const res = await adminFetch<{
data: { data: {
@ -1153,16 +1151,13 @@ export const getOrdersMetafields = async (): Promise<{ [key: string]: OrderMetaf
return res.body.data.customer.orders.nodes.reduce( return res.body.data.customer.orders.nodes.reduce(
(acc, order) => ({ (acc, order) => ({
...acc, ...acc,
[order.id]: { [order.id]: order
warrantyStatus: order.warrantyStatus?.value ?? null,
warrantyActivationDeadline: order.warrantyActivationDeadline?.value ?? null
}
}), }),
{} as { [key: string]: OrderMetafield } {} as { [key: string]: ShopifyOrderMetafield }
); );
}; };
export const getOrderMetafields = async (orderId: string): Promise<OrderMetafield> => { export const getOrderMetafields = async (orderId: string): Promise<ShopifyOrderMetafield> => {
const res = await adminFetch<{ const res = await adminFetch<{
data: { data: {
order: { order: {
@ -1175,13 +1170,26 @@ export const getOrderMetafields = async (orderId: string): Promise<OrderMetafiel
}>({ }>({
query: getOrderMetafieldsQuery, query: getOrderMetafieldsQuery,
variables: { id: `gid://shopify/Order/${orderId}` }, variables: { id: `gid://shopify/Order/${orderId}` },
tags: [`${TAGS.orderMetafields}/${orderId}`] tags: [TAGS.orderMetafields]
}); });
const order = res.body.data.order; const order = res.body.data.order;
return { return order;
warrantyStatus: order.warrantyStatus?.value ?? null, };
warrantyActivationDeadline: order.warrantyActivationDeadline?.value ?? null
}; export const getFile = async (id: string) => {
const res = await shopifyFetch<{
data: {
node: File;
};
variables: {
id: string;
};
}>({
query: getFileQuery,
variables: { id }
});
return res.body.data.node;
}; };

View File

@ -32,3 +32,15 @@ export const getMetaobjectsByIdsQuery = /* GraphQL */ `
} }
} }
`; `;
export const getFileQuery = /* GraphQL */ `
query getFile($id: ID!) {
node(id: $id) {
... on GenericFile {
id
url
alt
}
}
}
`;

View File

@ -858,12 +858,28 @@ export enum WarrantyStatus {
LimitedActivated = 'Limited Activation' LimitedActivated = 'Limited Activation'
} }
export type ShopifyOrderMetafield = { export type OrderMetafieldValue<T = string> = {
warrantyStatus: { value: WarrantyStatus } | null; value: T;
warrantyActivationDeadline: { value: string } | null; id: string;
key: string;
}; };
export type OrderMetafield = { export type ShopifyOrderMetafield = {
warrantyStatus: WarrantyStatus | null; warrantyStatus: OrderMetafieldValue | null;
warrantyActivationDeadline: string | null; warrantyActivationDeadline: OrderMetafieldValue | null;
warrantyActivationOdometer: OrderMetafieldValue | null;
warrantyActivationInstallation: OrderMetafieldValue | null;
warrantyActivationSelfInstall: OrderMetafieldValue | null;
warrantyActivationVIN: OrderMetafieldValue | null;
warrantyActivationMileage: OrderMetafieldValue | null;
}; };
export type File = {
id: string;
url: string;
alt: string;
};
export type UpdateOrderMetafieldInput =
| { key: string; value?: string | null; type: string; namespace: string }
| { id: string; value?: string | null; key: string };

View File

@ -25,7 +25,6 @@
"@headlessui/react": "^2.1.0", "@headlessui/react": "^2.1.0",
"@heroicons/react": "^2.1.3", "@heroicons/react": "^2.1.3",
"@hookform/resolvers": "^3.6.0", "@hookform/resolvers": "^3.6.0",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"geist": "^1.3.0", "geist": "^1.3.0",