chore: transfer repo
This commit is contained in:
251
components/cart/actions.ts
Normal file
251
components/cart/actions.ts
Normal file
@@ -0,0 +1,251 @@
|
||||
'use server';
|
||||
|
||||
import { TAGS } from 'lib/constants';
|
||||
import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
|
||||
import { revalidateTag } from 'next/cache';
|
||||
import { cookies } from 'next/headers';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export async function addItem(
|
||||
prevState: any,
|
||||
selectedVariantId: string | undefined,
|
||||
quantity: number = 1,
|
||||
attributes?: { key: string; value: string }[]
|
||||
) {
|
||||
const cookieStore = await cookies();
|
||||
let cartId = cookieStore.get('cartId')?.value;
|
||||
|
||||
if (!selectedVariantId) {
|
||||
return 'Error adding item to cart';
|
||||
}
|
||||
|
||||
try {
|
||||
if (!cartId) {
|
||||
const cart = await createCart();
|
||||
cartId = cart.id!;
|
||||
cookieStore.set('cartId', cartId);
|
||||
}
|
||||
|
||||
await addToCart(cartId, [{
|
||||
merchandiseId: selectedVariantId,
|
||||
quantity,
|
||||
attributes
|
||||
}]);
|
||||
revalidateTag(TAGS.cart);
|
||||
} catch (e) {
|
||||
return 'Error adding item to cart';
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeItem(prevState: any, merchandiseId: string, itemId?: string) {
|
||||
const cookieStore = await cookies();
|
||||
let cartId = cookieStore.get('cartId')?.value;
|
||||
|
||||
if (!cartId) {
|
||||
return 'Missing cart ID';
|
||||
}
|
||||
|
||||
try {
|
||||
const cart = await getCart(cartId);
|
||||
|
||||
if (!cart) {
|
||||
return 'Error fetching cart';
|
||||
}
|
||||
|
||||
// Find specific line item - first by itemId if provided, otherwise by merchandiseId
|
||||
let lineItem;
|
||||
|
||||
if (itemId) {
|
||||
// If we have a specific item ID (e.g., for box items), use that first
|
||||
lineItem = cart.lines.find((line) => line.id === itemId);
|
||||
}
|
||||
|
||||
// If no item ID was provided or no match was found, fall back to merchandise ID
|
||||
if (!lineItem) {
|
||||
lineItem = cart.lines.find((line) => line.merchandise.id === merchandiseId);
|
||||
}
|
||||
|
||||
if (lineItem && lineItem.id) {
|
||||
// Check if this is a box item being removed
|
||||
const lineAttributes = lineItem.attributes || [];
|
||||
const boxType = lineAttributes.find(attr => attr.key === '_box_type')?.value;
|
||||
const boxGroupId = lineAttributes.find(attr => attr.key === '_box_group_id')?.value;
|
||||
|
||||
// If this is a box item (not container), check if it's the last one before removing
|
||||
if (boxType === 'item' && boxGroupId) {
|
||||
// Find all items in this box (excluding the current one we're removing)
|
||||
const remainingBoxItems = cart.lines.filter(line => {
|
||||
const attrs = line.attributes || [];
|
||||
const itemBoxGroupId = attrs.find(attr => attr.key === '_box_group_id')?.value;
|
||||
const itemBoxType = attrs.find(attr => attr.key === '_box_type')?.value;
|
||||
|
||||
return itemBoxGroupId === boxGroupId &&
|
||||
line.id !== lineItem.id &&
|
||||
itemBoxType === 'item';
|
||||
});
|
||||
|
||||
// If this is the last item, find the box container and remove both together
|
||||
if (remainingBoxItems.length === 0) {
|
||||
const boxContainer = cart.lines.find(line => {
|
||||
const attrs = line.attributes || [];
|
||||
const containerBoxGroupId = attrs.find(attr => attr.key === '_box_group_id')?.value;
|
||||
const containerBoxType = attrs.find(attr => attr.key === '_box_type')?.value;
|
||||
|
||||
return containerBoxGroupId === boxGroupId && containerBoxType === 'container';
|
||||
});
|
||||
|
||||
// If box container exists, remove both item and container in a single operation
|
||||
if (boxContainer && boxContainer.id) {
|
||||
// Batched removal of both the item and box container
|
||||
await removeFromCart(cartId, [lineItem.id, boxContainer.id]);
|
||||
} else {
|
||||
// Just remove the item if no container found
|
||||
await removeFromCart(cartId, [lineItem.id]);
|
||||
}
|
||||
} else {
|
||||
// Not the last item, just remove this one
|
||||
await removeFromCart(cartId, [lineItem.id]);
|
||||
}
|
||||
} else {
|
||||
// Regular item or box container, just remove it
|
||||
await removeFromCart(cartId, [lineItem.id]);
|
||||
}
|
||||
|
||||
revalidateTag(TAGS.cart);
|
||||
} else {
|
||||
return 'Item not found in cart';
|
||||
}
|
||||
} catch (e) {
|
||||
return 'Error removing item from cart';
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateItemQuantity(
|
||||
prevState: any,
|
||||
payload: {
|
||||
merchandiseId: string;
|
||||
quantity: number;
|
||||
itemId?: string;
|
||||
}
|
||||
) {
|
||||
const cookieStore = await cookies();
|
||||
let cartId = cookieStore.get('cartId')?.value;
|
||||
|
||||
if (!cartId) {
|
||||
return 'Missing cart ID';
|
||||
}
|
||||
|
||||
const { merchandiseId, quantity, itemId } = payload;
|
||||
|
||||
try {
|
||||
const cart = await getCart(cartId);
|
||||
|
||||
if (!cart) {
|
||||
return 'Error fetching cart';
|
||||
}
|
||||
|
||||
// Find the specific line item to update
|
||||
let lineItem;
|
||||
|
||||
if (itemId) {
|
||||
// First try to find by specific item ID (for items in multiple boxes)
|
||||
lineItem = cart.lines.find(line => line.id === itemId);
|
||||
}
|
||||
|
||||
// Fall back to finding by merchandise ID if item ID didn't work
|
||||
if (!lineItem) {
|
||||
lineItem = cart.lines.find(line => line.merchandise.id === merchandiseId);
|
||||
}
|
||||
|
||||
if (lineItem && lineItem.id) {
|
||||
if (quantity === 0) {
|
||||
await removeFromCart(cartId, [lineItem.id]);
|
||||
} else {
|
||||
await updateCart(cartId, [
|
||||
{
|
||||
id: lineItem.id,
|
||||
merchandiseId,
|
||||
quantity
|
||||
}
|
||||
]);
|
||||
}
|
||||
} else if (quantity > 0) {
|
||||
// If the item doesn't exist in the cart and quantity > 0, add it
|
||||
await addToCart(cartId, [{ merchandiseId, quantity }]);
|
||||
}
|
||||
|
||||
revalidateTag(TAGS.cart);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return 'Error updating item quantity';
|
||||
}
|
||||
}
|
||||
|
||||
export async function redirectToCheckout() {
|
||||
const cookieStore = await cookies();
|
||||
let cartId = cookieStore.get('cartId')?.value;
|
||||
|
||||
if (!cartId) {
|
||||
return 'No cart found';
|
||||
}
|
||||
|
||||
let cart = await getCart(cartId);
|
||||
|
||||
if (!cart) {
|
||||
return 'Error fetching cart';
|
||||
}
|
||||
|
||||
if (!cart.checkoutUrl) {
|
||||
return 'No checkout URL available';
|
||||
}
|
||||
|
||||
redirect(cart.checkoutUrl);
|
||||
}
|
||||
|
||||
export async function createCartAndSetCookie() {
|
||||
const cookieStore = await cookies();
|
||||
let cart = await createCart();
|
||||
cookieStore.set('cartId', cart.id!);
|
||||
}
|
||||
|
||||
export async function validateDiscountCode(prevState: any, discountCode: string) {
|
||||
if (!discountCode || discountCode.trim() === '') {
|
||||
return {
|
||||
isValid: false,
|
||||
message: 'Please enter a discount code'
|
||||
};
|
||||
}
|
||||
|
||||
const cookieStore = await cookies();
|
||||
let cartId = cookieStore.get('cartId')?.value;
|
||||
|
||||
if (!cartId) {
|
||||
return {
|
||||
isValid: false,
|
||||
message: 'No cart found. Please add items to your cart first.'
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: Implement discount code validation
|
||||
const isValid = Math.random() > 0.5;
|
||||
|
||||
if (isValid) {
|
||||
return {
|
||||
isValid: true,
|
||||
message: 'Discount code applied successfully!'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
isValid: false,
|
||||
message: 'Invalid discount code. Please try again.'
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error validating discount code:', e);
|
||||
return {
|
||||
isValid: false,
|
||||
message: 'An error occurred while validating the discount code.'
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user