first commit

This commit is contained in:
Jelaletdin12
2025-11-10 10:07:48 +05:00
commit fdec9e4b0e
131 changed files with 16660 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
/**
* Custom axios adapter for mocking API responses in development
* Intercepts requests and routes them to mock handlers
*/
import type { AxiosRequestConfig } from "axios"
import { mockHandlers } from "./handlers"
interface MockRequest extends AxiosRequestConfig {
url?: string
}
export const createMockAdapter = () => {
return async (config: MockRequest) => {
const url = config.url || ""
const method = (config.method || "get").toLowerCase()
try {
if (method === "get") {
if (url === "/products") {
const response = await mockHandlers.getProducts()
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url.match(/^\/products\/\d+$/)) {
const id = Number.parseInt(url.split("/")[2])
const response = await mockHandlers.getProduct(id)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url === "/categories") {
const response = await mockHandlers.getCategories()
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url.match(/^\/categories\/.+$/)) {
const slug = url.split("/")[2]
const response = await mockHandlers.getCategory(slug)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url === "/cart") {
const response = await mockHandlers.getCart()
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url === "/favorites") {
const response = await mockHandlers.getFavorites()
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url === "/orders") {
const response = await mockHandlers.getOrders()
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url.match(/^\/orders\/\d+$/)) {
const id = Number.parseInt(url.split("/")[2])
const response = await mockHandlers.getOrder(id)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url.match(/^\/search/)) {
const params = new URLSearchParams(url.split("?")[1] || "")
const query = params.get("q") || ""
const response = await mockHandlers.search(query, {
category: params.get("category") || undefined,
priceFrom: params.get("priceFrom") ? Number.parseInt(params.get("priceFrom")!) : undefined,
priceTo: params.get("priceTo") ? Number.parseInt(params.get("priceTo")!) : undefined,
})
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
}
if (method === "post") {
if (url === "/cart/items") {
const { productId, quantity } = config.data
const response = await mockHandlers.addToCart(productId, quantity)
return Promise.resolve({ data: response.data, status: 201, config, headers: {}, statusText: "Created" })
}
if (url === "/favorites") {
const { productId } = config.data
const response = await mockHandlers.addToFavorites(productId)
return Promise.resolve({ data: response.data, status: 201, config, headers: {}, statusText: "Created" })
}
if (url.match(/^\/orders\/\d+\/cancel$/)) {
const orderId = Number.parseInt(url.split("/")[2])
const response = await mockHandlers.cancelOrder(orderId)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
}
if (method === "patch") {
if (url.match(/^\/cart\/items\/\d+$/)) {
const itemId = Number.parseInt(url.split("/")[3])
const { quantity } = config.data
const response = await mockHandlers.updateCartItemQuantity(itemId, quantity)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
}
if (method === "delete") {
if (url.match(/^\/cart\/items\/\d+$/)) {
const itemId = Number.parseInt(url.split("/")[3])
const response = await mockHandlers.removeFromCart(itemId)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
if (url.match(/^\/favorites\/\d+$/)) {
const productId = Number.parseInt(url.split("/")[2])
const response = await mockHandlers.removeFromFavorites(productId)
return Promise.resolve({ data: response.data, status: 200, config, headers: {}, statusText: "OK" })
}
}
// Fallback - endpoint not mocked
return Promise.reject({
response: { status: 404, data: { message: "Endpoint not found" }, config },
})
} catch (error: any) {
return Promise.reject({
response: {
status: 400,
data: { message: error.message },
config,
},
})
}
}
}

95
lib/mock-server/data.ts Normal file
View File

@@ -0,0 +1,95 @@
/**
* Mock data for development and testing
*/
export const mockProducts = [
{
id: 1,
name: "Premium Wireless Headphones",
price: 199.99,
category: "electronics",
image: "/wireless-headphones.png",
description: "High-quality sound with noise cancellation",
stock: 50,
},
{
id: 2,
name: "Classic Analog Watch",
price: 89.99,
category: "accessories",
image: "/analog-watch.png",
description: "Timeless design with precision movement",
stock: 30,
},
{
id: 3,
name: "Portable Charger 20000mAh",
price: 49.99,
category: "electronics",
image: "/portable-charger-lifestyle.png",
description: "Fast charging technology with dual ports",
stock: 100,
},
{
id: 4,
name: "Leather Messenger Bag",
price: 129.99,
category: "accessories",
image: "/leather-messenger-bag.png",
description: "Premium leather construction",
stock: 25,
},
{
id: 5,
name: "4K Webcam",
price: 149.99,
category: "electronics",
image: "/4k-webcam.jpg",
description: "Professional quality streaming camera",
stock: 40,
},
{
id: 6,
name: "USB-C Hub 7-in-1",
price: 59.99,
category: "electronics",
image: "/usb-c-hub.jpg",
description: "Multiple ports for connectivity",
stock: 75,
},
]
export const mockCategories = [
{
id: 1,
name: "Electronics",
slug: "electronics",
image: "/electronics-category.png",
},
{
id: 2,
name: "Accessories",
slug: "accessories",
image: "/accessories-category.png",
},
]
export const mockOrders = [
{
id: 101,
status: "delivered" as const,
total: 299.98,
createdAt: new Date("2024-11-01").toISOString(),
},
{
id: 102,
status: "processing" as const,
total: 199.99,
createdAt: new Date("2024-11-05").toISOString(),
},
]
export const mockFavorites = [
{ id: 1, productId: 1, addedAt: new Date().toISOString() },
{ id: 2, productId: 3, addedAt: new Date().toISOString() },
]

181
lib/mock-server/handlers.ts Normal file
View File

@@ -0,0 +1,181 @@
/**
* Mock HTTP handlers for development
* Simulates API responses for TanStack Query testing
*/
import { mockProducts, mockCategories, mockOrders, mockFavorites } from "./data"
interface MockCart {
id: string
items: Array<{ id: number; productId: number; quantity: number; price: number }>
total: number
}
// In-memory storage for development
const mockCart: MockCart = {
id: "cart-1",
items: [],
total: 0,
}
let mockUserFavorites = [...mockFavorites]
/**
* Simulate network delay for realistic testing
*/
export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
/**
* Mock API handlers
*/
export const mockHandlers = {
// Products
async getProducts() {
await delay(300)
return { data: mockProducts }
},
async getProduct(id: number) {
await delay(300)
const product = mockProducts.find((p) => p.id === id)
if (!product) throw new Error("Product not found")
return { data: product }
},
// Categories
async getCategories() {
await delay(300)
return { data: mockCategories }
},
async getCategory(slug: string) {
await delay(300)
const category = mockCategories.find((c) => c.slug === slug)
if (!category) throw new Error("Category not found")
const products = mockProducts.filter((p) => p.category === slug)
return { data: { ...category, products } }
},
// Cart operations
async getCart() {
await delay(200)
return { data: mockCart }
},
async addToCart(productId: number, quantity = 1) {
await delay(300)
const product = mockProducts.find((p) => p.id === productId)
if (!product) throw new Error("Product not found")
const existingItem = mockCart.items.find((item) => item.productId === productId)
if (existingItem) {
existingItem.quantity += quantity
} else {
mockCart.items.push({
id: Date.now(),
productId,
quantity,
price: product.price,
})
}
mockCart.total = mockCart.items.reduce((sum, item) => sum + item.price * item.quantity, 0)
return { data: mockCart }
},
async removeFromCart(itemId: number) {
await delay(300)
mockCart.items = mockCart.items.filter((item) => item.id !== itemId)
mockCart.total = mockCart.items.reduce((sum, item) => sum + item.price * item.quantity, 0)
return { data: mockCart }
},
async updateCartItemQuantity(itemId: number, quantity: number) {
await delay(300)
const item = mockCart.items.find((i) => i.id === itemId)
if (!item) throw new Error("Item not found")
item.quantity = Math.max(1, quantity)
mockCart.total = mockCart.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
return { data: mockCart }
},
// Favorites
async getFavorites() {
await delay(200)
return { data: mockUserFavorites }
},
async addToFavorites(productId: number) {
await delay(300)
const product = mockProducts.find((p) => p.id === productId)
if (!product) throw new Error("Product not found")
const exists = mockUserFavorites.find((f) => f.productId === productId)
if (!exists) {
mockUserFavorites.push({
id: Date.now(),
productId,
addedAt: new Date().toISOString(),
})
}
return { data: mockUserFavorites }
},
async removeFromFavorites(productId: number) {
await delay(300)
mockUserFavorites = mockUserFavorites.filter((f) => f.productId !== productId)
return { data: mockUserFavorites }
},
// Orders
async getOrders() {
await delay(300)
return { data: mockOrders }
},
async getOrder(id: number) {
await delay(300)
const order = mockOrders.find((o) => o.id === id)
if (!order) throw new Error("Order not found")
return { data: order }
},
async cancelOrder(orderId: number) {
await delay(300)
const order = mockOrders.find((o) => o.id === orderId)
if (!order) throw new Error("Order not found")
if (order.status !== "processing" && order.status !== "pending") {
throw new Error("Cannot cancel shipped or delivered orders")
}
order.status = "cancelled"
return { data: order }
},
// Search
async search(query: string, filters?: { category?: string; priceFrom?: number; priceTo?: number }) {
await delay(400)
let results = mockProducts
if (query) {
results = results.filter(
(p) =>
p.name.toLowerCase().includes(query.toLowerCase()) ||
p.description.toLowerCase().includes(query.toLowerCase()),
)
}
if (filters?.category) {
results = results.filter((p) => p.category === filters.category)
}
if (filters?.priceFrom) {
results = results.filter((p) => p.price >= filters.priceFrom!)
}
if (filters?.priceTo) {
results = results.filter((p) => p.price <= filters.priceTo!)
}
return { data: { products: results, total: results.length } }
},
}