Sales Trainer v0.1: corporate sales-training simulator (Flask+Vue, 15 personas, chat simulator, judge, analytics)
- Auth/roles (no self-reg), admin user provision, JWT - Analyze: sales kit + initial pain-fit from form/upload - Persona generator: 15 personas (5/tier) w/ pain variety, negotiation, init mode, channel, latent/revealable, wrong_text special - Chat simulator: per-mode initiation, one-shot, hidden signals, judge-LLM debrief+coaching - Trainee loop: win/lose board, weak-areas, user-generated personas - Admin analytics; EN+TH Vue SPA served by Flask - Deploy: Dockerfile, docker-compose, README, eng-log + HANDOFF - Tests (mock LLM): m0/m1/routes/e2e all pass
This commit is contained in:
57
frontend/src/api/index.js
Normal file
57
frontend/src/api/index.js
Normal file
@@ -0,0 +1,57 @@
|
||||
// API client with JWT auth injection.
|
||||
const TOKEN_KEY = 'st_token'
|
||||
|
||||
export function getToken() {
|
||||
return localStorage.getItem(TOKEN_KEY)
|
||||
}
|
||||
export function setToken(t) {
|
||||
if (t) localStorage.setItem(TOKEN_KEY, t)
|
||||
else localStorage.removeItem(TOKEN_KEY)
|
||||
}
|
||||
|
||||
async function request(method, url, body, isForm = false) {
|
||||
const headers = {}
|
||||
const token = getToken()
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`
|
||||
let payload = body
|
||||
if (!isForm && body !== undefined && body !== null) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
payload = JSON.stringify(body)
|
||||
}
|
||||
const res = await fetch(url, { method, headers, body: payload })
|
||||
let data = null
|
||||
try {
|
||||
data = await res.json()
|
||||
} catch (e) {
|
||||
/* ignore json parse errors */
|
||||
}
|
||||
if (!res.ok) {
|
||||
const msg = (data && (data.error || data.message)) || `HTTP ${res.status}`
|
||||
throw new Error(msg)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const api = {
|
||||
login: (email, password) => request('POST', '/api/auth/login', { email, password }),
|
||||
me: () => request('GET', '/api/auth/me'),
|
||||
adminCreateUser: (b) => request('POST', '/api/admin/users', b),
|
||||
adminListUsers: () => request('GET', '/api/admin/users'),
|
||||
adminUpdateUser: (email, b) => request('PUT', `/api/admin/users/${email}`, b),
|
||||
createGroup: (formData) => request('POST', '/api/groups', formData, true),
|
||||
listGroups: () => request('GET', '/api/groups'),
|
||||
getGroup: (id) => request('GET', `/api/groups/${id}`),
|
||||
analyzeGroup: (id) => request('POST', `/api/groups/${id}/analyze`),
|
||||
listPersonas: (gid) => request('GET', `/api/groups/${gid}/personas`),
|
||||
getPersona: (gid, pid) => request('GET', `/api/groups/${gid}/personas/${pid}`),
|
||||
updatePersona: (gid, pid, b) => request('PUT', `/api/groups/${gid}/personas/${pid}`, b),
|
||||
chatStart: (gid, pid) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/start`),
|
||||
chatSend: (gid, pid, text) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/send`, { text }),
|
||||
chatFinish: (gid, pid) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/finish`),
|
||||
mySessions: () => request('GET', '/api/chat/sessions'),
|
||||
myBoard: () => request('GET', '/api/me/board'),
|
||||
weakAreas: () => request('GET', '/api/me/weak-areas'),
|
||||
myPersonas: () => request('GET', '/api/me/personas'),
|
||||
generatePersona: (b) => request('POST', '/api/me/personas/generate', b),
|
||||
analytics: () => request('GET', '/api/analytics'),
|
||||
}
|
||||
Reference in New Issue
Block a user