Hi
@967091941873426493team!
I have an orders collection with an order
status
which has various payment/shipping statuses associated with the state of the order.
I would like to create a couple of hooks to do the following:
1. When I set a status of
order_ready_to_dispatch
I would like to create a new tracking request with my chosen courier, then write the response of that to the order record (I have these fields ready).
2. When I set a status of
order_shipped
I would like to create an email with details of the order, including the tracking information.
I have the email templates working and fire these off when I receive a payment_intent of succeeded in my stripe webhook.
I have a couple of questions around hooks:
1. Which hook should I use for these two use-cases?
2. How to prevent these from firing again if an order is updated and status remains the same; ie the status is
order_shipped
and I want to update any field. I wouldn't then want the email to sent again when I resave the record. Feels like I would need a log of events attached to the record ie every status changes writes a log? Or would an object of bools be better, allowing me to undo a state should something malfunction, thus then allowing the hook to fire again if needs be?
Advice here would be really welcome!
Thanks!
would an
afterChange
hook work for you? In this hook you can check your order status and perform additional actions based on it. To prevent duplicative hooks compare its value with another hidden field that you maintain. Here's a similar example to this:
https://github.com/payloadcms/payload/discussions/1996#discussioncomment-4885826Thanks
@808734492645785600- yeah that's what I was thinking to do (although keep the checkboxes visible, so can toggle/re-fire the actions if ever needs be).
Do you have some good examples of
afterChange
hooks, or good examples of hooks in general? I've not written one yet and would like to see how to do correctly.
PS Thanks for your work on the ecommerce boilerplate... it
reallyhelped me in getting my dynamic cart with payment_intents (and linking payload and stripe customers/orders together etc) working nicely.
What if instead of making a request when a field value is updated, you make it a custom REST endpoint or GraphQL mutation which modifies the field value? You can add a button somewhere if you need to call it manually. That would make the action more explicit.
That would make it more explicit I agree. If I could have this button on the order itself (in payload) that would work well I think... and could use the endpoint in the future on a admin dashboard etc.
Nice idea.
Do you know if it's easy to add a new button, which would then have access to the order item data (being inside the order collection record within payload).
sorry, meant to @ you in my reply 🙂
Adding button is also as simple as adding a field (
https://payloadcms.com/docs/fields/ui) though you need to create a component for it yourself. For that you probably need these React hooks (
https://payloadcms.com/docs/admin/hooks).
Thanks for the info
@378602619431682071- I'll take a look.
do you have any examples in any of your public repos for the use of a ui field type and a custom component?
It's not possible to use the buttons that are already a part of the admin ui??
There doesn't seem to be a component library exported from Payload, but maybe you can use the same classes 🤷 There's also SCSS variables and mixins that you can import if that's any use:
https://payloadcms.com/docs/admin/components#styling-custom-componentsLooking at the
website-cms
repo, they are using the admin ui components in a customisation of slatejs to support videos... so I guess I could use these too:
# ~/payloadcms/website-cms/src/fields/richText/video/Button/index.tsx
import { ElementButton } from 'payload/components/rich-text';
import { Form, Select, Text, Submit } from 'payload/components/forms';
import { MinimalTemplate, Button, X } from 'payload/components';
This feels like a lot of work, whereas the hook method is straightforward. I think i'll sleep on this!
The SEO plugin has some pretty good examples of this that I often share, check it out:
https://github.com/payloadcms/plugin-seo/blob/main/src/fields/MetaTitle.tsx.
@378602619431682071is right in that you create a field, assign your custom component to it, and use hooks within that component to interact with Payload state.
There doesn't seem to be a component library exported from Payload
Exactly, our Payload component library is not very well exported, this is a roadmap item we plan on tackling relatively soon, here are the details:
https://github.com/payloadcms/payload/discussions/293.
This feels like a lot of work, whereas the hook method is straightforward. I think i'll sleep on this!
This is 100% accurate. An
afterChange
hook is the best option here. This is where Payload shines.
Here's a demo hook based on your description. You could also place this hook on your
fielddirectly instead of the collection itself. BUT you'll need to add a second field to check the previous value against (here's an example:
https://github.com/payloadcms/payload/discussions/1996#discussioncomment-4885826)
{
slug: 'YOUR_COLLECTION',
hooks: {
afterChange: [
async ({ doc }) => {
const { orderStatus } = doc;
if (orderStatus === 'order_ready_to_dispatch') {
// Do something async, like update stock, etc
}
if (orderStatus === 'order_shipped') {
// Do something async, like send emails, etc
}
}
]
},
fields: [
{
name: 'orderStatus',
type: 'select',
options: [
{ label: 'Ready To Ship', value: 'order_ready_to_dispatch' },
{ label: 'Shipped', value: 'order_shipped' },
]
}
]
}
Hope this is helpful!
Thanks a lot for your help here, really great!
Star
Discord
online
Get dedicated engineering support directly from the Payload team.