From d679b46520a199d3333204822425f73f187f90a2 Mon Sep 17 00:00:00 2001
From: tedraykov <tedraykov@gmail.com>
Date: Tue, 9 Jul 2024 23:51:32 +0300
Subject: [PATCH] add server logic for core return metafields update

---
 components/orders/actions.tsx           | 101 +++++++++++++++++++++---
 components/orders/core-return-modal.tsx |  13 ++-
 components/orders/core-return.tsx       |   8 +-
 components/ui/combobox.tsx              |   2 +-
 lib/constants.ts                        |  10 +++
 lib/shopify/index.ts                    |  17 +---
 6 files changed, 122 insertions(+), 29 deletions(-)

diff --git a/components/orders/actions.tsx b/components/orders/actions.tsx
index 289649ea0..d7b1cfe63 100644
--- a/components/orders/actions.tsx
+++ b/components/orders/actions.tsx
@@ -3,13 +3,15 @@
 import { renderToBuffer } from '@react-pdf/renderer';
 import OrderConfirmationPdf from 'components/orders/order-confirmation-pdf';
 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 {
+  CoreReturnStatus,
   Order,
   OrderConfirmationContent,
   ShopifyOrderMetafield,
-  UpdateOrderMetafieldInput
+  UpdateOrderMetafieldInput,
+  WarrantyStatus
 } from 'lib/shopify/types';
 import { revalidateTag } from 'next/cache';
 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
-  const rawFormData = [
+  const metafields = [
     getMetafieldValue(
       '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 {
     await updateOrderMetafields({
       orderId: order.id,
-      metafields: rawFormData
+      metafields
     });
 
     revalidateTag(TAGS.orderMetafields);
@@ -166,21 +181,89 @@ export const confirmOrder = async ({ order, content, formData }: ConfirmOrderOpt
 };
 
 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(
       'coreReturnZip',
       {
-        key: '',
-        value: formData.get('name') as string | null,
-        type: 'file_reference'
+        key: 'core_return_zip',
+        value: formData.get('zip') as string | null,
+        type: 'single_line_text_field'
       },
       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 {
     await updateOrderMetafields({
       orderId: order.id,
-      metafields: rawFormData
+      metafields
     });
 
     revalidateTag(TAGS.orderMetafields);
diff --git a/components/orders/core-return-modal.tsx b/components/orders/core-return-modal.tsx
index 81a496b35..4e388ea72 100644
--- a/components/orders/core-return-modal.tsx
+++ b/components/orders/core-return-modal.tsx
@@ -18,7 +18,8 @@ export function CoreReturnModal({
 
   async function submitCoreReturn(formData: FormData) {
     startTransition(async () => {
-      returnCore(order, formData);
+      await returnCore(order, formData);
+      onClose();
     });
   }
 
@@ -77,10 +78,16 @@ export function CoreReturnModal({
                 <StatesCombobox defaultStateCode={order.shippingAddress.provinceCode} />
               </Fieldset>
               <div className="flex justify-end gap-2">
-                <Button variant="text" onClick={onClose}>
+                <Button variant="text" onClick={onClose} type="button">
                   Close
                 </Button>
-                <Button color="primary" variant="solid" disabled={submitting}>
+                <Button
+                  type="submit"
+                  color="primary"
+                  variant="solid"
+                  disabled={submitting}
+                  isLoading={submitting}
+                >
                   Submit
                 </Button>
               </div>
diff --git a/components/orders/core-return.tsx b/components/orders/core-return.tsx
index da6dcfba6..6324ce777 100644
--- a/components/orders/core-return.tsx
+++ b/components/orders/core-return.tsx
@@ -1,11 +1,17 @@
 'use client';
 import { Button } from 'components/ui';
-import { Order } from 'lib/shopify/types';
+import { CoreReturnStatus, Order } from 'lib/shopify/types';
 import { useState } from 'react';
 import { CoreReturnModal } from './core-return-modal';
+import { isBeforeToday } from 'lib/utils';
 
 export function CoreReturn({ order }: { order: Order }) {
   const [isOpen, setIsOpen] = useState(false);
+  const isPassDeadline = isBeforeToday(order?.coreReturnDeadline?.value);
+
+  if (order.coreReturnStatus?.value !== CoreReturnStatus.CoreNeeded || isPassDeadline) {
+    return null;
+  }
   return (
     <>
       <Button onClick={() => setIsOpen(true)}>Core Return</Button>
diff --git a/components/ui/combobox.tsx b/components/ui/combobox.tsx
index 890b26b04..c7992afd0 100644
--- a/components/ui/combobox.tsx
+++ b/components/ui/combobox.tsx
@@ -141,7 +141,7 @@ const Combobox = <T extends Record<string, unknown>, TMultiple extends boolean |
             autoFocus={autoFocus}
           />
           <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>
         </div>
         <ComboboxOptions anchor="bottom" className={optionsStyles()}>
diff --git a/lib/constants.ts b/lib/constants.ts
index 990b3e74e..a7268aadc 100644
--- a/lib/constants.ts
+++ b/lib/constants.ts
@@ -71,6 +71,16 @@ export const WARRANTY_FIELDS = [
   '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 = [
   '/transmissions',
   '/engines',
diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts
index c3f049e8f..04c0d9514 100644
--- a/lib/shopify/index.ts
+++ b/lib/shopify/index.ts
@@ -11,7 +11,6 @@ import {
   SHOPIFY_GRAPHQL_CUSTOMER_API_ENDPOINT,
   TAGS,
   VARIANT_METAFIELD_PREFIX,
-  WARRANTY_FIELDS,
   YEAR_FILTER_ID
 } from 'lib/constants';
 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>;
 
   if (validMetafields.length === 0) return null;
-
-  const shouldSetWarrantyStatusToActivated = WARRANTY_FIELDS.every((field) =>
-    validMetafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
-  );
+  console.log('Updating order metafields', { orderId, metafields: validMetafields });
 
   const response = await shopifyAdminFetch<ShopifyUpdateOrderMetafieldsOperation>({
     query: updateOrderMetafieldsMutation,
     variables: {
       input: {
-        metafields: shouldSetWarrantyStatusToActivated
-          ? validMetafields.concat([
-              {
-                key: 'warranty_status',
-                value: WarrantyStatus.Activated,
-                namespace: 'custom',
-                type: 'single_line_text_field'
-              }
-            ])
-          : validMetafields,
+        metafields: validMetafields,
         id: orderId
       }
     }