- Lista con eventos del día agrupados: manuales, escrituras, trámites - Visibilidad: eventos manuales y escrituras → todos los usuarios; trámites legales → solo creador, abogado nombrado o involucrado (mismo canView() que en el módulo de trámites) - Cada evento es clickable y navega al módulo correspondiente (/calendario, /escrituras/?edit=ID, /tramites/?edit=CODIGO) - Cards muestran: título + cliente + abogado + estatus, con tags de tipo y departamento; eventos manuales muestran rango horario y creador
464 lines
27 KiB
PHP
464 lines
27 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
require_once __DIR__ . '/../src/Auth.php';
|
||
require_once __DIR__ . '/../src/Db.php';
|
||
require_once __DIR__ . '/../src/Apps.php';
|
||
|
||
$authed = Auth::isAuthenticated();
|
||
$user = $authed ? Auth::user() : ['email' => '', 'name' => ''];
|
||
$apps = $authed ? Apps::catalog() : [];
|
||
|
||
/**
|
||
* Devuelve los eventos del día agrupados:
|
||
* - manuales: visibles a todos
|
||
* - escrituras (fecha_solicitud=hoy): visibles a todos
|
||
* - trámites (solicitud/vencimiento/término=hoy): solo creador, abogado nombrado o involucrado
|
||
*/
|
||
function todays_events(array $u, int $myId, bool $isSocio): array {
|
||
try {
|
||
$pdo = Db::pdo();
|
||
$today = date('Y-m-d');
|
||
|
||
$manual = $pdo->prepare(
|
||
'SELECT id, titulo, tipo, fecha, hora_inicio, hora_fin, ubicacion, creado_por_nombre, creado_por
|
||
FROM calendar_events WHERE fecha = :d
|
||
ORDER BY (hora_inicio IS NULL), hora_inicio, id'
|
||
);
|
||
$manual->execute([':d' => $today]);
|
||
$manualRows = $manual->fetchAll();
|
||
|
||
$esc = $pdo->prepare(
|
||
'SELECT id, tramite, cliente, abogado, estatus
|
||
FROM escrituras_tramites WHERE DATE(fecha_solicitud) = :d
|
||
ORDER BY id DESC'
|
||
);
|
||
$esc->execute([':d' => $today]);
|
||
$escRows = $esc->fetchAll();
|
||
|
||
if ($isSocio) {
|
||
$tra = $pdo->prepare(
|
||
"SELECT id, codigo, departamento, nombre, tipo_tramite, tipo_proceso,
|
||
cliente, abogado, estatus, fecha_solicitud, fecha_vencimiento, fecha_termino
|
||
FROM tramites_legales
|
||
WHERE DATE(fecha_solicitud) = :d
|
||
OR fecha_vencimiento = :d2
|
||
OR fecha_termino = :d3
|
||
ORDER BY id DESC"
|
||
);
|
||
$tra->execute([':d' => $today, ':d2' => $today, ':d3' => $today]);
|
||
} else {
|
||
$tra = $pdo->prepare(
|
||
"SELECT DISTINCT t.id, t.codigo, t.departamento, t.nombre, t.tipo_tramite, t.tipo_proceso,
|
||
t.cliente, t.abogado, t.estatus, t.fecha_solicitud, t.fecha_vencimiento, t.fecha_termino
|
||
FROM tramites_legales t
|
||
LEFT JOIN users ua ON ua.name = t.abogado AND ua.activo = 1
|
||
LEFT JOIN tramites_involucrados ti ON ti.tramite_id = t.id AND ti.user_id = :uid
|
||
WHERE (DATE(t.fecha_solicitud) = :d
|
||
OR t.fecha_vencimiento = :d2
|
||
OR t.fecha_termino = :d3)
|
||
AND (t.creado_por = :email OR ua.id = :uid2 OR ti.user_id IS NOT NULL)
|
||
ORDER BY t.id DESC"
|
||
);
|
||
$tra->execute([
|
||
':uid' => $myId, ':uid2' => $myId, ':email' => $u['email'],
|
||
':d' => $today, ':d2' => $today, ':d3' => $today,
|
||
]);
|
||
}
|
||
$traRows = $tra->fetchAll();
|
||
|
||
// Expandir trámites en 1..N entradas (una por fecha que coincida hoy)
|
||
$traEvents = [];
|
||
foreach ($traRows as $t) {
|
||
$title = $t['nombre'] ?: $t['tipo_tramite'] ?: $t['tipo_proceso'] ?: 'Trámite';
|
||
if (substr((string)$t['fecha_solicitud'], 0, 10) === $today) {
|
||
$traEvents[] = $t + ['evento' => 'solicitud', 'evento_label' => 'Solicitud', 'title' => $title];
|
||
}
|
||
if (($t['fecha_vencimiento'] ?? '') === $today) {
|
||
$traEvents[] = $t + ['evento' => 'vencimiento', 'evento_label' => 'Vencimiento', 'title' => $title];
|
||
}
|
||
if (($t['fecha_termino'] ?? '') === $today) {
|
||
$traEvents[] = $t + ['evento' => 'termino', 'evento_label' => 'Término procesal', 'title' => $title];
|
||
}
|
||
}
|
||
|
||
return [
|
||
'manual' => $manualRows,
|
||
'escrituras' => $escRows,
|
||
'tramites' => $traEvents,
|
||
];
|
||
} catch (Throwable $e) {
|
||
error_log('todays_events error: ' . $e->getMessage());
|
||
return ['manual' => [], 'escrituras' => [], 'tramites' => []];
|
||
}
|
||
}
|
||
|
||
function fmt_hour(?string $t): string {
|
||
if (!$t) return '';
|
||
return substr($t, 0, 5);
|
||
}
|
||
|
||
$todayEvents = $authed
|
||
? todays_events($user, Auth::userId(), Auth::isSocio())
|
||
: ['manual' => [], 'escrituras' => [], 'tramites' => []];
|
||
$hasToday = $authed && (
|
||
!empty($todayEvents['manual']) || !empty($todayEvents['escrituras']) || !empty($todayEvents['tramites'])
|
||
);
|
||
|
||
$DEPT_LABELS = ['adm' => 'Admin', 'corp' => 'Corp', 'mig' => 'Migración', 'lit' => 'Litigios'];
|
||
$DEPT_COLORS = ['adm' => '#6c5b95', 'corp' => '#9E7C2E', 'mig' => '#2980b9', 'lit' => '#722f37'];
|
||
$TIPO_LABELS = ['reserva_sala' => 'Reserva de sala', 'cumpleanos' => 'Cumpleaños', 'recordatorio' => 'Recordatorio', 'evento' => 'Evento'];
|
||
$TIPO_COLORS = ['reserva_sala' => '#2e7d8f', 'cumpleanos' => '#c2185b', 'recordatorio' => '#e67e22', 'evento' => '#27ae60'];
|
||
|
||
function initials(string $name): string {
|
||
$parts = preg_split('/\s+/u', trim($name));
|
||
$a = mb_substr($parts[0] ?? '', 0, 1);
|
||
$b = mb_substr($parts[1] ?? '', 0, 1);
|
||
return strtoupper($a . $b) ?: 'AA';
|
||
}
|
||
|
||
function icon(string $name): string {
|
||
$svgs = [
|
||
'document' => '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/>',
|
||
'briefcase' => '<rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/>',
|
||
'calendar' => '<rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>',
|
||
'users' => '<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
||
];
|
||
return $svgs[$name] ?? $svgs['document'];
|
||
}
|
||
?><!DOCTYPE html>
|
||
<html lang="es">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title><?= $authed ? 'Donna · AALN Portal' : 'Donna · AALN Law' ?></title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=DM+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
|
||
:root{
|
||
--navy:#1B3A6B;
|
||
--navy-d:#112446;
|
||
--navy-l:#2D5090;
|
||
--gold:#C9A84C;
|
||
--gold-l:#E8C96A;
|
||
--gold-d:#9E7C2E;
|
||
--off:#F7F6F3;
|
||
--gray-100:#EEEDE9;
|
||
--gray-200:#D6D4CC;
|
||
--gray-400:#9B9A96;
|
||
--gray-700:#4A4946;
|
||
--gray-900:#1A1916;
|
||
--shadow:0 1px 3px rgba(0,0,0,0.06),0 4px 16px rgba(0,0,0,0.06);
|
||
--shadow-lg:0 12px 40px rgba(17,36,70,0.18);
|
||
}
|
||
html,body{min-height:100%;}
|
||
body{font-family:'DM Sans',system-ui,sans-serif;color:var(--gray-900);background:var(--off);font-size:15px;-webkit-font-smoothing:antialiased;}
|
||
a{color:inherit;text-decoration:none;}
|
||
|
||
/* ───────── LANDING (anonymous) ───────── */
|
||
.landing{min-height:100vh;display:flex;flex-direction:column;background:linear-gradient(135deg,#0E1F3F 0%,#1B3A6B 55%,#2D5090 100%);color:#fff;position:relative;overflow:hidden;}
|
||
.landing::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse 60% 50% at 80% 10%,rgba(201,168,76,0.22),transparent 60%),radial-gradient(ellipse 40% 40% at 10% 90%,rgba(201,168,76,0.12),transparent 60%);pointer-events:none;}
|
||
.landing-nav{padding:28px 48px;display:flex;align-items:center;justify-content:space-between;position:relative;z-index:2;}
|
||
.brand{display:flex;align-items:center;gap:14px;}
|
||
.brand-mark{width:42px;height:42px;background:var(--gold);border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'DM Serif Display',serif;font-size:20px;color:var(--navy);}
|
||
.brand-text{display:flex;flex-direction:column;line-height:1.15;}
|
||
.brand-firm{font-size:11px;font-weight:600;color:var(--gold);letter-spacing:.18em;text-transform:uppercase;}
|
||
.brand-firm a{color:inherit;border-bottom:1px dotted transparent;transition:border-color .2s;}
|
||
.brand-firm a:hover{border-color:var(--gold);}
|
||
.brand-name{font-family:'DM Serif Display',serif;font-size:22px;color:#fff;}
|
||
.landing-foot-link{font-size:12px;color:rgba(255,255,255,0.55);letter-spacing:.06em;}
|
||
.landing-foot-link a{color:rgba(255,255,255,0.8);border-bottom:1px solid rgba(255,255,255,0.2);padding-bottom:1px;}
|
||
.landing-foot-link a:hover{color:var(--gold);border-color:var(--gold);}
|
||
|
||
.hero{flex:1;display:grid;grid-template-columns:1.1fr 1fr;gap:48px;padding:40px 80px 80px;align-items:center;position:relative;z-index:2;}
|
||
@media (max-width:980px){.hero{grid-template-columns:1fr;padding:24px 32px 48px;}}
|
||
.hero-text{max-width:560px;}
|
||
.hero-eyebrow{font-size:12px;font-weight:600;color:var(--gold);letter-spacing:.22em;text-transform:uppercase;margin-bottom:24px;display:flex;align-items:center;gap:12px;}
|
||
.hero-eyebrow::before{content:'';width:32px;height:1px;background:var(--gold);display:inline-block;}
|
||
.hero-title{font-family:'DM Serif Display',serif;font-size:clamp(40px,5.6vw,68px);line-height:1.05;color:#fff;margin-bottom:24px;font-weight:400;}
|
||
.hero-title em{font-style:italic;color:var(--gold-l);}
|
||
.hero-sub{font-size:17px;line-height:1.6;color:rgba(255,255,255,0.78);margin-bottom:36px;font-weight:300;max-width:520px;}
|
||
.btn-login{display:inline-flex;align-items:center;gap:12px;background:var(--gold);color:var(--navy-d);padding:16px 32px;border-radius:10px;font-weight:600;font-size:15px;letter-spacing:.02em;border:none;cursor:pointer;transition:transform .15s,box-shadow .15s,background .15s;box-shadow:0 6px 18px rgba(201,168,76,0.35);}
|
||
.btn-login:hover{background:var(--gold-l);transform:translateY(-1px);box-shadow:0 10px 24px rgba(201,168,76,0.42);}
|
||
.btn-login:active{transform:translateY(0);}
|
||
.btn-login svg{width:18px;height:18px;}
|
||
.login-meta{margin-top:18px;font-size:12px;color:rgba(255,255,255,0.5);letter-spacing:.04em;}
|
||
|
||
.hero-art{position:relative;height:420px;display:flex;align-items:center;justify-content:center;}
|
||
@media (max-width:980px){.hero-art{display:none;}}
|
||
.card-stack{position:relative;width:100%;max-width:420px;}
|
||
.art-card{position:absolute;background:rgba(255,255,255,0.06);border:1px solid rgba(201,168,76,0.25);backdrop-filter:blur(14px);border-radius:14px;padding:22px;color:#fff;box-shadow:var(--shadow-lg);}
|
||
.art-card-1{top:0;left:0;width:280px;transform:rotate(-3deg);}
|
||
.art-card-2{top:90px;right:0;width:300px;transform:rotate(2deg);}
|
||
.art-card-3{bottom:0;left:40px;width:280px;transform:rotate(-1deg);}
|
||
.art-card-eyebrow{font-size:9.5px;color:var(--gold);letter-spacing:.16em;text-transform:uppercase;font-weight:600;margin-bottom:10px;}
|
||
.art-card h4{font-family:'DM Serif Display',serif;font-size:16px;font-weight:400;line-height:1.3;margin-bottom:8px;color:#fff;}
|
||
.art-card p{font-size:12px;color:rgba(255,255,255,0.65);line-height:1.5;}
|
||
.art-card .pill{display:inline-block;font-size:10px;font-weight:600;padding:2px 8px;border-radius:20px;background:rgba(201,168,76,0.2);color:var(--gold-l);margin-top:8px;letter-spacing:.04em;}
|
||
|
||
/* ───────── DASHBOARD (authenticated) ───────── */
|
||
.dash-header{background:var(--navy);border-bottom:3px solid var(--gold);padding:0 32px;display:flex;align-items:center;justify-content:space-between;height:64px;position:sticky;top:0;z-index:200;}
|
||
.dash-header .brand-mark{width:36px;height:36px;font-size:16px;}
|
||
.dash-header .brand-name{font-size:18px;}
|
||
.user-chip{display:flex;align-items:center;gap:10px;background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.12);border-radius:24px;padding:5px 6px 5px 6px;color:#fff;}
|
||
.user-avatar{width:30px;height:30px;border-radius:50%;background:var(--gold);color:var(--navy-d);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex-shrink:0;}
|
||
.user-info{display:flex;flex-direction:column;line-height:1.15;padding-right:6px;}
|
||
.user-name{font-size:12.5px;font-weight:500;color:#fff;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
||
.user-email{font-size:10.5px;color:rgba(255,255,255,0.55);max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
||
.btn-logout{font-size:11px;padding:6px 12px;border:1px solid rgba(255,255,255,0.18);border-radius:18px;background:transparent;color:rgba(255,255,255,0.7);cursor:pointer;font-family:'DM Sans',sans-serif;transition:all .15s;}
|
||
.btn-logout:hover{background:rgba(255,255,255,0.12);color:#fff;border-color:rgba(255,255,255,0.3);}
|
||
.btn-gear,.btn-clock{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:1px solid rgba(255,255,255,0.18);border-radius:8px;color:rgba(255,255,255,0.85);transition:all .15s;text-decoration:none;font-family:'DM Sans',sans-serif;margin-right:8px;}
|
||
.btn-gear:hover,.btn-clock:hover{background:var(--gold);border-color:var(--gold);color:var(--navy);}
|
||
.btn-gear svg,.btn-clock svg{width:16px;height:16px;}
|
||
|
||
.dash-main{max-width:1180px;margin:0 auto;padding:48px 32px 80px;}
|
||
.dash-hero{margin-bottom:40px;}
|
||
.dash-greeting{font-family:'DM Serif Display',serif;font-size:36px;color:var(--navy);font-weight:400;line-height:1.15;margin-bottom:8px;}
|
||
.dash-greeting em{color:var(--gold-d);font-style:italic;}
|
||
.dash-sub{font-size:15px;color:var(--gray-700);max-width:560px;line-height:1.55;}
|
||
|
||
.section-label{font-size:11px;font-weight:600;color:var(--gray-400);letter-spacing:.18em;text-transform:uppercase;margin-bottom:18px;display:flex;align-items:center;gap:14px;}
|
||
.section-label::after{content:'';flex:1;height:1px;background:var(--gray-200);}
|
||
|
||
.app-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:20px;}
|
||
.app-card{background:#fff;border:1px solid var(--gray-100);border-radius:14px;padding:24px;display:flex;flex-direction:column;gap:14px;transition:all .2s;position:relative;box-shadow:var(--shadow);cursor:pointer;color:inherit;min-height:200px;}
|
||
.app-card.live:hover{transform:translateY(-3px);box-shadow:0 12px 32px rgba(17,36,70,0.10);border-color:var(--navy-l);}
|
||
.app-card.coming-soon{cursor:default;opacity:0.7;}
|
||
.app-card.coming-soon:hover{transform:none;}
|
||
.app-icon{width:48px;height:48px;border-radius:10px;background:rgba(27,58,107,0.08);color:var(--navy);display:flex;align-items:center;justify-content:center;}
|
||
.app-card.live .app-icon{background:linear-gradient(135deg,var(--navy) 0%,var(--navy-l) 100%);color:var(--gold-l);}
|
||
.app-icon svg{width:24px;height:24px;}
|
||
.app-title{font-family:'DM Serif Display',serif;font-size:22px;color:var(--navy);font-weight:400;line-height:1.2;}
|
||
.app-desc{font-size:13.5px;color:var(--gray-700);line-height:1.55;flex:1;}
|
||
.app-action{font-size:12px;font-weight:600;color:var(--gold-d);letter-spacing:.06em;text-transform:uppercase;display:flex;align-items:center;gap:6px;}
|
||
.app-action svg{width:14px;height:14px;transition:transform .2s;}
|
||
.app-card.live:hover .app-action svg{transform:translateX(4px);}
|
||
.badge-soon{position:absolute;top:18px;right:18px;font-size:10px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;padding:3px 10px;border-radius:20px;background:var(--gray-100);color:var(--gray-700);}
|
||
|
||
.dash-foot{text-align:center;padding:24px;font-size:11px;color:var(--gray-400);}
|
||
.dash-foot a{color:var(--navy);border-bottom:1px dotted var(--gray-400);}
|
||
|
||
/* ───────── Today's events ───────── */
|
||
.today-wrap{margin-top:48px;}
|
||
.today-list{display:flex;flex-direction:column;gap:10px;}
|
||
.today-empty{padding:18px 22px;background:#fff;border:1px dashed var(--gray-200);border-radius:12px;color:var(--gray-400);font-size:13.5px;text-align:center;}
|
||
.today-card{background:#fff;border:1px solid var(--gray-100);border-radius:12px;padding:14px 18px;display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:center;box-shadow:var(--shadow);transition:all .15s;color:inherit;}
|
||
.today-card.linkable{cursor:pointer;}
|
||
.today-card.linkable:hover{transform:translateX(3px);border-color:var(--navy-l);box-shadow:0 6px 18px rgba(17,36,70,0.08);}
|
||
.today-bar{width:5px;height:46px;border-radius:3px;flex-shrink:0;}
|
||
.today-body{min-width:0;}
|
||
.today-title{font-family:'DM Serif Display',serif;font-size:17px;color:var(--navy);line-height:1.25;font-weight:400;}
|
||
.today-meta{font-size:12.5px;color:var(--gray-700);margin-top:4px;display:flex;gap:10px;flex-wrap:wrap;align-items:center;}
|
||
.today-meta .dot{width:3px;height:3px;border-radius:50%;background:var(--gray-400);display:inline-block;}
|
||
.today-tags{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;align-items:center;}
|
||
.today-tag{font-size:10.5px;font-weight:600;padding:3px 9px;border-radius:20px;color:#fff;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;}
|
||
.today-time{font-size:13px;font-weight:600;color:var(--navy);font-variant-numeric:tabular-nums;white-space:nowrap;}
|
||
.today-code{font-family:'DM Mono','SF Mono',Menlo,monospace;font-size:11px;color:var(--gray-400);letter-spacing:.04em;}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<?php if (!$authed): ?>
|
||
<div class="landing">
|
||
<nav class="landing-nav">
|
||
<div class="brand">
|
||
<div class="brand-mark">D</div>
|
||
<div class="brand-text">
|
||
<span class="brand-firm"><a href="https://www.aalnlaw.com" target="_blank" rel="noopener">AALN · Arias, Abrego, López & Noriega</a></span>
|
||
<span class="brand-name">Donna</span>
|
||
</div>
|
||
</div>
|
||
<div class="landing-foot-link">
|
||
Portal interno · <a href="https://www.aalnlaw.com" target="_blank" rel="noopener">aalnlaw.com</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<section class="hero">
|
||
<div class="hero-text">
|
||
<div class="hero-eyebrow">Plataforma interna AALN</div>
|
||
<h1 class="hero-title">Tu equipo de trabajo, <em>siempre un paso adelante</em>.</h1>
|
||
<p class="hero-sub">Donna es el portal interno de AALN: control de escrituras, expedientes, agenda y herramientas internas en un solo lugar. Inicia sesión con tu correo corporativo.</p>
|
||
<form method="get" action="/auth/login.php">
|
||
<button class="btn-login" type="submit">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
|
||
Iniciar sesión con correo corporativo
|
||
</button>
|
||
</form>
|
||
<div class="login-meta">Autenticación segura vía Mailcow · mail.aal-law.com</div>
|
||
</div>
|
||
|
||
<div class="hero-art" aria-hidden="true">
|
||
<div class="card-stack">
|
||
<div class="art-card art-card-1">
|
||
<div class="art-card-eyebrow">Trámite #1284</div>
|
||
<h4>Constitución sociedad anónima</h4>
|
||
<p>Notaría Quinta · Lic. R. Abrego</p>
|
||
<span class="pill">En Registro</span>
|
||
</div>
|
||
<div class="art-card art-card-2">
|
||
<div class="art-card-eyebrow">Hoy · 14:30</div>
|
||
<h4>Audiencia preliminar</h4>
|
||
<p>Juzgado Primero Civil · Sala 3</p>
|
||
<span class="pill">Confirmada</span>
|
||
</div>
|
||
<div class="art-card art-card-3">
|
||
<div class="art-card-eyebrow">Cliente nuevo</div>
|
||
<h4>Tech Holdings, S.A.</h4>
|
||
<p>KYC pendiente · Asignado a M. Noriega</p>
|
||
<span class="pill">Onboarding</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<?php else: ?>
|
||
<header class="dash-header">
|
||
<div class="brand">
|
||
<div class="brand-mark">D</div>
|
||
<div class="brand-text">
|
||
<span class="brand-firm" style="color:var(--gold);">AALN · Donna</span>
|
||
<span class="brand-name" style="font-size:14px;color:rgba(255,255,255,0.7);">Portal interno</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;align-items:center;">
|
||
<a class="btn-clock" href="/horas/" title="Reporte de horas">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||
</a>
|
||
<?php if (Auth::isSocio()): ?>
|
||
<a class="btn-gear" href="/admin/" title="Panel de Control">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||
</a>
|
||
<?php endif; ?>
|
||
<div class="user-chip">
|
||
<div class="user-avatar"><?= htmlspecialchars(initials($user['name'] ?: $user['email'])) ?></div>
|
||
<div class="user-info">
|
||
<span class="user-name"><?= htmlspecialchars($user['name'] ?: $user['email']) ?></span>
|
||
<?php if ($user['name']): ?><span class="user-email"><?= htmlspecialchars($user['email']) ?></span><?php endif; ?>
|
||
</div>
|
||
<a href="/auth/logout.php" class="btn-logout">Cerrar sesión</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="dash-main">
|
||
<div class="dash-hero">
|
||
<h1 class="dash-greeting">Hola, <em><?= htmlspecialchars(explode(' ', $user['name'] ?: $user['email'])[0]) ?></em>.</h1>
|
||
<p class="dash-sub">Bienvenido a Donna. Elige una herramienta para empezar.</p>
|
||
</div>
|
||
|
||
<div class="section-label">Aplicaciones disponibles</div>
|
||
<div class="app-grid">
|
||
<?php foreach ($apps as $app): ?>
|
||
<?php $isLive = $app['status'] === 'live'; ?>
|
||
<a class="app-card <?= $isLive ? 'live' : 'coming-soon' ?>" href="<?= htmlspecialchars($app['href']) ?>"<?= $isLive ? '' : ' onclick="return false"' ?>>
|
||
<?php if (!$isLive): ?><span class="badge-soon">Próximamente</span><?php endif; ?>
|
||
<div class="app-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><?= icon($app['icon']) ?></svg>
|
||
</div>
|
||
<div class="app-title"><?= htmlspecialchars($app['title']) ?></div>
|
||
<div class="app-desc"><?= htmlspecialchars($app['description']) ?></div>
|
||
<?php if ($isLive): ?>
|
||
<div class="app-action">
|
||
Abrir
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
|
||
</div>
|
||
<?php endif; ?>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<?php
|
||
$meses = ['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'];
|
||
$dias = ['domingo','lunes','martes','miércoles','jueves','viernes','sábado'];
|
||
$ts = strtotime(date('Y-m-d'));
|
||
$hoyFmt = $dias[(int)date('w', $ts)] . ' ' . (int)date('j', $ts) . ' de ' . $meses[(int)date('n', $ts) - 1];
|
||
?>
|
||
<div class="today-wrap">
|
||
<div class="section-label">Eventos de hoy · <?= htmlspecialchars($hoyFmt) ?></div>
|
||
<div class="today-list">
|
||
<?php if (!$hasToday): ?>
|
||
<div class="today-empty">No hay eventos programados para hoy.</div>
|
||
<?php else: ?>
|
||
|
||
<?php foreach ($todayEvents['manual'] as $m):
|
||
$tipo = $m['tipo'] ?: 'evento';
|
||
$color = $TIPO_COLORS[$tipo] ?? '#27ae60';
|
||
$tipoLabel = $TIPO_LABELS[$tipo] ?? 'Evento';
|
||
$time = '';
|
||
if ($m['hora_inicio']) {
|
||
$time = fmt_hour($m['hora_inicio']);
|
||
if ($m['hora_fin']) $time .= ' – ' . fmt_hour($m['hora_fin']);
|
||
} else { $time = 'Todo el día'; }
|
||
$metaBits = [htmlspecialchars($m['creado_por_nombre'] ?: $m['creado_por'])];
|
||
if ($m['ubicacion']) $metaBits[] = htmlspecialchars($m['ubicacion']);
|
||
?>
|
||
<a class="today-card linkable" href="/calendario/">
|
||
<div class="today-bar" style="background:<?= $color ?>"></div>
|
||
<div class="today-body">
|
||
<div class="today-title"><?= htmlspecialchars($m['titulo']) ?></div>
|
||
<div class="today-meta">
|
||
<span class="today-time"><?= htmlspecialchars($time) ?></span>
|
||
<?php foreach ($metaBits as $i => $b): ?>
|
||
<span class="dot"></span><span><?= $b ?></span>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<div class="today-tags">
|
||
<span class="today-tag" style="background:<?= $color ?>"><?= htmlspecialchars($tipoLabel) ?></span>
|
||
</div>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
|
||
<?php foreach ($todayEvents['escrituras'] as $e): ?>
|
||
<a class="today-card linkable" href="/escrituras/?edit=<?= (int)$e['id'] ?>">
|
||
<div class="today-bar" style="background:#1B3A6B"></div>
|
||
<div class="today-body">
|
||
<div class="today-title"><?= htmlspecialchars($e['tramite'] ?: 'Escritura sin nombre') ?></div>
|
||
<div class="today-meta">
|
||
<span><?= htmlspecialchars($e['cliente'] ?: '—') ?></span>
|
||
<span class="dot"></span><span><?= htmlspecialchars($e['abogado'] ?: '—') ?></span>
|
||
<?php if ($e['estatus']): ?><span class="dot"></span><span><?= htmlspecialchars($e['estatus']) ?></span><?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<div class="today-tags">
|
||
<span class="today-tag" style="background:#1B3A6B">Escritura</span>
|
||
<span class="today-tag" style="background:var(--gray-400)">Solicitud</span>
|
||
</div>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
|
||
<?php foreach ($todayEvents['tramites'] as $t):
|
||
$dept = $t['departamento'];
|
||
$color = $DEPT_COLORS[$dept] ?? '#666';
|
||
$dLab = $DEPT_LABELS[$dept] ?? $dept;
|
||
?>
|
||
<a class="today-card linkable" href="/tramites/?edit=<?= urlencode($t['codigo']) ?>">
|
||
<div class="today-bar" style="background:<?= $color ?>"></div>
|
||
<div class="today-body">
|
||
<div class="today-title"><?= htmlspecialchars($t['title']) ?> <span class="today-code">· <?= htmlspecialchars($t['codigo']) ?></span></div>
|
||
<div class="today-meta">
|
||
<span><?= htmlspecialchars($t['cliente'] ?: '—') ?></span>
|
||
<span class="dot"></span><span><?= htmlspecialchars($t['abogado'] ?: '—') ?></span>
|
||
<?php if ($t['estatus']): ?><span class="dot"></span><span><?= htmlspecialchars($t['estatus']) ?></span><?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<div class="today-tags">
|
||
<span class="today-tag" style="background:<?= $color ?>"><?= htmlspecialchars($dLab) ?></span>
|
||
<span class="today-tag" style="background:var(--gray-400)"><?= htmlspecialchars($t['evento_label']) ?></span>
|
||
</div>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<footer class="dash-foot">
|
||
Donna · AALN Law — <a href="https://www.aalnlaw.com" target="_blank" rel="noopener">aalnlaw.com</a>
|
||
</footer>
|
||
<?php endif; ?>
|
||
</body>
|
||
</html>
|