commerce icon indicating copy to clipboard operation
commerce copied to clipboard

[BC] Feature request - Integration of the route /subscriptions

Open Florian-crg opened this issue 4 years ago • 6 comments
trafficstars

https://developer.bigcommerce.com/api-reference/storefront/storefront-subscriptions/subscription/postsubscriptions

Florian-crg avatar Sep 12 '21 08:09 Florian-crg

Super easy to implement on your own. In framework/bigcommerce create api endpoint subscribe and make it somewhat similar to this

const { data } = await config.storeApiFetch('/v3/customers/subscribers', {
      method: 'POST',
      body: JSON.stringify(
        {
          ...(firstName && { first_name: firstName }),
          ...(lastName && { last_name: lastName }),
          email,
        },
      ),
    })

I made name and last name conditional because BC API doesn't require them

Then just make a use-subscribe hook

import { useCallback } from 'react'
import type { MutationHook } from '@commerce/utils/types'
import { CommerceError } from '@commerce/utils/errors'
import useSubscribe, { UseSubscribe } from '@commerce/customer/use-subscribe'
import type { SubscriberHook } from '../types/subscribe'


export default useSubscribe as UseSubscribe<typeof handler>

export const handler: MutationHook<SubscriberHook> = {
  fetchOptions: {
    url: '/api/subscribe',
    method: 'POST',
  },
  async fetcher({ input: { email, firstName, lastName }, options, fetch }) {
    if (!(email)) {
      throw new CommerceError({
        message:
          'An email is required to subscribe',
      })
    }

    return fetch({
      ...options,
      body: { email, firstName, lastName },
    })
  },
  useHook: ({ fetch }) => () => {

    return useCallback(
      async function subscribe(input) {
        const data = await fetch({ input })
        return data
      },
      [fetch]
    )
  },
}

For my project I made types for everything extra so thats why they are imported but you can take those out I guess if you need this functionality urgently. Also you will need to add it to the provider files and commerce folder

kogan007 avatar Sep 15 '21 04:09 kogan007

What is in your @commerce/customer/use-subscribe ? Do you have a working exemple somewhere ?

I wrote the code bellow, inspired from the use-signup.

import { useHook, useMutationHook } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher'
import type { HookFetcherFn, MutationHook } from '../utils/types'
import type { SubscriptionsHook } from '../types/subscriptions'
import type { Provider } from '..'

export type UseSubscribe<
    H extends MutationHook<SubscriptionsHook<any>> = MutationHook<SubscriptionsHook>
    > = ReturnType<H['useHook']>

export const fetcher: HookFetcherFn<SubscriptionsHook> = mutationFetcher

const fn = (provider: Provider) => provider.subscriptions?.useSubscriptions!

const useSubscribe: UseSubscribe = (...args) => {
    const hook = useHook(fn)
    return useMutationHook({ fetcher, ...hook })(...args)
}

export default useSubscribe

Florian-crg avatar Sep 15 '21 16:09 Florian-crg

What is in your @commerce/customer/use-subscribe ? Do you have a working exemple somewhere ?

I wrote the code bellow, inspired from the use-signup.

import { useHook, useMutationHook } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher'
import type { HookFetcherFn, MutationHook } from '../utils/types'
import type { SubscriptionsHook } from '../types/subscriptions'
import type { Provider } from '..'

export type UseSubscribe<
    H extends MutationHook<SubscriptionsHook<any>> = MutationHook<SubscriptionsHook>
    > = ReturnType<H['useHook']>

export const fetcher: HookFetcherFn<SubscriptionsHook> = mutationFetcher

const fn = (provider: Provider) => provider.subscriptions?.useSubscriptions!

const useSubscribe: UseSubscribe = (...args) => {
    const hook = useHook(fn)
    return useMutationHook({ fetcher, ...hook })(...args)
}

export default useSubscribe

Yeah mine is super similar to yours. Unfortunately my only example is in a project I'm using for work so I can't share it.

import { mutationFetcher } from '../utils/default-fetcher'
import type { MutationHook, HookFetcherFn } from '../utils/types'
import type { SubscriberHook } from '../types/subscribe'
import type { Provider } from '..'

export type UseSubscribe<
  H extends MutationHook<SubscriberHook<any>> = MutationHook<SubscriberHook>
> = ReturnType<H['useHook']>

export const fetcher: HookFetcherFn<SubscriberHook> = mutationFetcher

const fn = (provider: Provider) => provider.subscribe?.useSubscribe!

const useSubscribe: UseSubscribe = (...args) => {
  const hook = useHook(fn)
  return useMutationHook({ fetcher, ...hook })(...args)
}

export default useSubscribe

This is what mine looks like. Just don't forget to create those types for the hook, the input, result, etc and add it to the provider

kogan007 avatar Sep 15 '21 16:09 kogan007

I understand, thanks for your help though.

Yes they are similar :/ I am facing the error triggered due to these lines I guess

const useSubscribe: UseSubscribe = (...args) => {
    const hook = useHook(fn)
    return useMutationHook({ fetcher, ...hook })(...args)
}

Where it says that TypeError: hook.useHook is not a function in framework/commerce/utils/use-hook.ts :/

Idk what I am doing wrong, I tried to make the same implementation of what already exist..

Florian-crg avatar Sep 28 '21 07:09 Florian-crg

Make sure you're not forgetting to add the hook in bigcommerce/provider.ts and likewise in commerce/index.tsx

kogan007 avatar Oct 08 '21 16:10 kogan007

Thx it works better now ;)

Florian-crg avatar Oct 09 '21 08:10 Florian-crg

Hey there! Thank you for opening this issue. We have decided to take Next.js Commerce in a new direction and will be closing out current PRs and issues due to this change. Please see this PR for more details: https://github.com/vercel/commerce/pull/966

leerob avatar Apr 18 '23 02:04 leerob