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
+184
View File
@@ -0,0 +1,184 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useAuthStore } from '@/stores/auth'
const auth = useAuthStore()
const email = ref('')
const password = ref('')
const showPassword = ref(false)
async function handleLogin() {
if (!email.value || !password.value) return
await auth.login({ email: email.value, password: password.value })
}
</script>
<template>
<div class="login-bg">
<div class="login-card">
<div class="login-circles">
<span class="c c1"></span>
<span class="c c2"></span>
<span class="c c3"></span>
</div>
<h1 class="login-brand">teloprax</h1>
<p class="login-tagline">Tecnología con prescripción</p>
<div class="login-divider"></div>
<p class="login-sub">Centro de diagnóstico multi-proyecto</p>
<form @submit.prevent="handleLogin" class="login-form">
<div class="field">
<label>Email</label>
<input v-model="email" type="email" placeholder="ricardo@..." autocomplete="email" />
</div>
<div class="field">
<label>Contraseña</label>
<div class="password-wrap">
<input
v-model="password"
:type="showPassword ? 'text' : 'password'"
placeholder="••••••••"
autocomplete="current-password"
/>
<button type="button" class="toggle-btn" @click="showPassword = !showPassword">
{{ showPassword ? '' : '' }}
</button>
</div>
</div>
<p v-if="auth.error" class="error-msg">{{ auth.error }}</p>
<button type="submit" class="login-btn" :disabled="auth.loading">
{{ auth.loading ? 'Ingresando...' : 'Iniciar diagnóstico' }}
</button>
</form>
<p class="login-footer">kappa.lambdaanalytics.co</p>
</div>
</div>
</template>
<style scoped>
.login-bg {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #1A1A2E;
}
.login-card {
width: 420px;
padding: 44px 40px;
background: #141428;
border: 1px solid #2A2A45;
border-radius: 12px;
text-align: center;
}
.login-circles {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
margin-bottom: 20px;
}
.c {
display: block;
border-radius: 50%;
border: 2px solid #E63946;
}
.c1 { width: 10px; height: 10px; opacity: 0.35; }
.c2 { width: 14px; height: 14px; opacity: 0.65; }
.c3 { width: 18px; height: 18px; background: #E63946; border: none; }
.login-brand {
font-family: 'Space Grotesk', sans-serif;
font-weight: 700;
font-size: 26px;
color: #FFFFFF;
letter-spacing: -0.5px;
margin: 0;
}
.login-tagline {
margin: 4px 0 0;
font-size: 13px;
color: #E63946;
font-weight: 500;
letter-spacing: 0.2px;
}
.login-divider {
width: 40px;
height: 2px;
background: #2A2A45;
margin: 20px auto;
}
.login-sub {
margin: 0 0 28px;
font-size: 13px;
color: #8888AA;
}
.login-form { display: flex; flex-direction: column; gap: 14px; text-align: left; }
.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 11px; color: #8888AA; text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; }
.field input {
padding: 10px 12px;
background: #1A1A2E;
border: 1px solid #2A2A45;
border-radius: 6px;
color: #E6EDF3;
font-size: 14px;
outline: none;
transition: border-color 0.15s;
}
.field input:focus {
border-color: #E63946;
box-shadow: 0 0 0 2px rgba(230,57,70,0.12);
}
.field input::placeholder { color: #555577; }
.password-wrap { position: relative; }
.password-wrap input { width: 100%; box-sizing: border-box; padding-right: 40px; }
.toggle-btn {
position: absolute;
right: 8px; top: 50%;
transform: translateY(-50%);
background: none; border: none;
color: #8888AA; font-size: 16px;
cursor: pointer; padding: 4px;
}
.toggle-btn:hover { color: #E6EDF3; }
.error-msg {
margin: 0;
font-size: 12px;
color: #F85149;
padding: 8px 12px;
background: rgba(248,81,73,0.08);
border: 1px solid rgba(248,81,73,0.15);
border-radius: 6px;
}
.login-btn {
padding: 11px;
background: #E63946;
color: #fff;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
margin-top: 6px;
transition: background 0.15s;
}
.login-btn:hover { background: #C62E3A; }
.login-btn:disabled { opacity: 0.5; cursor: default; }
.login-footer {
margin: 28px 0 0;
font-size: 11px;
color: #444466;
}
</style>