Initial commit: IT Nexus Web-App
This commit is contained in:
89
frontend/src/services/aiService.js
Normal file
89
frontend/src/services/aiService.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import api from './api';
|
||||
|
||||
const aiService = {
|
||||
getStatus: async () => {
|
||||
const response = await api.get('/ai/status');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
chat: async (messages, userMode = false) => {
|
||||
const response = await api.post('/ai/chat', { messages, userMode });
|
||||
return response.data.data.reply;
|
||||
},
|
||||
|
||||
getKnowledgeBase: async () => {
|
||||
const response = await api.get('/ai/knowledge-base');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
addKnowledgeEntry: async (data) => {
|
||||
const response = await api.post('/ai/knowledge-base', data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
importTextToKb: async (text) => {
|
||||
const response = await api.post('/ai/knowledge-base/import-text', { text });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
importUrlToKb: async (url) => {
|
||||
const response = await api.post('/ai/knowledge-base/import-url', { url });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
importCrawlToKb: async (url, maxPages) => {
|
||||
const response = await api.post('/ai/knowledge-base/import-crawl', { url, maxPages }, { timeout: 300000 });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
importFileToKb: async (file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
try {
|
||||
const response = await api.post('/ai/knowledge-base/import-text', {
|
||||
file: reader.result,
|
||||
filename: file.name,
|
||||
});
|
||||
resolve(response.data.data);
|
||||
} catch (err) { reject(err); }
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
},
|
||||
|
||||
uploadKbImage: async (id, file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
try {
|
||||
const response = await api.post(`/ai/knowledge-base/${id}/images`, {
|
||||
image: reader.result,
|
||||
filename: file.name,
|
||||
});
|
||||
resolve(response.data.data);
|
||||
} catch (err) { reject(err); }
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
},
|
||||
|
||||
deleteKbImage: async (id, filename) => {
|
||||
const response = await api.delete(`/ai/knowledge-base/${id}/images/${encodeURIComponent(filename)}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
updateKnowledgeEntry: async (id, data) => {
|
||||
const response = await api.put(`/ai/knowledge-base/${id}`, data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
deleteKnowledgeEntry: async (id) => {
|
||||
const response = await api.delete(`/ai/knowledge-base/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default aiService;
|
||||
62
frontend/src/services/api.js
Normal file
62
frontend/src/services/api.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const API_URL = process.env.REACT_APP_API_URL || '/api';
|
||||
|
||||
// Create axios instance
|
||||
const api = axios.create({
|
||||
baseURL: API_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
// Request interceptor to add token to requests
|
||||
api.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
if (typeof config.headers?.set === 'function') {
|
||||
config.headers.set('Authorization', `Bearer ${token}`);
|
||||
} else if (config.headers) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`;
|
||||
} else {
|
||||
config.headers = { 'Authorization': `Bearer ${token}` };
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Response interceptor to handle errors globally
|
||||
api.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
// Handle 401 Unauthorized - token expired or invalid
|
||||
if (error.response.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
|
||||
// Return the error response for handling in components
|
||||
return Promise.reject(error.response.data);
|
||||
} else if (error.request) {
|
||||
// Network error
|
||||
return Promise.reject({
|
||||
status: 'error',
|
||||
message: 'Network error. Please check your connection.',
|
||||
});
|
||||
} else {
|
||||
// Re-throw original error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default api;
|
||||
173
frontend/src/services/assetService.js
Normal file
173
frontend/src/services/assetService.js
Normal file
@@ -0,0 +1,173 @@
|
||||
import api from './api';
|
||||
|
||||
const assetService = {
|
||||
/**
|
||||
* Get all assets
|
||||
*/
|
||||
getAll: async () => {
|
||||
const response = await api.get('/assets');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get asset by ID
|
||||
*/
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/assets/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get asset by serial number
|
||||
*/
|
||||
getBySerial: async (serialNumber) => {
|
||||
const response = await api.get(`/assets/serial/${serialNumber}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get assets by status
|
||||
*/
|
||||
getByStatus: async (status) => {
|
||||
const response = await api.get(`/assets/status/${status}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get assets by type
|
||||
*/
|
||||
getByType: async (type) => {
|
||||
const response = await api.get(`/assets/type/${type}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create new asset
|
||||
*/
|
||||
create: async (assetData) => {
|
||||
const response = await api.post('/assets', assetData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update asset
|
||||
*/
|
||||
update: async (id, assetData) => {
|
||||
const response = await api.put(`/assets/${id}`, assetData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete asset
|
||||
*/
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/assets/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Assign asset to user
|
||||
*/
|
||||
assign: async (id, userId, notes) => {
|
||||
const response = await api.post(`/assets/${id}/assign`, {
|
||||
user_id: userId,
|
||||
notes: notes
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Unassign asset from user
|
||||
*/
|
||||
unassign: async (id, newStatus) => {
|
||||
const response = await api.post(`/assets/${id}/unassign`, {
|
||||
new_status: newStatus
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get assignment history for an asset
|
||||
*/
|
||||
getAssignmentHistory: async (id) => {
|
||||
const response = await api.get(`/assets/${id}/history`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get statistics
|
||||
*/
|
||||
getStatistics: async () => {
|
||||
const response = await api.get('/assets/stats');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Open printable label PDF in new tab
|
||||
*/
|
||||
printLabel: async (id, copies = 1, size = 'medium') => {
|
||||
const response = await api.get(`/assets/${id}/label`, {
|
||||
params: { copies, size },
|
||||
responseType: 'blob',
|
||||
});
|
||||
const blob = new Blob([response.data], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.open(url, '_blank');
|
||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
||||
},
|
||||
|
||||
/**
|
||||
* Import managed devices from Microsoft Intune
|
||||
* Returns { imported, skipped, errors }
|
||||
*/
|
||||
importFromIntune: async () => {
|
||||
const response = await api.post('/assets/import/intune');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all inspections for an asset
|
||||
*/
|
||||
getInspections: (assetId) => api.get(`/assets/${assetId}/inspections`).then(r => r.data.data),
|
||||
|
||||
/**
|
||||
* Create an inspection for an asset
|
||||
*/
|
||||
createInspection: (assetId, data) => api.post(`/assets/${assetId}/inspections`, data).then(r => r.data.data),
|
||||
|
||||
/**
|
||||
* Open handover protocol PDF in new tab
|
||||
*/
|
||||
printHandoverProtocol: async (id) => {
|
||||
const response = await api.get(`/assets/${id}/handover-protocol`, {
|
||||
responseType: 'blob',
|
||||
});
|
||||
const blob = new Blob([response.data], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.open(url, '_blank');
|
||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
||||
},
|
||||
|
||||
// Asset Types
|
||||
getTypes: async () => {
|
||||
const response = await api.get('/asset-types');
|
||||
return response.data;
|
||||
},
|
||||
createType: async (data) => {
|
||||
const response = await api.post('/asset-types', data);
|
||||
return response.data;
|
||||
},
|
||||
updateType: async (id, data) => {
|
||||
const response = await api.put(`/asset-types/${id}`, data);
|
||||
return response.data;
|
||||
},
|
||||
deleteType: async (id) => {
|
||||
await api.delete(`/asset-types/${id}`);
|
||||
},
|
||||
syncFromAgent: async (id) => {
|
||||
const response = await api.post(`/assets/${id}/sync-agent`);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default assetService;
|
||||
88
frontend/src/services/authService.js
Normal file
88
frontend/src/services/authService.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import api from './api';
|
||||
|
||||
const authService = {
|
||||
/**
|
||||
* Login user
|
||||
*/
|
||||
login: async (username, password) => {
|
||||
const response = await api.post('/auth/login', { username, password });
|
||||
if (response.data.data.token) {
|
||||
localStorage.setItem('token', response.data.data.token);
|
||||
localStorage.setItem('user', JSON.stringify(response.data.data.user));
|
||||
}
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Logout user
|
||||
*/
|
||||
logout: async () => {
|
||||
try {
|
||||
await api.post('/auth/logout');
|
||||
} catch (error) {
|
||||
// Ignore errors on logout
|
||||
} finally {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get current user info
|
||||
*/
|
||||
getCurrentUser: async () => {
|
||||
const response = await api.get('/auth/me');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Change password
|
||||
*/
|
||||
changePassword: async (currentPassword, newPassword) => {
|
||||
const response = await api.post('/auth/change-password', {
|
||||
currentPassword,
|
||||
newPassword,
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get user from localStorage
|
||||
*/
|
||||
getStoredUser: () => {
|
||||
const user = localStorage.getItem('user');
|
||||
return user ? JSON.parse(user) : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get token from localStorage
|
||||
*/
|
||||
getToken: () => {
|
||||
return localStorage.getItem('token');
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if user is authenticated
|
||||
*/
|
||||
isAuthenticated: () => {
|
||||
return !!localStorage.getItem('token');
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch user data using a token (for kiosk URL-token login)
|
||||
*/
|
||||
fetchUserFromToken: async (token) => {
|
||||
try {
|
||||
const response = await fetch('/api/auth/me', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
if (!response.ok) return null;
|
||||
const data = await response.json();
|
||||
return data.data || data.user || data;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default authService;
|
||||
15
frontend/src/services/entraService.js
Normal file
15
frontend/src/services/entraService.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import api from './api';
|
||||
|
||||
const BASE = '/entra';
|
||||
|
||||
const entraService = {
|
||||
getUsers: async () => { const r = await api.get(`${BASE}/users`); return r.data.data; },
|
||||
getUserGroups: async (userId) => { const r = await api.get(`${BASE}/users/${userId}/groups`); return r.data.data; },
|
||||
getGroups: async () => { const r = await api.get(`${BASE}/groups`); return r.data.data; },
|
||||
getGroupMembers: async (groupId) => { const r = await api.get(`${BASE}/groups/${groupId}/members`); return r.data.data; },
|
||||
addGroupMember: async (groupId, userId) => { const r = await api.post(`${BASE}/groups/${groupId}/members`, { userId }); return r.data; },
|
||||
removeGroupMember: async (groupId, userId) => { const r = await api.delete(`${BASE}/groups/${groupId}/members/${userId}`); return r.data; },
|
||||
getRoles: async () => { const r = await api.get(`${BASE}/roles`); return r.data.data; },
|
||||
};
|
||||
|
||||
export default entraService;
|
||||
12
frontend/src/services/externalAlertService.js
Normal file
12
frontend/src/services/externalAlertService.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import api from './api';
|
||||
|
||||
const base = '/external-alerts';
|
||||
|
||||
const externalAlertService = {
|
||||
getAll: (params) => api.get(base, { params }).then(r => r.data.data),
|
||||
acknowledge: (id) => api.post(`${base}/${id}/acknowledge`).then(r => r.data.data),
|
||||
createTicket: (id) => api.post(`${base}/${id}/create-ticket`).then(r => r.data.data),
|
||||
remove: (id) => api.delete(`${base}/${id}`).then(r => r.data),
|
||||
};
|
||||
|
||||
export default externalAlertService;
|
||||
77
frontend/src/services/fidoKeyService.js
Normal file
77
frontend/src/services/fidoKeyService.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import api from './api';
|
||||
|
||||
const fidoKeyService = {
|
||||
/**
|
||||
* Get all FIDO keys
|
||||
*/
|
||||
getAll: async () => {
|
||||
const response = await api.get('/fido-keys');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get FIDO key by ID
|
||||
*/
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/fido-keys/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get FIDO key by serial number
|
||||
*/
|
||||
getBySerial: async (serialNumber) => {
|
||||
const response = await api.get(`/fido-keys/serial/${serialNumber}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get FIDO keys by status
|
||||
*/
|
||||
getByStatus: async (status) => {
|
||||
const response = await api.get(`/fido-keys/status/${status}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create new FIDO key
|
||||
*/
|
||||
create: async (keyData) => {
|
||||
const response = await api.post('/fido-keys', keyData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update FIDO key
|
||||
*/
|
||||
update: async (id, keyData) => {
|
||||
const response = await api.put(`/fido-keys/${id}`, keyData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update FIDO key status
|
||||
*/
|
||||
updateStatus: async (id, status) => {
|
||||
const response = await api.put(`/fido-keys/${id}/status`, { status });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete FIDO key
|
||||
*/
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/fido-keys/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get statistics
|
||||
*/
|
||||
getStatistics: async () => {
|
||||
const response = await api.get('/fido-keys/stats');
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default fidoKeyService;
|
||||
23
frontend/src/services/isoService.js
Normal file
23
frontend/src/services/isoService.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import api from './api';
|
||||
|
||||
const BASE = '/iso-tasks';
|
||||
|
||||
const isoService = {
|
||||
getAll: async (params = {}) => {
|
||||
const res = await api.get(BASE, { params });
|
||||
return res.data.data;
|
||||
},
|
||||
create: async (data) => {
|
||||
const res = await api.post(BASE, data);
|
||||
return res.data.data;
|
||||
},
|
||||
update: async (id, data) => {
|
||||
const res = await api.put(`${BASE}/${id}`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
delete: async (id) => {
|
||||
await api.delete(`${BASE}/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
export default isoService;
|
||||
31
frontend/src/services/itTopicService.js
Normal file
31
frontend/src/services/itTopicService.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import api from './api';
|
||||
|
||||
const BASE = '/it-topics';
|
||||
|
||||
const itTopicService = {
|
||||
getAll: async (params = {}) => {
|
||||
const res = await api.get(BASE, { params });
|
||||
return res.data.data;
|
||||
},
|
||||
getOne: async (id) => {
|
||||
const res = await api.get(`${BASE}/${id}`);
|
||||
return res.data.data;
|
||||
},
|
||||
create: async (data) => {
|
||||
const res = await api.post(BASE, data);
|
||||
return res.data.data;
|
||||
},
|
||||
update: async (id, data) => {
|
||||
const res = await api.put(`${BASE}/${id}`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
delete: async (id) => {
|
||||
await api.delete(`${BASE}/${id}`);
|
||||
},
|
||||
syncToPlanner: async () => {
|
||||
const res = await api.post(`${BASE}/planner/sync`);
|
||||
return res.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default itTopicService;
|
||||
45
frontend/src/services/licenseService.js
Normal file
45
frontend/src/services/licenseService.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import api from './api';
|
||||
|
||||
const licenseService = {
|
||||
getAll: async () => {
|
||||
const response = await api.get('/licenses');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/licenses/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
create: async (data) => {
|
||||
const response = await api.post('/licenses', data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
update: async (id, data) => {
|
||||
const response = await api.put(`/licenses/${id}`, data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/licenses/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
getStatistics: async () => {
|
||||
const response = await api.get('/licenses/statistics');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
importFromEntra: async () => {
|
||||
const response = await api.post('/licenses/import/entra');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getLicenseUsers: async (id) => {
|
||||
const response = await api.get(`/licenses/${id}/users`);
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default licenseService;
|
||||
10
frontend/src/services/monitoringService.js
Normal file
10
frontend/src/services/monitoringService.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import api from './api';
|
||||
|
||||
const monitoringService = {
|
||||
getAll: () => api.get('/monitoring').then(r => r.data.data),
|
||||
getStatistics: () => api.get('/monitoring/statistics').then(r => r.data.data),
|
||||
getById: (id) => api.get(`/monitoring/${id}`).then(r => r.data.data),
|
||||
delete: (id) => api.delete(`/monitoring/${id}`).then(r => r.data),
|
||||
};
|
||||
|
||||
export default monitoringService;
|
||||
24
frontend/src/services/networkMonitorService.js
Normal file
24
frontend/src/services/networkMonitorService.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import api from './api';
|
||||
|
||||
const base = '/network-monitor';
|
||||
|
||||
const networkMonitorService = {
|
||||
getAll: () => api.get(base).then(r => r.data.data),
|
||||
getStats: () => api.get(`${base}/statistics`).then(r => r.data.data),
|
||||
getChecks: (id, h) => api.get(`${base}/${id}/checks?hours=${h}`).then(r => r.data.data),
|
||||
create: (data) => api.post(base, data).then(r => r.data.data),
|
||||
update: (id, d) => api.put(`${base}/${id}`, d).then(r => r.data.data),
|
||||
delete: (id) => api.delete(`${base}/${id}`),
|
||||
checkNow: (id) => api.post(`${base}/${id}/check-now`).then(r => r.data.data),
|
||||
|
||||
discover: (subnet) => api.post(`${base}/discover`, { subnet }, { timeout: 120000 }).then(r => r.data),
|
||||
getUptimeStats: () => api.get(`${base}/uptime-stats`).then(r => r.data.data),
|
||||
|
||||
createSSE: () => {
|
||||
const token = localStorage.getItem('token');
|
||||
const apiBase = process.env.REACT_APP_API_URL || '/api';
|
||||
return new EventSource(`${apiBase}/network-monitor/sse?token=${token}`);
|
||||
},
|
||||
};
|
||||
|
||||
export default networkMonitorService;
|
||||
78
frontend/src/services/offboardingService.js
Normal file
78
frontend/src/services/offboardingService.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import api from './api';
|
||||
|
||||
const offboardingService = {
|
||||
/**
|
||||
* Get all offboarding protocols
|
||||
*/
|
||||
getAll: async () => {
|
||||
const response = await api.get('/offboarding');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get offboarding protocol by ID
|
||||
*/
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/offboarding/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create new offboarding protocol
|
||||
*/
|
||||
create: async (protocolData) => {
|
||||
const response = await api.post('/offboarding', protocolData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update offboarding protocol
|
||||
*/
|
||||
update: async (id, protocolData) => {
|
||||
const response = await api.put(`/offboarding/${id}`, protocolData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return assets for offboarding
|
||||
*/
|
||||
returnAssets: async (id, assetReturns) => {
|
||||
const response = await api.post(`/offboarding/${id}/return-assets`, {
|
||||
asset_returns: assetReturns
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Regenerate PDF for offboarding protocol
|
||||
*/
|
||||
regeneratePdf: async (id) => {
|
||||
const response = await api.post(`/offboarding/${id}/regenerate-pdf`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete offboarding protocol
|
||||
*/
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/offboarding/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get statistics
|
||||
*/
|
||||
getStatistics: async () => {
|
||||
const response = await api.get('/offboarding/stats');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Download PDF
|
||||
*/
|
||||
downloadPdf: (pdfPath) => {
|
||||
return `/${pdfPath}`;
|
||||
},
|
||||
};
|
||||
|
||||
export default offboardingService;
|
||||
54
frontend/src/services/onboardingProcessService.js
Normal file
54
frontend/src/services/onboardingProcessService.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import api from './api';
|
||||
|
||||
const BASE = '/onboarding-processes';
|
||||
|
||||
const onboardingProcessService = {
|
||||
// Departments
|
||||
getDepartments: async () => {
|
||||
const res = await api.get(`${BASE}/departments`);
|
||||
return res.data.data;
|
||||
},
|
||||
createDepartment: async (data) => {
|
||||
const res = await api.post(`${BASE}/departments`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
updateDepartment: async (id, data) => {
|
||||
const res = await api.put(`${BASE}/departments/${id}`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
deleteDepartment: async (id) => {
|
||||
await api.delete(`${BASE}/departments/${id}`);
|
||||
},
|
||||
reorderDepartments: async (ids) => {
|
||||
await api.put(`${BASE}/departments/reorder`, { ids });
|
||||
},
|
||||
|
||||
// Processes
|
||||
getProcesses: async (params = {}) => {
|
||||
const res = await api.get(`${BASE}/processes`, { params });
|
||||
return res.data.data;
|
||||
},
|
||||
getChecklistProcesses: async (appliesTo, departmentId) => {
|
||||
// appliesTo: 'onboarding' or 'offboarding'; departmentId: optional filter
|
||||
const params = { applies_to: appliesTo };
|
||||
if (departmentId) params.department_id = departmentId;
|
||||
const res = await api.get(`${BASE}/processes`, { params });
|
||||
return res.data.data;
|
||||
},
|
||||
createProcess: async (data) => {
|
||||
const res = await api.post(`${BASE}/processes`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
updateProcess: async (id, data) => {
|
||||
const res = await api.put(`${BASE}/processes/${id}`, data);
|
||||
return res.data.data;
|
||||
},
|
||||
deleteProcess: async (id) => {
|
||||
await api.delete(`${BASE}/processes/${id}`);
|
||||
},
|
||||
reorderProcesses: async (department_id, ids) => {
|
||||
await api.put(`${BASE}/processes/reorder`, { department_id, ids });
|
||||
},
|
||||
};
|
||||
|
||||
export default onboardingProcessService;
|
||||
76
frontend/src/services/onboardingService.js
Normal file
76
frontend/src/services/onboardingService.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import api from './api';
|
||||
|
||||
const onboardingService = {
|
||||
/**
|
||||
* Get all onboarding protocols
|
||||
*/
|
||||
getAll: async () => {
|
||||
const response = await api.get('/onboarding');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get onboarding protocol by ID
|
||||
*/
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/onboarding/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create new onboarding protocol
|
||||
*/
|
||||
create: async (protocolData) => {
|
||||
const response = await api.post('/onboarding', protocolData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update onboarding protocol
|
||||
*/
|
||||
update: async (id, protocolData) => {
|
||||
const response = await api.put(`/onboarding/${id}`, protocolData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Regenerate PDF for onboarding protocol
|
||||
*/
|
||||
regeneratePdf: async (id) => {
|
||||
const response = await api.post(`/onboarding/${id}/regenerate-pdf`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Send confirmation email with PDF to employee
|
||||
*/
|
||||
sendConfirmationEmail: async (id) => {
|
||||
const response = await api.post(`/onboarding/${id}/send-confirmation`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete onboarding protocol
|
||||
*/
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/onboarding/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get statistics
|
||||
*/
|
||||
getStatistics: async () => {
|
||||
const response = await api.get('/onboarding/stats');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Download PDF
|
||||
*/
|
||||
downloadPdf: (pdfPath) => {
|
||||
return `/${pdfPath}`;
|
||||
},
|
||||
};
|
||||
|
||||
export default onboardingService;
|
||||
26
frontend/src/services/portalGuideService.js
Normal file
26
frontend/src/services/portalGuideService.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import api from './api';
|
||||
|
||||
const portalGuideService = {
|
||||
getAll: async () => {
|
||||
const res = await api.get('/portal-guides');
|
||||
return res.data;
|
||||
},
|
||||
getById: async (id) => {
|
||||
const res = await api.get(`/portal-guides/${id}`);
|
||||
return res.data;
|
||||
},
|
||||
getHtmlUrl: (id) => `/api/portal-guides/${id}/html`,
|
||||
create: async (data) => {
|
||||
const res = await api.post('/portal-guides', data);
|
||||
return res.data;
|
||||
},
|
||||
update: async (id, data) => {
|
||||
const res = await api.put(`/portal-guides/${id}`, data);
|
||||
return res.data;
|
||||
},
|
||||
delete: async (id) => {
|
||||
await api.delete(`/portal-guides/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
export default portalGuideService;
|
||||
14
frontend/src/services/riskService.js
Normal file
14
frontend/src/services/riskService.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import api from './api';
|
||||
|
||||
const BASE = '/risks';
|
||||
|
||||
const riskService = {
|
||||
getAll: async (params = {}) => { const r = await api.get(BASE, { params }); return r.data.data; },
|
||||
getStats: async () => { const r = await api.get(`${BASE}/stats`); return r.data.data; },
|
||||
sync: async () => { const r = await api.post(`${BASE}/sync`); return r.data.data; },
|
||||
create: async (data) => { const r = await api.post(BASE, data); return r.data.data; },
|
||||
update: async (id, data) => { const r = await api.put(`${BASE}/${id}`, data); return r.data.data; },
|
||||
delete: async (id) => { await api.delete(`${BASE}/${id}`); },
|
||||
};
|
||||
|
||||
export default riskService;
|
||||
10
frontend/src/services/scannerService.js
Normal file
10
frontend/src/services/scannerService.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import api from './api';
|
||||
|
||||
const scannerService = {
|
||||
getSites: () => api.get('/scanner/sites').then(r => r.data.data),
|
||||
getAssets: (params) => api.get('/scanner/assets', { params }).then(r => r.data.data),
|
||||
getAlerts: (params) => api.get('/scanner/alerts', { params }).then(r => r.data.data),
|
||||
getStats: () => api.get('/scanner/stats').then(r => r.data.data),
|
||||
};
|
||||
|
||||
export default scannerService;
|
||||
60
frontend/src/services/shareService.js
Normal file
60
frontend/src/services/shareService.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const API = process.env.REACT_APP_API_URL || '/api';
|
||||
|
||||
const getHeaders = () => ({
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
});
|
||||
|
||||
export const createShare = async (formData) => {
|
||||
const res = await fetch(`${API}/shares`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
|
||||
body: formData, // FormData — kein Content-Type Header setzen!
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.json();
|
||||
throw new Error(err.error || 'Fehler beim Erstellen');
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const getAllShares = async () => {
|
||||
const res = await fetch(`${API}/shares`, { headers: getHeaders() });
|
||||
if (!res.ok) throw new Error('Fehler beim Laden');
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const deleteShare = async (id) => {
|
||||
const res = await fetch(`${API}/shares/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: getHeaders(),
|
||||
});
|
||||
if (!res.ok) throw new Error('Fehler beim Löschen');
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const getPublicShare = async (token) => {
|
||||
const res = await fetch(`${API}/shares/public/${token}`);
|
||||
if (!res.ok) {
|
||||
const err = await res.json();
|
||||
throw new Error(err.error || 'Nicht gefunden');
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const accessShare = async (token, password) => {
|
||||
const res = await fetch(`${API}/shares/public/${token}/access`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.json();
|
||||
throw new Error(err.error || 'Zugriff verweigert');
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const getFileDownloadUrl = (token, password) => {
|
||||
const base = `${API}/shares/public/${token}/file`;
|
||||
return password ? `${base}?password=${encodeURIComponent(password)}` : base;
|
||||
};
|
||||
8
frontend/src/services/teamsActivityService.js
Normal file
8
frontend/src/services/teamsActivityService.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import api from './api';
|
||||
|
||||
const teamsActivityService = {
|
||||
getNewChannels: () => api.get('/teams-activity/new-channels').then(r => r.data.data),
|
||||
markRead: () => api.post('/teams-activity/mark-read'),
|
||||
};
|
||||
|
||||
export default teamsActivityService;
|
||||
106
frontend/src/services/ticketService.js
Normal file
106
frontend/src/services/ticketService.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import api from './api';
|
||||
|
||||
const ticketService = {
|
||||
getAll: async (filters = {}) => {
|
||||
const params = {};
|
||||
if (filters.status) params.status = filters.status;
|
||||
if (filters.priority) params.priority = filters.priority;
|
||||
if (filters.category) params.category = filters.category;
|
||||
if (filters.assigned_to) params.assigned_to = filters.assigned_to;
|
||||
if (filters.search) params.search = filters.search;
|
||||
const response = await api.get('/tickets', { params });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/tickets/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getStats: async () => {
|
||||
const response = await api.get('/tickets/stats');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getMetrics: async (days = 30) => {
|
||||
const response = await api.get('/tickets/metrics', { params: { days } });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
create: async (data) => {
|
||||
const response = await api.post('/tickets', data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
update: async (id, data) => {
|
||||
const response = await api.put(`/tickets/${id}`, data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
bulkUpdate: async (ids, data) => {
|
||||
const response = await api.put('/tickets/bulk', { ids, data });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/tickets/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
addComment: async (id, comment, isInternal = false) => {
|
||||
const response = await api.post(`/tickets/${id}/comments`, {
|
||||
comment,
|
||||
is_internal: isInternal,
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
aiReply: async (id, message, history = []) => {
|
||||
const response = await api.post(`/tickets/${id}/ai-reply`, { message, history });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
deleteComment: async (ticketId, commentId) => {
|
||||
const response = await api.delete(`/tickets/${ticketId}/comments/${commentId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
getHistory: async (id) => {
|
||||
const response = await api.get(`/tickets/${id}/history`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
getPdfUrl: (id) => `/api/tickets/${id}/pdf`,
|
||||
|
||||
getLinks: async (id) => {
|
||||
const response = await api.get(`/tickets/${id}/links`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
addLink: async (id, linked_ticket_number, link_type = 'related') => {
|
||||
const response = await api.post(`/tickets/${id}/links`, { linked_ticket_number, link_type });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
removeLink: async (ticketId, linkId) => {
|
||||
const response = await api.delete(`/tickets/${ticketId}/links/${linkId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
snooze: async (id, snoozed_until) => {
|
||||
const response = await api.put(`/tickets/${id}/snooze`, { snoozed_until });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
addAssignee: async (ticketId, userId) => {
|
||||
const response = await api.post(`/tickets/${ticketId}/assignees`, { user_id: userId });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
removeAssignee: async (ticketId, userId) => {
|
||||
const response = await api.delete(`/tickets/${ticketId}/assignees/${userId}`);
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default ticketService;
|
||||
9
frontend/src/services/unifiService.js
Normal file
9
frontend/src/services/unifiService.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import api from './api';
|
||||
const base = '/unifi';
|
||||
const unifiService = {
|
||||
getConfig: () => api.get(`${base}/config`).then(r => r.data.data),
|
||||
saveConfig: (cfg) => api.post(`${base}/config`, cfg).then(r => r.data.data),
|
||||
getDevices: () => api.get(`${base}/devices`).then(r => r.data.data),
|
||||
sync: () => api.post(`${base}/sync`).then(r => r.data.data),
|
||||
};
|
||||
export default unifiService;
|
||||
94
frontend/src/services/userService.js
Normal file
94
frontend/src/services/userService.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import api from './api';
|
||||
|
||||
const userService = {
|
||||
/**
|
||||
* Get all users
|
||||
*/
|
||||
getAll: async () => {
|
||||
const response = await api.get('/users');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get user by ID
|
||||
*/
|
||||
getById: async (id) => {
|
||||
const response = await api.get(`/users/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create new user
|
||||
*/
|
||||
create: async (userData) => {
|
||||
const response = await api.post('/users', userData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update user
|
||||
*/
|
||||
update: async (id, userData) => {
|
||||
const response = await api.put(`/users/${id}`, userData);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete user
|
||||
*/
|
||||
delete: async (id) => {
|
||||
const response = await api.delete(`/users/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Assign role to user
|
||||
*/
|
||||
assignRole: async (id, roleId) => {
|
||||
const response = await api.put(`/users/${id}/role`, { role_id: roleId });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Activate/Deactivate user
|
||||
*/
|
||||
toggleStatus: async (id, isActive) => {
|
||||
const response = await api.put(`/users/${id}/activate`, { is_active: isActive });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all roles
|
||||
*/
|
||||
getRoles: async () => {
|
||||
const response = await api.get('/users/roles');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get available Azure AD groups for import
|
||||
*/
|
||||
getAzureGroups: async () => {
|
||||
const response = await api.get('/users/import/azure/groups');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Import users from an Azure AD group
|
||||
* Returns { imported, skipped, errors }
|
||||
*/
|
||||
importFromAzure: async (groupId, roleId) => {
|
||||
const response = await api.post('/users/import/azure', { group_id: groupId, role_id: roleId });
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get audit logs
|
||||
*/
|
||||
getAuditLogs: async (limit = 100, offset = 0) => {
|
||||
const response = await api.get(`/users/audit-logs?limit=${limit}&offset=${offset}`);
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default userService;
|
||||
35
frontend/src/services/warehouseService.js
Normal file
35
frontend/src/services/warehouseService.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import api from './api';
|
||||
|
||||
const base = '/warehouse';
|
||||
|
||||
const warehouseService = {
|
||||
// Summary
|
||||
getSummary: () => api.get(`${base}/summary`).then(r => r.data),
|
||||
getViolations: () => api.get(`${base}/violations`).then(r => r.data),
|
||||
|
||||
// Locations
|
||||
getLocations: () => api.get(`${base}/locations`).then(r => r.data),
|
||||
createLocation: (data) => api.post(`${base}/locations`, data).then(r => r.data),
|
||||
updateLocation: (id, d) => api.put(`${base}/locations/${id}`, d).then(r => r.data),
|
||||
deleteLocation: (id) => api.delete(`${base}/locations/${id}`).then(r => r.data),
|
||||
|
||||
// Movements
|
||||
getMovements: (params) => api.get(`${base}/movements`, { params }).then(r => r.data),
|
||||
createMovement: (data) => api.post(`${base}/movements`, data).then(r => r.data),
|
||||
|
||||
// Stock thresholds
|
||||
getThresholds: () => api.get(`${base}/thresholds`).then(r => r.data),
|
||||
upsertThreshold: (data) => api.post(`${base}/thresholds`, data).then(r => r.data),
|
||||
deleteThreshold: (cat) => api.delete(`${base}/thresholds/${encodeURIComponent(cat)}`).then(r => r.data),
|
||||
|
||||
// Purchase orders
|
||||
getOrders: (params) => api.get(`${base}/orders`, { params }).then(r => r.data),
|
||||
createOrder: (data) => api.post(`${base}/orders`, data).then(r => r.data),
|
||||
updateOrder: (id, d) => api.put(`${base}/orders/${id}`, d).then(r => r.data),
|
||||
deleteOrder: (id) => api.delete(`${base}/orders/${id}`).then(r => r.data),
|
||||
|
||||
// QR Code URL
|
||||
getQrUrl: (assetId) => `${api.defaults.baseURL}${base}/qr/${assetId}`,
|
||||
};
|
||||
|
||||
export default warehouseService;
|
||||
Reference in New Issue
Block a user