307 lines
9.2 KiB
TypeScript
307 lines
9.2 KiB
TypeScript
import { apiFetch } from './client';
|
||
import { API_ENDPOINTS } from './config';
|
||
import { catalogService, ProductResponse, CategoryResponse, BrandResponse, DeviceModelResponse, ServiceTypeResponse, MOCK_PRODUCTS, MOCK_CATEGORIES, MOCK_BRANDS, MOCK_DEVICE_MODELS, MOCK_SERVICE_TYPES } from './catalogService';
|
||
import { mapProductCardToProductResponse } from '@/utils/productMapper';
|
||
|
||
export interface LiveSearchResult {
|
||
products: ProductResponse[];
|
||
categories: CategoryResponse[];
|
||
brands: BrandResponse[];
|
||
services: ServiceTypeResponse[];
|
||
}
|
||
|
||
export interface BannerItem {
|
||
id: string;
|
||
title: string;
|
||
subtitle: string;
|
||
discount_tag: string;
|
||
image_url: string;
|
||
cta_text: string;
|
||
cta_link: string;
|
||
}
|
||
|
||
export interface ProductReview {
|
||
review_id: string;
|
||
product_id: string;
|
||
author_name: string;
|
||
rating: number;
|
||
verified_buyer: boolean;
|
||
review_date: string;
|
||
title: string;
|
||
comment: string;
|
||
}
|
||
|
||
export interface TrustBadge {
|
||
id: string;
|
||
title: string;
|
||
subtitle: string;
|
||
icon: string;
|
||
}
|
||
|
||
export interface BlogPost {
|
||
post_id: string;
|
||
title: string;
|
||
excerpt: string;
|
||
author: string;
|
||
date: string;
|
||
image_url: string;
|
||
}
|
||
|
||
export interface FooterInfo {
|
||
phone: string;
|
||
email: string;
|
||
address: string;
|
||
copyright: string;
|
||
// Legacy format (StorefrontRouter static stubs) — kept for backwards compatibility
|
||
get_to_know_us?: { label: string; href: string }[];
|
||
information?: { label: string; href: string }[];
|
||
orders_returns?: { label: string; href: string }[];
|
||
our_store?: { label: string; href: string }[];
|
||
// New CMS format (dynamic columns)
|
||
social_links?: { platform: string; url: string; icon?: string }[];
|
||
columns?: { title: string; links: { label: string; href: string }[] }[];
|
||
payment_methods?: { name: string; icon_url?: string }[];
|
||
}
|
||
|
||
export interface StorefrontSettings {
|
||
store_name?: string;
|
||
logo_url?: string;
|
||
primary_wordmark_url?: string;
|
||
secondary_wordmark_url?: string;
|
||
favicon_url?: string;
|
||
support_phone?: string;
|
||
currency_code?: string;
|
||
advance_percent?: number;
|
||
theme_color?: string;
|
||
[key: string]: unknown;
|
||
}
|
||
|
||
export type MegaMenuBadge = 'new' | 'hot' | 'trending' | 'featured';
|
||
|
||
export interface MegaMenuLink {
|
||
label: string;
|
||
href: string;
|
||
badge?: MegaMenuBadge | string | null;
|
||
accent?: boolean;
|
||
}
|
||
|
||
export interface MegaMenuData {
|
||
nav_key: string;
|
||
groups: { title: string; links: MegaMenuLink[] }[];
|
||
promo?: { image_url?: string; badge?: string; title?: string; href?: string } | null;
|
||
featured_category_ids?: string[];
|
||
/** Product slugs for Top Rated (deals) and Featured Products (products). */
|
||
featured_product_ids?: string[];
|
||
}
|
||
|
||
export interface AllMegaMenus {
|
||
shop?: MegaMenuData;
|
||
deals?: MegaMenuData;
|
||
products?: MegaMenuData;
|
||
}
|
||
|
||
/** Product slugs saved on deals (Top Rated) and products (Featured) mega menus. */
|
||
export function getMegaMenuProductSlugs(menu?: MegaMenuData | null): string[] {
|
||
if (!menu) return [];
|
||
const dedicated = (menu.featured_product_ids || []).map(String).filter(Boolean);
|
||
if (dedicated.length) return dedicated;
|
||
if (menu.nav_key === 'shop') return [];
|
||
return (menu.featured_category_ids || []).map(String).filter(Boolean);
|
||
}
|
||
|
||
export interface CatalogFiltersData {
|
||
highlights: { label: string; value: string; icon?: string }[];
|
||
price_ranges: { label: string; min?: number | null; max?: number | null }[];
|
||
}
|
||
|
||
export const storefrontService = {
|
||
async getLiveSearch(query: string, category?: string): Promise<LiveSearchResult> {
|
||
if (!query || query.trim().length < 2) {
|
||
return { products: [], categories: [], brands: [], services: [] };
|
||
}
|
||
|
||
try {
|
||
return await apiFetch<LiveSearchResult>(API_ENDPOINTS.STOREFRONT_LIVE_SEARCH(query.trim(), category));
|
||
} catch {
|
||
try {
|
||
const res = await catalogService.getProductsPaginated({
|
||
search: query.trim(),
|
||
limit: 8,
|
||
category: category && category !== 'all' ? category : undefined,
|
||
});
|
||
return {
|
||
products: res.products.map((p) => mapProductCardToProductResponse(p)),
|
||
categories: [],
|
||
brands: [],
|
||
services: [],
|
||
};
|
||
} catch {
|
||
return { products: [], categories: [], brands: [], services: [] };
|
||
}
|
||
}
|
||
},
|
||
|
||
async getBanners(): Promise<BannerItem[]> {
|
||
try {
|
||
return await apiFetch<BannerItem[]>(API_ENDPOINTS.STOREFRONT_BANNERS);
|
||
} catch {
|
||
return MOCK_BANNERS;
|
||
}
|
||
},
|
||
|
||
async getReviews(productId: string): Promise<ProductReview[]> {
|
||
try {
|
||
return await apiFetch<ProductReview[]>(`/api/v1/storefront/reviews/${productId}`);
|
||
} catch {
|
||
return MOCK_REVIEWS;
|
||
}
|
||
},
|
||
|
||
async getTrustBadges(): Promise<TrustBadge[]> {
|
||
try {
|
||
return await apiFetch<TrustBadge[]>('/api/v1/storefront/trust-badges');
|
||
} catch {
|
||
return MOCK_TRUST_BADGES;
|
||
}
|
||
},
|
||
|
||
async getBlogPosts(): Promise<BlogPost[]> {
|
||
try {
|
||
return await apiFetch<BlogPost[]>('/api/v1/storefront/blog-posts');
|
||
} catch {
|
||
return MOCK_BLOG_POSTS;
|
||
}
|
||
},
|
||
|
||
async getFooterInfo(): Promise<FooterInfo> {
|
||
try {
|
||
return await apiFetch<FooterInfo>('/api/v1/storefront/footer-info');
|
||
} catch {
|
||
return MOCK_FOOTER_INFO;
|
||
}
|
||
},
|
||
|
||
async getSettings(): Promise<StorefrontSettings> {
|
||
try {
|
||
return await apiFetch<StorefrontSettings>('/api/v1/storefront/settings');
|
||
} catch {
|
||
return { store_name: 'iFixKart', currency_code: 'INR', advance_percent: 20 };
|
||
}
|
||
},
|
||
|
||
async getMegaMenu(): Promise<AllMegaMenus> {
|
||
try {
|
||
return await apiFetch<AllMegaMenus>('/api/v1/storefront/mega-menu');
|
||
} catch {
|
||
return {};
|
||
}
|
||
},
|
||
|
||
async getFaqLayout(): Promise<unknown> {
|
||
try {
|
||
return await apiFetch<unknown>('/api/v1/storefront/layout/faq');
|
||
} catch {
|
||
return [];
|
||
}
|
||
},
|
||
|
||
async getCatalogFilters(): Promise<CatalogFiltersData> {
|
||
try {
|
||
return await apiFetch<CatalogFiltersData>('/api/v1/storefront/catalog-filters');
|
||
} catch {
|
||
return {
|
||
highlights: [
|
||
{ label: 'Sale', value: 'sale', icon: 'tag' },
|
||
{ label: 'Trending', value: 'trending', icon: 'trending-up' },
|
||
{ label: 'New Arrivals', value: 'new', icon: 'sparkles' },
|
||
],
|
||
price_ranges: [
|
||
{ label: 'Under ₹500', min: null, max: 500 },
|
||
{ label: '₹500 – ₹1,000', min: 500, max: 1000 },
|
||
{ label: '₹1,000 – ₹5,000', min: 1000, max: 5000 },
|
||
{ label: '₹5,000 – ₹15,000', min: 5000, max: 15000 },
|
||
{ label: 'Above ₹15,000', min: 15000, max: null },
|
||
],
|
||
};
|
||
}
|
||
},
|
||
};
|
||
|
||
|
||
export const MOCK_BANNERS: BannerItem[] = [
|
||
{
|
||
id: 'b1',
|
||
title: 'Next-Gen Tech & Electronics',
|
||
subtitle: 'Up to 40% Off on Top Smartphones, Laptops & Wearables',
|
||
discount_tag: 'SUMMER TECH SALE 2026',
|
||
image_url: 'https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=1200',
|
||
cta_text: 'Shop Now',
|
||
cta_link: '/products',
|
||
},
|
||
];
|
||
|
||
export const MOCK_REVIEWS: ProductReview[] = [
|
||
{
|
||
review_id: 'rev_01',
|
||
product_id: 'p1',
|
||
author_name: 'Alex Morgan',
|
||
rating: 5,
|
||
verified_buyer: true,
|
||
review_date: '2026-07-20',
|
||
title: 'Exceptional Quality!',
|
||
comment: 'Exceptional build quality and super-fast delivery! Highly recommended.',
|
||
},
|
||
];
|
||
|
||
export const MOCK_TRUST_BADGES: TrustBadge[] = [
|
||
{ id: 'tb1', title: 'Free Shipping', subtitle: 'On order over $100', icon: 'truck' },
|
||
{ id: 'tb2', title: 'Flexible & Easy Return', subtitle: 'Return within 14 days', icon: 'refresh' },
|
||
{ id: 'tb3', title: '24/7 Support Services', subtitle: 'Any Time Customer Support', icon: 'headset' },
|
||
{ id: 'tb4', title: 'Secure payment', subtitle: '100% Fast & Secure Payment', icon: 'shield' },
|
||
];
|
||
|
||
export const MOCK_BLOG_POSTS: BlogPost[] = [
|
||
{
|
||
post_id: 'bp1',
|
||
title: 'How to Write a Blog Post Your Readers Will Love in 5 Steps',
|
||
excerpt: 'Why the world would end without travel coupons. The 16 worst...',
|
||
author: 'Admin',
|
||
date: 'July 24, 2026',
|
||
image_url: 'https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=500',
|
||
},
|
||
];
|
||
|
||
export const MOCK_FOOTER_INFO: FooterInfo = {
|
||
phone: '+91 98765 43210',
|
||
email: 'support@ifixkart.com',
|
||
address: 'iFixKart Electronics & OEM Repair Hub, India',
|
||
copyright: '© 2026 iFixKart Commerce & Service Platform. All rights reserved.',
|
||
get_to_know_us: [
|
||
{ label: 'About Us', href: '/about' },
|
||
{ label: 'Term & Policy', href: '/terms' },
|
||
{ label: 'Careers', href: '/careers' },
|
||
{ label: 'News & Blog', href: '/blog' },
|
||
{ label: 'Contact Us', href: '/contact' },
|
||
],
|
||
information: [
|
||
{ label: 'Help Center', href: '/help' },
|
||
{ label: 'Feedback', href: '/feedback' },
|
||
{ label: 'FAQs', href: '/faqs' },
|
||
{ label: 'Size Guide', href: '/size-guide' },
|
||
{ label: 'Payments', href: '/payments' },
|
||
],
|
||
orders_returns: [
|
||
{ label: 'Track Order', href: '/account' },
|
||
{ label: 'Delivery', href: '/delivery' },
|
||
{ label: 'Services', href: '/services' },
|
||
{ label: 'Returns', href: '/returns' },
|
||
{ label: 'Exchange', href: '/exchange' },
|
||
],
|
||
our_store: [
|
||
{ label: 'Affiliate', href: '/affiliate' },
|
||
{ label: 'Best Seller', href: '/products?sort=best-sellers' },
|
||
{ label: 'New Products', href: '/products?sort=newest' },
|
||
{ label: 'On Sale', href: '/products?on_sale=true' },
|
||
{ label: 'Featured', href: '/products?featured=true' },
|
||
],
|
||
};
|