/ src / lib / data / customer.ts
customer.ts
  1  "use server"
  2  
  3  import { sdk } from "@lib/config"
  4  import medusaError from "@lib/util/medusa-error"
  5  import { HttpTypes } from "@medusajs/types"
  6  import { revalidateTag } from "next/cache"
  7  import { redirect } from "next/navigation"
  8  import {
  9    getAuthHeaders,
 10    getCacheOptions,
 11    getCacheTag,
 12    getCartId,
 13    removeAuthToken,
 14    removeCartId,
 15    setAuthToken,
 16  } from "./cookies"
 17  
 18  export const retrieveCustomer =
 19    async (): Promise<HttpTypes.StoreCustomer | null> => {
 20      const authHeaders = await getAuthHeaders()
 21  
 22      if (!authHeaders) return null
 23  
 24      const headers = {
 25        ...authHeaders,
 26      }
 27  
 28      const next = {
 29        ...(await getCacheOptions("customers")),
 30      }
 31  
 32      return await sdk.client
 33        .fetch<{ customer: HttpTypes.StoreCustomer }>(`/store/customers/me`, {
 34          method: "GET",
 35          query: {
 36            fields: "*orders",
 37          },
 38          headers,
 39          next,
 40          cache: "force-cache",
 41        })
 42        .then(({ customer }) => customer)
 43        .catch(() => null)
 44    }
 45  
 46  export const updateCustomer = async (body: HttpTypes.StoreUpdateCustomer) => {
 47    const headers = {
 48      ...(await getAuthHeaders()),
 49    }
 50  
 51    const updateRes = await sdk.store.customer
 52      .update(body, {}, headers)
 53      .then(({ customer }) => customer)
 54      .catch(medusaError)
 55  
 56    const cacheTag = await getCacheTag("customers")
 57    revalidateTag(cacheTag)
 58  
 59    return updateRes
 60  }
 61  
 62  export async function signup(_currentState: unknown, formData: FormData) {
 63    const password = formData.get("password") as string
 64    const customerForm = {
 65      email: formData.get("email") as string,
 66      first_name: formData.get("first_name") as string,
 67      last_name: formData.get("last_name") as string,
 68      phone: formData.get("phone") as string,
 69    }
 70  
 71    try {
 72      const token = await sdk.auth.register("customer", "emailpass", {
 73        email: customerForm.email,
 74        password: password,
 75      })
 76  
 77      await setAuthToken(token as string)
 78  
 79      const headers = {
 80        ...(await getAuthHeaders()),
 81      }
 82  
 83      const { customer: createdCustomer } = await sdk.store.customer.create(
 84        customerForm,
 85        {},
 86        headers
 87      )
 88  
 89      const loginToken = await sdk.auth.login("customer", "emailpass", {
 90        email: customerForm.email,
 91        password,
 92      })
 93  
 94      await setAuthToken(loginToken as string)
 95  
 96      const customerCacheTag = await getCacheTag("customers")
 97      revalidateTag(customerCacheTag)
 98  
 99      await transferCart()
100  
101      return createdCustomer
102    } catch (error: any) {
103      return error.toString()
104    }
105  }
106  
107  export async function login(_currentState: unknown, formData: FormData) {
108    const email = formData.get("email") as string
109    const password = formData.get("password") as string
110  
111    try {
112      await sdk.auth
113        .login("customer", "emailpass", { email, password })
114        .then(async (token) => {
115          await setAuthToken(token as string)
116          const customerCacheTag = await getCacheTag("customers")
117          revalidateTag(customerCacheTag)
118        })
119    } catch (error: any) {
120      return error.toString()
121    }
122  
123    try {
124      await transferCart()
125    } catch (error: any) {
126      return error.toString()
127    }
128  }
129  
130  export async function signout(countryCode: string) {
131    await sdk.auth.logout()
132  
133    await removeAuthToken()
134  
135    const customerCacheTag = await getCacheTag("customers")
136    revalidateTag(customerCacheTag)
137  
138    await removeCartId()
139  
140    const cartCacheTag = await getCacheTag("carts")
141    revalidateTag(cartCacheTag)
142  
143    redirect(`/${countryCode}/account`)
144  }
145  
146  export async function transferCart() {
147    const cartId = await getCartId()
148  
149    if (!cartId) {
150      return
151    }
152  
153    const headers = await getAuthHeaders()
154  
155    await sdk.store.cart.transferCart(cartId, {}, headers)
156  
157    const cartCacheTag = await getCacheTag("carts")
158    revalidateTag(cartCacheTag)
159  }
160  
161  export const addCustomerAddress = async (
162    currentState: Record<string, unknown>,
163    formData: FormData
164  ): Promise<any> => {
165    const isDefaultBilling = (currentState.isDefaultBilling as boolean) || false
166    const isDefaultShipping = (currentState.isDefaultShipping as boolean) || false
167  
168    const address = {
169      first_name: formData.get("first_name") as string,
170      last_name: formData.get("last_name") as string,
171      company: formData.get("company") as string,
172      address_1: formData.get("address_1") as string,
173      address_2: formData.get("address_2") as string,
174      city: formData.get("city") as string,
175      postal_code: formData.get("postal_code") as string,
176      province: formData.get("province") as string,
177      country_code: formData.get("country_code") as string,
178      phone: formData.get("phone") as string,
179      is_default_billing: isDefaultBilling,
180      is_default_shipping: isDefaultShipping,
181    }
182  
183    const headers = {
184      ...(await getAuthHeaders()),
185    }
186  
187    return sdk.store.customer
188      .createAddress(address, {}, headers)
189      .then(async ({ customer }) => {
190        const customerCacheTag = await getCacheTag("customers")
191        revalidateTag(customerCacheTag)
192        return { success: true, error: null }
193      })
194      .catch((err) => {
195        return { success: false, error: err.toString() }
196      })
197  }
198  
199  export const deleteCustomerAddress = async (
200    addressId: string
201  ): Promise<void> => {
202    const headers = {
203      ...(await getAuthHeaders()),
204    }
205  
206    await sdk.store.customer
207      .deleteAddress(addressId, headers)
208      .then(async () => {
209        const customerCacheTag = await getCacheTag("customers")
210        revalidateTag(customerCacheTag)
211        return { success: true, error: null }
212      })
213      .catch((err) => {
214        return { success: false, error: err.toString() }
215      })
216  }
217  
218  export const updateCustomerAddress = async (
219    currentState: Record<string, unknown>,
220    formData: FormData
221  ): Promise<any> => {
222    const addressId =
223      (currentState.addressId as string) || (formData.get("addressId") as string)
224  
225    if (!addressId) {
226      return { success: false, error: "Address ID is required" }
227    }
228  
229    const address = {
230      first_name: formData.get("first_name") as string,
231      last_name: formData.get("last_name") as string,
232      company: formData.get("company") as string,
233      address_1: formData.get("address_1") as string,
234      address_2: formData.get("address_2") as string,
235      city: formData.get("city") as string,
236      postal_code: formData.get("postal_code") as string,
237      province: formData.get("province") as string,
238      country_code: formData.get("country_code") as string,
239    } as HttpTypes.StoreUpdateCustomerAddress
240  
241    const phone = formData.get("phone") as string
242  
243    if (phone) {
244      address.phone = phone
245    }
246  
247    const headers = {
248      ...(await getAuthHeaders()),
249    }
250  
251    return sdk.store.customer
252      .updateAddress(addressId, address, {}, headers)
253      .then(async () => {
254        const customerCacheTag = await getCacheTag("customers")
255        revalidateTag(customerCacheTag)
256        return { success: true, error: null }
257      })
258      .catch((err) => {
259        return { success: false, error: err.toString() }
260      })
261  }