Alpha v0.1.0 — KAPPA Hub inicial

- Auth con KAPPA (login + token Bearer)
- Cliente HTTP para 10 endpoints (proyectos, HUs, bitácoras, planeaciones)
- Dashboard multi-proyecto con concepto médico Teloprax
- Calendario colombiano con 19 feriados (Ley Emiliani + Pascua)
- Scheduler tipo cron con Dexie (reglas recurrentes, toasts, log)
- Diseño marca Teloprax: Inter, Space Grotesk, #1A1A2E, rojo #E63946
- Stack: Vue 3 + TypeScript + Pinia + Vite + Bun
This commit is contained in:
2026-05-22 20:18:54 -05:00
commit 66fd4e175a
26 changed files with 2227 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
import type {
KappaLoginPayload,
KappaLoginResponse,
KappaInitiative,
KappaUserStory,
KappaLogbookMaster,
KappaLogbookEntry,
KappaPlanningMaster,
KappaPlanningEntry,
KappaBusinessRule,
KappaRequirement,
} from '@/types/kappa'
const BASE = '/api'
class KappaAPI {
private token: string | null = null
constructor() {
this.token = localStorage.getItem('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) {
localStorage.setItem('kappa_token', this.token)
}
return data
}
logout() {
this.token = null
localStorage.removeItem('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/')
}
// ─── 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)
}
}
export const kappa = new KappaAPI()