scaffold initial project structure and global design system

This commit is contained in:
2026-08-22 12:00:38 +05:30
parent f995332312
commit b23a8b7edd
23 changed files with 5962 additions and 0 deletions
+143
View File
@@ -0,0 +1,143 @@
import api, { setToken, setStoredUser, removeToken, removeStoredUser } from './api'
export const adminService = {
// ── Authentication ──
auth: {
login: async (email, password) => {
const res = await api.post('/api/admin/auth/login', { email, password })
if (res?.data?.token) {
setToken(res.data.token)
if (res.data.user) {
setStoredUser(res.data.user)
}
}
return res
},
verifyTotp: async (email, totp, sessionToken) => {
const res = await api.post('/api/admin/auth/verify-totp', { email, totp, sessionToken })
if (res?.data?.token) {
setToken(res.data.token)
if (res.data.user) {
setStoredUser(res.data.user)
}
}
return res
},
verify2fa: async (email, code) => {
const res = await api.post('/api/admin/auth/verify-2fa', { email, code })
if (res?.data?.token) {
setToken(res.data.token)
if (res.data.user) {
setStoredUser(res.data.user)
}
}
return res
},
setup2fa: () => api.post('/api/admin/auth/setup-2fa'),
confirm2fa: (totp) => api.post('/api/admin/auth/confirm-2fa', { totp }),
changePassword: (old_password, new_password) =>
api.post('/api/admin/auth/change-password', { old_password, new_password }),
logout: () => {
removeToken()
removeStoredUser()
},
},
// ── User Management (RBAC) ──
users: {
list: (params = {}) => api.get('/api/admin/users', params),
all: () => api.get('/api/admin/users/all'),
get: (id) => api.get(`/api/admin/users/${id}`),
create: (data) => api.post('/api/admin/users', data),
update: (id, data) => api.patch(`/api/admin/users/${id}`, data),
suspend: (id, reason) => api.post(`/api/admin/users/${id}/suspend`, { reason }),
reinstate: (id) => api.post(`/api/admin/users/${id}/reinstate`),
reset2fa: (id, verification_evidence) =>
api.post(`/api/admin/users/${id}/reset-2fa`, { verification_evidence }),
forceLogout: (id) => api.post(`/api/admin/users/${id}/force-logout`),
delete: (id) => api.delete(`/api/admin/users/${id}`),
getActivity: (id) => api.get(`/api/admin/users/${id}/activity`),
},
// ── Approvals (Two-person rule) ──
approvals: {
list: (params = {}) => api.get('/api/admin/approvals', params),
create: (data) => api.post('/api/admin/approvals', data),
approve: (id, note) => api.post(`/api/admin/approvals/${id}/approve`, { note }),
reject: (id, reason) => api.post(`/api/admin/approvals/${id}/reject`, { reason }),
},
// ── Financial Engine ──
finance: {
getSummary: () => api.get('/api/admin/finance/summary'),
getRevenue: (params = {}) => api.get('/api/admin/finance/revenue', params),
getPayouts: (params = {}) => api.get('/api/admin/finance/payouts', params),
getRefunds: (params = {}) => api.get('/api/admin/finance/refunds', params),
getReconciliation: () => api.get('/api/admin/finance/reconciliation'),
getCaregiverEarnings: (params = {}) => api.get('/api/admin/finance/caregiver-earnings', params),
getRefundAuthorisations: () => api.get('/api/admin/finance/refund-authorisations'),
approveRefund: (id) => api.post(`/api/admin/finance/refund-authorisations/${id}/approve`),
rejectRefund: (id, reason) => api.post(`/api/admin/finance/refund-authorisations/${id}/reject`, { reason }),
},
// ── Dynamic Configuration ──
config: {
get: () => api.get('/api/admin/config'),
update: (data) => api.patch('/api/admin/config', data),
getHistory: () => api.get('/api/admin/config/history'),
},
// ── Metrics & Growth ──
metrics: {
growth: () => api.get('/api/admin/metrics/growth'),
engagement: () => api.get('/api/admin/metrics/engagement'),
quality: () => api.get('/api/admin/metrics/quality'),
},
// ── Break-Glass Access Grants ──
accessGrants: {
list: () => api.get('/api/admin/access-grants'),
create: (data) => api.post('/api/admin/access-grants', data),
revoke: (id) => api.post(`/api/admin/access-grants/${id}/revoke`),
},
// ── Audit Logs ──
auditLog: {
list: (params = {}) => api.get('/api/admin/audit-log', params),
get: (id) => api.get(`/api/admin/audit-log/${id}`),
export: (format = 'json') => api.get('/api/admin/audit-log/export', { format }),
},
// ── Compliance & Data Governance ──
compliance: {
getDataRequests: () => api.get('/api/admin/compliance/data-requests'),
fulfilDataRequest: (id) => api.post(`/api/admin/compliance/data-requests/${id}/fulfil`),
rejectDataRequest: (id, reason) => api.post(`/api/admin/compliance/data-requests/${id}/reject`, { reason }),
getRetentionReport: () => api.get('/api/admin/compliance/retention-report'),
},
// ── System Operations ──
system: {
getHealth: () => api.get('/api/admin/system/health'),
getJobs: () => api.get('/api/admin/system/jobs'),
triggerJob: (name) => api.post(`/api/admin/system/jobs/${encodeURIComponent(name)}/trigger`),
setMaintenanceMode: (enabled, reason) =>
api.post('/api/admin/system/maintenance-mode', { enabled, reason }),
getIntegrations: () => api.get('/api/admin/system/integrations'),
testIntegration: (name) =>
api.post(`/api/admin/system/integrations/${encodeURIComponent(name)}/test`),
},
// ── Announcements & Broadcasts ──
announcements: {
list: () => api.get('/api/admin/announcements'),
create: (data) => api.post('/api/admin/announcements', data),
cancel: (id) => api.post(`/api/admin/announcements/${id}/cancel`),
},
}
export default adminService
+96
View File
@@ -0,0 +1,96 @@
// Base API client configured for CureSelect Super Admin Backend
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
const API_KEY = import.meta.env.VITE_API_KEY || 'DUMUqJrNeyuaPDSZSsMf91qjgwc5K3N7'
export const getToken = () => localStorage.getItem('admin_token')
export const setToken = (token) => localStorage.setItem('admin_token', token)
export const removeToken = () => localStorage.removeItem('admin_token')
export const getStoredUser = () => {
try {
const raw = localStorage.getItem('admin_user')
return raw ? JSON.parse(raw) : null
} catch {
return null
}
}
export const setStoredUser = (user) => localStorage.setItem('admin_user', JSON.stringify(user))
export const removeStoredUser = () => localStorage.removeItem('admin_user')
async function request(endpoint, options = {}) {
const url = endpoint.startsWith('http') ? endpoint : `${API_BASE_URL}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`
const headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'x-api-key': API_KEY,
...options.headers,
}
const token = getToken()
if (token && !headers['Authorization']) {
headers['Authorization'] = `Bearer ${token}`
}
const config = {
...options,
headers,
}
if (config.body && typeof config.body === 'object' && !(config.body instanceof FormData)) {
config.body = JSON.stringify(config.body)
}
try {
const response = await fetch(url, config)
const data = await response.json().catch(() => null)
if (!response.ok) {
if (response.status === 401 && !endpoint.includes('/auth/login')) {
// Token expired or unauthorized
removeToken()
removeStoredUser()
window.dispatchEvent(new Event('auth:unauthorized'))
}
const errorMessage = data?.message || data?.errors?.description || `HTTP error ${response.status}: ${response.statusText}`
const error = new Error(errorMessage)
error.status = response.status
error.data = data
throw error
}
return data
} catch (err) {
if (!err.status && err.message === 'Failed to fetch') {
const connErr = new Error(`Cannot connect to backend server at ${API_BASE_URL}. Ensure PHP server is running.`)
connErr.status = 0
throw connErr
}
throw err
}
}
export const api = {
get: (endpoint, params = {}, headers = {}) => {
const query = new URLSearchParams(
Object.entries(params).filter(([_, v]) => v !== undefined && v !== null && v !== '')
).toString()
const url = query ? `${endpoint}?${query}` : endpoint
return request(url, { method: 'GET', headers })
},
post: (endpoint, body = {}, headers = {}) => {
return request(endpoint, { method: 'POST', body, headers })
},
patch: (endpoint, body = {}, headers = {}) => {
return request(endpoint, { method: 'PATCH', body, headers })
},
put: (endpoint, body = {}, headers = {}) => {
return request(endpoint, { method: 'PUT', body, headers })
},
delete: (endpoint, body = {}, headers = {}) => {
return request(endpoint, { method: 'DELETE', body, headers })
},
}
export default api