ifixkart-storefront/services/api/storefrontService.ts

307 lines
9.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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' },
],
};