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:
sdarbinyan
2026-08-13 09:06:46 +04:00
parent 9f784406d7
commit c0bce7feac
2 changed files with 36 additions and 19 deletions

View File

@@ -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 {