Initial commit: SIBU 2.0 MISSION
This commit is contained in:
22
frontend/src/services/analyticsService.ts
Normal file
22
frontend/src/services/analyticsService.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { apiClient } from './apiClient'
|
||||
|
||||
export interface AnalyticsEvent {
|
||||
event_name: 'app_open' | 'screen_view' | 'route_selected' | 'stop_selected' | 'schedule_viewed' | 'reminder_created' | 'promo_view' | 'promo_click' | 'taxi_view' | 'taxi_click' | 'shuttle_view' | 'shuttle_contact' | 'business_view' | 'business_contact'
|
||||
screen_name?: string
|
||||
item_id?: string
|
||||
properties?: Record<string, any>
|
||||
}
|
||||
|
||||
export const analyticsService = {
|
||||
logEvent(event: AnalyticsEvent) {
|
||||
// Log asynchronously without awaiting to avoid blocking UI
|
||||
apiClient.post('/api/analytics/event', event).catch(error => {
|
||||
console.warn('Analytics capture failed:', error)
|
||||
})
|
||||
},
|
||||
|
||||
async getStats() {
|
||||
const response = await apiClient.get('/api/analytics/dashboard/stats')
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
59
frontend/src/services/apiClient.ts
Normal file
59
frontend/src/services/apiClient.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/** Base API client for making HTTP requests to the backend */
|
||||
import axios from 'axios'
|
||||
import type { AxiosInstance, AxiosError } from 'axios'
|
||||
|
||||
export const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
|
||||
|
||||
class ApiClient {
|
||||
private client: AxiosInstance
|
||||
|
||||
constructor() {
|
||||
this.client = axios.create({
|
||||
baseURL: API_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 10000,
|
||||
})
|
||||
|
||||
// Request interceptor
|
||||
this.client.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('auth_token')
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// Response interceptor
|
||||
this.client.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error: AxiosError) => {
|
||||
// Handle common errors
|
||||
if (error.response) {
|
||||
// Server responded with error status
|
||||
console.error('API Error:', error.response.status, error.response.data)
|
||||
} else if (error.request) {
|
||||
// Request made but no response
|
||||
console.error('Network Error:', error.request)
|
||||
} else {
|
||||
// Something else happened
|
||||
console.error('Error:', error.message)
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
get instance(): AxiosInstance {
|
||||
return this.client
|
||||
}
|
||||
}
|
||||
|
||||
export const apiClient = new ApiClient().instance
|
||||
|
||||
55
frontend/src/services/authService.ts
Normal file
55
frontend/src/services/authService.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { apiClient, API_URL } from './apiClient'
|
||||
|
||||
export interface LoginResponse {
|
||||
access_token: string
|
||||
token_type: string
|
||||
role: string
|
||||
full_name: string
|
||||
profile_photo_url?: string
|
||||
}
|
||||
|
||||
export const authService = {
|
||||
async login(params: { email: string; password: string; keep_session?: boolean }): Promise<LoginResponse> {
|
||||
const response = await apiClient.post<LoginResponse>('/api/auth/login', params)
|
||||
return response.data
|
||||
},
|
||||
|
||||
async registerPassenger(data: any) {
|
||||
const response = await apiClient.post('/api/auth/register/passenger', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
async registerDriver(formData: FormData) {
|
||||
const response = await apiClient.post('/api/auth/register/driver', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
async getCurrentUser() {
|
||||
const response = await apiClient.get('/api/auth/me')
|
||||
return response.data
|
||||
},
|
||||
|
||||
async updateMe(formData: FormData) {
|
||||
const response = await apiClient.patch('/api/auth/me', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
logout() {
|
||||
localStorage.removeItem('auth_token')
|
||||
localStorage.removeItem('user_role')
|
||||
localStorage.removeItem('user_name')
|
||||
localStorage.removeItem('profile_photo_url')
|
||||
},
|
||||
|
||||
getApiUrl() {
|
||||
return API_URL
|
||||
}
|
||||
}
|
||||
57
frontend/src/services/busStopsService.ts
Normal file
57
frontend/src/services/busStopsService.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/** Service for bus stop-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { BusStop, Route } from '@/types'
|
||||
|
||||
export const busStopsService = {
|
||||
/** Get all bus stops */
|
||||
async getAllBusStops(): Promise<BusStop[]> {
|
||||
const response = await apiClient.get<BusStop[]>('/api/bus-stops')
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get a single bus stop by ID */
|
||||
async getBusStopById(id: string): Promise<BusStop> {
|
||||
const response = await apiClient.get<BusStop>(`/api/bus-stops/${id}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get all routes passing through a bus stop */
|
||||
async getBusStopRoutes(stopId: string): Promise<Route[]> {
|
||||
const response = await apiClient.get<Route[]>(`/api/bus-stops/${stopId}/routes`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get estimated next bus arrivals (Mock Data) */
|
||||
async getNextBusArrivals(_stopId: string): Promise<{ routeName: string; arrivalTime: string }[]> {
|
||||
// Mock delay to simulate network request
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
// Generate some random mock arrivals
|
||||
const mockArrivals = [
|
||||
{ routeName: "Ruta Boquete - David", arrivalTime: "5 min" },
|
||||
{ routeName: "Ruta David - Boquete", arrivalTime: "12 min" },
|
||||
{ routeName: "Ruta Circular", arrivalTime: "25 min" }
|
||||
];
|
||||
|
||||
// Randomly return 1-3 arrivals
|
||||
return mockArrivals.slice(0, Math.floor(Math.random() * 3) + 1);
|
||||
},
|
||||
|
||||
/** Create a new bus stop (Admin) */
|
||||
async createBusStop(data: import('@/types').BusStopCreate): Promise<BusStop> {
|
||||
const response = await apiClient.post<BusStop>('/api/bus-stops', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Update a bus stop (Admin) */
|
||||
async updateBusStop(id: string, data: import('@/types').BusStopUpdate): Promise<BusStop> {
|
||||
const response = await apiClient.put<BusStop>(`/api/bus-stops/${id}`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Delete a bus stop (Admin) */
|
||||
async deleteBusStop(id: string): Promise<void> {
|
||||
await apiClient.delete(`/api/bus-stops/${id}`)
|
||||
}
|
||||
}
|
||||
|
||||
42
frontend/src/services/businessService.ts
Normal file
42
frontend/src/services/businessService.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/** Service for business-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Business } from '@/types'
|
||||
|
||||
export const businessService = {
|
||||
/** Get all businesses */
|
||||
async getAllBusinesses(): Promise<Business[]> {
|
||||
const response = await apiClient.get<Business[]>('/api/businesses')
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get a single business by ID */
|
||||
async getBusiness(id: string): Promise<Business> {
|
||||
const response = await apiClient.get<Business>(`/api/businesses/${id}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Create a new business */
|
||||
async createBusiness(businessData: FormData): Promise<Business> {
|
||||
const response = await apiClient.post<Business>('/api/businesses', businessData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Update an existing business */
|
||||
async updateBusiness(id: string, businessData: FormData): Promise<Business> {
|
||||
const response = await apiClient.patch<Business>(`/api/businesses/${id}`, businessData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Delete a business */
|
||||
async deleteBusiness(id: string): Promise<void> {
|
||||
await apiClient.delete(`/api/businesses/${id}`)
|
||||
},
|
||||
}
|
||||
61
frontend/src/services/couponsService.ts
Normal file
61
frontend/src/services/couponsService.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/** Service for coupon-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Coupon } from '@/types'
|
||||
|
||||
export interface CouponFilters {
|
||||
category?: string
|
||||
is_active?: boolean
|
||||
active_only?: boolean
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
|
||||
/** Get a single coupon by ID */
|
||||
async getCouponById(id: string): Promise<Coupon> {
|
||||
const response = await apiClient.get<Coupon>(`/api/coupons/${id}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** 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
|
||||
},
|
||||
|
||||
/** 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
|
||||
},
|
||||
|
||||
/** Delete a coupon */
|
||||
async deleteCoupon(id: string): Promise<void> {
|
||||
await apiClient.delete(`/api/coupons/${id}`)
|
||||
},
|
||||
|
||||
/** Claim a coupon */
|
||||
async claimCoupon(id: string): Promise<any> {
|
||||
const response = await apiClient.post(`/api/coupons/${id}/claim`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get current user's claimed coupons */
|
||||
async getMyCoupons(): Promise<any[]> {
|
||||
const response = await apiClient.get('/api/coupons/my-coupons')
|
||||
return response.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
|
||||
}
|
||||
}
|
||||
|
||||
74
frontend/src/services/favoritesService.ts
Normal file
74
frontend/src/services/favoritesService.ts
Normal file
@ -0,0 +1,74 @@
|
||||
/** Service for favorite-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Favorite } from '@/types'
|
||||
|
||||
export const favoritesService = {
|
||||
/** Get all favorites for the current user */
|
||||
async getMyFavorites(itemType?: string): Promise<Favorite[]> {
|
||||
const params = itemType ? { item_type: itemType } : {}
|
||||
const response = await apiClient.get<Favorite[]>('/api/favorites', { params })
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Add a new favorite */
|
||||
async addFavorite(
|
||||
itemType: 'route' | 'stop' | 'taxi' | 'coupon' | 'business',
|
||||
itemId: string,
|
||||
itemName?: string,
|
||||
itemImage?: string
|
||||
): Promise<Favorite> {
|
||||
const response = await apiClient.post<Favorite>('/api/favorites', {
|
||||
item_type: itemType,
|
||||
item_id: itemId,
|
||||
item_name: itemName,
|
||||
item_image: itemImage
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Remove a favorite by type and ID */
|
||||
async removeFavorite(itemType: string, itemId: string): Promise<void> {
|
||||
await apiClient.delete(`/api/favorites/${itemType}/${itemId}`)
|
||||
},
|
||||
|
||||
/** Remove a favorite by favorite ID (legacy support) */
|
||||
async removeFavoriteById(favoriteId: string): Promise<void> {
|
||||
// This requires finding the favorite first to get type and id
|
||||
const favorites = await this.getMyFavorites()
|
||||
const favorite = favorites.find(f => f.id === favoriteId)
|
||||
if (favorite) {
|
||||
await this.removeFavorite(favorite.item_type, favorite.item_id)
|
||||
}
|
||||
},
|
||||
|
||||
/** Check if an item is favorited */
|
||||
async checkFavorite(itemType: string, itemId: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await apiClient.get<{ is_favorite: boolean }>(
|
||||
`/api/favorites/check/${itemType}/${itemId}`
|
||||
)
|
||||
return response.data.is_favorite
|
||||
} catch (error) {
|
||||
console.error('Error checking favorite:', error)
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
/** Toggle favorite status */
|
||||
async toggleFavorite(
|
||||
itemType: 'route' | 'stop' | 'taxi' | 'coupon' | 'business',
|
||||
itemId: string,
|
||||
itemName?: string,
|
||||
itemImage?: string
|
||||
): Promise<boolean> {
|
||||
const isFavorite = await this.checkFavorite(itemType, itemId)
|
||||
|
||||
if (isFavorite) {
|
||||
await this.removeFavorite(itemType, itemId)
|
||||
return false
|
||||
} else {
|
||||
await this.addFavorite(itemType, itemId, itemName, itemImage)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
28
frontend/src/services/reportsService.ts
Normal file
28
frontend/src/services/reportsService.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
export interface Report {
|
||||
id: string;
|
||||
user_id?: string;
|
||||
user_name?: string;
|
||||
message: string;
|
||||
status: 'pending' | 'resolved' | 'archived';
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export const reportsService = {
|
||||
async sendReport(message: string) {
|
||||
const response = await apiClient.post('/api/reports', { message });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getReports() {
|
||||
// This would be for the admin
|
||||
const response = await apiClient.get('/api/reports');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async updateReportStatus(reportId: string, status: string) {
|
||||
const response = await apiClient.patch(`/api/reports/${reportId}`, { status });
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
56
frontend/src/services/routesService.ts
Normal file
56
frontend/src/services/routesService.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/** Service for route-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Route, BusStop } from '@/types'
|
||||
|
||||
export const routesService = {
|
||||
/** Get all routes with optional filtering */
|
||||
async getAllRoutes(filters?: { originCity?: string, destinationCity?: string }): Promise<Route[]> {
|
||||
const response = await apiClient.get<Route[]>('/api/routes', {
|
||||
params: {
|
||||
origin_city: filters?.originCity,
|
||||
destination_city: filters?.destinationCity
|
||||
}
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get a single route by ID */
|
||||
async getRouteById(id: string): Promise<Route> {
|
||||
const response = await apiClient.get<Route>(`/api/routes/${id}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get all stops for a route */
|
||||
async getRouteStops(routeId: string): Promise<BusStop[]> {
|
||||
const response = await apiClient.get<BusStop[]>(`/api/routes/${routeId}/stops`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Create a new route (Admin) */
|
||||
async createRoute(data: import('@/types').RouteCreate): Promise<Route> {
|
||||
const response = await apiClient.post<Route>('/api/routes', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Update a route (Admin) */
|
||||
async updateRoute(id: string, data: import('@/types').RouteUpdate): Promise<Route> {
|
||||
const response = await apiClient.put<Route>(`/api/routes/${id}`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Delete a route (Admin) */
|
||||
async deleteRoute(id: string): Promise<void> {
|
||||
await apiClient.delete(`/api/routes/${id}`)
|
||||
},
|
||||
|
||||
/** Add a stop to a route (Admin) */
|
||||
async addStopToRoute(routeId: string, data: import('@/types').RouteStopCreate): Promise<void> {
|
||||
await apiClient.post(`/api/routes/${routeId}/stops`, data)
|
||||
},
|
||||
|
||||
/** Update a stop on a route (Admin) - including reorder */
|
||||
async updateRouteStop(routeId: string, stopId: string, data: import('@/types').RouteStopUpdate): Promise<void> {
|
||||
await apiClient.put(`/api/routes/${routeId}/stops/${stopId}`, data)
|
||||
}
|
||||
}
|
||||
|
||||
32
frontend/src/services/schedulesService.ts
Normal file
32
frontend/src/services/schedulesService.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
export const schedulesService = {
|
||||
async getRouteSchedules(routeId: string, onlyPublished = true) {
|
||||
const response = await apiClient.get('/api/schedules', {
|
||||
params: { route_id: routeId, only_published: onlyPublished }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getStopSchedules(stopId: string, onlyPublished = true) {
|
||||
const response = await apiClient.get('/api/schedules', {
|
||||
params: { stop_id: stopId, only_published: onlyPublished }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async createSchedule(scheduleData: any) {
|
||||
const response = await apiClient.post('/api/schedules', scheduleData);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async updateSchedule(scheduleId: string, updateData: any) {
|
||||
const response = await apiClient.put(`/api/schedules/${scheduleId}`, updateData);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async deleteSchedule(scheduleId: string) {
|
||||
const response = await apiClient.delete(`/api/schedules/${scheduleId}`);
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
27
frontend/src/services/shuttlesService.ts
Normal file
27
frontend/src/services/shuttlesService.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/** Service for shuttle-related API calls (Intercity/Tourism) */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Shuttle } from '@/types'
|
||||
|
||||
export interface ShuttleFilters {
|
||||
origin?: string
|
||||
destination?: string
|
||||
company_name?: string
|
||||
trip_type?: string
|
||||
is_active?: boolean
|
||||
}
|
||||
|
||||
export const shuttlesService = {
|
||||
/** Get all shuttles with optional filters */
|
||||
async getAllShuttles(filters?: ShuttleFilters): Promise<Shuttle[]> {
|
||||
const response = await apiClient.get<Shuttle[]>('/api/shuttles', {
|
||||
params: filters,
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get a single shuttle by ID */
|
||||
async getShuttleById(id: string): Promise<Shuttle> {
|
||||
const response = await apiClient.get<Shuttle>(`/api/shuttles/${id}`)
|
||||
return response.data
|
||||
},
|
||||
}
|
||||
27
frontend/src/services/taxisService.ts
Normal file
27
frontend/src/services/taxisService.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/** Service for taxi-related API calls */
|
||||
import { apiClient } from './apiClient'
|
||||
import type { Taxi } from '@/types'
|
||||
|
||||
export interface TaxiFilters {
|
||||
corregimiento?: string
|
||||
shift?: string
|
||||
english_speaking?: boolean
|
||||
is_active?: boolean
|
||||
}
|
||||
|
||||
export const taxisService = {
|
||||
/** Get all taxis with optional filters */
|
||||
async getAllTaxis(filters?: TaxiFilters): Promise<Taxi[]> {
|
||||
const response = await apiClient.get<Taxi[]>('/api/taxis', {
|
||||
params: filters,
|
||||
})
|
||||
return response.data
|
||||
},
|
||||
|
||||
/** Get a single taxi by ID */
|
||||
async getTaxiById(id: string): Promise<Taxi> {
|
||||
const response = await apiClient.get<Taxi>(`/api/taxis/${id}`)
|
||||
return response.data
|
||||
},
|
||||
}
|
||||
|
||||
32
frontend/src/services/telemetryService.ts
Normal file
32
frontend/src/services/telemetryService.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { apiClient } from './apiClient'
|
||||
|
||||
export interface TelemetryData {
|
||||
latitude: number
|
||||
longitude: number
|
||||
speed?: number
|
||||
heading?: number
|
||||
status?: 'active' | 'offline' | 'break'
|
||||
}
|
||||
|
||||
export interface ActiveUnit {
|
||||
user_id: string
|
||||
full_name: string
|
||||
latitude: number
|
||||
longitude: number
|
||||
speed?: number
|
||||
heading?: number
|
||||
timestamp: string
|
||||
vehicle_type: string
|
||||
license_plate: string
|
||||
}
|
||||
|
||||
export const telemetryService = {
|
||||
async sendTelemetry(data: TelemetryData) {
|
||||
return await apiClient.post('/api/telemetry', data)
|
||||
},
|
||||
|
||||
async getActiveUnits(): Promise<ActiveUnit[]> {
|
||||
const response = await apiClient.get<ActiveUnit[]>('/api/telemetry/active')
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
27
frontend/src/services/usersService.ts
Normal file
27
frontend/src/services/usersService.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
export const usersService = {
|
||||
async searchUsers(email: string) {
|
||||
const response = await apiClient.get('/api/users/search', {
|
||||
params: { email }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getUserDetails(userId: string) {
|
||||
const response = await apiClient.get(`/api/users/${userId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getPendingDrivers() {
|
||||
const response = await apiClient.get('/api/users/pending-drivers');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async verifyUser(userId: string, isVerified: boolean) {
|
||||
const response = await apiClient.post(`/api/users/${userId}/verify`, null, {
|
||||
params: { is_verified: isVerified }
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user