fix: Buy Now raced ahead of addToCart, per-product SEO tags never applied
CartService.addItem() fired an async dynamic import + API call for new items but returned void immediately - buyNow() navigated to /cart before the item was actually added, landing the user on an empty or stale cart. addItem() now returns a Promise that resolves once the cart signal actually contains the item; buyNow() awaits it before navigating. Also wired SeoService.setItemMeta()/resetToDefaults() into the product detail page - built and working, but never called anywhere, so every product page rendered the site-wide default OG/Twitter tags instead of per-product ones. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -203,20 +203,30 @@ export class CartService {
|
||||
return this.cartItems().findIndex(item => this.isSameCartLine(item, itemID, variant));
|
||||
}
|
||||
|
||||
addItem(itemID: number, quantity: number = 1, variant?: CartVariant): void {
|
||||
/**
|
||||
* Resolves once the item is actually present in the cart signal - not
|
||||
* merely once the call was fired. New (not-yet-in-cart) items fetch their
|
||||
* details from the API first, so callers that navigate straight after
|
||||
* (e.g. Buy Now -> /cart) must await this rather than treat it as fired
|
||||
* synchronously.
|
||||
*/
|
||||
addItem(itemID: number, quantity: number = 1, variant?: CartVariant): Promise<void> {
|
||||
// Prevent duplicate API calls for same item
|
||||
if (this.addingItems.has(itemID)) return;
|
||||
|
||||
if (this.addingItems.has(itemID)) return Promise.resolve();
|
||||
|
||||
const currentItems = this.cartItems();
|
||||
const existingItem = currentItems.find(i => this.isSameCartLine(i, itemID, variant));
|
||||
|
||||
|
||||
if (existingItem) {
|
||||
// Item exists, increase quantity
|
||||
this.updateQuantity(itemID, existingItem.quantity + quantity, variant);
|
||||
} else {
|
||||
// Get item details from API and add to cart
|
||||
this.addingItems.add(itemID);
|
||||
import('./api.service').then(({ ApiService }) => {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Get item details from API and add to cart
|
||||
this.addingItems.add(itemID);
|
||||
return import('./api.service').then(({ ApiService }) =>
|
||||
new Promise<void>((resolve) => {
|
||||
this.injector.get(ApiService).getItem(itemID).subscribe({
|
||||
next: (item) => {
|
||||
const cartItem = this.normalizeCartItem({
|
||||
@@ -229,17 +239,19 @@ export class CartService {
|
||||
});
|
||||
this.cartItems.set([...this.cartItems(), cartItem]);
|
||||
this.addingItems.delete(itemID);
|
||||
resolve();
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error adding to cart:', err);
|
||||
this.addingItems.delete(itemID);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.error('Error loading API service:', err);
|
||||
this.addingItems.delete(itemID);
|
||||
});
|
||||
}
|
||||
})
|
||||
).catch((err) => {
|
||||
console.error('Error loading API service:', err);
|
||||
this.addingItems.delete(itemID);
|
||||
});
|
||||
}
|
||||
|
||||
updateQuantity(itemID: number, quantity: number, variant?: CartVariant): void {
|
||||
|
||||
Reference in New Issue
Block a user