149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
export interface ProductImage {
|
|
imageId: string;
|
|
imageLabel: string;
|
|
imageTag: string;
|
|
imageUrl: string;
|
|
imageText: string;
|
|
imageLastModified: string;
|
|
}
|
|
|
|
export interface CommercialOffer {
|
|
Price: number;
|
|
ListPrice: number;
|
|
PriceWithoutDiscount: number;
|
|
FullSellingPrice: number;
|
|
RewardValue: number;
|
|
PriceValidUntil: string;
|
|
AvailableQuantity: number;
|
|
IsAvailable: boolean;
|
|
GiftSkuIds: string[];
|
|
Installments: {
|
|
Value: number;
|
|
InterestRate: number;
|
|
TotalValuePlusInterestRate: number;
|
|
NumberOfInstallments: number;
|
|
}[];
|
|
discountHighLight: unknown[];
|
|
teasers: unknown[];
|
|
}
|
|
|
|
export interface ProductSeller {
|
|
sellerId: string;
|
|
sellerName: string;
|
|
addToCartLink: string;
|
|
sellerDefault: boolean;
|
|
commertialOffer: CommercialOffer;
|
|
}
|
|
|
|
export interface ProductItem {
|
|
itemId: string;
|
|
name: string;
|
|
nameComplete: string;
|
|
complementName: string;
|
|
ean: string;
|
|
referenceId: { Key: string; Value: string }[];
|
|
measurementUnit: string;
|
|
unitMultiplier: number;
|
|
modalType: null;
|
|
isKit: boolean;
|
|
images: ProductImage[];
|
|
Talla: string[];
|
|
variations: string[];
|
|
sellers: ProductSeller[];
|
|
Videos: unknown[];
|
|
estimatedDateArrival: null;
|
|
}
|
|
|
|
export interface Product {
|
|
productId: string;
|
|
productName: string;
|
|
brand: string;
|
|
brandId: number;
|
|
brandImageUrl: null | string;
|
|
linkText: string;
|
|
productReference: string;
|
|
productReferenceCode: string;
|
|
categoryId: string;
|
|
productTitle: string;
|
|
metaTagDescription: string;
|
|
releaseDate: string;
|
|
clusterHighlights: Record<string, unknown>;
|
|
productClusters: Record<string, string>;
|
|
searchableClusters: Record<string, unknown>;
|
|
categories: string[];
|
|
categoriesIds: string[];
|
|
link: string;
|
|
description: string;
|
|
items: ProductItem[];
|
|
}
|
|
|
|
const FIXED_PRODUCT_ID = '169520';
|
|
|
|
export async function fetchProduct(productId: string = FIXED_PRODUCT_ID): Promise<Product | null> {
|
|
try {
|
|
// Use our Next.js API route as a proxy to avoid CORS issues
|
|
const response = await fetch(`/api/products/${productId}`);
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({}));
|
|
console.error('Failed to fetch product:', response.status, errorData);
|
|
return null;
|
|
}
|
|
|
|
const product = await response.json();
|
|
return product;
|
|
} catch (error) {
|
|
console.error('Error fetching product:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function getProductImages(product: Product): string[] {
|
|
const allImages: string[] = [];
|
|
|
|
product.items.forEach(item => {
|
|
item.images.forEach(image => {
|
|
if (image.imageUrl && !allImages.includes(image.imageUrl)) {
|
|
allImages.push(image.imageUrl);
|
|
}
|
|
});
|
|
});
|
|
|
|
return allImages;
|
|
}
|
|
|
|
export function getProductPricing(product: Product) {
|
|
const firstAvailableItem = product.items.find(item =>
|
|
item.sellers.some(seller => seller.commertialOffer.IsAvailable)
|
|
);
|
|
|
|
if (!firstAvailableItem) {
|
|
return { price: 0, listPrice: 0, discount: 0, isAvailable: false };
|
|
}
|
|
|
|
const seller = firstAvailableItem.sellers.find(s => s.commertialOffer.IsAvailable);
|
|
if (!seller) {
|
|
return { price: 0, listPrice: 0, discount: 0, isAvailable: false };
|
|
}
|
|
|
|
const { Price, ListPrice } = seller.commertialOffer;
|
|
const discount = ListPrice > Price ? Math.round(((ListPrice - Price) / ListPrice) * 100) : 0;
|
|
|
|
return {
|
|
price: Price,
|
|
listPrice: ListPrice,
|
|
discount,
|
|
isAvailable: true
|
|
};
|
|
}
|
|
|
|
export function getProductVariants(product: Product) {
|
|
return product.items.map(item => ({
|
|
itemId: item.itemId,
|
|
name: item.name,
|
|
sizes: item.Talla,
|
|
images: item.images.map(img => img.imageUrl),
|
|
isAvailable: item.sellers.some(seller => seller.commertialOffer.IsAvailable),
|
|
price: item.sellers.find(s => s.commertialOffer.IsAvailable)?.commertialOffer.Price || 0
|
|
}));
|
|
} |