first commit
This commit is contained in:
18
lib/hooks/index.ts
Normal file
18
lib/hooks/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export * from "./useProducts"
|
||||
export * from "./useCategories"
|
||||
export * from "./useCart"
|
||||
export * from "./useFavorites"
|
||||
export * from "./useOrders"
|
||||
export * from "./useSearch"
|
||||
export * from "./useUserProfile"
|
||||
export * from "./useOpenStore"
|
||||
export * from "./useRegions"
|
||||
export * from "./useAddresses"
|
||||
export * from "./usePaymentTypes"
|
||||
export * from "./useCategories"
|
||||
|
||||
export * from "./useMedia"
|
||||
export * from "./useCollections"
|
||||
|
||||
// Export types
|
||||
export type { Product, Category, Cart, CartItem, Order, Favorite, Banner } from "@/lib/types/api"
|
||||
14
lib/hooks/useAddresses.ts
Normal file
14
lib/hooks/useAddresses.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Address } from "@/lib/types/api"
|
||||
|
||||
export function useAddresses() {
|
||||
return useQuery({
|
||||
queryKey: ["addresses"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Address[]>("/api/v1/addresses")
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
})
|
||||
}
|
||||
192
lib/hooks/useAuth.ts
Normal file
192
lib/hooks/useAuth.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query"
|
||||
import { apiClient, setAuthToken, clearAuthToken, setGuestToken } from "@/lib/api"
|
||||
import { queryClient } from "@/lib/queryClient"
|
||||
|
||||
interface LoginCredentials {
|
||||
phone_number: string
|
||||
password?: string
|
||||
}
|
||||
|
||||
interface RegisterData {
|
||||
phone_number: string
|
||||
name?: string
|
||||
email?: string
|
||||
}
|
||||
|
||||
interface VerifyTokenData {
|
||||
phone_number: string
|
||||
code: string
|
||||
}
|
||||
|
||||
interface AuthResponse {
|
||||
token?: string
|
||||
data?: string
|
||||
user?: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Guest Token alma (RTK mantığı)
|
||||
*/
|
||||
export function useGetGuestToken() {
|
||||
return useMutation({
|
||||
mutationFn: async (): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>("/auth/guest-token", {}, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
const token = data?.token || data?.data
|
||||
if (token) {
|
||||
setGuestToken(token)
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Error fetching guest token:", error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Login mutation (RTK mantığı)
|
||||
*/
|
||||
export function useLogin() {
|
||||
return useMutation({
|
||||
mutationFn: async (credentials: LoginCredentials): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>("/auth/login", credentials)
|
||||
return response.data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
const token = data?.token || data?.data
|
||||
if (token) {
|
||||
setAuthToken(token)
|
||||
apiClient.setAuthToken(token)
|
||||
|
||||
// Tüm cache'i temizle ve yeniden fetch et
|
||||
queryClient.invalidateQueries()
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Login error:", error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Register mutation (RTK mantığı)
|
||||
*/
|
||||
export function useRegister() {
|
||||
return useMutation({
|
||||
mutationFn: async (userData: RegisterData): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>("/auth/register", userData)
|
||||
return response.data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
const token = data?.token || data?.data
|
||||
if (token) {
|
||||
setAuthToken(token)
|
||||
apiClient.setAuthToken(token)
|
||||
|
||||
// Tüm cache'i temizle
|
||||
queryClient.invalidateQueries()
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Register error:", error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Token doğrulama (RTK mantığı)
|
||||
*/
|
||||
export function useVerifyToken() {
|
||||
return useMutation({
|
||||
mutationFn: async (verifyData: VerifyTokenData): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>(
|
||||
"/auth/verify",
|
||||
verifyData,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
}
|
||||
)
|
||||
return response.data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
const token = data?.data || data?.token
|
||||
if (token) {
|
||||
setAuthToken(token)
|
||||
apiClient.setAuthToken(token)
|
||||
|
||||
// Tüm cache'i temizle
|
||||
queryClient.invalidateQueries()
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Error verifying token:", error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout işlemi
|
||||
*/
|
||||
export function useLogout() {
|
||||
return useMutation({
|
||||
mutationFn: async () => {
|
||||
// Backend'e logout isteği gönder (eğer endpoint varsa)
|
||||
try {
|
||||
await apiClient.post("/auth/logout")
|
||||
} catch (error) {
|
||||
// Logout endpoint yoksa da devam et
|
||||
console.warn("Logout endpoint not available")
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
clearAuthToken()
|
||||
apiClient.clearAuthToken()
|
||||
|
||||
// Tüm cache'i temizle
|
||||
queryClient.clear()
|
||||
|
||||
// Login sayfasına yönlendir
|
||||
if (typeof window !== "undefined") {
|
||||
window.location.href = "/login"
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Kullanıcı bilgilerini getir
|
||||
*/
|
||||
export function useUser(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["user", "me"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get("/auth/me")
|
||||
return response.data
|
||||
},
|
||||
enabled: options?.enabled !== false,
|
||||
staleTime: 1000 * 60 * 5, // 5 dakika
|
||||
retry: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication durumunu kontrol et
|
||||
*/
|
||||
export function useAuthStatus() {
|
||||
const { data: user, isLoading, error } = useUser({ enabled: true })
|
||||
|
||||
return {
|
||||
isAuthenticated: !!user && !error,
|
||||
isLoading,
|
||||
user,
|
||||
}
|
||||
}
|
||||
92
lib/hooks/useCart.ts
Normal file
92
lib/hooks/useCart.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Cart, CartItem } from "@/lib/types/api"
|
||||
|
||||
export function useCart() {
|
||||
return useQuery({
|
||||
queryKey: ["cart"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Cart>("/api/v1/carts")
|
||||
return response.data
|
||||
},
|
||||
staleTime: 0, // Always fetch fresh
|
||||
retry: 1,
|
||||
})
|
||||
}
|
||||
|
||||
export function useAddToCart() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ productId, quantity = 1 }: { productId: number; quantity?: number }) => {
|
||||
const response = await apiClient.post<Cart>("/api/v1/carts", {
|
||||
product_id: productId,
|
||||
quantity,
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["cart"] })
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error("[v0] Add to cart error:", error.response?.data?.message || error.message)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useRemoveFromCart() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (itemId: number) => {
|
||||
await apiClient.delete(`/api/v1/carts/${itemId}`)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["cart"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useUpdateCartItemQuantity() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ itemId, quantity }: { itemId: number; quantity: number }) => {
|
||||
const response = await apiClient.patch<CartItem>(`/api/v1/carts/${itemId}`, {
|
||||
quantity,
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["cart"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreateOrder() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (payload: {
|
||||
customer_name?: string
|
||||
customer_phone?: string
|
||||
customer_address: string
|
||||
shipping_method: string
|
||||
payment_type_id: number
|
||||
delivery_time?: string
|
||||
delivery_at?: string
|
||||
region: string
|
||||
note?: string
|
||||
}) => {
|
||||
const response = await apiClient.post("/api/v1/orders", payload)
|
||||
return response.data
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["cart"] })
|
||||
queryClient.invalidateQueries({ queryKey: ["orders"] })
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error("[v0] Create order error:", error.response?.data?.message || error.message)
|
||||
},
|
||||
})
|
||||
}
|
||||
158
lib/hooks/useCategories.ts
Normal file
158
lib/hooks/useCategories.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Category, Product, PaginatedResponse } from "@/lib/types/api"
|
||||
|
||||
// Get all categories as tree
|
||||
export function useCategories(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["categories"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Category>>("/categories", {
|
||||
params: { type: "tree" },
|
||||
})
|
||||
return response.data.data || response.data
|
||||
},
|
||||
enabled: options?.enabled !== false,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
})
|
||||
}
|
||||
|
||||
// Get single category by ID
|
||||
export function useCategory(id: number | string, options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["category", id],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Category>(`/categories/${id}`)
|
||||
return response.data
|
||||
},
|
||||
enabled: options?.enabled !== false && !!id,
|
||||
staleTime: 1000 * 60 * 15,
|
||||
})
|
||||
}
|
||||
|
||||
// Get products for a single category with pagination
|
||||
export function useCategoryProducts(
|
||||
categoryId: number | string,
|
||||
options?: {
|
||||
enabled?: boolean
|
||||
page?: number
|
||||
limit?: number
|
||||
}
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ["category", categoryId, "products", options?.page, options?.limit],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/categories/${categoryId}/products`,
|
||||
{
|
||||
params: {
|
||||
page: options?.page || 1,
|
||||
limit: options?.limit
|
||||
},
|
||||
}
|
||||
)
|
||||
return {
|
||||
data: response.data.data || [],
|
||||
pagination: response.data.pagination || {}
|
||||
}
|
||||
},
|
||||
enabled: options?.enabled !== false && !!categoryId,
|
||||
})
|
||||
}
|
||||
|
||||
// Get ALL products from category and its children - NO pagination (for initial load)
|
||||
export function useAllCategoryProducts(
|
||||
category: Category | undefined,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ["category", category?.id, "all-products"],
|
||||
queryFn: async () => {
|
||||
if (!category) return []
|
||||
|
||||
const fetchProducts = async (categoryId: number) => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/categories/${categoryId}/products`
|
||||
)
|
||||
return response.data.data || []
|
||||
}
|
||||
|
||||
let allProducts = await fetchProducts(category.id)
|
||||
|
||||
if (category.children && category.children.length > 0) {
|
||||
for (const child of category.children) {
|
||||
const childProducts = await fetchProducts(child.id)
|
||||
allProducts = [...allProducts, ...childProducts]
|
||||
}
|
||||
}
|
||||
|
||||
return allProducts
|
||||
},
|
||||
enabled: options?.enabled !== false && !!category,
|
||||
})
|
||||
}
|
||||
|
||||
// Get products from category and children WITH pagination (mimics RTK getAllCategoryProductsPaginated)
|
||||
export function useAllCategoryProductsPaginated(
|
||||
category: Category | undefined,
|
||||
options?: {
|
||||
enabled?: boolean
|
||||
page?: number
|
||||
limit?: number
|
||||
}
|
||||
) {
|
||||
const page = options?.page || 1
|
||||
const limit = options?.limit || 6
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["category", category?.id, "paginated-products", page, limit],
|
||||
queryFn: async () => {
|
||||
if (!category) {
|
||||
return {
|
||||
data: [],
|
||||
pagination: {
|
||||
currentPage: page,
|
||||
hasMorePages: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const categoryIds = [category.id]
|
||||
if (category.children && category.children.length > 0) {
|
||||
category.children.forEach((child) => categoryIds.push(child.id))
|
||||
}
|
||||
|
||||
const perCategoryLimit = Math.ceil(limit / categoryIds.length)
|
||||
const hasMoreByCategory: Record<number, boolean> = {}
|
||||
let allPageProducts: Product[] = []
|
||||
|
||||
for (const categoryId of categoryIds) {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/categories/${categoryId}/products`,
|
||||
{
|
||||
params: {
|
||||
page,
|
||||
limit: perCategoryLimit
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (response.data.data) {
|
||||
allPageProducts = [...allPageProducts, ...response.data.data]
|
||||
hasMoreByCategory[categoryId] = !!response.data.pagination?.next_page_url
|
||||
}
|
||||
}
|
||||
|
||||
const hasMorePages = Object.values(hasMoreByCategory).some((hasMore) => hasMore)
|
||||
|
||||
return {
|
||||
data: allPageProducts,
|
||||
pagination: {
|
||||
currentPage: page,
|
||||
hasMorePages
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled: options?.enabled !== false && !!category,
|
||||
})
|
||||
}
|
||||
108
lib/hooks/useCollections.ts
Normal file
108
lib/hooks/useCollections.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Collection, Product, PaginatedResponse } from "@/lib/types/api"
|
||||
|
||||
// Get all collections
|
||||
export function useCollections(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["collections"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Collection>>("/collections")
|
||||
return response.data.data || response.data
|
||||
},
|
||||
enabled: options?.enabled !== false,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
})
|
||||
}
|
||||
|
||||
// Get single collection by ID
|
||||
export function useCollection(id: number | string, options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["collection", id],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Collection>(`/collections/${id}`)
|
||||
return response.data
|
||||
},
|
||||
enabled: options?.enabled !== false && !!id,
|
||||
staleTime: 1000 * 60 * 15,
|
||||
})
|
||||
}
|
||||
|
||||
// Get collection products (non-paginated)
|
||||
export function useCollectionProducts(
|
||||
collectionId: number | string,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ["collection", collectionId, "products"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/collections/${collectionId}/products`
|
||||
)
|
||||
const data = response.data.data || []
|
||||
return {
|
||||
data,
|
||||
isEmpty: data.length === 0,
|
||||
}
|
||||
},
|
||||
enabled: options?.enabled !== false && !!collectionId,
|
||||
})
|
||||
}
|
||||
|
||||
// Check if collection has products (limit=1 for efficiency)
|
||||
export function useCollectionHasProducts(
|
||||
collectionId: number | string,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ["collection", collectionId, "has-products"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/collections/${collectionId}/products`,
|
||||
{
|
||||
params: { limit: 1 },
|
||||
}
|
||||
)
|
||||
return {
|
||||
hasProducts: response.data.data && response.data.data.length > 0,
|
||||
}
|
||||
},
|
||||
enabled: options?.enabled !== false && !!collectionId,
|
||||
staleTime: 1000 * 60 * 5, // 5 minutes
|
||||
})
|
||||
}
|
||||
|
||||
// Get collection products with pagination
|
||||
export function useCollectionProductsPaginated(
|
||||
collectionId: number | string,
|
||||
options?: {
|
||||
enabled?: boolean
|
||||
page?: number
|
||||
limit?: number
|
||||
}
|
||||
) {
|
||||
const page = options?.page || 1
|
||||
const limit = options?.limit || 6
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["collection", collectionId, "products-paginated", page, limit],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>(
|
||||
`/collections/${collectionId}/products`,
|
||||
{
|
||||
params: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
}
|
||||
)
|
||||
const data = response.data.data || []
|
||||
return {
|
||||
data,
|
||||
pagination: response.data.pagination || {},
|
||||
isEmpty: data.length === 0,
|
||||
}
|
||||
},
|
||||
enabled: options?.enabled !== false && !!collectionId,
|
||||
})
|
||||
}
|
||||
42
lib/hooks/useFavorites.ts
Normal file
42
lib/hooks/useFavorites.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Favorite } from "@/lib/types/api"
|
||||
|
||||
export function useFavorites() {
|
||||
return useQuery({
|
||||
queryKey: ["favorites"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Favorite[]>("/favorites")
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 5,
|
||||
retry: 1,
|
||||
})
|
||||
}
|
||||
|
||||
export function useAddToFavorites() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (productId: number) => {
|
||||
const response = await apiClient.post<Favorite[]>("/favorites", { product_id: productId })
|
||||
return response.data
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["favorites"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useRemoveFromFavorites() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (productId: number) => {
|
||||
await apiClient.delete(`/favorites/${productId}`)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["favorites"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
29
lib/hooks/useMedia.ts
Normal file
29
lib/hooks/useMedia.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Carousel, Banner, PaginatedResponse } from "@/lib/types/api"
|
||||
|
||||
// Get all carousels
|
||||
export function useCarousels(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["carousels"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Carousel>>("/media/carousels")
|
||||
return response.data.data || response.data
|
||||
},
|
||||
enabled: options?.enabled !== false,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
})
|
||||
}
|
||||
|
||||
// Get all banners
|
||||
export function useBanners(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["banners"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Banner>>("/media/banners")
|
||||
return response.data.data || response.data
|
||||
},
|
||||
enabled: options?.enabled !== false,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
})
|
||||
}
|
||||
38
lib/hooks/useOpenStore.ts
Normal file
38
lib/hooks/useOpenStore.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
"use client"
|
||||
|
||||
import { useMutation } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import { API_ENDPOINTS } from "@/lib/config/api-endpoints"
|
||||
|
||||
interface OpenStoreData {
|
||||
firstName: string
|
||||
lastName: string
|
||||
email: string
|
||||
phone: string
|
||||
patentFile: File
|
||||
}
|
||||
|
||||
interface OpenStoreResponse {
|
||||
success: boolean
|
||||
message: string
|
||||
}
|
||||
|
||||
export function useOpenStore() {
|
||||
return useMutation({
|
||||
mutationFn: async (data: OpenStoreData) => {
|
||||
const formData = new FormData()
|
||||
formData.append("first_name", data.firstName)
|
||||
formData.append("last_name", data.lastName)
|
||||
formData.append("email", data.email)
|
||||
formData.append("phone", data.phone)
|
||||
formData.append("patent_file", data.patentFile)
|
||||
|
||||
const response = await apiClient.post<OpenStoreResponse>(API_ENDPOINTS.openStore, formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
})
|
||||
}
|
||||
59
lib/hooks/useOrders.ts
Normal file
59
lib/hooks/useOrders.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Order, PaginatedResponse } from "@/lib/types/api"
|
||||
|
||||
export function useOrders(options?: { page?: number; perPage?: number }) {
|
||||
return useQuery({
|
||||
queryKey: ["orders", options?.page],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Order>>("/orders", {
|
||||
params: {
|
||||
page: options?.page || 1,
|
||||
per_page: options?.perPage || 20,
|
||||
},
|
||||
})
|
||||
return response.data.data || response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 5,
|
||||
retry: 1,
|
||||
})
|
||||
}
|
||||
|
||||
export function useOrder(id: number | string) {
|
||||
return useQuery({
|
||||
queryKey: ["order", id],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Order>(`/orders/${id}`)
|
||||
return response.data
|
||||
},
|
||||
enabled: !!id,
|
||||
})
|
||||
}
|
||||
|
||||
export function useCancelOrder() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (orderId: number) => {
|
||||
await apiClient.post(`/orders/${orderId}/cancel`, {})
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["orders"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreateOrder() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (orderData: any) => {
|
||||
const response = await apiClient.post<Order>("/orders", orderData)
|
||||
return response.data
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["orders"] })
|
||||
queryClient.invalidateQueries({ queryKey: ["cart"] })
|
||||
},
|
||||
})
|
||||
}
|
||||
14
lib/hooks/usePaymentTypes.ts
Normal file
14
lib/hooks/usePaymentTypes.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { PaymentTypeOption } from "@/lib/types/api"
|
||||
|
||||
export function usePaymentTypes() {
|
||||
return useQuery({
|
||||
queryKey: ["paymentTypes"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaymentTypeOption[]>("/api/v1/order-payments")
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 60, // 1 hour
|
||||
})
|
||||
}
|
||||
50
lib/hooks/useProducts.ts
Normal file
50
lib/hooks/useProducts.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Product, PaginatedResponse } from "@/lib/types/api"
|
||||
|
||||
interface UseProductsOptions {
|
||||
enabled?: boolean
|
||||
staleTime?: number
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export function useProducts(options?: UseProductsOptions) {
|
||||
return useQuery({
|
||||
queryKey: ["products", options?.page, options?.perPage],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<PaginatedResponse<Product>>("/products", {
|
||||
params: {
|
||||
page: options?.page || 1,
|
||||
per_page: options?.perPage || 20,
|
||||
},
|
||||
})
|
||||
return response.data.data || response.data
|
||||
},
|
||||
staleTime: options?.staleTime ?? 1000 * 60 * 5, // 5 minutes
|
||||
enabled: options?.enabled !== false,
|
||||
})
|
||||
}
|
||||
|
||||
export function useProduct(id: number | string, options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["product", id],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Product>(`/products/${id}`)
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
enabled: options?.enabled !== false && !!id,
|
||||
})
|
||||
}
|
||||
|
||||
export function useProductsBySlug(slug: string, options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["products", "slug", slug],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Product>(`/products/${slug}`)
|
||||
return response.data
|
||||
},
|
||||
enabled: options?.enabled !== false && !!slug,
|
||||
})
|
||||
}
|
||||
14
lib/hooks/useRegions.ts
Normal file
14
lib/hooks/useRegions.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { Region } from "@/lib/types/api"
|
||||
|
||||
export function useRegions() {
|
||||
return useQuery({
|
||||
queryKey: ["regions"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<Region[]>("/api/v1/regions")
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 60, // 1 hour
|
||||
})
|
||||
}
|
||||
28
lib/hooks/useSearch.ts
Normal file
28
lib/hooks/useSearch.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import type { SearchFilters, SearchResponse } from "@/lib/types/api"
|
||||
|
||||
export function useSearch(options: SearchFilters) {
|
||||
const { q, category_id, brand_id, price_from, price_to, page = 1, per_page = 20 } = options
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["search", { q, category_id, brand_id, price_from, price_to, page, per_page }],
|
||||
queryFn: async () => {
|
||||
const params = new URLSearchParams({
|
||||
page: String(page),
|
||||
per_page: String(per_page),
|
||||
})
|
||||
|
||||
if (q) params.append("q", q)
|
||||
if (category_id) params.append("category_id", String(category_id))
|
||||
if (brand_id) params.append("brand_id", String(brand_id))
|
||||
if (price_from) params.append("price_from", String(price_from))
|
||||
if (price_to) params.append("price_to", String(price_to))
|
||||
|
||||
const response = await apiClient.get<SearchResponse>(`/search?${params}`)
|
||||
return response.data
|
||||
},
|
||||
enabled: !!q && q.length > 0,
|
||||
staleTime: 1000 * 60 * 5,
|
||||
})
|
||||
}
|
||||
18
lib/hooks/useUserProfile.ts
Normal file
18
lib/hooks/useUserProfile.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
"use client"
|
||||
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { apiClient } from "@/lib/api"
|
||||
import { API_ENDPOINTS } from "@/lib/config/api-endpoints"
|
||||
import type { UserProfile } from "@/lib/types/api"
|
||||
|
||||
export function useUserProfile(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ["user", "profile"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get<UserProfile>(API_ENDPOINTS.profile)
|
||||
return response.data
|
||||
},
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
enabled: options?.enabled !== false,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user