first commit

This commit is contained in:
Stefan Hacker
2026-01-29 01:16:54 +01:00
commit e209e9bbca
12105 changed files with 2480672 additions and 0 deletions
+773
View File
@@ -0,0 +1,773 @@
import axios from 'axios';
import type { ApiResponse, Customer, Contract, ContractTask, ContractTaskSubtask, ContractTaskStatus, SalesPlatform, CancellationPeriod, ContractDuration, ContractCategory, Provider, Tariff, User, Address, BankCard, IdentityDocument, Meter, MeterReading, Role, PortalSettings, CustomerRepresentative, CustomerSummary } from '../types';
const api = axios.create({
baseURL: '/api',
headers: {
'Content-Type': 'application/json',
},
});
// Add auth token to requests
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Handle auth errors and extract error messages
api.interceptors.response.use(
(response) => response,
(error) => {
// Bei 401 nur dann zur Login-Seite umleiten, wenn wir NICHT gerade auf der Login-Seite sind
// Login-Endpunkte ausschließen, da 401 dort "falsches Passwort" bedeutet
const isLoginEndpoint = error.config?.url?.includes('/auth/login') ||
error.config?.url?.includes('/auth/customer-login');
if (error.response?.status === 401 && !isLoginEndpoint) {
localStorage.removeItem('token');
localStorage.removeItem('user');
window.location.href = '/login';
}
// Extract error message from response
const message = error.response?.data?.error || error.message || 'Ein Fehler ist aufgetreten';
const enhancedError = new Error(message);
return Promise.reject(enhancedError);
}
);
// Auth
export const authApi = {
login: async (email: string, password: string) => {
const res = await api.post<ApiResponse<{ token: string; user: User }>>('/auth/login', { email, password });
return res.data;
},
customerLogin: async (email: string, password: string) => {
const res = await api.post<ApiResponse<{ token: string; user: User }>>('/auth/customer-login', { email, password });
return res.data;
},
me: async () => {
const res = await api.get<ApiResponse<User>>('/auth/me');
return res.data;
},
};
// Customers
export const customerApi = {
getAll: async (params?: { search?: string; type?: string; page?: number; limit?: number }) => {
const res = await api.get<ApiResponse<Customer[]>>('/customers', { params });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<Customer>>(`/customers/${id}`);
return res.data;
},
create: async (data: Partial<Customer>) => {
const res = await api.post<ApiResponse<Customer>>('/customers', data);
return res.data;
},
update: async (id: number, data: Partial<Customer>) => {
const res = await api.put<ApiResponse<Customer>>(`/customers/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/customers/${id}`);
return res.data;
},
// Portal-Einstellungen
getPortalSettings: async (customerId: number) => {
const res = await api.get<ApiResponse<PortalSettings>>(`/customers/${customerId}/portal`);
return res.data;
},
updatePortalSettings: async (customerId: number, data: { portalEnabled?: boolean; portalEmail?: string | null }) => {
const res = await api.put<ApiResponse<PortalSettings>>(`/customers/${customerId}/portal`, data);
return res.data;
},
setPortalPassword: async (customerId: number, password: string) => {
const res = await api.post<ApiResponse<void>>(`/customers/${customerId}/portal/password`, { password });
return res.data;
},
getPortalPassword: async (customerId: number) => {
const res = await api.get<ApiResponse<{ password: string | null }>>(`/customers/${customerId}/portal/password`);
return res.data;
},
// Vertreter-Verwaltung
getRepresentatives: async (customerId: number) => {
const res = await api.get<ApiResponse<CustomerRepresentative[]>>(`/customers/${customerId}/representatives`);
return res.data;
},
addRepresentative: async (customerId: number, representativeId: number, notes?: string) => {
const res = await api.post<ApiResponse<CustomerRepresentative>>(`/customers/${customerId}/representatives`, { representativeId, notes });
return res.data;
},
removeRepresentative: async (customerId: number, representativeId: number) => {
const res = await api.delete<ApiResponse<void>>(`/customers/${customerId}/representatives/${representativeId}`);
return res.data;
},
searchForRepresentative: async (customerId: number, search: string) => {
const res = await api.get<ApiResponse<CustomerSummary[]>>(`/customers/${customerId}/representatives/search`, { params: { search } });
return res.data;
},
};
// Addresses
export const addressApi = {
getByCustomer: async (customerId: number) => {
const res = await api.get<ApiResponse<Address[]>>(`/customers/${customerId}/addresses`);
return res.data;
},
create: async (customerId: number, data: Partial<Address>) => {
const res = await api.post<ApiResponse<Address>>(`/customers/${customerId}/addresses`, data);
return res.data;
},
update: async (id: number, data: Partial<Address>) => {
const res = await api.put<ApiResponse<Address>>(`/addresses/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/addresses/${id}`);
return res.data;
},
};
// Bank Cards
export const bankCardApi = {
getByCustomer: async (customerId: number, showInactive = false) => {
const res = await api.get<ApiResponse<BankCard[]>>(`/customers/${customerId}/bank-cards`, { params: { showInactive } });
return res.data;
},
create: async (customerId: number, data: Partial<BankCard>) => {
const res = await api.post<ApiResponse<BankCard>>(`/customers/${customerId}/bank-cards`, data);
return res.data;
},
update: async (id: number, data: Partial<BankCard>) => {
const res = await api.put<ApiResponse<BankCard>>(`/bank-cards/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/bank-cards/${id}`);
return res.data;
},
};
// Identity Documents
export const documentApi = {
getByCustomer: async (customerId: number, showInactive = false) => {
const res = await api.get<ApiResponse<IdentityDocument[]>>(`/customers/${customerId}/documents`, { params: { showInactive } });
return res.data;
},
create: async (customerId: number, data: Partial<IdentityDocument>) => {
const res = await api.post<ApiResponse<IdentityDocument>>(`/customers/${customerId}/documents`, data);
return res.data;
},
update: async (id: number, data: Partial<IdentityDocument>) => {
const res = await api.put<ApiResponse<IdentityDocument>>(`/documents/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/documents/${id}`);
return res.data;
},
};
// Meters
export const meterApi = {
getByCustomer: async (customerId: number, showInactive = false) => {
const res = await api.get<ApiResponse<Meter[]>>(`/customers/${customerId}/meters`, { params: { showInactive } });
return res.data;
},
create: async (customerId: number, data: Partial<Meter>) => {
const res = await api.post<ApiResponse<Meter>>(`/customers/${customerId}/meters`, data);
return res.data;
},
update: async (id: number, data: Partial<Meter>) => {
const res = await api.put<ApiResponse<Meter>>(`/meters/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/meters/${id}`);
return res.data;
},
getReadings: async (meterId: number) => {
const res = await api.get<ApiResponse<MeterReading[]>>(`/meters/${meterId}/readings`);
return res.data;
},
addReading: async (meterId: number, data: Partial<MeterReading>) => {
const res = await api.post<ApiResponse<MeterReading>>(`/meters/${meterId}/readings`, data);
return res.data;
},
updateReading: async (meterId: number, readingId: number, data: Partial<MeterReading>) => {
const res = await api.put<ApiResponse<MeterReading>>(`/meters/${meterId}/readings/${readingId}`, data);
return res.data;
},
deleteReading: async (meterId: number, readingId: number) => {
const res = await api.delete<ApiResponse<void>>(`/meters/${meterId}/readings/${readingId}`);
return res.data;
},
};
// Stressfrei-Wechseln E-Mail-Adressen
export interface StressfreiEmail {
id: number;
customerId: number;
email: string;
platform?: string;
notes?: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export const stressfreiEmailApi = {
getByCustomer: async (customerId: number, includeInactive = false) => {
const res = await api.get<ApiResponse<StressfreiEmail[]>>(`/customers/${customerId}/stressfrei-emails`, { params: { includeInactive } });
return res.data;
},
create: async (customerId: number, data: { email: string; platform?: string; notes?: string }) => {
const res = await api.post<ApiResponse<StressfreiEmail>>(`/customers/${customerId}/stressfrei-emails`, data);
return res.data;
},
update: async (id: number, data: Partial<StressfreiEmail>) => {
const res = await api.put<ApiResponse<StressfreiEmail>>(`/stressfrei-emails/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/stressfrei-emails/${id}`);
return res.data;
},
};
// Contracts
export const contractApi = {
getAll: async (params?: { customerId?: number; type?: string; status?: string; search?: string; page?: number; limit?: number }) => {
const res = await api.get<ApiResponse<Contract[]>>('/contracts', { params });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<Contract>>(`/contracts/${id}`);
return res.data;
},
create: async (data: Partial<Contract> & { [key: string]: unknown }) => {
const res = await api.post<ApiResponse<Contract>>('/contracts', data);
return res.data;
},
update: async (id: number, data: Partial<Contract> & { [key: string]: unknown }) => {
const res = await api.put<ApiResponse<Contract>>(`/contracts/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/contracts/${id}`);
return res.data;
},
createFollowUp: async (id: number) => {
const res = await api.post<ApiResponse<Contract>>(`/contracts/${id}/follow-up`);
return res.data;
},
getPassword: async (id: number) => {
const res = await api.get<ApiResponse<{ password: string }>>(`/contracts/${id}/password`);
return res.data;
},
getSimCardCredentials: async (simCardId: number) => {
const res = await api.get<ApiResponse<{ pin: string | null; puk: string | null }>>(`/contracts/simcard/${simCardId}/credentials`);
return res.data;
},
getInternetCredentials: async (contractId: number) => {
const res = await api.get<ApiResponse<{ password: string | null }>>(`/contracts/${contractId}/internet-credentials`);
return res.data;
},
getSipCredentials: async (phoneNumberId: number) => {
const res = await api.get<ApiResponse<{ password: string | null }>>(`/contracts/phonenumber/${phoneNumberId}/sip-credentials`);
return res.data;
},
// Vertrags-Cockpit
getCockpit: async () => {
const res = await api.get<ApiResponse<import('../types').CockpitResult>>('/contracts/cockpit');
return res.data;
},
};
// Contract Tasks (Aufgaben)
export const contractTaskApi = {
// Alle Tasks über alle Verträge (für Task-Liste & Dashboard)
getAll: async (params?: { status?: ContractTaskStatus; customerId?: number }) => {
const res = await api.get<ApiResponse<ContractTask[]>>('/tasks', { params });
return res.data;
},
// Task-Statistik (offene Aufgaben)
getStats: async () => {
const res = await api.get<ApiResponse<{ openCount: number }>>('/tasks/stats');
return res.data;
},
// Tasks für einen spezifischen Vertrag
getByContract: async (contractId: number, status?: ContractTaskStatus) => {
const res = await api.get<ApiResponse<ContractTask[]>>(`/contracts/${contractId}/tasks`, { params: { status } });
return res.data;
},
create: async (contractId: number, data: { title: string; description?: string; visibleInPortal?: boolean }) => {
const res = await api.post<ApiResponse<ContractTask>>(`/contracts/${contractId}/tasks`, data);
return res.data;
},
update: async (taskId: number, data: { title?: string; description?: string; visibleInPortal?: boolean }) => {
const res = await api.put<ApiResponse<ContractTask>>(`/tasks/${taskId}`, data);
return res.data;
},
complete: async (taskId: number) => {
const res = await api.post<ApiResponse<ContractTask>>(`/tasks/${taskId}/complete`);
return res.data;
},
reopen: async (taskId: number) => {
const res = await api.post<ApiResponse<ContractTask>>(`/tasks/${taskId}/reopen`);
return res.data;
},
delete: async (taskId: number) => {
const res = await api.delete<ApiResponse<void>>(`/tasks/${taskId}`);
return res.data;
},
// Subtasks
createSubtask: async (taskId: number, title: string) => {
const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/tasks/${taskId}/subtasks`, { title });
return res.data;
},
// Kundenportal: Antwort auf eigenes Ticket
createReply: async (taskId: number, title: string) => {
const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/tasks/${taskId}/reply`, { title });
return res.data;
},
updateSubtask: async (subtaskId: number, title: string) => {
const res = await api.put<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}`, { title });
return res.data;
},
completeSubtask: async (subtaskId: number) => {
const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}/complete`);
return res.data;
},
reopenSubtask: async (subtaskId: number) => {
const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}/reopen`);
return res.data;
},
deleteSubtask: async (subtaskId: number) => {
const res = await api.delete<ApiResponse<void>>(`/subtasks/${subtaskId}`);
return res.data;
},
// Support-Ticket erstellen (für Kundenportal)
createSupportTicket: async (contractId: number, data: { title: string; description?: string }) => {
const res = await api.post<ApiResponse<ContractTask>>(`/contracts/${contractId}/support-ticket`, data);
return res.data;
},
};
// App Settings
export const appSettingsApi = {
getPublic: async () => {
const res = await api.get<ApiResponse<Record<string, string>>>('/settings/public');
return res.data;
},
getAll: async () => {
const res = await api.get<ApiResponse<Record<string, string>>>('/settings');
return res.data;
},
update: async (settings: Record<string, string>) => {
const res = await api.put<ApiResponse<void>>('/settings', settings);
return res.data;
},
updateOne: async (key: string, value: string) => {
const res = await api.put<ApiResponse<void>>(`/settings/${key}`, { value });
return res.data;
},
};
// Platforms
export const platformApi = {
getAll: async (includeInactive = false) => {
const res = await api.get<ApiResponse<SalesPlatform[]>>('/platforms', { params: { includeInactive } });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<SalesPlatform>>(`/platforms/${id}`);
return res.data;
},
create: async (data: Partial<SalesPlatform>) => {
const res = await api.post<ApiResponse<SalesPlatform>>('/platforms', data);
return res.data;
},
update: async (id: number, data: Partial<SalesPlatform>) => {
const res = await api.put<ApiResponse<SalesPlatform>>(`/platforms/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/platforms/${id}`);
return res.data;
},
};
// Cancellation Periods
export const cancellationPeriodApi = {
getAll: async (includeInactive = false) => {
const res = await api.get<ApiResponse<CancellationPeriod[]>>('/cancellation-periods', { params: { includeInactive } });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<CancellationPeriod>>(`/cancellation-periods/${id}`);
return res.data;
},
create: async (data: Partial<CancellationPeriod>) => {
const res = await api.post<ApiResponse<CancellationPeriod>>('/cancellation-periods', data);
return res.data;
},
update: async (id: number, data: Partial<CancellationPeriod>) => {
const res = await api.put<ApiResponse<CancellationPeriod>>(`/cancellation-periods/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/cancellation-periods/${id}`);
return res.data;
},
};
// Contract Durations
export const contractDurationApi = {
getAll: async (includeInactive = false) => {
const res = await api.get<ApiResponse<ContractDuration[]>>('/contract-durations', { params: { includeInactive } });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<ContractDuration>>(`/contract-durations/${id}`);
return res.data;
},
create: async (data: Partial<ContractDuration>) => {
const res = await api.post<ApiResponse<ContractDuration>>('/contract-durations', data);
return res.data;
},
update: async (id: number, data: Partial<ContractDuration>) => {
const res = await api.put<ApiResponse<ContractDuration>>(`/contract-durations/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/contract-durations/${id}`);
return res.data;
},
};
// Contract Categories (Vertragstypen)
export const contractCategoryApi = {
getAll: async (includeInactive = false) => {
const res = await api.get<ApiResponse<ContractCategory[]>>('/contract-categories', { params: { includeInactive } });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<ContractCategory>>(`/contract-categories/${id}`);
return res.data;
},
create: async (data: Partial<ContractCategory>) => {
const res = await api.post<ApiResponse<ContractCategory>>('/contract-categories', data);
return res.data;
},
update: async (id: number, data: Partial<ContractCategory>) => {
const res = await api.put<ApiResponse<ContractCategory>>(`/contract-categories/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/contract-categories/${id}`);
return res.data;
},
};
// Providers (Anbieter)
export const providerApi = {
getAll: async (includeInactive = false) => {
const res = await api.get<ApiResponse<Provider[]>>('/providers', { params: { includeInactive } });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<Provider>>(`/providers/${id}`);
return res.data;
},
create: async (data: Partial<Provider>) => {
const res = await api.post<ApiResponse<Provider>>('/providers', data);
return res.data;
},
update: async (id: number, data: Partial<Provider>) => {
const res = await api.put<ApiResponse<Provider>>(`/providers/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/providers/${id}`);
return res.data;
},
getTariffs: async (providerId: number, includeInactive = false) => {
const res = await api.get<ApiResponse<Tariff[]>>(`/providers/${providerId}/tariffs`, { params: { includeInactive } });
return res.data;
},
createTariff: async (providerId: number, data: Partial<Tariff>) => {
const res = await api.post<ApiResponse<Tariff>>(`/providers/${providerId}/tariffs`, data);
return res.data;
},
};
// Tariffs (Tarife)
export const tariffApi = {
getById: async (id: number) => {
const res = await api.get<ApiResponse<Tariff>>(`/tariffs/${id}`);
return res.data;
},
update: async (id: number, data: Partial<Tariff>) => {
const res = await api.put<ApiResponse<Tariff>>(`/tariffs/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/tariffs/${id}`);
return res.data;
},
};
// Upload
export const uploadApi = {
uploadBankCardDocument: async (bankCardId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/bank-cards/${bankCardId}`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
uploadIdentityDocument: async (documentId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/documents/${documentId}`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteBankCardDocument: async (bankCardId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/bank-cards/${bankCardId}`);
return res.data;
},
deleteIdentityDocument: async (documentId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/documents/${documentId}`);
return res.data;
},
uploadBusinessRegistration: async (customerId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/business-registration`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteBusinessRegistration: async (customerId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/business-registration`);
return res.data;
},
uploadCommercialRegister: async (customerId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/commercial-register`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteCommercialRegister: async (customerId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/commercial-register`);
return res.data;
},
uploadPrivacyPolicy: async (customerId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/privacy-policy`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deletePrivacyPolicy: async (customerId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/privacy-policy`);
return res.data;
},
// Contract Documents
uploadCancellationLetter: async (contractId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-letter`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteCancellationLetter: async (contractId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-letter`);
return res.data;
},
uploadCancellationConfirmation: async (contractId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-confirmation`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteCancellationConfirmation: async (contractId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-confirmation`);
return res.data;
},
uploadCancellationLetterOptions: async (contractId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-letter-options`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteCancellationLetterOptions: async (contractId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-letter-options`);
return res.data;
},
uploadCancellationConfirmationOptions: async (contractId: number, file: File) => {
const formData = new FormData();
formData.append('document', file);
const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-confirmation-options`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return res.data;
},
deleteCancellationConfirmationOptions: async (contractId: number) => {
const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-confirmation-options`);
return res.data;
},
};
// Users
export const userApi = {
getAll: async (params?: { search?: string; isActive?: boolean; roleId?: number; page?: number; limit?: number }) => {
const res = await api.get<ApiResponse<User[]>>('/users', { params });
return res.data;
},
getById: async (id: number) => {
const res = await api.get<ApiResponse<User>>(`/users/${id}`);
return res.data;
},
create: async (data: { email: string; password: string; firstName: string; lastName: string; roleIds: number[]; customerId?: number }) => {
const res = await api.post<ApiResponse<User>>('/users', data);
return res.data;
},
update: async (id: number, data: Partial<User> & { password?: string; roleIds?: number[] }) => {
const res = await api.put<ApiResponse<User>>(`/users/${id}`, data);
return res.data;
},
delete: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/users/${id}`);
return res.data;
},
getRoles: async () => {
const res = await api.get<ApiResponse<Role[]>>('/users/roles/list');
return res.data;
},
};
// Developer
export const developerApi = {
getSchema: async () => {
const res = await api.get<ApiResponse<any[]>>('/developer/schema');
return res.data;
},
getTableData: async (tableName: string, page = 1, limit = 50) => {
const res = await api.get<ApiResponse<any[]>>(`/developer/table/${tableName}`, { params: { page, limit } });
return res.data;
},
updateRow: async (tableName: string, id: string, data: Record<string, any>) => {
const res = await api.put<ApiResponse<any>>(`/developer/table/${tableName}/${id}`, data);
return res.data;
},
deleteRow: async (tableName: string, id: string) => {
const res = await api.delete<ApiResponse<void>>(`/developer/table/${tableName}/${id}`);
return res.data;
},
getReference: async (tableName: string) => {
const res = await api.get<ApiResponse<any[]>>(`/developer/reference/${tableName}`);
return res.data;
},
};
// Email Provider (für Stressfrei-Wechseln Provisionierung)
export interface EmailProviderConfig {
id: number;
name: string;
type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN';
apiUrl: string;
apiKey?: string;
username?: string;
passwordEncrypted?: string;
domain: string;
defaultForwardEmail?: string;
isActive: boolean;
isDefault: boolean;
createdAt: string;
updatedAt: string;
}
export interface EmailOperationResult {
success: boolean;
message?: string;
error?: string;
}
export const emailProviderApi = {
// Config CRUD
getConfigs: async () => {
const res = await api.get<ApiResponse<EmailProviderConfig[]>>('/email-providers/configs');
return res.data;
},
getConfig: async (id: number) => {
const res = await api.get<ApiResponse<EmailProviderConfig>>(`/email-providers/configs/${id}`);
return res.data;
},
createConfig: async (data: Partial<EmailProviderConfig> & { password?: string }) => {
const res = await api.post<ApiResponse<EmailProviderConfig>>('/email-providers/configs', data);
return res.data;
},
updateConfig: async (id: number, data: Partial<EmailProviderConfig> & { password?: string }) => {
const res = await api.put<ApiResponse<EmailProviderConfig>>(`/email-providers/configs/${id}`, data);
return res.data;
},
deleteConfig: async (id: number) => {
const res = await api.delete<ApiResponse<void>>(`/email-providers/configs/${id}`);
return res.data;
},
// Email Operations
testConnection: async (options?: {
id?: number;
testData?: {
type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN';
apiUrl: string;
apiKey?: string;
username?: string;
password?: string;
domain: string;
};
}) => {
const body = options?.testData
? { ...options.testData }
: options?.id
? { id: options.id }
: {};
const res = await api.post<ApiResponse<EmailOperationResult>>('/email-providers/test-connection', body);
return res.data;
},
getDomain: async () => {
const res = await api.get<ApiResponse<{ domain: string | null }>>('/email-providers/domain');
return res.data;
},
checkEmailExists: async (localPart: string) => {
const res = await api.get<ApiResponse<{ exists: boolean; email?: string }>>(`/email-providers/check/${localPart}`);
return res.data;
},
provisionEmail: async (localPart: string, customerEmail: string) => {
const res = await api.post<ApiResponse<EmailOperationResult>>('/email-providers/provision', { localPart, customerEmail });
return res.data;
},
deprovisionEmail: async (localPart: string) => {
const res = await api.delete<ApiResponse<EmailOperationResult>>(`/email-providers/deprovision/${localPart}`);
return res.data;
},
};
export default api;