Initial commit: SmoothSchedule multi-tenant scheduling platform
This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
112
frontend/src/hooks/useServices.ts
Normal file
112
frontend/src/hooks/useServices.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Service Management Hooks
|
||||
*/
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import apiClient from '../api/client';
|
||||
import { Service } from '../types';
|
||||
|
||||
/**
|
||||
* Hook to fetch all services for current business
|
||||
*/
|
||||
export const useServices = () => {
|
||||
return useQuery<Service[]>({
|
||||
queryKey: ['services'],
|
||||
queryFn: async () => {
|
||||
const { data } = await apiClient.get('/api/services/');
|
||||
|
||||
// Transform backend format to frontend format
|
||||
return data.map((s: any) => ({
|
||||
id: String(s.id),
|
||||
name: s.name,
|
||||
durationMinutes: s.duration || s.duration_minutes,
|
||||
price: parseFloat(s.price),
|
||||
description: s.description || '',
|
||||
}));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to get a single service
|
||||
*/
|
||||
export const useService = (id: string) => {
|
||||
return useQuery<Service>({
|
||||
queryKey: ['services', id],
|
||||
queryFn: async () => {
|
||||
const { data } = await apiClient.get(`/api/services/${id}/`);
|
||||
|
||||
return {
|
||||
id: String(data.id),
|
||||
name: data.name,
|
||||
durationMinutes: data.duration || data.duration_minutes,
|
||||
price: parseFloat(data.price),
|
||||
description: data.description || '',
|
||||
};
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to create a service
|
||||
*/
|
||||
export const useCreateService = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (serviceData: Omit<Service, 'id'>) => {
|
||||
const backendData = {
|
||||
name: serviceData.name,
|
||||
duration: serviceData.durationMinutes,
|
||||
price: serviceData.price.toString(),
|
||||
description: serviceData.description,
|
||||
};
|
||||
|
||||
const { data } = await apiClient.post('/api/services/', backendData);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['services'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to update a service
|
||||
*/
|
||||
export const useUpdateService = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, updates }: { id: string; updates: Partial<Service> }) => {
|
||||
const backendData: any = {};
|
||||
if (updates.name) backendData.name = updates.name;
|
||||
if (updates.durationMinutes) backendData.duration = updates.durationMinutes;
|
||||
if (updates.price) backendData.price = updates.price.toString();
|
||||
if (updates.description !== undefined) backendData.description = updates.description;
|
||||
|
||||
const { data } = await apiClient.patch(`/api/services/${id}/`, backendData);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['services'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to delete a service
|
||||
*/
|
||||
export const useDeleteService = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
await apiClient.delete(`/api/services/${id}/`);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['services'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user