Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | export type Product = {
title: string;
reviews?: number;
rating?: number;
averageRating?: number;
price: number;
discountedPrice: number;
stock?: number;
description?: string;
id: number;
imgs?: {
thumbnails: string[];
previews: string[];
};
details?: string[];
specifications?: ProductSpecifications;
};
// Product specifications as flexible JSON object
export interface ProductSpecifications {
[key: string]: string | number | boolean;
}
// Database Product model with specifications and details
export interface DBProduct {
id: number;
title: string;
description?: string | null;
price: number;
discountedPrice: number;
stock: number;
sku?: string | null;
categoryId: number;
specifications?: ProductSpecifications | null;
details?: string | null; // JSON string array
createdAt: Date;
updatedAt: Date;
}
// Product with parsed details array
export interface ProductWithDetails extends Omit<DBProduct, 'details'> {
details?: string[] | null;
}
// Helper function to parse details from JSON string to array
export function parseProductDetails(detailsString?: string | null): string[] {
if (!detailsString) return [];
try {
const parsed = JSON.parse(detailsString);
return Array.isArray(parsed) ? parsed : [];
} catch {
return [];
}
}
// Helper function to format specifications for display
export function formatSpecificationValue(value: string | number | boolean): string {
if (typeof value === 'boolean') {
return value ? 'Yes' : 'No';
}
return String(value);
}
// Type guards for discriminating between legacy and database products
/**
* Type guard to check if a product is from the database
* @param product - Product to check
* @returns true if product has database-specific fields
*/
export function isDBProduct(product: unknown): product is DBProduct {
return typeof product === 'object' && product !== null && 'categoryId' in product && 'sku' in product;
}
/**
* Type guard to check if a product uses the legacy format
* @param product - Product to check
* @returns true if product has legacy imgs structure
*/
export function isLegacyProduct(product: unknown): product is Product {
return typeof product === 'object' && product !== null && 'imgs' in product && !('categoryId' in product);
}
// Union type for components that can accept both formats during migration
/**
* Union type for components being migrated from legacy to database format
* Use this type when a component needs to support both Product and DBProduct
*/
export type AnyProduct = Product | DBProduct;
|