diff --git a/package-lock.json b/package-lock.json index 95684bd0..ad80bffb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "dependencies": { "@next/third-parties": "^16.1.6", "@sentry/nextjs": "^10.38.0", - "@spree/next": "^0.13.0", - "@spree/sdk": "^0.13.0", + "@spree/next": "^0.14.1", + "@spree/sdk": "^0.14.2", "@stripe/react-stripe-js": "^5.6.0", "@stripe/stripe-js": "^8.7.0", "class-variance-authority": "^0.7.1", @@ -5485,20 +5485,20 @@ } }, "node_modules/@spree/next": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@spree/next/-/next-0.13.0.tgz", - "integrity": "sha512-uHIlYjUMmcbRaq3mnxRCNUmeMYggjO3PvfzCRDkyiik5kqf36xoykmBQMZbY3BaHju2+a8+T4apZoyMtE7SDsA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@spree/next/-/next-0.14.1.tgz", + "integrity": "sha512-W1KOEyhWBSVkDmOg/gExBx7Q3zDR9ZfvSV4f5An4I5h0/oQuHX2MZpZW9gallVttuCXVrMEd8kZhwn66LRg2Sw==", "license": "MIT", "peerDependencies": { - "@spree/sdk": ">=0.13.0", + "@spree/sdk": ">=0.14.2", "next": ">=15.0.0", "react": ">=19.0.0" } }, "node_modules/@spree/sdk": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@spree/sdk/-/sdk-0.13.0.tgz", - "integrity": "sha512-vm/j9/EDvObyhBx84PcCa9ok2n3RCINIxAnn8Yid8XSuvE3Lcm5dLtSsasVfS6iztLHMKVWuBa4u4Ux9zWnCIA==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@spree/sdk/-/sdk-0.14.2.tgz", + "integrity": "sha512-ahUW/ZbGhVAfL8DRtDUHIdpAkXHLa6GTx0AUXfaqXRQgXFvHp5vMkQd0+NY5Ykxt61Vwp2/wxGVnSvXK6990Fw==", "license": "MIT", "engines": { "node": ">=18.0.0" diff --git a/package.json b/package.json index f398dfde..8480ef5b 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "dependencies": { "@next/third-parties": "^16.1.6", "@sentry/nextjs": "^10.38.0", - "@spree/next": "^0.13.0", - "@spree/sdk": "^0.13.0", + "@spree/next": "^0.14.1", + "@spree/sdk": "^0.14.2", "@stripe/react-stripe-js": "^5.6.0", "@stripe/stripe-js": "^8.7.0", "class-variance-authority": "^0.7.1", diff --git a/src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx b/src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx index b5f2aad7..8cb45952 100644 --- a/src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx +++ b/src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx @@ -230,8 +230,8 @@ export default function CheckoutPage({ params }: CheckoutPageProps) { const handleAutoSave = useCallback( async (addressData: { email: string; - ship_address?: AddressParams; - ship_address_id?: string; + shipping_address?: AddressParams; + shipping_address_id?: string; }) => { const currentOrder = cartRef.current; if (!currentOrder) return; @@ -242,11 +242,11 @@ export default function CheckoutPage({ params }: CheckoutPageProps) { try { const updateResult = await updateOrderAddresses(currentOrder.id, { email: addressData.email, - ...(addressData.ship_address && { - ship_address: addressData.ship_address, + ...(addressData.shipping_address && { + shipping_address: addressData.shipping_address, }), - ...(addressData.ship_address_id && { - ship_address_id: addressData.ship_address_id, + ...(addressData.shipping_address_id && { + shipping_address_id: addressData.shipping_address_id, }), }); @@ -315,7 +315,10 @@ export default function CheckoutPage({ params }: CheckoutPageProps) { // Handle billing address update (called by PaymentSection before gateway confirmation) const handleUpdateBillingAddress = useCallback( - async (data: { bill_address: AddressParams }): Promise => { + async (data: { + billing_address?: AddressParams; + use_shipping?: boolean; + }): Promise => { const currentOrder = cartRef.current; if (!currentOrder) return false; @@ -323,7 +326,10 @@ export default function CheckoutPage({ params }: CheckoutPageProps) { try { const updateResult = await updateOrderAddresses(currentOrder.id, { - bill_address: data.bill_address, + ...(data.billing_address && { + billing_address: data.billing_address, + }), + ...(data.use_shipping && { use_shipping: data.use_shipping }), }); if (!updateResult.success) { diff --git a/src/app/[country]/[locale]/(checkout)/order-placed/[id]/page.tsx b/src/app/[country]/[locale]/(checkout)/order-placed/[id]/page.tsx index 8d55195d..9d0ead80 100644 --- a/src/app/[country]/[locale]/(checkout)/order-placed/[id]/page.tsx +++ b/src/app/[country]/[locale]/(checkout)/order-placed/[id]/page.tsx @@ -106,7 +106,7 @@ export default function OrderPlacedPage({ params }: OrderPlacedPageProps) { } const customerName = - order.bill_address?.full_name || order.ship_address?.full_name || ""; + order.billing_address?.full_name || order.shipping_address?.full_name || ""; return (
@@ -168,14 +168,15 @@ export default function OrderPlacedPage({ params }: OrderPlacedPageProps) { {order.display_delivery_total}
- {order.promo_total && Number.parseFloat(order.promo_total) !== 0 && ( -
- Discount - - {order.display_promo_total} - -
- )} + {order.discount_total && + Number.parseFloat(order.discount_total) !== 0 && ( +
+ Discount + + {order.display_discount_total} + +
+ )}
Tax {order.display_tax_total} @@ -202,55 +203,57 @@ export default function OrderPlacedPage({ params }: OrderPlacedPageProps) { )}
- {order.ship_address && ( + {order.shipping_address && (

Shipping Address

- {order.ship_address.full_name} + {order.shipping_address.full_name}

- {order.ship_address.company && ( -

{order.ship_address.company}

+ {order.shipping_address.company && ( +

{order.shipping_address.company}

)} -

{order.ship_address.address1}

- {order.ship_address.address2 && ( -

{order.ship_address.address2}

+

{order.shipping_address.address1}

+ {order.shipping_address.address2 && ( +

{order.shipping_address.address2}

)}

- {order.ship_address.city}, {order.ship_address.state_text}{" "} - {order.ship_address.zipcode} + {order.shipping_address.city},{" "} + {order.shipping_address.state_text}{" "} + {order.shipping_address.postal_code}

-

{order.ship_address.country_name}

- {order.ship_address.phone && ( -

{order.ship_address.phone}

+

{order.shipping_address.country_name}

+ {order.shipping_address.phone && ( +

{order.shipping_address.phone}

)}
)} - {order.bill_address && ( + {order.billing_address && (

Billing Address

- {order.bill_address.full_name} + {order.billing_address.full_name}

- {order.bill_address.company && ( -

{order.bill_address.company}

+ {order.billing_address.company && ( +

{order.billing_address.company}

)} -

{order.bill_address.address1}

- {order.bill_address.address2 && ( -

{order.bill_address.address2}

+

{order.billing_address.address1}

+ {order.billing_address.address2 && ( +

{order.billing_address.address2}

)}

- {order.bill_address.city}, {order.bill_address.state_text}{" "} - {order.bill_address.zipcode} + {order.billing_address.city},{" "} + {order.billing_address.state_text}{" "} + {order.billing_address.postal_code}

-

{order.bill_address.country_name}

+

{order.billing_address.country_name}

)} diff --git a/src/app/[country]/[locale]/(storefront)/cart/page.tsx b/src/app/[country]/[locale]/(storefront)/cart/page.tsx index 2d761259..b8a2ca24 100644 --- a/src/app/[country]/[locale]/(storefront)/cart/page.tsx +++ b/src/app/[country]/[locale]/(storefront)/cart/page.tsx @@ -20,7 +20,12 @@ export default function CartPage() { // Track view_cart when cart loads with items useEffect(() => { - if (!loading && cart && cart.item_count > 0 && !viewCartFiredRef.current) { + if ( + !loading && + cart && + cart.total_quantity > 0 && + !viewCartFiredRef.current + ) { trackViewCart(cart); viewCartFiredRef.current = true; } @@ -141,10 +146,10 @@ export default function CartPage() {
Subtotal
{cart.display_item_total}
- {cart.promo_total && parseFloat(cart.promo_total) < 0 && ( + {cart.discount_total && parseFloat(cart.discount_total) < 0 && (
Discount
-
{cart.display_promo_total}
+
{cart.display_discount_total}
)} {cart.delivery_total && parseFloat(cart.delivery_total) > 0 && ( diff --git a/src/components/account/CreditCardList.tsx b/src/components/account/CreditCardList.tsx index 3140e43f..044f0520 100644 --- a/src/components/account/CreditCardList.tsx +++ b/src/components/account/CreditCardList.tsx @@ -41,13 +41,13 @@ function CreditCardItem({

- {getCardLabel(card.cc_type)} ending in {card.last_digits} + {getCardLabel(card.brand)} ending in {card.last4}

Exp {String(card.month).padStart(2, "0")}/{card.year} @@ -73,9 +73,8 @@ function CreditCardItem({ Remove payment method? - This will remove the {getCardLabel(card.cc_type)} ending in{" "} - {card.last_digits} from your account. This action cannot be - undone. + This will remove the {getCardLabel(card.brand)} ending in{" "} + {card.last4} from your account. This action cannot be undone. diff --git a/src/components/account/OrderDetail.tsx b/src/components/account/OrderDetail.tsx index e77c7e2c..b019191f 100644 --- a/src/components/account/OrderDetail.tsx +++ b/src/components/account/OrderDetail.tsx @@ -23,13 +23,13 @@ function PaymentSourceInfo({ payment }: { payment: Payment }) { return (

- {getCardLabel(card.cc_type)} ending in {card.last_digits} + {getCardLabel(card.brand)} ending in {card.last4}

Expires {String(card.month).padStart(2, "0")}/{card.year} @@ -67,7 +67,7 @@ function AddressBlock({ address }: { address: Address }) {

{address.address1}

{address.address2 &&

{address.address2}

}

- {address.city}, {address.state_text} {address.zipcode} + {address.city}, {address.state_text} {address.postal_code}

{address.country_name}

{address.phone &&

{address.phone}

} @@ -255,7 +255,7 @@ export function OrderDetail({ order, basePath }: OrderDetailProps) { @@ -273,23 +273,23 @@ export function OrderDetail({ order, basePath }: OrderDetailProps) {
)} - {order.special_instructions && ( + {order.customer_note && (

- Special Instructions + Customer Note

-

{order.special_instructions}

+

{order.customer_note}

)}
- {order.bill_address && ( + {order.billing_address && (

Billing Address

- +
)} {order.payments && order.payments.length > 0 && ( @@ -324,14 +324,15 @@ export function OrderDetail({ order, basePath }: OrderDetailProps) { {order.display_delivery_total}
- {order.promo_total && Number.parseFloat(order.promo_total) !== 0 && ( -
- Discount - - {order.display_promo_total} - -
- )} + {order.discount_total && + Number.parseFloat(order.discount_total) !== 0 && ( +
+ Discount + + {order.display_discount_total} + +
+ )} {Number.parseFloat(order.tax_total) > 0 && (
Tax diff --git a/src/components/addresses/AddressManagement.tsx b/src/components/addresses/AddressManagement.tsx index 44553e9a..54cc3588 100644 --- a/src/components/addresses/AddressManagement.tsx +++ b/src/components/addresses/AddressManagement.tsx @@ -50,7 +50,7 @@ function AddressCard({ address, onEdit, onDelete }: AddressCardProps) {

{address.address1}

{address.address2 &&

{address.address2}

}

- {address.city}, {address.state_text} {address.zipcode} + {address.city}, {address.state_text} {address.postal_code}

{address.country_name}

{address.phone &&

{address.phone}

} diff --git a/src/components/cart/CartDrawer.tsx b/src/components/cart/CartDrawer.tsx index e5756dda..a499f9ad 100644 --- a/src/components/cart/CartDrawer.tsx +++ b/src/components/cart/CartDrawer.tsx @@ -44,7 +44,12 @@ export function CartDrawer() { // Track view_cart when drawer opens with items (fire once per open) useEffect(() => { - if (isOpen && cart && cart.item_count > 0 && !viewCartFiredRef.current) { + if ( + isOpen && + cart && + cart.total_quantity > 0 && + !viewCartFiredRef.current + ) { trackViewCart(cart); viewCartFiredRef.current = true; } @@ -216,10 +221,10 @@ export function CartDrawer() { Subtotal {cart?.display_item_total}
- {cart?.promo_total && parseFloat(cart.promo_total) < 0 && ( + {cart?.discount_total && parseFloat(cart.discount_total) < 0 && (
Discount - {cart.display_promo_total} + {cart.display_discount_total}
)}
diff --git a/src/components/checkout/AddressEditModal.tsx b/src/components/checkout/AddressEditModal.tsx index 519489b3..15174500 100644 --- a/src/components/checkout/AddressEditModal.tsx +++ b/src/components/checkout/AddressEditModal.tsx @@ -19,12 +19,12 @@ import { AddressFormFields } from "./AddressFormFields"; interface AddressEditModalProps { address: { id?: string; - firstname: string | null; - lastname: string | null; + first_name: string | null; + last_name: string | null; address1: string | null; address2: string | null; city: string | null; - zipcode: string | null; + postal_code: string | null; phone: string | null; company: string | null; country_iso: string; diff --git a/src/components/checkout/AddressFormFields.tsx b/src/components/checkout/AddressFormFields.tsx index 7f903774..ec5b30f2 100644 --- a/src/components/checkout/AddressFormFields.tsx +++ b/src/components/checkout/AddressFormFields.tsx @@ -54,19 +54,19 @@ export function AddressFormFields({
onChange("firstname", e.target.value)} + value={address.first_name} + onChange={(e) => onChange("first_name", e.target.value)} placeholder="First name (optional)" /> onChange("lastname", e.target.value)} + value={address.last_name} + onChange={(e) => onChange("last_name", e.target.value)} placeholder="Last name" />
@@ -152,11 +152,11 @@ export function AddressFormFields({ )} onChange("zipcode", e.target.value)} + value={address.postal_code} + onChange={(e) => onChange("postal_code", e.target.value)} placeholder="ZIP code" />
diff --git a/src/components/checkout/AddressSection.tsx b/src/components/checkout/AddressSection.tsx index 27f25b7f..f932a5b2 100644 --- a/src/components/checkout/AddressSection.tsx +++ b/src/components/checkout/AddressSection.tsx @@ -26,8 +26,8 @@ interface AddressSectionProps { onEmailBlur: (email: string) => Promise; onAutoSave: (data: { email: string; - ship_address?: AddressParams; - ship_address_id?: string; + shipping_address?: AddressParams; + shipping_address_id?: string; }) => Promise; onUpdateSavedAddress?: ( id: string, @@ -39,10 +39,10 @@ interface AddressSectionProps { } const REQUIRED_ADDRESS_FIELDS: (keyof AddressFormData)[] = [ - "lastname", + "last_name", "address1", "city", - "zipcode", + "postal_code", "country_iso", ]; @@ -56,9 +56,12 @@ function buildAutoSaveHash( savedAddressId?: string, ): string { if (savedAddressId) { - return JSON.stringify({ email, ship_address_id: savedAddressId }); + return JSON.stringify({ email, shipping_address_id: savedAddressId }); } - return JSON.stringify({ email, ship_address: formDataToAddress(address) }); + return JSON.stringify({ + email, + shipping_address: formDataToAddress(address), + }); } export function AddressSection({ @@ -78,7 +81,9 @@ export function AddressSection({ // Determine initial saved address: use the first saved address when the // cart doesn't have a shipping address yet (authenticated users). const initialSavedAddress = - !cart.ship_address && isAuthenticated && initialSavedAddresses.length > 0 + !cart.shipping_address && + isAuthenticated && + initialSavedAddresses.length > 0 ? initialSavedAddresses[0] : undefined; @@ -86,7 +91,7 @@ export function AddressSection({ const [shipAddress, setShipAddress] = useState(() => initialSavedAddress ? addressToFormData(initialSavedAddress) - : addressToFormData(cart.ship_address), + : addressToFormData(cart.shipping_address), ); const [savedAddresses, setSavedAddresses] = useState(initialSavedAddresses); const [editingAddress, setEditingAddress] = useState
(null); @@ -123,7 +128,7 @@ export function AddressSection({ try { await onAutoSave({ email: currentEmail, - ship_address_id: savedAddrId, + shipping_address_id: savedAddrId, }); lastSavedRef.current = hash; } catch { @@ -139,7 +144,7 @@ export function AddressSection({ try { await onAutoSave({ email: currentEmail, - ship_address: formDataToAddress(currentAddress), + shipping_address: formDataToAddress(currentAddress), }); lastSavedRef.current = hash; } catch { diff --git a/src/components/checkout/AddressSelector.tsx b/src/components/checkout/AddressSelector.tsx index d3b9ad04..05656b3d 100644 --- a/src/components/checkout/AddressSelector.tsx +++ b/src/components/checkout/AddressSelector.tsx @@ -39,7 +39,7 @@ export function AddressSelector({ (addr) => addr.address1 === currentAddress.address1 && addr.city === currentAddress.city && - addr.zipcode === currentAddress.zipcode && + addr.postal_code === currentAddress.postal_code && addr.country_iso === currentAddress.country_iso, ); if (match) return match.id; @@ -48,19 +48,19 @@ export function AddressSelector({ savedAddresses, currentAddress.address1, currentAddress.city, - currentAddress.zipcode, + currentAddress.postal_code, currentAddress.country_iso, ]); const handleSelectAddress = (addressId: string) => { if (addressId === "new") { // Clear form for new address - onChange("firstname", ""); - onChange("lastname", ""); + onChange("first_name", ""); + onChange("last_name", ""); onChange("address1", ""); onChange("address2", ""); onChange("city", ""); - onChange("zipcode", ""); + onChange("postal_code", ""); onChange("phone", ""); onChange("company", ""); onChange("country_iso", ""); @@ -116,8 +116,8 @@ export function AddressSelector({

{address.address1} {address.address2 && `, ${address.address2}`}, {address.city},{" "} - {address.state_text || address.state_name} {address.zipcode},{" "} - {address.country_name} + {address.state_text || address.state_name}{" "} + {address.postal_code}, {address.country_name}

{onEditAddress && ( diff --git a/src/components/checkout/CouponCode.tsx b/src/components/checkout/CouponCode.tsx index 36fecd90..be1ab046 100644 --- a/src/components/checkout/CouponCode.tsx +++ b/src/components/checkout/CouponCode.tsx @@ -18,8 +18,8 @@ export function CouponCode({ cart, onApply, onRemove }: CouponCodeProps) { const [removing, setRemoving] = useState(null); const [error, setError] = useState(null); - const appliedPromotions = cart.promotions || []; - const couponPromotions = appliedPromotions.filter( + const appliedDiscounts = cart.discounts || []; + const couponPromotions = appliedDiscounts.filter( (p): p is typeof p & { code: string } => !!p.code, ); diff --git a/src/components/checkout/PaymentSection.tsx b/src/components/checkout/PaymentSection.tsx index 3195c32a..b089c6cc 100644 --- a/src/components/checkout/PaymentSection.tsx +++ b/src/components/checkout/PaymentSection.tsx @@ -31,7 +31,6 @@ import { getCreditCards } from "@/lib/data/credit-cards"; import { createCheckoutPaymentSession } from "@/lib/data/payment"; import { type AddressFormData, - addressesMatch, addressToFormData, formDataToAddress, updateAddressField, @@ -49,7 +48,8 @@ interface PaymentSectionProps { isAuthenticated: boolean; fetchStates: (countryIso: string) => Promise; onUpdateBillingAddress: (data: { - bill_address: AddressParams; + billing_address?: AddressParams; + use_shipping?: boolean; }) => Promise; onPaymentComplete: (paymentSessionId: string) => Promise; processing: boolean; @@ -76,15 +76,15 @@ export const PaymentSection = forwardRef< ) { // Initialize billing address from cart, check if it matches shipping const shipAddressData = useMemo( - () => addressToFormData(cart.ship_address), - [cart.ship_address], + () => addressToFormData(cart.shipping_address), + [cart.shipping_address], ); const billAddressData = useMemo( - () => addressToFormData(cart.bill_address), - [cart.bill_address], + () => addressToFormData(cart.billing_address), + [cart.billing_address], ); const initialUseShipping = - !cart.bill_address || addressesMatch(shipAddressData, cart.bill_address); + !cart.billing_address || cart.shipping_eq_billing_address; const [billAddress, setBillAddress] = useState( initialUseShipping ? shipAddressData : billAddressData, @@ -258,12 +258,17 @@ export const PaymentSection = forwardRef< try { // 1. Update billing address - const billingData = formDataToAddress( - useShippingForBilling ? shipAddressData : billAddress, - ); - const addressSuccess = await onUpdateBillingAddress({ - bill_address: billingData, - }); + let addressSuccess: boolean; + if (useShippingForBilling) { + addressSuccess = await onUpdateBillingAddress({ + use_shipping: true, + }); + } else { + const billingData = formDataToAddress(billAddress); + addressSuccess = await onUpdateBillingAddress({ + billing_address: billingData, + }); + } if (!addressSuccess) { setProcessing(false); @@ -368,12 +373,12 @@ export const PaymentSection = forwardRef< value={card.gateway_payment_profile_id ?? card.id} /> - {getCardLabel(card.cc_type)} ending in {card.last_digits} + {getCardLabel(card.brand)} ending in {card.last4} Exp {String(card.month).padStart(2, "0")}/{card.year} diff --git a/src/components/checkout/Summary.tsx b/src/components/checkout/Summary.tsx index e387b47b..540f4326 100644 --- a/src/components/checkout/Summary.tsx +++ b/src/components/checkout/Summary.tsx @@ -65,10 +65,12 @@ export function Summary({ cart }: SummaryProps) { )}
- {parseFloat(cart.promo_total) !== 0 && ( + {cart.discount_total && parseFloat(cart.discount_total) !== 0 && (
Discount - {cart.display_promo_total} + + {cart.display_discount_total} +
)} diff --git a/src/components/products/VariantPicker.tsx b/src/components/products/VariantPicker.tsx index 7eb563e8..0dcb014a 100644 --- a/src/components/products/VariantPicker.tsx +++ b/src/components/products/VariantPicker.tsx @@ -136,12 +136,12 @@ export function VariantPicker({
- {optionType.presentation} + {optionType.label} {selectedValue && ( - {getOptionValueDetails(optionType.id, selectedValue) - ?.presentation || selectedValue} + {getOptionValueDetails(optionType.id, selectedValue)?.label || + selectedValue} )}
@@ -166,7 +166,7 @@ export function VariantPicker({ key={value} onClick={() => handleOptionSelect(optionType.id, value)} disabled={!isAvailable} - title={optionValue?.presentation || value} + title={optionValue?.label || value} className={` w-10 h-10 rounded-lg border-1 transition-all relative ${isSelected ? "border-gray-900 ring-2 ring-primary ring-offset-2" : "border-gray-200"} @@ -213,7 +213,7 @@ export function VariantPicker({ : "" } > - {optionValue?.presentation || value} + {optionValue?.label || value} {!isPurchasable && isAvailable && ( (Out of stock) diff --git a/src/components/products/filters/FilterChips.tsx b/src/components/products/filters/FilterChips.tsx index fe56ef5a..25bb9c23 100644 --- a/src/components/products/filters/FilterChips.tsx +++ b/src/components/products/filters/FilterChips.tsx @@ -44,7 +44,7 @@ export function FilterChips({ if (option) { chips.push({ key: `option-${optionValueId}`, - label: `${optionFilter.presentation}: ${option.presentation}`, + label: `${optionFilter.label}: ${option.label}`, onRemove: () => onRemoveOptionValue(optionValueId), }); } diff --git a/src/components/products/filters/MobileFilterDrawer.tsx b/src/components/products/filters/MobileFilterDrawer.tsx index b6f84140..a598244c 100644 --- a/src/components/products/filters/MobileFilterDrawer.tsx +++ b/src/components/products/filters/MobileFilterDrawer.tsx @@ -168,12 +168,12 @@ function MobileOptionSection({ selectedValues: string[]; onToggle: (id: string) => void; }) { - const isColorFilter = isColorOption(filter.presentation); + const isColorFilter = isColorOption(filter.label); return (

- {filter.presentation} + {filter.label}

{isColorFilter ? (
@@ -196,13 +196,13 @@ function MobileOptionSection({ : "border-gray-200" }`} style={{ - backgroundColor: resolveColor(option.presentation), + backgroundColor: resolveColor(option.label), }} /> - {option.presentation} + {option.label} ({option.count}) {isSelected && ( @@ -228,7 +228,7 @@ function MobileOptionSection({ : "border-gray-300 text-gray-700 hover:border-gray-400" }`} > - {option.presentation} + {option.label} ); })} diff --git a/src/components/products/filters/OptionDropdownContent.tsx b/src/components/products/filters/OptionDropdownContent.tsx index 27eff052..96c02cf2 100644 --- a/src/components/products/filters/OptionDropdownContent.tsx +++ b/src/components/products/filters/OptionDropdownContent.tsx @@ -13,7 +13,7 @@ export function OptionDropdownContent({ selectedValues, onToggle, }: OptionDropdownContentProps) { - const isColorFilter = isColorOption(filter.presentation); + const isColorFilter = isColorOption(filter.label); return ( <> @@ -30,11 +30,11 @@ export function OptionDropdownContent({ )} - {option.presentation} + {option.label} ({option.count}) diff --git a/src/components/products/filters/ProductFilters.tsx b/src/components/products/filters/ProductFilters.tsx index b67edad8..32f76917 100644 --- a/src/components/products/filters/ProductFilters.tsx +++ b/src/components/products/filters/ProductFilters.tsx @@ -160,7 +160,7 @@ export const FilterBar = memo(function FilterBar({ {optionFilters.map((filter) => ( toggleDropdown(filter.id)} diff --git a/src/lib/analytics/gtm.ts b/src/lib/analytics/gtm.ts index b1245f02..d6d2f404 100644 --- a/src/lib/analytics/gtm.ts +++ b/src/lib/analytics/gtm.ts @@ -107,9 +107,10 @@ export function mapLineItemToGA4Item( item.item_list_name = options.listName; } - const promoTotal = safeParseFloat(lineItem.promo_total); - if (promoTotal < 0) { - item.discount = Math.abs(promoTotal); + const discountTotal = safeParseFloat(lineItem.discount_total); + if (discountTotal < 0) { + const quantity = Math.max(lineItem.quantity ?? 1, 1); + item.discount = Math.abs(discountTotal) / quantity; } return item; @@ -218,7 +219,7 @@ function buildOrderEcommercePayload( order: Cart | Order, extras?: Record, ): Record { - const coupon = order.promotions?.[0]?.code; + const coupon = order.discounts?.find((d) => d.code)?.code; return { currency: order.currency, value: safeParseFloat(order.total), diff --git a/src/lib/data/checkout.ts b/src/lib/data/checkout.ts index 9a8aa35d..c953a2ef 100644 --- a/src/lib/data/checkout.ts +++ b/src/lib/data/checkout.ts @@ -38,10 +38,11 @@ export async function getCompletedOrder(cartId: string): Promise { export async function updateOrderAddresses( cartId: string, addresses: { - ship_address?: AddressParams; - bill_address?: AddressParams; - ship_address_id?: string; - bill_address_id?: string; + shipping_address?: AddressParams; + billing_address?: AddressParams; + shipping_address_id?: string; + billing_address_id?: string; + use_shipping?: boolean; email?: string; }, ) { diff --git a/src/lib/utils/address.ts b/src/lib/utils/address.ts index 515ad362..fc1a27c7 100644 --- a/src/lib/utils/address.ts +++ b/src/lib/utils/address.ts @@ -1,12 +1,12 @@ import type { AddressParams } from "@spree/sdk"; export interface AddressFormData { - firstname: string; - lastname: string; + first_name: string; + last_name: string; address1: string; address2: string; city: string; - zipcode: string; + postal_code: string; phone: string; company: string; country_iso: string; @@ -15,12 +15,12 @@ export interface AddressFormData { } export const emptyAddress: AddressFormData = { - firstname: "", - lastname: "", + first_name: "", + last_name: "", address1: "", address2: "", city: "", - zipcode: "", + postal_code: "", phone: "", company: "", country_iso: "", @@ -30,12 +30,12 @@ export const emptyAddress: AddressFormData = { export function addressToFormData( address?: { - firstname: string | null; - lastname: string | null; + first_name: string | null; + last_name: string | null; address1: string | null; address2: string | null; city: string | null; - zipcode: string | null; + postal_code: string | null; phone: string | null; company: string | null; country_iso: string; @@ -45,12 +45,12 @@ export function addressToFormData( ): AddressFormData { if (!address) return { ...emptyAddress }; return { - firstname: address.firstname || "", - lastname: address.lastname || "", + first_name: address.first_name || "", + last_name: address.last_name || "", address1: address.address1 || "", address2: address.address2 || "", city: address.city || "", - zipcode: address.zipcode || "", + postal_code: address.postal_code || "", phone: address.phone || "", company: address.company || "", country_iso: address.country_iso || "", @@ -61,12 +61,12 @@ export function addressToFormData( export function formDataToAddress(data: AddressFormData): AddressParams { return { - firstname: data.firstname, - lastname: data.lastname, + first_name: data.first_name, + last_name: data.last_name, address1: data.address1, address2: data.address2 || undefined, city: data.city, - zipcode: data.zipcode, + postal_code: data.postal_code, phone: data.phone || undefined, company: data.company || undefined, country_iso: data.country_iso, @@ -91,28 +91,3 @@ export function updateAddressField( } return updated; } - -export function addressesMatch( - a: AddressFormData | undefined | null, - b: - | { - firstname: string | null; - lastname: string | null; - address1: string | null; - city: string | null; - zipcode: string | null; - country_iso: string; - } - | undefined - | null, -): boolean { - if (!a || !b) return false; - return ( - a.firstname === (b.firstname || "") && - a.lastname === (b.lastname || "") && - a.address1 === (b.address1 || "") && - a.city === (b.city || "") && - a.zipcode === (b.zipcode || "") && - a.country_iso === b.country_iso - ); -}