We developed the code to apply a discount in the cart. I would normally put in a pull request for this type of thing, but our code now has so many conflicts, it would be too complicated. I figured I'd just post the basic code here and hopefully it will help people who are looking to get this functionality. Adapt to your base code, obviously.
export async function applyDiscount(
prevState: any,
formData: FormData
) {
//console.log ("Form Data", formData)
const cartId = cookies().get('cartId')?.value;
if (!cartId) {
return 'Missing cart ID';
}
const schema = z.object({
discountCode: z.string().min(1),
});
const parse = schema.safeParse({
discountCode: formData.get("discountCode"),
});
if (!parse.success) {
return "Error applying discount. Discount code required.";
}
const data = parse.data;
let discountCodes = []; // Create a new empty array - actually this array should be the current array of discount codes, but as we only allow one code now, we create an empty array
discountCodes.push(data.discountCode); // Push the string into the array
// Ensure the discount codes are unique - this is not really necessary now, because we are only using one code
const uniqueCodes = discountCodes.filter((value, index, array) => {
return array.indexOf(value) === index;
});
try {
await updateDiscounts(cartId, uniqueCodes);
//close cart and have tooltip for c
revalidateTag(TAGS.cart);
} catch (e) {
return 'Error applying discount';
}
}
export async function removeDiscount(
prevState: any,
payload: {
discount: string;
discounts: string[];
}
) {
//console.log ("payload", payload)
const cartId = cookies().get('cartId')?.value;
if (!cartId) {
return 'Missing cart ID';
}
const code = payload?.discount
const codes = payload?.discounts ?? [] //the entire array of discounts
if (!code) {
return "Error removing discount. Discount code required.";
}
let discountCodes = codes;
//remove the code from the array and return the array
let newCodes = discountCodes.filter(item => item !== code);
try {
await updateDiscounts(cartId, newCodes);
//close cart and have tooltip for c
revalidateTag(TAGS.cart);
} catch (e) {
return 'Error applying discount';
}
}
Add a Form Component in your Modal for the cart that is something like this (we use Shadcn, so many our components come from there)
export function ApplyCartDiscount({ cart }: { cart: Cart }) {
const [message, formAction] = useFormState(applyDiscount, null);
//console.log('Cart Discount Codes', cart?.discountCodes);
//filter the discount codes to remove those where applicablce is false and then jsut get the code in array
//if we have a discount code we don't show the form
const filteredCodes =
cart?.discountCodes && cart?.discountCodes.length
? cart?.discountCodes.filter((code) => code.applicable).map((code) => code.code)
: [];
We developed the code to apply a discount in the cart. I would normally put in a pull request for this type of thing, but our code now has so many conflicts, it would be too complicated. I figured I'd just post the basic code here and hopefully it will help people who are looking to get this functionality. Adapt to your base code, obviously.
Add a Function in lib/shopify/index where all the functions are:
Add an Action in cart/actions.ts
Add a Form Component in your Modal for the cart that is something like this (we use Shadcn, so many our components come from there)
export function ApplyCartDiscount({ cart }: { cart: Cart }) { const [message, formAction] = useFormState(applyDiscount, null); //console.log('Cart Discount Codes', cart?.discountCodes); //filter the discount codes to remove those where applicablce is false and then jsut get the code in array //if we have a discount code we don't show the form const filteredCodes = cart?.discountCodes && cart?.discountCodes.length ? cart?.discountCodes.filter((code) => code.applicable).map((code) => code.code) : [];
return ( <> {filteredCodes && filteredCodes.length > 0 ? (
); }