- Implement color request modal popup instead of separate page - Add Serbian translations throughout - Fix Safari form styling issues with custom CSS - Add 'Other' option to material and finish dropdowns - Create admin panel for managing color requests - Add database migration for color_requests table - Implement API endpoints for color request management
134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
import axios from 'axios';
|
|
import { Filament } from '@/src/types/filament';
|
|
|
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api';
|
|
|
|
// Create axios instance with default config
|
|
const api = axios.create({
|
|
baseURL: API_URL,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
// Add auth token to requests
|
|
api.interceptors.request.use((config) => {
|
|
const token = localStorage.getItem('authToken');
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
});
|
|
|
|
// Handle auth errors
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
(error) => {
|
|
if (error.response?.status === 401 || error.response?.status === 403) {
|
|
// Clear auth data
|
|
localStorage.removeItem('authToken');
|
|
localStorage.removeItem('tokenExpiry');
|
|
|
|
// Only redirect if we're in a protected admin route
|
|
if (window.location.pathname.includes('/upadaj/')) {
|
|
window.location.href = '/upadaj';
|
|
}
|
|
}
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
export const authService = {
|
|
login: async (username: string, password: string) => {
|
|
const response = await api.post('/login', { username, password });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
export const colorService = {
|
|
getAll: async () => {
|
|
const response = await api.get('/colors');
|
|
return response.data;
|
|
},
|
|
|
|
create: async (color: { name: string; hex: string; cena_refill?: number; cena_spulna?: number }) => {
|
|
const response = await api.post('/colors', color);
|
|
return response.data;
|
|
},
|
|
|
|
update: async (id: string, color: { name: string; hex: string; cena_refill?: number; cena_spulna?: number }) => {
|
|
const response = await api.put(`/colors/${id}`, color);
|
|
return response.data;
|
|
},
|
|
|
|
delete: async (id: string) => {
|
|
const response = await api.delete(`/colors/${id}`);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
export const filamentService = {
|
|
getAll: async () => {
|
|
const cacheBuster = Date.now();
|
|
const response = await api.get(`/filaments?_t=${cacheBuster}`);
|
|
return response.data;
|
|
},
|
|
|
|
create: async (filament: Partial<Filament>) => {
|
|
const response = await api.post('/filaments', filament);
|
|
return response.data;
|
|
},
|
|
|
|
update: async (id: string, filament: Partial<Filament>) => {
|
|
const response = await api.put(`/filaments/${id}`, filament);
|
|
return response.data;
|
|
},
|
|
|
|
delete: async (id: string) => {
|
|
const response = await api.delete(`/filaments/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
updateBulkSale: async (data: {
|
|
filamentIds?: string[];
|
|
salePercentage: number;
|
|
saleStartDate?: string;
|
|
saleEndDate?: string;
|
|
enableSale: boolean;
|
|
}) => {
|
|
const response = await api.post('/filaments/sale/bulk', data);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
export const colorRequestService = {
|
|
getAll: async () => {
|
|
const response = await api.get('/color-requests');
|
|
return response.data;
|
|
},
|
|
|
|
submit: async (request: {
|
|
color_name: string;
|
|
material_type: string;
|
|
finish_type?: string;
|
|
user_email?: string;
|
|
user_name?: string;
|
|
description?: string;
|
|
reference_url?: string;
|
|
}) => {
|
|
const response = await api.post('/color-requests', request);
|
|
return response.data;
|
|
},
|
|
|
|
updateStatus: async (id: string, status: string, admin_notes?: string) => {
|
|
const response = await api.put(`/color-requests/${id}`, { status, admin_notes });
|
|
return response.data;
|
|
},
|
|
|
|
delete: async (id: string) => {
|
|
const response = await api.delete(`/color-requests/${id}`);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
export default api; |