import axios from 'axios' const api = axios.create({ baseURL: '' }) api.interceptors.request.use(config => { const token = localStorage.getItem('esn_token') if (token) config.headers.Authorization = `Bearer ${token}` return config }) api.interceptors.response.use( res => res, err => { if (err.response?.status === 401) { localStorage.removeItem('esn_token') if (location.pathname !== '/login') location.href = '/login' } return Promise.reject(err) } ) export default api const unwrap = (p: Promise) => p.then(r => r.data?.data) // ── Auth ────────────────────────────────────────────────────────────────── export const login = (username: string, password: string) => api.post('/api/auth/login', { username, password }) export const getMe = () => api.get('/api/auth/me') export const logout = () => api.post('/api/auth/logout') // ── 2FA / OTP / 계정 보안 (마이페이지, access 토큰 필요) ───────────────────── // 보안 불변: setup 응답(secret/qrImage)은 화면 표시용만 — 로그/저장 금지. raw 응답 반환(호출부 res.data.data). export const otpSetup = () => api.post('/api/auth/otp/setup') export const otpConfirm = (code: string) => api.post('/api/auth/otp/confirm', { code }) export const otpDisable = () => api.post('/api/auth/otp/disable') export const changePassword = (currentPassword: string, newPassword: string) => api.post('/api/auth/change-password', { currentPassword, newPassword }) // 관리자 OTP 초기화 — 대상 사용자 OTP 해제(다음 로그인 시 재등록). 시크릿 미조회. export const adminOtpReset = (id: number) => unwrap(api.post(`/api/users/${id}/otp-reset`)) // ── Auth: 로그인 보조 3종 (공개 — 회원가입 승인대기 / 아이디찾기 / 비밀번호 초기화) ── export interface SignupReq { username: string; password: string; name: string; email: string; phone: string; tenantCode: string } export interface SignupRes { username: string; status: string } export interface FindIdRes { found: boolean; maskedUsername: string } export const signup = (d: SignupReq) => unwrap(api.post('/api/auth/signup', d)) as Promise export const findId = (name: string, email: string) => unwrap(api.post('/api/auth/find-id', { name, email })) as Promise export const resetPassword = (username: string, name: string, email: string) => api.post('/api/auth/reset-password', { username, name, email }) // ── Dashboard ──────────────────────────────────────────────────────────── export const getDashboard = (tenantCode?: string) => unwrap(api.get(`/api/dashboard${tenantCode ? `?tenantCode=${tenantCode}` : ''}`)) // ── Tenants ────────────────────────────────────────────────────────────── export const getTenants = () => unwrap(api.get('/api/tenants')) export const createTenant = (d: object) => unwrap(api.post('/api/tenants', d)) export const updateTenant = (id: number, d: object) => unwrap(api.put(`/api/tenants/${id}`, d)) export const deleteTenant = (id: number) => api.delete(`/api/tenants/${id}`) // ── Stores ─────────────────────────────────────────────────────────────── export const getStores = (params?: object) => unwrap(api.get('/api/stores', { params })) export const getStore = (id: number) => unwrap(api.get(`/api/stores/${id}`)) export const createStore = (d: object) => unwrap(api.post('/api/stores', d)) export const updateStore = (id: number, d: object) => unwrap(api.put(`/api/stores/${id}`, d)) export const deleteStore = (id: number) => api.delete(`/api/stores/${id}`) // ── Store Groups ───────────────────────────────────────────────────────── export const getStoreGroups = (tenantCode?: string) => unwrap(api.get('/api/store-groups', { params: { tenantCode } })) export const createStoreGroup = (d: object) => unwrap(api.post('/api/store-groups', d)) export const updateStoreGroup = (id: number, d: object) => unwrap(api.put(`/api/store-groups/${id}`, d)) export const deleteStoreGroup = (id: number) => api.delete(`/api/store-groups/${id}`) // ── Templates ──────────────────────────────────────────────────────────── export const getTemplates = (params?: object) => unwrap(api.get('/api/templates', { params })) export const createTemplate = (d: object) => unwrap(api.post('/api/templates', d)) export const updateTemplate = (id: number, d: object) => unwrap(api.put(`/api/templates/${id}`, d)) export const deleteTemplate = (id: number) => api.delete(`/api/templates/${id}`) // ── POS CVT ────────────────────────────────────────────────────────────── export const getPosCvt = (params?: object) => unwrap(api.get('/api/pos-cvt', { params })) export const processPosCvt = (id: number) => unwrap(api.put(`/api/pos-cvt/${id}/process`)) export const ignorePosCvt = (id: number) => unwrap(api.put(`/api/pos-cvt/${id}/ignore`)) // ── Alarms ─────────────────────────────────────────────────────────────── export const getAlarms = (params?: object) => unwrap(api.get('/api/alarms', { params })) export const createAlarm = (d: object) => unwrap(api.post('/api/alarms', d)) export const resolveAlarm = (id: number, resolution: string) => unwrap(api.put(`/api/alarms/${id}/resolve`, { resolution })) export const deleteAlarm = (id: number) => api.delete(`/api/alarms/${id}`) // ── HCore ──────────────────────────────────────────────────────────────── export const getHCore = (params?: object) => unwrap(api.get('/api/hcore', { params })) export const updateHCoreStatus = (id: number, status: string) => unwrap(api.put(`/api/hcore/${id}/status`, { status })) // ── Works ──────────────────────────────────────────────────────────────── export const getWorks = (params?: object) => unwrap(api.get('/api/works', { params })) export const createWork = (d: object) => unwrap(api.post('/api/works', d)) export const updateWork = (id: number, d: object) => unwrap(api.put(`/api/works/${id}`, d)) export const deleteWork = (id: number) => api.delete(`/api/works/${id}`) // ── Firmware ───────────────────────────────────────────────────────────── export const getFirmware = (params?: object) => unwrap(api.get('/api/firmware', { params })) export const createFirmware = (d: object) => unwrap(api.post('/api/firmware', d)) export const deleteFirmware = (id: number) => api.delete(`/api/firmware/${id}`) // ── Users ──────────────────────────────────────────────────────────────── export const getUsers = (params?: object) => unwrap(api.get('/api/users', { params })) export const createUser = (d: object) => unwrap(api.post('/api/users', d)) export const updateUser = (id: number, d: object) => unwrap(api.put(`/api/users/${id}`, d)) export const deleteUser = (id: number) => api.delete(`/api/users/${id}`) // ── Products ───────────────────────────────────────────────────────────── export const getProducts = (params?: object) => unwrap(api.get('/api/products', { params })) export const createProduct = (d: object) => unwrap(api.post('/api/products', d)) export const updateProduct = (id: number, d: object) => unwrap(api.put(`/api/products/${id}`, d)) export const deleteProduct = (id: number) => api.delete(`/api/products/${id}`) // ── Admin: 감사 로그 ─────────────────────────────────────────────────────── export const getAuditLogs = (params?: object) => unwrap(api.get('/api/admin/audit', { params })) export const getAuditCount = (params?: object) => unwrap(api.get('/api/admin/audit/count', { params })) // ── Admin: 시스템 설정 ───────────────────────────────────────────────────── export const getSettings = (category?: string) => unwrap(api.get('/api/admin/settings', { params: category ? { category } : {} })) export const updateSetting = (key: string, value: string) => unwrap(api.put(`/api/admin/settings/${encodeURIComponent(key)}`, { value })) // ── Users (active toggle) ────────────────────────────────────────────────── export const setUserActive = (id: number, active: boolean) => unwrap(api.put(`/api/users/${id}/active`, { active })) // ── AI ─────────────────────────────────────────────────────────────────── export const analyzeAlarm = (d: object) => unwrap(api.post('/api/ai/analyze-alarm', d)) export const classifyPos = (d: object) => unwrap(api.post('/api/ai/classify-pos', d)) export const aiChat = (message: string) => unwrap(api.post('/api/ai/chat', { message })) // ── AI 기법 (중앙 guardia-rag 경유 — 테넌트 격리) ───────────────────────────── // X-Tenant-Code 헤더로 테넌트 격리. 토글 조회/변경 + 대표 기능(/agent·/structured) 경유. export const ragToggles = (tenantCode?: string) => unwrap(api.get('/api/ai/rag/toggles', { params: { tenantCode } })) export const ragUpdateToggle = (key: string, value: string | number | boolean, tenantCode?: string) => unwrap(api.put(`/api/ai/rag/toggles/${key}`, { value, tenantCode }, tenantCode ? { headers: { 'X-Tenant-Code': tenantCode } } : undefined)) export const ragAnalyzeAlarm = (d: object, tenantCode?: string) => unwrap(api.post('/api/ai/rag/analyze-alarm', d, tenantCode ? { headers: { 'X-Tenant-Code': tenantCode } } : undefined)) export const ragClassifyPos = (d: object, tenantCode?: string) => unwrap(api.post('/api/ai/rag/classify-pos', d, tenantCode ? { headers: { 'X-Tenant-Code': tenantCode } } : undefined)) export const ragFeedback = (d: object, tenantCode?: string) => unwrap(api.post('/api/ai/rag/feedback', d, tenantCode ? { headers: { 'X-Tenant-Code': tenantCode } } : undefined))