Files
Alpha/src/services/kappa-api.ts
T
ricardo fff84c552c users: tabla + sync detalle + lookups para roles/companies
- db.ts v6: tablas users + lookups con schema
- users-db.ts: CRUD users + lookups
- user-sync.ts: fetch /api/users/{id}/ con concurrencia 5
- kappa-api.ts: +getUserDetail(id)
- users store: +syncDetails() con progreso + mapeo roleId→name
- UsersView: boton 'Sincronizar roles' con progreso
- UserRecord: username, isStaff, phone, position, lastActive, createdAt
2026-05-29 00:14:30 -05:00

218 lines
7.8 KiB
TypeScript

import { storage } from '@/services/storage'
import type {
KappaLoginPayload,
KappaLoginResponse,
KappaInitiative,
KappaUserStory,
KappaEpicDevelopment,
KappaCreateEpicPayload,
KappaLogbookMaster,
KappaLogbookEntry,
KappaPlanningMaster,
KappaPlanningEntry,
KappaBusinessRule,
KappaRequirement,
KappaEmployee,
KappaPending,
KappaTypeImpediment,
PaginatedResponse,
} from '@/types/kappa'
const BASE = '/api'
class KappaAPI {
private token: string | null = null
constructor() {
this.token = storage.get('kappa_token')
}
private get headers(): Record<string, string> {
const h: Record<string, string> = {
'Content-Type': 'application/json',
}
if (this.token) {
h['Authorization'] = `Bearer ${this.token}`
}
return h
}
private async request<T>(
method: string,
path: string,
body?: unknown
): Promise<T> {
const opts: RequestInit = {
method,
headers: this.headers,
}
if (body && method !== 'GET') {
opts.body = JSON.stringify(body)
}
const res = await fetch(`${BASE}${path}`, opts)
if (!res.ok) {
const text = await res.text()
throw new Error(`KAPPA ${method} ${path}: ${res.status}${text.slice(0, 200)}`)
}
return res.json()
}
// ─── Auth ────────────────────────────────────────────
async login(payload: KappaLoginPayload): Promise<KappaLoginResponse> {
const data = await this.request<KappaLoginResponse>(
'POST',
'/users/login/',
payload
)
this.token = data.access || data.token || data.key || null
if (this.token) {
storage.set('kappa_token', this.token)
}
return data
}
logout() {
this.token = null
storage.remove('kappa_token')
}
get isAuthenticated(): boolean {
return !!this.token
}
// ─── Proyectos (Initiatives) ─────────────────────────
async getInitiatives(): Promise<KappaInitiative[]> {
return this.request<KappaInitiative[]>('GET', '/initiatives-all/')
}
// ─── User Stories ────────────────────────────────────
async createUserStory(story: KappaUserStory): Promise<KappaUserStory> {
return this.request<KappaUserStory>('POST', '/userstorys/create/', story)
}
// ─── Users ───────────────────────────────────────────
async getUsers(): Promise<unknown[]> {
return this.request<unknown[]>('GET', '/users/all/')
}
async getUserDetail(id: number): Promise<Record<string, unknown>> {
return this.request<Record<string, unknown>>('GET', `/users/${id}/`)
}
async getEmployees(page = 1): Promise<PaginatedResponse<KappaEmployee>> {
return this.request<PaginatedResponse<KappaEmployee>>('GET', `/employees/?page=${page}`)
}
async getUserStories(initiativeId?: number, page = 1, pageSize = 100): Promise<PaginatedResponse<KappaUserStory>> {
const params = new URLSearchParams()
if (initiativeId) params.set('initiative', String(initiativeId))
params.set('page', String(page))
params.set('page_size', String(pageSize))
return this.request<PaginatedResponse<KappaUserStory>>('GET', `/userstorys/?${params.toString()}`)
}
async getAllUserStories(initiativeId: number): Promise<KappaUserStory[]> {
const first = await this.getUserStories(initiativeId, 1, 100)
const all = [...first.results]
const totalPages = Math.ceil(first.count / 100)
for (let p = 2; p <= totalPages; p++) {
const page = await this.getUserStories(initiativeId, p, 100)
all.push(...page.results)
}
return all
}
async getEpicDevelopment(initiativeId: number, page = 1, pageSize = 50): Promise<PaginatedResponse<KappaEpicDevelopment>> {
return this.request<PaginatedResponse<KappaEpicDevelopment>>('GET', `/epicdevelopment/?initiative=${initiativeId}&page=${page}&page_size=${pageSize}`)
}
async getAllEpicDevelopment(initiativeId: number): Promise<KappaEpicDevelopment[]> {
const first = await this.getEpicDevelopment(initiativeId, 1, 100)
const all = [...first.results]
const totalPages = Math.ceil(first.count / 100)
for (let p = 2; p <= totalPages; p++) {
const page = await this.getEpicDevelopment(initiativeId, p, 100)
all.push(...page.results)
}
return all
}
async createEpicDevelopment(data: KappaCreateEpicPayload): Promise<KappaEpicDevelopment> {
return this.request<KappaEpicDevelopment>('POST', '/epicdevelopment/create/', data)
}
async updateEpicDevelopment(id: number, data: Partial<KappaCreateEpicPayload>): Promise<KappaEpicDevelopment> {
return this.request<KappaEpicDevelopment>('POST', `/epicdevelopment/update/${id}/`, data)
}
async deleteEpicDevelopment(id: number): Promise<void> {
await this.request('POST', `/epicdevelopment/delete/${id}/`)
}
async getLogbooks(initiativeId?: number): Promise<KappaLogbookEntry[]> {
const path = initiativeId ? `/logbooks/?initiative=${initiativeId}` : '/logbooks/'
return this.request<KappaLogbookEntry[]>('GET', path)
}
async getPlannings(initiativeId?: number): Promise<KappaPlanningEntry[]> {
const path = initiativeId ? `/plannings/?initiative=${initiativeId}` : '/plannings/'
return this.request<KappaPlanningEntry[]>('GET', path)
}
async getBusinessRules(initiativeId?: number): Promise<KappaBusinessRule[]> {
const path = initiativeId ? `/business-rules/?initiative=${initiativeId}` : '/business-rules/'
return this.request<KappaBusinessRule[]>('GET', path)
}
async getRequirements(initiativeId?: number): Promise<KappaRequirement[]> {
const path = initiativeId ? `/functionalrequirements/?initiative=${initiativeId}` : '/functionalrequirements/'
return this.request<KappaRequirement[]>('GET', path)
}
// ─── Bitácoras (Logbooks) ────────────────────────────
async createLogbookMaster(data: KappaLogbookMaster): Promise<KappaLogbookMaster> {
return this.request<KappaLogbookMaster>('POST', '/logbooks_master/create/', data)
}
async createLogbookEntry(data: KappaLogbookEntry): Promise<KappaLogbookEntry> {
return this.request<KappaLogbookEntry>('POST', '/logbooks/create/', data)
}
// ─── Planeaciones (Plannings) ────────────────────────
async createPlanningMaster(data: KappaPlanningMaster): Promise<KappaPlanningMaster> {
return this.request<KappaPlanningMaster>('POST', '/plannings_master/create/', data)
}
async createPlanningEntry(data: KappaPlanningEntry): Promise<KappaPlanningEntry> {
return this.request<KappaPlanningEntry>('POST', '/plannings/create/', data)
}
// ─── Business Rules ──────────────────────────────────
async createBusinessRule(data: KappaBusinessRule): Promise<unknown> {
return this.request<unknown>('POST', '/business-rules/create/', data)
}
// ─── Requisitos ──────────────────────────────────────
async createRequirement(data: KappaRequirement): Promise<unknown> {
return this.request<unknown>('POST', '/functionalrequirements/create/', data)
}
async getPendings(huId: number, page = 1): Promise<PaginatedResponse<KappaPending>> {
return this.request<PaginatedResponse<KappaPending>>('GET', `/pendings/?hu=${huId}&page=${page}`)
}
async getTypeImpediments(): Promise<KappaTypeImpediment[]> {
return this.request<KappaTypeImpediment[]>('GET', '/typeimpediments/')
}
}
export const kappa = new KappaAPI()