🚀 Feat(Core): Migración oficial y total B a Supabase (Auth, DB, APIs) + Eliminación de Backend Python y Fixes Firebase + Soporte Vite Vercel
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/** Service for coupon-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import { supabase } from '@/supabase'
|
||||
import type { Coupon } from '@/types'
|
||||
|
||||
export interface CouponFilters {
|
||||
@ -11,51 +11,93 @@ export interface CouponFilters {
|
||||
export const couponsService = {
|
||||
/** Get all coupons with optional filters */
|
||||
async getAllCoupons(filters?: CouponFilters): Promise<Coupon[]> {
|
||||
const response = await apiClient.get<Coupon[]>('/api/coupons', {
|
||||
params: filters,
|
||||
})
|
||||
return response.data
|
||||
let query = supabase.from('coupons').select('*, business:businesses(*)')
|
||||
|
||||
if (filters?.category) query = query.eq('category', filters.category)
|
||||
if (filters?.is_active !== undefined) query = query.eq('is_active', filters.is_active)
|
||||
if (filters?.active_only !== undefined && filters.active_only) {
|
||||
query = query.eq('is_active', true)
|
||||
}
|
||||
|
||||
const { data, error } = await query
|
||||
if (error) throw new Error(error.message)
|
||||
return data as Coupon[]
|
||||
},
|
||||
|
||||
/** Get a single coupon by ID */
|
||||
async getCouponById(id: string): Promise<Coupon> {
|
||||
const response = await apiClient.get<Coupon>(`/api/coupons/${id}`)
|
||||
return response.data
|
||||
const { data, error } = await supabase.from('coupons').select('*, business:businesses(*)').eq('id', id).single()
|
||||
if (error) throw new Error(error.message)
|
||||
return data as Coupon
|
||||
},
|
||||
|
||||
/** Create a new coupon */
|
||||
async createCoupon(coupon: Omit<Coupon, 'id' | 'created_at' | 'updated_at'>): Promise<Coupon> {
|
||||
const response = await apiClient.post<Coupon>('/api/coupons', coupon)
|
||||
return response.data
|
||||
// Prevent sending nested business properties over insert
|
||||
const { business, ...payload } = coupon as any
|
||||
const { data, error } = await supabase.from('coupons').insert([payload]).select().single()
|
||||
if (error) throw new Error(error.message)
|
||||
return data as Coupon
|
||||
},
|
||||
|
||||
/** Update an existing coupon */
|
||||
async updateCoupon(id: string, coupon: Partial<Coupon>): Promise<Coupon> {
|
||||
const response = await apiClient.patch<Coupon>(`/api/coupons/${id}`, coupon)
|
||||
return response.data
|
||||
const { business, ...payload } = coupon as any
|
||||
const { data, error } = await supabase.from('coupons').update(payload).eq('id', id).select().single()
|
||||
if (error) throw new Error(error.message)
|
||||
return data as Coupon
|
||||
},
|
||||
|
||||
/** Delete a coupon */
|
||||
async deleteCoupon(id: string): Promise<void> {
|
||||
await apiClient.delete(`/api/coupons/${id}`)
|
||||
const { error } = await supabase.from('coupons').delete().eq('id', id)
|
||||
if (error) throw new Error(error.message)
|
||||
},
|
||||
|
||||
/** Claim a coupon */
|
||||
async claimCoupon(id: string): Promise<any> {
|
||||
const response = await apiClient.post(`/api/coupons/${id}/claim`)
|
||||
return response.data
|
||||
const { data: userData, error: userError } = await supabase.auth.getUser()
|
||||
if (userError || !userData?.user) throw new Error('User not logged in.')
|
||||
|
||||
const claimPayload = {
|
||||
user_id: userData.user.id,
|
||||
coupon_id: id,
|
||||
status: 'claimed',
|
||||
redemption_code: Math.random().toString(36).substring(2, 8).toUpperCase()
|
||||
}
|
||||
|
||||
const { data, error } = await supabase.from('user_coupons').insert([claimPayload]).select().single()
|
||||
// If error code is duplicate, it means they already claimed it (handled properly).
|
||||
if (error) throw error
|
||||
|
||||
return data
|
||||
},
|
||||
|
||||
/** Get current user's claimed coupons */
|
||||
async getMyCoupons(): Promise<any[]> {
|
||||
const response = await apiClient.get('/api/coupons/my-coupons')
|
||||
return response.data
|
||||
const { data: userData } = await supabase.auth.getUser()
|
||||
if (!userData || !userData.user) return []
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('user_coupons')
|
||||
.select('*, coupon:coupons(*, business:businesses(*))')
|
||||
.eq('user_id', userData.user.id)
|
||||
|
||||
if (error) throw new Error(error.message)
|
||||
return data || []
|
||||
},
|
||||
|
||||
/** Validate a coupon by code (merchants/drivers only) */
|
||||
async validateCoupon(code: string): Promise<any> {
|
||||
const response = await apiClient.post(`/api/coupons/validate/${code}`)
|
||||
return response.data
|
||||
const { data, error } = await supabase
|
||||
.from('user_coupons')
|
||||
.update({ status: 'redeemed', redeemed_at: new Date().toISOString() })
|
||||
.eq('redemption_code', code)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw new Error(error.message)
|
||||
if (!data) throw new Error('Invalid code or already redeemed.')
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user