← back to Wine Finder Next
lib/services/mockWineData.ts
166 lines
/**
* Mock Wine Data Generator
* Generates realistic auction and retail data for testing the arbitrage UI
* until real API keys are obtained
*/
export interface MockWineListing {
id: string;
name: string;
vintage?: number;
region?: string;
rating?: number;
provider: 'auction' | 'retail';
providerName: string;
currentPrice: {
amount: number;
currency: string;
};
url: string;
imageUrl?: string;
availability?: string;
bidCount?: number;
closingDate?: string;
lastUpdated: string;
lastSale?: {
price: number;
source: string;
date: string;
daysAgo: number;
};
}
const PREMIUM_WINES = [
{ name: 'Caymus Cabernet Sauvignon', vintage: 2021, region: 'Napa Valley, California' },
{ name: 'Opus One', vintage: 2019, region: 'Napa Valley, California' },
{ name: 'Silver Oak Cabernet Sauvignon', vintage: 2020, region: 'Alexander Valley, California' },
{ name: 'Screaming Eagle Cabernet Sauvignon', vintage: 2018, region: 'Napa Valley, California' },
{ name: 'Stags Leap Wine Cellars Artemis Cabernet', vintage: 2021, region: 'Napa Valley, California' },
{ name: 'Duckhorn Merlot', vintage: 2020, region: 'Napa Valley, California' },
{ name: 'Far Niente Chardonnay', vintage: 2022, region: 'Napa Valley, California' },
{ name: 'Shafer Hillside Select Cabernet', vintage: 2019, region: 'Napa Valley, California' },
{ name: 'Ridge Monte Bello', vintage: 2020, region: 'Santa Cruz Mountains, California' },
{ name: 'Joseph Phelps Insignia', vintage: 2019, region: 'Napa Valley, California' },
{ name: 'Dom Pérignon Champagne', vintage: 2013, region: 'Champagne, France' },
{ name: 'Château Margaux', vintage: 2016, region: 'Bordeaux, France' },
{ name: 'Château Lafite Rothschild', vintage: 2015, region: 'Pauillac, Bordeaux, France' },
{ name: 'Penfolds Grange', vintage: 2018, region: 'South Australia' },
{ name: 'Cloudy Bay Sauvignon Blanc', vintage: 2023, region: 'Marlborough, New Zealand' },
];
export function generateMockWineData(query: string): MockWineListing[] {
const wines: MockWineListing[] = [];
const now = new Date().toISOString();
// Filter wines that match the query
const matchingWines = PREMIUM_WINES.filter(wine =>
wine.name.toLowerCase().includes(query.toLowerCase()) ||
query.toLowerCase().split(' ').some(term => wine.name.toLowerCase().includes(term))
);
// If no matches, use first 5 wines
const winesToUse = matchingWines.length > 0 ? matchingWines : PREMIUM_WINES.slice(0, 5);
winesToUse.forEach((wine, idx) => {
// Generate retail listing (lower price)
const basePrice = 50 + (idx * 20);
const retailPrice = basePrice + Math.random() * 50;
wines.push({
id: `vivino-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
name: wine.name,
vintage: wine.vintage,
region: wine.region,
rating: 4.0 + Math.random() * 0.9,
provider: 'retail',
providerName: 'Vivino',
currentPrice: {
amount: parseFloat(retailPrice.toFixed(2)),
currency: 'USD',
},
url: `https://www.vivino.com/wines/${idx + 1000}`,
imageUrl: 'https://images.vivino.com/thumbs/placeholder_pl_480x640.png',
availability: 'In Stock',
lastUpdated: now,
});
// Generate Wine.com retail listing (slightly different price)
wines.push({
id: `winecom-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
name: wine.name,
vintage: wine.vintage,
region: wine.region,
rating: 4.0 + Math.random() * 0.9,
provider: 'retail',
providerName: 'Wine.com',
currentPrice: {
amount: parseFloat((retailPrice + Math.random() * 20 - 10).toFixed(2)),
currency: 'USD',
},
url: `https://www.wine.com/product/${idx + 5000}`,
availability: 'In Stock',
lastUpdated: now,
});
// Generate auction listings (higher prices for arbitrage opportunities)
const auctionPrice = retailPrice + 50 + Math.random() * 100;
const daysAgo = Math.floor(Math.random() * 90) + 1; // 1-90 days ago
const lastSaleDate = new Date(Date.now() - (daysAgo * 24 * 60 * 60 * 1000));
wines.push({
id: `winebid-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
name: wine.name,
vintage: wine.vintage,
region: wine.region,
provider: 'auction',
providerName: 'WineBid',
currentPrice: {
amount: parseFloat(auctionPrice.toFixed(2)),
currency: 'USD',
},
url: `https://www.winebid.com/auction/${idx + 10000}`,
bidCount: Math.floor(Math.random() * 20) + 5,
closingDate: new Date(Date.now() + Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
lastUpdated: now,
lastSale: {
price: parseFloat((auctionPrice * (0.85 + Math.random() * 0.25)).toFixed(2)), // ±15% from current
source: 'WineBid',
date: lastSaleDate.toISOString(),
daysAgo,
},
});
// Sometimes add Zachys auction
if (Math.random() > 0.5) {
const zachysPrice = auctionPrice + Math.random() * 30 - 15;
const zachysDaysAgo = Math.floor(Math.random() * 60) + 1;
const zachysLastSale = new Date(Date.now() - (zachysDaysAgo * 24 * 60 * 60 * 1000));
wines.push({
id: `zachys-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
name: wine.name,
vintage: wine.vintage,
region: wine.region,
provider: 'auction',
providerName: 'Zachys',
currentPrice: {
amount: parseFloat(zachysPrice.toFixed(2)),
currency: 'USD',
},
url: `https://www.zachys.com/auction/${idx + 20000}`,
bidCount: Math.floor(Math.random() * 15) + 3,
closingDate: new Date(Date.now() + Math.random() * 14 * 24 * 60 * 60 * 1000).toISOString(),
lastUpdated: now,
lastSale: {
price: parseFloat((zachysPrice * (0.9 + Math.random() * 0.2)).toFixed(2)),
source: 'Zachys',
date: zachysLastSale.toISOString(),
daysAgo: zachysDaysAgo,
},
});
}
});
return wines;
}