import { useState, useRef, useEffect } from "react";
// ─── ICONS (inline SVG components) ────────────────────────────────────────────
const Icon = ({ d, size = 18, stroke = "currentColor", fill = "none", strokeWidth = 1.8 }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke={stroke} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round">
{Array.isArray(d) ? d.map((p, i) => <path key={i} d={p} />) : <path d={d} />}
</svg>
);
const icons = {
dashboard: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
hospital: ["M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z", "M9 22V12h6v10"],
users: ["M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2", "M23 21v-2a4 4 0 0 0-3-3.87", "M16 3.13a4 4 0 0 1 0 7.75", "M9 7a4 4 0 1 0 0 8 4 4 0 0 0 0-8z"],
calendar: ["M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2z"],
mic: ["M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3 3 3 0 0 1-3-3V5a3 3 0 0 1 3-3z", "M19 10v2a7 7 0 0 1-14 0v-2", "M12 19v3", "M8 22h8"],
upload: ["M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", "M17 8l-5-5-5 5", "M12 3v12"],
pill: "M10.5 20H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v7.5",
lab: ["M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v11l-4 8h14l-4-8V3"],
billing: ["M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"],
analytics: ["M3 3v18h18", "M18 17V9", "M13 17V5", "M8 17v-3"],
settings: ["M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16z", "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"],
plus: ["M12 5v14", "M5 12h14"],
search: ["M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z", "M21 21l-4.35-4.35"],
bell: ["M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9", "M13.73 21a2 2 0 0 1-3.46 0"],
logout: ["M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 0 2-2h4", "M16 17l5-5-5-5", "M21 12H9"],
heart: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z",
file: ["M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z", "M13 2v7h7"],
check: "M20 6L9 17l-5-5",
queue: ["M8 6h13", "M8 12h13", "M8 18h13", "M3 6h.01", "M3 12h.01", "M3 18h.01"],
freeze: ["M12 2v20", "M2 12h20", "M12 2l4 4m-8 0l4-4", "M12 22l4-4m-8 0l4 4", "M2 12l4 4m0-8l-4 4", "M22 12l-4 4m0-8l4 4"],
pharmacy: ["M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v11l-4 8h14l-4-8V3", "M12 12v4", "M10 14h4"],
donor: ["M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2", "M9 7a4 4 0 1 0 0 8 4 4 0 0 0 0-8z", "M23 21v-2a4 4 0 0 0-3-3.87"],
telemedicine: ["M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.15 13a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.06 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 21 16.92z"],
inventory: ["M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z", "M7 7h.01"],
eye: ["M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z", "M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"],
edit: ["M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7", "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"],
close: ["M18 6L6 18", "M6 6l12 12"],
chevronDown: "M6 9l6 6 6-6",
chevronRight: "M9 18l6-6-6-6",
activity: ["M22 12h-4l-3 9L9 3l-3 9H2"],
sparkle: ["M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5z"],
brain: "M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-1.07-4.56A3 3 0 0 1 4.5 9.5a3 3 0 0 1 2.5-2.96A2.5 2.5 0 0 1 9.5 2zM14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 1.07-4.56A3 3 0 0 0 19.5 9.5a3 3 0 0 0-2.5-2.96A2.5 2.5 0 0 0 14.5 2z",
audio: ["M9 18V5l12-2v13", "M6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z", "M18 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"],
translate: ["M5 8l6 6", "M4 14l6-6 2-3", "M2 5h12", "M7 2h1", "M22 22l-5-10-5 10", "M14 18h6"],
};
// ─── COLOR SYSTEM ─────────────────────────────────────────────────────────────
const styles = `
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&family=DM+Sans:wght@300;400;500;600&family=Playfair+Display:ital,wght@1,400;0,600&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--rose-deep: #8B1A4A;
--rose-mid: #C14B7A;
--rose-soft: #E8829A;
--blush: #F5C5D0;
--blush-light: #FDF0F3;
--gold: #C9954A;
--gold-light: #F0D9B5;
--gold-pale: #FBF5EC;
--cream: #FEFAF6;
--sage: #7A9E87;
--sage-light: #C8DDD0;
--charcoal: #2C1F2E;
--charcoal-mid: #4A3550;
--muted: #9E8FA8;
--border: rgba(139,26,74,0.12);
--shadow-sm: 0 2px 12px rgba(139,26,74,0.06);
--shadow-md: 0 8px 32px rgba(139,26,74,0.12);
--shadow-lg: 0 20px 60px rgba(139,26,74,0.18);
--radius: 16px;
--radius-sm: 10px;
}
body { font-family: 'DM Sans', sans-serif; background: var(--cream); color: var(--charcoal); }
.app { display: flex; height: 100vh; overflow: hidden; }
/* SIDEBAR */
.sidebar {
width: 260px; min-width: 260px;
background: linear-gradient(160deg, var(--charcoal) 0%, var(--charcoal-mid) 100%);
display: flex; flex-direction: column;
position: relative; overflow: hidden;
box-shadow: 4px 0 30px rgba(44,31,46,0.3);
}
.sidebar::before {
content: ''; position: absolute; top: -60px; right: -60px;
width: 200px; height: 200px;
background: radial-gradient(circle, rgba(193,75,122,0.2) 0%, transparent 70%);
pointer-events: none;
}
.sidebar::after {
content: ''; position: absolute; bottom: 40px; left: -40px;
width: 160px; height: 160px;
background: radial-gradient(circle, rgba(201,149,74,0.15) 0%, transparent 70%);
pointer-events: none;
}
.sidebar-logo {
padding: 28px 24px 20px;
border-bottom: 1px solid rgba(255,255,255,0.07);
}
.logo-mark {
display: flex; align-items: center; gap: 12px;
}
.logo-icon {
width: 40px; height: 40px;
background: linear-gradient(135deg, var(--rose-mid), var(--gold));
border-radius: 12px;
display: flex; align-items: center; justify-content: center;
color: white; flex-shrink: 0;
box-shadow: 0 4px 14px rgba(193,75,122,0.4);
}
.logo-text { line-height: 1.1; }
.logo-name { font-family: 'Cormorant Garamond', serif; font-size: 17px; font-weight: 600; color: white; letter-spacing: 0.3px; }
.logo-sub { font-size: 10px; color: var(--muted); letter-spacing: 1.5px; text-transform: uppercase; margin-top: 2px; }
.sidebar-role {
margin: 16px 24px 8px;
padding: 10px 14px;
background: rgba(201,149,74,0.12);
border: 1px solid rgba(201,149,74,0.2);
border-radius: var(--radius-sm);
}
.role-label { font-size: 9px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--gold); margin-bottom: 2px; }
.role-name { font-size: 13px; color: white; font-weight: 500; }
.sidebar-nav { flex: 1; overflow-y: auto; padding: 8px 0; scrollbar-width: none; }
.sidebar-nav::-webkit-scrollbar { display: none; }
.nav-section { padding: 16px 24px 6px; font-size: 9px; letter-spacing: 2px; text-transform: uppercase; color: rgba(255,255,255,0.3); }
.nav-item {
display: flex; align-items: center; gap: 12px;
padding: 10px 20px 10px 24px;
cursor: pointer; transition: all 0.2s;
position: relative; border-radius: 0;
color: rgba(255,255,255,0.55); font-size: 13.5px;
margin: 1px 0;
}
.nav-item:hover { color: white; background: rgba(255,255,255,0.05); }
.nav-item.active {
color: white;
background: linear-gradient(90deg, rgba(193,75,122,0.25) 0%, transparent 100%);
}
.nav-item.active::before {
content: ''; position: absolute; left: 0; top: 0; bottom: 0;
width: 3px; background: linear-gradient(180deg, var(--rose-mid), var(--gold));
border-radius: 0 2px 2px 0;
}
.nav-item .nav-icon { opacity: 0.7; flex-shrink: 0; }
.nav-item.active .nav-icon { opacity: 1; color: var(--rose-soft); }
.nav-badge {
margin-left: auto; background: var(--rose-deep);
color: white; font-size: 10px; padding: 2px 7px;
border-radius: 20px; font-weight: 600;
}
.sidebar-footer {
padding: 16px 24px;
border-top: 1px solid rgba(255,255,255,0.07);
}
.user-card { display: flex; align-items: center; gap: 10px; }
.user-avatar {
width: 36px; height: 36px; border-radius: 10px;
background: linear-gradient(135deg, var(--rose-mid), var(--rose-deep));
display: flex; align-items: center; justify-content: center;
color: white; font-size: 14px; font-weight: 600; flex-shrink: 0;
}
.user-info { flex: 1; min-width: 0; }
.user-name { font-size: 13px; color: white; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-email { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.logout-btn { color: var(--muted); cursor: pointer; transition: color 0.2s; }
.logout-btn:hover { color: var(--rose-soft); }
/* MAIN CONTENT */
.main { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--cream); }
.topbar {
height: 64px; display: flex; align-items: center;
padding: 0 32px; gap: 16px;
background: rgba(254,250,246,0.9);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--border);
position: sticky; top: 0; z-index: 10;
box-shadow: var(--shadow-sm);
}
.topbar-title { font-family: 'Cormorant Garamond', serif; font-size: 22px; font-weight: 600; color: var(--charcoal); flex: 1; }
.topbar-title span { color: var(--rose-mid); font-style: italic; }
.search-bar {
display: flex; align-items: center; gap: 8px;
background: white; border: 1px solid var(--border);
border-radius: 10px; padding: 8px 14px;
width: 260px; transition: all 0.2s;
}
.search-bar:focus-within { border-color: var(--rose-soft); box-shadow: 0 0 0 3px rgba(193,75,122,0.08); }
.search-bar input { border: none; outline: none; font-size: 13px; background: transparent; color: var(--charcoal); width: 100%; }
.search-bar input::placeholder { color: var(--muted); }
.topbar-actions { display: flex; align-items: center; gap: 10px; }
.icon-btn {
width: 38px; height: 38px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.2s; background: white;
border: 1px solid var(--border); color: var(--charcoal-mid);
position: relative;
}
.icon-btn:hover { background: var(--blush-light); border-color: var(--rose-soft); color: var(--rose-deep); }
.notif-dot {
position: absolute; top: 7px; right: 7px;
width: 7px; height: 7px; background: var(--rose-mid);
border-radius: 50%; border: 1.5px solid var(--cream);
}
.content { flex: 1; overflow-y: auto; padding: 28px 32px; }
/* CARDS */
.card {
background: white; border-radius: var(--radius);
border: 1px solid var(--border); box-shadow: var(--shadow-sm);
overflow: hidden;
}
.card-header {
padding: 20px 24px; border-bottom: 1px solid var(--border);
display: flex; align-items: center; gap: 12px;
}
.card-icon {
width: 38px; height: 38px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.card-icon.rose { background: var(--blush-light); color: var(--rose-mid); }
.card-icon.gold { background: var(--gold-pale); color: var(--gold); }
.card-icon.sage { background: rgba(122,158,135,0.12); color: var(--sage); }
.card-title { font-size: 15px; font-weight: 600; color: var(--charcoal); }
.card-subtitle { font-size: 12px; color: var(--muted); margin-top: 1px; }
.card-body { padding: 24px; }
/* STAT CARDS */
.stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
.stat-card {
background: white; border-radius: var(--radius);
border: 1px solid var(--border);
padding: 20px 24px;
position: relative; overflow: hidden;
transition: all 0.25s; cursor: default;
}
.stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.stat-card::before {
content: ''; position: absolute; top: 0; left: 0; right: 0;
height: 3px;
}
.stat-card.rose::before { background: linear-gradient(90deg, var(--rose-deep), var(--rose-soft)); }
.stat-card.gold::before { background: linear-gradient(90deg, var(--gold), var(--gold-light)); }
.stat-card.sage::before { background: linear-gradient(90deg, var(--sage), var(--sage-light)); }
.stat-card.purple::before { background: linear-gradient(90deg, #7B4FA6, #C084FC); }
.stat-bg-icon {
position: absolute; right: 16px; top: 50%;
transform: translateY(-50%);
opacity: 0.06; color: var(--rose-deep);
}
.stat-label { font-size: 11px; letter-spacing: 0.8px; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.stat-value { font-family: 'Cormorant Garamond', serif; font-size: 34px; font-weight: 600; color: var(--charcoal); line-height: 1; margin-bottom: 6px; }
.stat-change { font-size: 11px; display: flex; align-items: center; gap: 4px; }
.stat-change.up { color: var(--sage); }
.stat-change.down { color: var(--rose-mid); }
/* GRID LAYOUTS */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
/* TABLES */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
thead tr { border-bottom: 2px solid var(--border); }
thead th { padding: 12px 16px; text-align: left; font-size: 11px; letter-spacing: 0.8px; text-transform: uppercase; color: var(--muted); font-weight: 600; }
tbody tr { border-bottom: 1px solid rgba(139,26,74,0.05); transition: background 0.15s; }
tbody tr:hover { background: var(--blush-light); }
tbody td { padding: 13px 16px; font-size: 13.5px; color: var(--charcoal); }
tbody tr:last-child { border-bottom: none; }
/* BADGES */
.badge {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 10px; border-radius: 20px;
font-size: 11px; font-weight: 600; letter-spacing: 0.3px;
}
.badge.rose { background: var(--blush); color: var(--rose-deep); }
.badge.gold { background: var(--gold-pale); color: #8B6020; }
.badge.sage { background: rgba(122,158,135,0.15); color: #3D6B4F; }
.badge.purple { background: rgba(123,79,166,0.12); color: #5B2D8E; }
.badge.blue { background: rgba(59,130,246,0.1); color: #1D4ED8; }
.badge.red { background: rgba(239,68,68,0.1); color: #B91C1C; }
/* BUTTONS */
.btn {
display: inline-flex; align-items: center; gap: 7px;
padding: 9px 20px; border-radius: var(--radius-sm);
font-size: 13px; font-weight: 500; cursor: pointer;
transition: all 0.2s; border: none; font-family: 'DM Sans', sans-serif;
}
.btn-primary {
background: linear-gradient(135deg, var(--rose-deep), var(--rose-mid));
color: white; box-shadow: 0 4px 14px rgba(139,26,74,0.3);
}
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(139,26,74,0.4); }
.btn-secondary {
background: white; color: var(--charcoal);
border: 1px solid var(--border);
}
.btn-secondary:hover { background: var(--blush-light); border-color: var(--rose-soft); }
.btn-gold {
background: linear-gradient(135deg, var(--gold), #E0AA5A);
color: white; box-shadow: 0 4px 14px rgba(201,149,74,0.3);
}
.btn-gold:hover { transform: translateY(-1px); }
.btn-sm { padding: 6px 14px; font-size: 12px; }
.btn-icon { padding: 8px; }
/* FORM ELEMENTS */
.form-group { margin-bottom: 18px; }
.form-label { display: block; font-size: 12px; font-weight: 600; color: var(--charcoal-mid); margin-bottom: 6px; letter-spacing: 0.3px; }
.form-input {
width: 100%; padding: 10px 14px;
border: 1.5px solid var(--border); border-radius: var(--radius-sm);
font-size: 13.5px; color: var(--charcoal); background: white;
transition: all 0.2s; font-family: 'DM Sans', sans-serif; outline: none;
}
.form-input:focus { border-color: var(--rose-soft); box-shadow: 0 0 0 3px rgba(193,75,122,0.08); }
.form-select {
width: 100%; padding: 10px 14px;
border: 1.5px solid var(--border); border-radius: var(--radius-sm);
font-size: 13.5px; color: var(--charcoal); background: white;
cursor: pointer; outline: none; font-family: 'DM Sans', sans-serif;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239E8FA8' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-position: right 12px center;
padding-right: 36px;
}
.form-select:focus { border-color: var(--rose-soft); box-shadow: 0 0 0 3px rgba(193,75,122,0.08); }
.form-row { display: grid; gap: 16px; }
.form-row.cols-2 { grid-template-columns: 1fr 1fr; }
.form-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
/* MODAL */
.modal-overlay {
position: fixed; inset: 0; background: rgba(44,31,46,0.5);
backdrop-filter: blur(4px); z-index: 100;
display: flex; align-items: center; justify-content: center;
padding: 20px;
}
.modal {
background: white; border-radius: 20px;
box-shadow: var(--shadow-lg);
width: 100%; max-width: 600px;
max-height: 90vh; overflow-y: auto;
animation: modalIn 0.25s ease;
}
@keyframes modalIn { from { opacity: 0; transform: scale(0.95) translateY(10px); } to { opacity: 1; transform: scale(1) translateY(0); } }
.modal-header {
padding: 24px 28px 20px;
border-bottom: 1px solid var(--border);
display: flex; align-items: center; justify-content: space-between;
}
.modal-title { font-family: 'Cormorant Garamond', serif; font-size: 22px; font-weight: 600; color: var(--charcoal); }
.modal-body { padding: 24px 28px; }
.modal-footer { padding: 16px 28px 24px; display: flex; gap: 10px; justify-content: flex-end; }
/* SECTION HEADER */
.section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
.section-title { font-family: 'Cormorant Garamond', serif; font-size: 26px; font-weight: 600; color: var(--charcoal); }
.section-subtitle { font-size: 13px; color: var(--muted); margin-top: 2px; }
/* PATIENT CARD */
.patient-card {
background: white; border-radius: var(--radius);
border: 1px solid var(--border); padding: 20px;
transition: all 0.25s; cursor: pointer;
}
.patient-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--rose-soft); }
.patient-avatar {
width: 46px; height: 46px; border-radius: 14px;
background: linear-gradient(135deg, var(--blush), var(--rose-soft));
display: flex; align-items: center; justify-content: center;
font-size: 18px; font-weight: 600; color: var(--rose-deep);
flex-shrink: 0;
}
/* VOICE RECORDER */
.recorder-panel {
background: linear-gradient(135deg, var(--charcoal) 0%, var(--charcoal-mid) 100%);
border-radius: var(--radius); padding: 28px; color: white;
position: relative; overflow: hidden;
}
.recorder-panel::before {
content: ''; position: absolute; top: -40px; right: -40px;
width: 180px; height: 180px;
background: radial-gradient(circle, rgba(193,75,122,0.25) 0%, transparent 70%);
}
.rec-btn {
width: 80px; height: 80px; border-radius: 50%;
background: linear-gradient(135deg, var(--rose-mid), var(--rose-deep));
display: flex; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.3s;
box-shadow: 0 8px 30px rgba(193,75,122,0.5);
border: none; color: white;
margin: 0 auto;
}
.rec-btn.recording {
background: linear-gradient(135deg, #E53E3E, #C53030);
animation: pulse 1.5s ease-in-out infinite;
box-shadow: 0 8px 30px rgba(229,62,62,0.6);
}
@keyframes pulse { 0%, 100% { transform: scale(1); box-shadow: 0 8px 30px rgba(193,75,122,0.5); } 50% { transform: scale(1.05); box-shadow: 0 12px 40px rgba(193,75,122,0.7); } }
.waveform { display: flex; align-items: center; justify-content: center; gap: 3px; height: 40px; margin: 20px 0; }
.wave-bar {
width: 3px; background: rgba(255,255,255,0.3); border-radius: 2px;
animation: wave 1.2s ease-in-out infinite;
}
.wave-bar.active { background: var(--rose-soft); }
@keyframes wave {
0%, 100% { height: 8px; }
50% { height: 28px; }
}
/* PROGRESS */
.progress-bar { background: var(--blush); border-radius: 20px; height: 6px; overflow: hidden; }
.progress-fill { height: 100%; border-radius: 20px; background: linear-gradient(90deg, var(--rose-deep), var(--rose-soft)); transition: width 0.5s ease; }
/* TIMELINE */
.timeline { position: relative; padding-left: 24px; }
.timeline::before { content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: var(--border); }
.timeline-item { position: relative; margin-bottom: 20px; }
.timeline-dot {
position: absolute; left: -20px; top: 4px;
width: 10px; height: 10px; border-radius: 50%;
background: var(--rose-mid); border: 2px solid white;
box-shadow: 0 0 0 2px var(--rose-soft);
}
.timeline-content { background: var(--blush-light); border-radius: var(--radius-sm); padding: 12px 16px; }
.timeline-title { font-size: 13px; font-weight: 600; color: var(--charcoal); }
.timeline-time { font-size: 11px; color: var(--muted); margin-top: 3px; }
/* TABS */
.tabs { display: flex; gap: 4px; background: var(--blush-light); border-radius: var(--radius-sm); padding: 4px; margin-bottom: 20px; }
.tab {
flex: 1; padding: 9px 16px; border-radius: 8px;
font-size: 13px; font-weight: 500; cursor: pointer;
transition: all 0.2s; text-align: center;
color: var(--muted); border: none; background: transparent;
font-family: 'DM Sans', sans-serif;
}
.tab.active { background: white; color: var(--rose-deep); box-shadow: var(--shadow-sm); }
/* EMBRYO GRID */
.embryo-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; }
.embryo-cell {
aspect-ratio: 1; border-radius: 10px;
border: 1.5px solid var(--border);
display: flex; flex-direction: column; align-items: center; justify-content: center;
font-size: 11px; font-weight: 600; cursor: pointer;
transition: all 0.2s; background: white; gap: 4px;
}
.embryo-cell:hover { transform: scale(1.04); box-shadow: var(--shadow-sm); }
.embryo-cell.grade-a { border-color: var(--sage); background: rgba(122,158,135,0.08); color: var(--sage); }
.embryo-cell.grade-b { border-color: var(--gold); background: var(--gold-pale); color: #8B6020; }
.embryo-cell.grade-c { border-color: var(--rose-soft); background: var(--blush-light); color: var(--rose-deep); }
.embryo-cell.frozen { border-color: #7FC8E8; background: rgba(127,200,232,0.1); color: #1B6FA8; }
/* AI PANEL */
.ai-panel {
background: linear-gradient(135deg, #1A0A2E 0%, #2D1B4E 100%);
border-radius: var(--radius); padding: 24px; color: white;
position: relative; overflow: hidden;
}
.ai-panel::before {
content: ''; position: absolute; top: -30px; left: -30px;
width: 200px; height: 200px;
background: radial-gradient(circle, rgba(139,26,74,0.3) 0%, transparent 70%);
}
.ai-panel::after {
content: ''; position: absolute; bottom: -40px; right: -20px;
width: 160px; height: 160px;
background: radial-gradient(circle, rgba(201,149,74,0.2) 0%, transparent 70%);
}
.ai-header { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; position: relative; z-index: 1; }
.ai-badge { background: linear-gradient(135deg, var(--gold), #E0AA5A); color: white; font-size: 10px; padding: 3px 10px; border-radius: 20px; font-weight: 700; letter-spacing: 1px; }
.ai-suggestion { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1); border-radius: var(--radius-sm); padding: 14px 16px; margin-bottom: 10px; position: relative; z-index: 1; }
.ai-suggestion-title { font-size: 13px; font-weight: 600; color: var(--gold-light); margin-bottom: 4px; }
.ai-suggestion-text { font-size: 12px; color: rgba(255,255,255,0.7); line-height: 1.6; }
/* TANKS */
.tank-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.tank-cell {
border-radius: 10px; padding: 14px; text-align: center;
border: 1.5px solid var(--border); background: white; cursor: pointer;
transition: all 0.2s;
}
.tank-cell:hover { border-color: var(--rose-soft); background: var(--blush-light); }
.tank-cell.occupied { background: rgba(127,200,232,0.1); border-color: #7FC8E8; }
.tank-cell.full { background: var(--blush-light); border-color: var(--rose-soft); }
.tank-label { font-size: 11px; font-weight: 700; letter-spacing: 1px; color: var(--charcoal-mid); }
.tank-count { font-family: 'Cormorant Garamond', serif; font-size: 22px; font-weight: 600; color: var(--charcoal); margin-top: 4px; }
.tank-sub { font-size: 10px; color: var(--muted); }
/* HORIZONTAL SCROLL PILLS */
.pill-row { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.pill-row::-webkit-scrollbar { display: none; }
.pill {
padding: 7px 18px; border-radius: 20px; white-space: nowrap;
font-size: 12px; font-weight: 500; cursor: pointer;
border: 1.5px solid var(--border); background: white; color: var(--charcoal-mid);
transition: all 0.2s; flex-shrink: 0;
}
.pill.active { background: var(--rose-deep); border-color: var(--rose-deep); color: white; }
.pill:hover:not(.active) { border-color: var(--rose-soft); color: var(--rose-deep); }
/* UPLOAD ZONE */
.upload-zone {
border: 2px dashed var(--border); border-radius: var(--radius);
padding: 32px; text-align: center; cursor: pointer;
transition: all 0.2s; background: var(--blush-light);
}
.upload-zone:hover { border-color: var(--rose-mid); background: white; }
.upload-icon { color: var(--rose-soft); margin-bottom: 10px; }
.upload-text { font-size: 14px; color: var(--charcoal-mid); }
.upload-sub { font-size: 12px; color: var(--muted); margin-top: 4px; }
/* CONSENT FORM */
.consent-item {
display: flex; align-items: flex-start; gap: 12px;
padding: 14px 16px; border: 1px solid var(--border);
border-radius: var(--radius-sm); margin-bottom: 10px;
background: white; transition: all 0.2s;
}
.consent-item:hover { border-color: var(--rose-soft); }
.consent-check {
width: 20px; height: 20px; border-radius: 6px;
border: 2px solid var(--border); flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.2s; margin-top: 1px;
}
.consent-check.checked { background: var(--rose-mid); border-color: var(--rose-mid); color: white; }
.consent-text { font-size: 13px; color: var(--charcoal); line-height: 1.5; }
.consent-sub { font-size: 11px; color: var(--muted); margin-top: 3px; }
/* NOTIFICATION */
.notif-item {
display: flex; align-items: flex-start; gap: 10px;
padding: 12px 16px; border-bottom: 1px solid var(--border);
transition: background 0.15s; cursor: pointer;
}
.notif-item:hover { background: var(--blush-light); }
.notif-icon { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.notif-content { flex: 1; }
.notif-title { font-size: 13px; font-weight: 600; color: var(--charcoal); }
.notif-desc { font-size: 12px; color: var(--muted); margin-top: 2px; }
.notif-time { font-size: 11px; color: var(--muted); margin-top: 4px; }
/* QUEUE */
.queue-item {
display: flex; align-items: center; gap: 12px;
padding: 12px 16px; border-bottom: 1px solid var(--border);
transition: background 0.15s;
}
.queue-item:hover { background: var(--blush-light); }
.queue-num {
width: 30px; height: 30px; border-radius: 8px;
display: flex; align-items: center; justify-content: center;
font-size: 13px; font-weight: 700; flex-shrink: 0;
background: var(--blush); color: var(--rose-deep);
}
/* SCROLLBAR */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--blush); border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: var(--rose-soft); }
/* DIVIDER */
.divider { height: 1px; background: var(--border); margin: 20px 0; }
/* INFO BOX */
.info-box {
padding: 14px 16px; border-radius: var(--radius-sm);
display: flex; align-items: flex-start; gap: 10px;
}
.info-box.rose { background: var(--blush-light); border-left: 3px solid var(--rose-mid); }
.info-box.gold { background: var(--gold-pale); border-left: 3px solid var(--gold); }
.info-box.sage { background: rgba(122,158,135,0.1); border-left: 3px solid var(--sage); }
.info-box.purple { background: rgba(123,79,166,0.08); border-left: 3px solid #7B4FA6; }
.info-box-title { font-size: 13px; font-weight: 600; color: var(--charcoal); }
.info-box-text { font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.5; }
/* DRUG CARD */
.drug-card {
background: white; border: 1px solid var(--border);
border-radius: var(--radius-sm); padding: 14px 16px;
display: flex; align-items: center; gap: 12px;
transition: all 0.2s;
}
.drug-card:hover { border-color: var(--rose-soft); background: var(--blush-light); }
.drug-icon {
width: 38px; height: 38px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.drug-name { font-size: 13.5px; font-weight: 600; color: var(--charcoal); }
.drug-detail { font-size: 12px; color: var(--muted); margin-top: 2px; }
.drug-stock { margin-left: auto; text-align: right; }
.drug-qty { font-family: 'Cormorant Garamond', serif; font-size: 20px; font-weight: 600; color: var(--charcoal); }
.drug-unit { font-size: 11px; color: var(--muted); }
/* FOLLICLE CHART */
.follicle-table td { font-size: 12px; }
.follicle-table td:first-child { font-weight: 600; color: var(--charcoal); }
.follicle-dot {
display: inline-flex; align-items: center; justify-content: center;
width: 28px; height: 28px; border-radius: 50%;
font-size: 10px; font-weight: 700;
}
.follicle-dot.small { background: rgba(122,158,135,0.15); color: var(--sage); }
.follicle-dot.medium { background: var(--gold-pale); color: #8B6020; }
.follicle-dot.large { background: var(--blush); color: var(--rose-deep); }
@media (max-width: 1100px) {
.stats-grid { grid-template-columns: repeat(2, 1fr); }
.sidebar { width: 220px; min-width: 220px; }
}
`;
// ─── DATA ──────────────────────────────────────────────────────────────────────
const hospitals = [
{ id: 1, name: "Bloom IVF Centre", city: "Mumbai", doctors: 12, patients: 384, status: "active", cycles: 47 },
{ id: 2, name: "Nova Fertility Clinic", city: "Bangalore", doctors: 8, patients: 216, status: "active", cycles: 31 },
{ id: 3, name: "Ankur ART Centre", city: "Chennai", doctors: 6, patients: 142, status: "active", cycles: 19 },
{ id: 4, name: "Parivar Fertility Hub", city: "Delhi", doctors: 15, patients: 502, status: "pending", cycles: 0 },
];
const patients = [
{ id: "PT-F001", name: "Priya Sharma", age: 32, partner: "Rohan Sharma", type: "IVF", stage: "Stimulation", doctor: "Dr. Meera Iyer", bmi: 22.4, cycle: 2, amh: "1.8 ng/mL" },
{ id: "PT-F002", name: "Ananya Pillai", age: 29, partner: "Kiran Pillai", type: "IUI", stage: "Monitoring", doctor: "Dr. Sonal Gupta", bmi: 24.1, cycle: 1, amh: "3.2 ng/mL" },
{ id: "PT-F003", name: "Ritu Verma", age: 36, partner: "Anil Verma", type: "FET", stage: "Preparation", doctor: "Dr. Meera Iyer", bmi: 26.8, cycle: 3, amh: "0.9 ng/mL" },
{ id: "PT-F004", name: "Kavitha Nair", age: 34, partner: "Suresh Nair", type: "ICSI", stage: "Egg Retrieval", doctor: "Dr. Priya Reddy", bmi: 23.7, cycle: 1, amh: "2.1 ng/mL" },
];
const queueItems = [
{ num: 1, name: "Ananya Pillai", type: "Follicle Scan", status: "In Room", time: "09:15 AM" },
{ num: 2, name: "Priya Sharma", type: "Consultation", status: "Vitals", time: "09:30 AM" },
{ num: 3, name: "Deepa Murthy", type: "Blood Draw", status: "Waiting", time: "09:45 AM" },
{ num: 4, name: "Ritu Verma", type: "FET Review", status: "Waiting", time: "10:00 AM" },
{ num: 5, name: "Lakshmi Rao", type: "IUI Procedure", status: "Scheduled", time: "10:30 AM" },
];
const embryos = [
{ id: "E01", day: 5, grade: "A", quality: "4AA", status: "frozen" },
{ id: "E02", day: 5, grade: "A", quality: "4AB", status: "frozen" },
{ id: "E03", day: 3, grade: "B", quality: "8C", status: "frozen" },
{ id: "E04", day: 5, grade: "A", quality: "3BB", status: "frozen" },
{ id: "E05", day: 3, grade: "B", quality: "6C", status: "grade-b" },
{ id: "E06", day: 2, grade: "C", quality: "4C", status: "grade-c" },
{ id: "E07", day: 5, grade: "A", quality: "4AA", status: "grade-a" },
{ id: "E08", day: 5, grade: "B", quality: "3AB", status: "frozen" },
{ id: "E09", day: 3, grade: "C", quality: "5C", status: "grade-c" },
{ id: "E10", day: 5, grade: "A", quality: "4BA", status: "grade-a" },
{ id: "E11", day: 1, grade: "-", quality: "Arrested", status: "grade-c" },
{ id: "E12", day: 5, grade: "B", quality: "3BB", status: "frozen" },
];
const drugs = [
{ name: "Gonal-F 450IU", category: "Stimulation", stock: 48, unit: "vials", cold: true, expiry: "2025-06", alert: false },
{ name: "Cetrotide 0.25mg", category: "GnRH Antagonist", stock: 22, unit: "kits", cold: false, expiry: "2025-09", alert: false },
{ name: "Pregnyl 5000IU", category: "Trigger", stock: 5, unit: "amps", cold: true, expiry: "2025-04", alert: true },
{ name: "Crinone 8% Gel", category: "Progesterone", stock: 30, unit: "tubes", cold: false, expiry: "2025-11", alert: false },
{ name: "Menopur 150IU", category: "Stimulation", stock: 8, unit: "vials", cold: true, expiry: "2025-05", alert: true },
{ name: "Lupron 5mg", category: "GnRH Agonist", stock: 15, unit: "kits", cold: false, expiry: "2025-08", alert: false },
];
const consentForms = [
{ id: 1, title: "IVF Treatment Consent", desc: "Understanding of the IVF procedure, risks, and alternatives", signed: true },
{ id: 2, title: "ICSI Procedure Consent", desc: "Intracytoplasmic Sperm Injection procedure authorization", signed: true },
{ id: 3, title: "Embryo Cryopreservation", desc: "Consent for embryo freezing, storage duration, and disposition", signed: false },
{ id: 4, title: "Genetic Testing (PGT-A)", desc: "Authorization for preimplantation genetic testing", signed: false },
{ id: 5, title: "Third Party Reproduction", desc: "Consent for use of donor gametes if required", signed: false },
];
// ─── COMPONENT: DASHBOARD ─────────────────────────────────────────────────────
function Dashboard() {
return (
<div>
<div className="section-header">
<div>
<div className="section-title">Good Morning, <span style={{ color: "var(--rose-mid)", fontStyle: "italic" }}>Dr. Anjali</span> ✦</div>
<div className="section-subtitle">Tuesday, 10 March 2026 · Bloom IVF Centre, Mumbai</div>
</div>
<div style={{ display: "flex", gap: 10 }}>
<button className="btn btn-secondary btn-sm"><Icon d={icons.calendar} size={14} /> Schedule</button>
<button className="btn btn-primary btn-sm"><Icon d={icons.plus} size={14} /> New Patient</button>
</div>
</div>
<div className="stats-grid">
{[
{ label: "Active Cycles", value: "47", change: "+8 this month", dir: "up", type: "rose", icon: icons.heart },
{ label: "Egg Retrievals Today", value: "3", change: "2 scheduled", dir: "up", type: "gold", icon: icons.lab },
{ label: "Embryos in Storage", value: "284", change: "12 new this week", dir: "up", type: "sage", icon: icons.freeze },
{ label: "Success Rate (IVF)", value: "64%", change: "+4% vs last quarter", dir: "up", type: "purple", icon: icons.analytics },
].map((s, i) => (
<div key={i} className={`stat-card ${s.type}`}>
<div className="stat-bg-icon"><Icon d={s.icon} size={56} /></div>
<div className="stat-label">{s.label}</div>
<div className="stat-value">{s.value}</div>
<div className={`stat-change ${s.dir}`}>↑ {s.change}</div>
</div>
))}
</div>
<div className="grid-2" style={{ gap: 20, marginBottom: 20 }}>
{/* Today's Queue */}
<div className="card">
<div className="card-header">
<div className="card-icon rose"><Icon d={icons.queue} size={18} /></div>
<div>
<div className="card-title">Live Queue</div>
<div className="card-subtitle">Reception · Today</div>
</div>
<span className="badge rose" style={{ marginLeft: "auto" }}>5 Patients</span>
</div>
<div>
{queueItems.map((q) => (
<div key={q.num} className="queue-item">
<div className="queue-num">{q.num}</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--charcoal)" }}>{q.name}</div>
<div style={{ fontSize: 12, color: "var(--muted)" }}>{q.type} · {q.time}</div>
</div>
<span className={`badge ${q.status === "In Room" ? "sage" : q.status === "Vitals" ? "gold" : "rose"}`}>{q.status}</span>
</div>
))}
</div>
</div>
{/* Embryo Storage Snapshot */}
<div className="card">
<div className="card-header">
<div className="card-icon" style={{ background: "rgba(127,200,232,0.12)", color: "#1B6FA8" }}><Icon d={icons.freeze} size={18} /></div>
<div>
<div className="card-title">Cryostorage Map</div>
<div className="card-subtitle">Tank 1 — 48 straws</div>
</div>
<button className="btn btn-secondary btn-sm" style={{ marginLeft: "auto" }}>View All</button>
</div>
<div className="card-body">
<div className="tank-grid">
{Array.from({ length: 16 }, (_, i) => ({
label: `C${i + 1}`,
count: Math.floor(Math.random() * 6),
full: i < 10,
occupied: i < 14,
})).map((t, i) => (
<div key={i} className={`tank-cell ${t.full ? "full" : t.occupied ? "occupied" : ""}`}>
<div className="tank-label">{t.label}</div>
<div className="tank-count">{t.count}</div>
<div className="tank-sub">straws</div>
</div>
))}
</div>
</div>
</div>
</div>
<div className="grid-2" style={{ gap: 20 }}>
{/* Recent Patients */}
<div className="card">
<div className="card-header">
<div className="card-icon rose"><Icon d={icons.users} size={18} /></div>
<div>
<div className="card-title">Active Patients</div>
<div className="card-subtitle">Current cycle patients</div>
</div>
</div>
<div className="card-body" style={{ padding: "16px 0 0" }}>
{patients.map((p) => (
<div key={p.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 24px", borderBottom: "1px solid var(--border)", cursor: "pointer", transition: "background 0.15s" }}
onMouseEnter={e => e.currentTarget.style.background = "var(--blush-light)"}
onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
<div className="patient-avatar">{p.name[0]}{p.partner.split(" ")[0][0]}</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 13.5, fontWeight: 600 }}>{p.name}</div>
<div style={{ fontSize: 12, color: "var(--muted)" }}>{p.id} · {p.doctor}</div>
</div>
<div style={{ textAlign: "right" }}>
<span className={`badge ${p.type === "IVF" ? "rose" : p.type === "IUI" ? "sage" : p.type === "FET" ? "gold" : "purple"}`}>{p.type}</span>
<div style={{ fontSize: 11, color: "var(--muted)", marginTop: 4 }}>{p.stage}</div>
</div>
</div>
))}
</div>
</div>
{/* AI Highlights + Alerts */}
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div className="ai-panel">
<div className="ai-header">
<div style={{ flex: 1 }}>
<span className="ai-badge">✦ AI INSIGHTS</span>
<div style={{ fontSize: 15, fontWeight: 600, marginTop: 8, color: "white" }}>Today's Recommendations</div>
</div>
<Icon d={icons.brain} size={28} stroke="rgba(255,255,255,0.2)" />
</div>
{[
{ title: "Trigger Decision — Priya Sharma", text: "E2: 3200 pg/mL, Lead follicle 19mm. Recommend HCG trigger tonight at 10:30 PM for OPU in 36h." },
{ title: "Expiry Alert — Pregnyl 5000IU", text: "5 ampoules expiring April 2025. Reorder immediately. Consider Ovitrelle as alternative." },
].map((a, i) => (
<div key={i} className="ai-suggestion">
<div className="ai-suggestion-title">{a.title}</div>
<div className="ai-suggestion-text">{a.text}</div>
</div>
))}
</div>
<div className="card">
<div className="card-header">
<div className="card-icon gold"><Icon d={icons.bell} size={18} /></div>
<div><div className="card-title">Alerts</div></div>
<span className="badge red" style={{ marginLeft: "auto" }}>3 Urgent</span>
</div>
{[
{ icon: icons.pill, color: "red", title: "Low Stock: Menopur 150IU", desc: "Only 8 vials remaining", time: "Now" },
{ icon: icons.calendar, color: "gold", title: "Consent Pending — Ritu Verma", desc: "Cryopreservation form unsigned", time: "1h ago" },
{ icon: icons.activity, color: "sage", title: "Cycle Day 2 — Kavitha Nair", desc: "Ready for stimulation start", time: "Today" },
].map((n, i) => (
<div key={i} className="notif-item">
<div className="notif-icon" style={{ background: n.color === "red" ? "rgba(239,68,68,0.1)" : n.color === "gold" ? "var(--gold-pale)" : "rgba(122,158,135,0.1)", color: n.color === "red" ? "#B91C1C" : n.color === "gold" ? "var(--gold)" : "var(--sage)" }}>
<Icon d={n.icon} size={16} />
</div>
<div className="notif-content">
<div className="notif-title">{n.title}</div>
<div className="notif-desc">{n.desc}</div>
</div>
<div className="notif-time">{n.time}</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}
// ─── COMPONENT: HOSPITALS ─────────────────────────────────────────────────────
function Hospitals({ onShowModal }) {
return (
<div>
<div className="section-header">
<div>
<div className="section-title">Hospital Network</div>
<div className="section-subtitle">Manage all partner clinics and their access</div>
</div>
<button className="btn btn-primary" onClick={onShowModal}><Icon d={icons.plus} size={15} /> Add Hospital</button>
</div>
<div className="stats-grid" style={{ gridTemplateColumns: "repeat(3,1fr)", marginBottom: 24 }}>
{[
{ label: "Total Hospitals", value: "4", type: "rose" },
{ label: "Active Hospitals", value: "3", type: "sage" },
{ label: "Pending Approval", value: "1", type: "gold" },
].map((s, i) => (
<div key={i} className={`stat-card ${s.type}`}>
<div className="stat-label">{s.label}</div>
<div className="stat-value">{s.value}</div>
</div>
))}
</div>
<div className="card">
<div className="table-wrap">
<table>
<thead>
<tr>
<th>Hospital</th>
<th>City</th>
<th>Doctors</th>
<th>Active Patients</th>
<th>Active Cycles</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{hospitals.map((h) => (
<tr key={h.id}>
<td><div style={{ fontWeight: 600 }}>{h.name}</div><div style={{ fontSize: 11, color: "var(--muted)" }}>ID: HSP-{String(h.id).padStart(3, "0")}</div></td>
<td>{h.city}</td>
<td><span className="badge blue">{h.doctors} Doctors</span></td>
<td>{h.patients}</td>
<td>{h.cycles}</td>
<td><span className={`badge ${h.status === "active" ? "sage" : "gold"}`}>{h.status === "active" ? "Active" : "Pending"}</span></td>
<td>
<div style={{ display: "flex", gap: 6 }}>
<button className="btn btn-secondary btn-sm"><Icon d={icons.eye} size={13} /> View</button>
<button className="btn btn-gold btn-sm"><Icon d={icons.users} size={13} /> Access</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
// ─── COMPONENT: PATIENTS ──────────────────────────────────────────────────────
function Patients({ onShowModal }) {
const [activeTab, setActiveTab] = useState("all");
const [selectedPatient, setSelectedPatient] = useState(null);
if (selectedPatient) {
return <PatientDetail patient={selectedPatient} onBack={() => setSelectedPatient(null)} />;
}
return (
<div>
<div className="section-header">
<div>
<div className="section-title">Patient Management</div>
<div className="section-subtitle">Electronic Medical Records · Couple-Centric View</div>
</div>
<button className="btn btn-primary" onClick={onShowModal}><Icon d={icons.plus} size={15} /> Register Patient</button>
</div>
<div className="tabs">
{["all", "ivf", "iui", "fet", "icsi"].map(t => (
<button key={t} className={`tab ${activeTab === t ? "active" : ""}`} onClick={() => setActiveTab(t)}>
{t.toUpperCase()}
</button>
))}
</div>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
{patients.filter(p => activeTab === "all" || p.type.toLowerCase() === activeTab).map((p) => (
<div key={p.id} className="patient-card" onClick={() => setSelectedPatient(p)}>
<div style={{ display: "flex", alignItems: "flex-start", gap: 14, marginBottom: 14 }}>
<div className="patient-avatar" style={{ width: 52, height: 52, fontSize: 20 }}>{p.name[0]}{p.partner.split(" ")[0][0]}</div>
<div style={{ flex: 1 }}>
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<span style={{ fontSize: 15, fontWeight: 600 }}>{p.name}</span>
<span className={`badge ${p.type === "IVF" ? "rose" : p.type === "IUI" ? "sage" : p.type === "FET" ? "gold" : "purple"}`}>{p.type}</span>
</div>
<div style={{ fontSize: 12, color: "var(--muted)", marginTop: 2 }}>Partner: {p.partner} · {p.id}</div>
<div style={{ fontSize: 12, color: "var(--muted)" }}>{p.doctor}</div>
</div>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 10 }}>
{[
{ label: "Age", value: `${p.age} yrs` },
{ label: "Cycle #", value: `#${p.cycle}` },
{ label: "BMI", value: p.bmi },
{ label: "AMH", value: p.amh },
{ label: "Stage", value: p.stage, full: true },
].map((d, i) => (
<div key={i} style={{ background: "var(--blush-light)", borderRadius: 8, padding: "8px 10px", gridColumn: d.full ? "span 3" : undefined }}>
<div style={{ fontSize: 10, color: "var(--muted)", letterSpacing: "0.5px", textTransform: "uppercase" }}>{d.label}</div>
<div style={{ fontSize: 13, fontWeight: 600, color: "var(--charcoal)", marginTop: 2 }}>{d.value}</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}
// ─── COMPONENT: PATIENT DETAIL (EMR) ─────────────────────────────────────────
function PatientDetail({ patient, onBack }) {
const [activeTab, setActiveTab] = useState("overview");
const tabs = ["overview", "art cycle", "lab", "documents", "voice & ai"];
return (
<div>
<div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 20 }}>
<button className="btn btn-secondary btn-sm" onClick={onBack}>← Back</button>
<div style={{ flex: 1 }}>
<div className="section-title">{patient.name} <span style={{ color: "var(--muted)", fontSize: 16 }}>& {patient.partner}</span></div>
<div className="section-subtitle">{patient.id} · {patient.type} Cycle #{patient.cycle} · {patient.stage}</div>
</div>
<span className={`badge ${patient.type === "IVF" ? "rose" : patient.type === "IUI" ? "sage" : "gold"}`} style={{ fontSize: 13, padding: "5px 14px" }}>{patient.type}</span>
</div>
<div className="tabs">
{tabs.map(t => (
<button key={t} className={`tab ${activeTab === t ? "active" : ""}`} onClick={() => setActiveTab(t)}>{t.charAt(0).toUpperCase() + t.slice(1)}</button>
))}
</div>
{activeTab === "overview" && <PatientOverview patient={patient} />}
{activeTab === "art cycle" && <ARTCycle patient={patient} />}
{activeTab === "lab" && <LabModule patient={patient} />}
{activeTab === "documents" && <DocumentsModule patient={patient} />}
{activeTab === "voice & ai" && <VoiceAIModule patient={patient} />}
</div>
);
}
function PatientOverview({ patient }) {
const [consents, setConsents] = useState(consentForms.map(c => ({ ...c })));
return (
<div className="grid-2">
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.activity} size={18} /></div><div><div className="card-title">Vitals & Health</div></div></div>
<div className="card-body">
<div className="form-row cols-2">
{[
{ label: "Age", value: `${patient.age} years` },
{ label: "BMI", value: patient.bmi },
{ label: "Blood Group", value: "B+" },
{ label: "BP", value: "118/76 mmHg" },
{ label: "Height", value: "162 cm" },
{ label: "Weight", value: "60 kg" },
].map((v, i) => (
<div key={i} style={{ background: "var(--blush-light)", borderRadius: 8, padding: "10px 12px" }}>
<div style={{ fontSize: 10, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.5px" }}>{v.label}</div>
<div style={{ fontSize: 14, fontWeight: 600, color: "var(--charcoal)", marginTop: 3 }}>{v.value}</div>
</div>
))}
</div>
<div className="divider" />
<div style={{ fontWeight: 600, fontSize: 13, marginBottom: 10 }}>Viral Markers</div>
{[
{ name: "HIV I & II", result: "Non-Reactive", expiry: "2026-01-10", ok: true },
{ name: "Hepatitis B (HBsAg)", result: "Non-Reactive", expiry: "2026-01-10", ok: true },
{ name: "Hepatitis C", result: "Non-Reactive", expiry: "2026-01-10", ok: true },
{ name: "Syphilis (VDRL)", result: "Non-Reactive", expiry: "2026-01-10", ok: true },
].map((v, i) => (
<div key={i} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "8px 0", borderBottom: "1px solid var(--border)" }}>
<span style={{ fontSize: 13 }}>{v.name}</span>
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
<span className="badge sage">{v.result}</span>
<span style={{ fontSize: 11, color: "var(--muted)" }}>Exp: {v.expiry}</span>
</div>
</div>
))}
</div>
</div>
<div className="card">
<div className="card-header"><div className="card-icon gold"><Icon d={icons.file} size={18} /></div><div><div className="card-title">Lifestyle</div></div></div>
<div className="card-body">
{[
{ label: "Smoking", value: "Non-smoker", good: true },
{ label: "Alcohol", value: "Occasional", good: true },
{ label: "Stress Level", value: "Moderate", good: false },
{ label: "Exercise", value: "3x/week", good: true },
].map((l, i) => (
<div key={i} style={{ display: "flex", justifyContent: "space-between", padding: "9px 0", borderBottom: "1px solid var(--border)" }}>
<span style={{ fontSize: 13, color: "var(--muted)" }}>{l.label}</span>
<span style={{ fontSize: 13, fontWeight: 600, color: l.good ? "var(--sage)" : "var(--gold)" }}>{l.value}</span>
</div>
))}
</div>
</div>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.check} size={18} /></div><div><div className="card-title">Digital Consent Forms</div><div className="card-subtitle">IVF/ART mandatory consents</div></div></div>
<div className="card-body">
{consents.map((c) => (
<div key={c.id} className="consent-item">
<div className={`consent-check ${c.signed ? "checked" : ""}`} onClick={() => setConsents(prev => prev.map(x => x.id === c.id ? { ...x, signed: !x.signed } : x))}>
{c.signed && <Icon d={icons.check} size={12} />}
</div>
<div>
<div className="consent-text">{c.title}</div>
<div className="consent-sub">{c.desc}</div>
</div>
<span className={`badge ${c.signed ? "sage" : "gold"}`} style={{ marginLeft: "auto", whiteSpace: "nowrap" }}>{c.signed ? "Signed" : "Pending"}</span>
</div>
))}
</div>
</div>
<div className="card">
<div className="card-header"><div className="card-icon gold"><Icon d={icons.calendar} size={18} /></div><div><div className="card-title">Appointment Timeline</div></div></div>
<div className="card-body">
<div className="timeline">
{[
{ title: "Day 2 Baseline Scan", time: "Feb 28, 2026 · 9:00 AM", note: "AFC: 12, AFC: 14" },
{ title: "Stimulation Started (Gonal-F 300IU)", time: "Mar 1, 2026 · 9:30 AM", note: "Cetrotide from Day 5" },
{ title: "Follicular Monitoring Scan", time: "Mar 5, 2026", note: "Lead: 14mm R, 13mm L" },
{ title: "HCG Trigger Injection", time: "Mar 8, 2026 · 10:30 PM", note: "Pregnyl 10000IU" },
{ title: "Egg Retrieval (OPU) — Upcoming", time: "Mar 10, 2026 · 8:00 AM", note: "Scheduled" },
].map((t, i) => (
<div key={i} className="timeline-item">
<div className="timeline-dot" style={i === 4 ? { background: "var(--gold)" } : {}} />
<div className="timeline-content">
<div className="timeline-title">{t.title}</div>
<div className="timeline-time">{t.time}</div>
<div style={{ fontSize: 11, color: "var(--charcoal-mid)", marginTop: 3 }}>{t.note}</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
}
// ─── COMPONENT: ART CYCLE ─────────────────────────────────────────────────────
function ARTCycle() {
const days = ["D2", "D3", "D4", "D5", "D6", "D7", "D8"];
const follicleData = {
"Right": [[8, 9, 0, 0], [10, 11, 8, 0], [12, 12, 10, 0], [13, 13, 12, 0], [15, 14, 13, 0], [17, 16, 14, 0], [19, 18, 16, 14]],
"Left": [[7, 8, 0, 0], [9, 9, 7, 0], [11, 10, 9, 0], [12, 12, 10, 0], [14, 13, 11, 0], [16, 15, 12, 0], [18, 17, 15, 12]],
};
const hormones = [
{ day: "D2", e2: 45, lh: 5.2, p4: 0.4, fsh: 8.1 },
{ day: "D4", e2: 180, lh: 4.8, p4: 0.5, fsh: 7.2 },
{ day: "D6", e2: 620, lh: 3.9, p4: 0.6, fsh: 6.8 },
{ day: "D8", e2: 3240, lh: 4.1, p4: 0.8, fsh: 5.5 },
];
const medications = [
{ name: "Gonal-F 300IU", type: "Stimulation", color: "rose", days: [1, 2, 3, 4, 5, 6, 7] },
{ name: "Cetrotide 0.25mg", type: "Antagonist", color: "purple", days: [4, 5, 6, 7] },
{ name: "Crinone 8%", type: "Support", color: "sage", days: [7] },
];
return (
<div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
<div className="grid-2">
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.activity} size={18} /></div><div><div className="card-title">Follicle Growth Chart</div><div className="card-subtitle">Stimulation Day 2–8</div></div></div>
<div className="card-body">
{["Right", "Left"].map(ovary => (
<div key={ovary} style={{ marginBottom: 16 }}>
<div style={{ fontSize: 12, fontWeight: 700, color: "var(--rose-mid)", letterSpacing: 1, textTransform: "uppercase", marginBottom: 10 }}>{ovary} Ovary</div>
<div style={{ display: "grid", gridTemplateColumns: `60px repeat(${days.length}, 1fr)`, gap: 4 }}>
<div style={{ fontSize: 10, color: "var(--muted)", padding: "4px 0" }}>Follicle</div>
{days.map(d => <div key={d} style={{ fontSize: 10, color: "var(--muted)", textAlign: "center", padding: "4px 0", fontWeight: 600 }}>{d}</div>)}
{[0, 1, 2, 3].map(fi => (
<>
<div key={`lbl${fi}`} style={{ fontSize: 11, color: "var(--muted)", padding: "4px 0" }}>F{fi + 1}</div>
{follicleData[ovary].map((dayData, di) => {
const v = dayData[fi];
const cls = v === 0 ? "" : v < 12 ? "small" : v < 16 ? "medium" : "large";
return <div key={di} style={{ display: "flex", justifyContent: "center" }}>
{v > 0 ? <span className={`follicle-dot ${cls}`}>{v}</span> : <span style={{ fontSize: 11, color: "var(--border)" }}>—</span>}
</div>;
})}
</>
))}
</div>
</div>
))}
</div>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div className="card">
<div className="card-header"><div className="card-icon gold"><Icon d={icons.analytics} size={18} /></div><div><div className="card-title">Hormone Levels</div></div></div>
<div className="card-body">
<div className="table-wrap">
<table>
<thead><tr><th>Day</th><th>E2 (pg/mL)</th><th>LH (mIU/mL)</th><th>P4 (ng/mL)</th><th>FSH</th></tr></thead>
<tbody>
{hormones.map(h => (
<tr key={h.day}>
<td><strong>{h.day}</strong></td>
<td style={{ color: h.e2 > 2000 ? "var(--rose-mid)" : "inherit", fontWeight: h.e2 > 2000 ? 600 : 400 }}>{h.e2}</td>
<td>{h.lh}</td>
<td>{h.p4}</td>
<td>{h.fsh}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="info-box rose" style={{ marginTop: 12 }}>
<Icon d={icons.sparkle} size={16} stroke="var(--rose-mid)" />
<div><div className="info-box-title">AI Analysis</div><div className="info-box-text">E2 at 3240 pg/mL with lead follicle 19mm — ideal trigger criteria met. Proceed with HCG 10000IU trigger tonight.</div></div>
</div>
</div>
</div>
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.calendar} size={18} /></div><div><div className="card-title">Medication Calendar</div></div></div>
<div className="card-body">
{medications.map((med, i) => (
<div key={i} style={{ marginBottom: 12 }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
<span style={{ fontSize: 13, fontWeight: 600 }}>{med.name}</span>
<span className={`badge ${med.color}`}>{med.type}</span>
</div>
<div style={{ display: "flex", gap: 4 }}>
{days.map((d, di) => (
<div key={di} style={{
flex: 1, height: 28, borderRadius: 6,
background: med.days.includes(di + 1) ? `var(--${med.color === "rose" ? "rose-mid" : med.color === "purple" ? "charcoal-mid" : "sage"})` : "var(--border)",
display: "flex", alignItems: "center", justifyContent: "center",
fontSize: 10, color: med.days.includes(di + 1) ? "white" : "var(--muted)", fontWeight: 600
}}>{d}</div>
))}
</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
}
// ─── COMPONENT: LAB ───────────────────────────────────────────────────────────
function LabModule() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
<div className="grid-2">
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.lab} size={18} /></div><div><div className="card-title">Embryology Lab</div><div className="card-subtitle">Embryo Grading Dashboard</div></div></div>
<div className="card-body">
<div className="embryo-grid">
{embryos.map((e) => (
<div key={e.id} className={`embryo-cell ${e.status}`}>
<div style={{ fontSize: 9, opacity: 0.7 }}>{e.id}</div>
<div style={{ fontSize: 14, fontWeight: 700 }}>{e.quality}</div>
<div style={{ fontSize: 9 }}>D{e.day}</div>
</div>
))}
</div>
<div style={{ display: "flex", gap: 8, marginTop: 14, flexWrap: "wrap" }}>
{[
{ label: "Grade A (Blastocyst)", color: "grade-a" },
{ label: "Grade B", color: "grade-b" },
{ label: "Grade C", color: "grade-c" },
{ label: "Frozen", color: "frozen" },
].map((l, i) => (
<div key={i} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 11, color: "var(--muted)" }}>
<div className={`embryo-cell ${l.color}`} style={{ width: 14, height: 14, borderRadius: 4, padding: 0, minHeight: "unset" }} />
{l.label}
</div>
))}
</div>
</div>
</div>
<div className="card">
<div className="card-header"><div className="card-icon gold"><Icon d={icons.lab} size={18} /></div><div><div className="card-title">Andrology Report</div><div className="card-subtitle">Semen Analysis</div></div></div>
<div className="card-body">
{[
{ param: "Volume", value: "3.2 mL", ref: "≥1.4 mL", ok: true },
{ param: "Concentration", value: "18 M/mL", ref: "≥16 M/mL", ok: true },
{ param: "Total Motility (PR+NP)", value: "52%", ref: "≥42%", ok: true },
{ param: "Progressive Motility", value: "38%", ref: "≥30%", ok: true },
{ param: "Normal Morphology", value: "3%", ref: "≥4%", ok: false },
{ param: "Vitality", value: "72%", ref: "≥54%", ok: true },
{ param: "DNA Fragmentation", value: "18%", ref: "<25%", ok: true },
].map((s, i) => (
<div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "9px 0", borderBottom: "1px solid var(--border)" }}>
<span style={{ fontSize: 13 }}>{s.param}</span>
<div style={{ display: "flex", gap: 10, alignItems: "center" }}>
<span style={{ fontSize: 13, fontWeight: 600, color: s.ok ? "var(--sage)" : "var(--rose-mid)" }}>{s.value}</span>
<span style={{ fontSize: 11, color: "var(--muted)" }}>{s.ref}</span>
</div>
</div>
))}
<div className="info-box gold" style={{ marginTop: 14 }}>
<Icon d={icons.sparkle} size={16} stroke="var(--gold)" />
<div><div className="info-box-title">ICSI Recommended</div><div className="info-box-text">Borderline morphology (3% vs 4% WHO). ICSI preferred over conventional IVF for optimal fertilization.</div></div>
</div>
</div>
</div>
</div>
</div>
);
}
// ─── COMPONENT: DOCUMENTS ─────────────────────────────────────────────────────
function DocumentsModule({ patient }) {
const docs = [
{ name: "Day2_Baseline_Scan_Report.pdf", type: "Scan", size: "1.2 MB", date: "Feb 28, 2026", icon: icons.file },
{ name: "Semen_Analysis_Rohan_Sharma.pdf", type: "Lab", size: "0.8 MB", date: "Feb 20, 2026", icon: icons.lab },
{ name: "AMH_Hormone_Panel.pdf", type: "Lab", size: "0.6 MB", date: "Feb 15, 2026", icon: icons.lab },
{ name: "D8_Follicle_Monitoring_Scan.pdf", type: "Scan", size: "1.8 MB", date: "Mar 8, 2026", icon: icons.file },
{ name: "Embryo_Photos_Day5.jpg", type: "Image", size: "3.4 MB", date: "Mar 12, 2026", icon: icons.eye },
];
return (
<div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
<div className="upload-zone">
<div className="upload-icon"><Icon d={icons.upload} size={36} /></div>
<div className="upload-text">Drop files here or <span style={{ color: "var(--rose-mid)", fontWeight: 600, cursor: "pointer" }}>browse</span></div>
<div className="upload-sub">Supports PDF, JPG, PNG, DICOM · Max 50MB per file</div>
</div>
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.file} size={18} /></div><div><div className="card-title">Patient Documents</div><div className="card-subtitle">{patient.name} · {patient.id}</div></div></div>
<div className="table-wrap">
<table>
<thead><tr><th>File Name</th><th>Type</th><th>Size</th><th>Date</th><th>Actions</th></tr></thead>
<tbody>
{docs.map((d, i) => (
<tr key={i}>
<td><div style={{ display: "flex", alignItems: "center", gap: 8 }}><div style={{ width: 30, height: 30, borderRadius: 8, background: "var(--blush-light)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--rose-mid)" }}><Icon d={d.icon} size={14} /></div><span style={{ fontWeight: 500 }}>{d.name}</span></div></td>
<td><span className={`badge ${d.type === "Scan" ? "rose" : d.type === "Image" ? "purple" : "gold"}`}>{d.type}</span></td>
<td style={{ color: "var(--muted)" }}>{d.size}</td>
<td style={{ color: "var(--muted)" }}>{d.date}</td>
<td><div style={{ display: "flex", gap: 6 }}><button className="btn btn-secondary btn-sm"><Icon d={icons.eye} size={13} /> View</button></div></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
// ─── COMPONENT: VOICE & AI ────────────────────────────────────────────────────
function VoiceAIModule({ patient }) {
const [recording, setRecording] = useState(false);
const [step, setStep] = useState(0); // 0: record, 1: translate, 2: transcript, 3: ai
const [transcript, setTranscript] = useState(`Patient presents with irregular cycles, moderate pelvic pain during menstruation, and difficulty conceiving for 18 months. AMH is 1.8, AFC 14. Husband semen analysis shows borderline morphology at 3%. Patient reports high work stress and disrupted sleep. Previous laparoscopy 2 years ago — no endometriosis found. Ready to proceed with IVF Cycle #2. Starting stimulation today Day 2. Gonal-F 300 IU recommended.`);
const [editing, setEditing] = useState(false);
const [aiLoading, setAiLoading] = useState(false);
const [aiResponse, setAiResponse] = useState(null);
const waveHeights = [8, 14, 20, 12, 24, 10, 18, 8, 22, 16, 10, 20, 14, 8, 18, 12, 24, 10, 16, 8];
const handleAI = async () => {
setAiLoading(true);
try {
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1000,
system: "You are a specialized IVF fertility clinic AI assistant. Based on patient symptoms and clinical notes, provide medication suggestions and clinical recommendations. Format your response as JSON with fields: diagnosis_summary, medications (array of {name, dose, route, duration, rationale}), monitoring_plan, and lifestyle_recommendations. Be concise and clinically appropriate.",
messages: [{ role: "user", content: `Patient: ${patient.name}, Age ${patient.age}, BMI ${patient.bmi}, AMH ${patient.amh}\n\nClinical Notes:\n${transcript}\n\nProvide IVF medication protocol and recommendations.` }]
})
});
const data = await res.json();
const text = data.content?.find(c => c.type === "text")?.text || "{}";
try {
const clean = text.replace(/```json|```/g, "").trim();
setAiResponse(JSON.parse(clean));
} catch {
setAiResponse({ diagnosis_summary: text, medications: [], monitoring_plan: "", lifestyle_recommendations: "" });
}
} catch (err) {
setAiResponse({ diagnosis_summary: "AI service unavailable. Please check connection.", medications: [], monitoring_plan: "Manual review required.", lifestyle_recommendations: "" });
}
setAiLoading(false);
setStep(3);
};
return (
<div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
{/* Step Indicator */}
<div style={{ display: "flex", gap: 0, background: "white", borderRadius: "var(--radius)", border: "1px solid var(--border)", overflow: "hidden" }}>
{["🎙 Record", "🌐 Translate", "📝 Transcript", "✦ AI Rx"].map((s, i) => (
<div key={i} onClick={() => setStep(i)} style={{ flex: 1, padding: "12px 8px", textAlign: "center", fontSize: 12, fontWeight: 600, cursor: "pointer", transition: "all 0.2s", background: step === i ? "var(--rose-deep)" : "transparent", color: step === i ? "white" : step > i ? "var(--sage)" : "var(--muted)", borderRight: i < 3 ? "1px solid var(--border)" : "none" }}>
{s}
</div>
))}
</div>
{step === 0 && (
<div className="recorder-panel">
<div style={{ textAlign: "center", position: "relative", zIndex: 1 }}>
<div style={{ fontSize: 13, color: "rgba(255,255,255,0.6)", marginBottom: 6 }}>Patient: {patient.name} · {new Date().toLocaleDateString()}</div>
<div style={{ fontFamily: "Cormorant Garamond", fontSize: 22, color: "white", marginBottom: 20 }}>
{recording ? "Recording in progress..." : "Ready to Record"}
</div>
<div className="waveform">
{waveHeights.map((h, i) => (
<div key={i} className={`wave-bar ${recording ? "active" : ""}`} style={{ height: recording ? undefined : h, animationDelay: `${i * 0.06}s` }} />
))}
</div>
<button className={`rec-btn ${recording ? "recording" : ""}`} onClick={() => setRecording(!recording)}>
<Icon d={icons.mic} size={32} />
</button>
{recording && <div style={{ fontSize: 13, color: "var(--rose-soft)", marginTop: 16 }}>● 00:02:34 — Tap to stop</div>}
{!recording && (
<div style={{ marginTop: 20, display: "flex", gap: 10, justifyContent: "center" }}>
<div style={{ background: "rgba(255,255,255,0.08)", borderRadius: 10, padding: "8px 16px", fontSize: 12, color: "rgba(255,255,255,0.6)" }}>Duration: 2m 34s</div>
<div style={{ background: "rgba(255,255,255,0.08)", borderRadius: 10, padding: "8px 16px", fontSize: 12, color: "rgba(255,255,255,0.6)" }}>Format: .wav · 4.8 MB</div>
</div>
)}
{!recording && <button className="btn btn-gold" style={{ marginTop: 16 }} onClick={() => setStep(1)}>Proceed to Translation →</button>}
</div>
</div>
)}
{step === 1 && (
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.translate} size={18} /></div><div><div className="card-title">Language Translation</div><div className="card-subtitle">Convert Indian language audio to English</div></div></div>
<div className="card-body">
<div className="form-row cols-2" style={{ marginBottom: 20 }}>
<div className="form-group">
<label className="form-label">Source Language</label>
<select className="form-select">
<option>Tamil</option><option>Hindi</option><option>Telugu</option><option>Kannada</option><option>Malayalam</option><option>Bengali</option><option>Marathi</option><option>Gujarati</option>
</select>
</div>
<div className="form-group">
<label className="form-label">Target Language</label>
<select className="form-select"><option>English</option></select>
</div>
</div>
<div style={{ background: "var(--blush-light)", borderRadius: "var(--radius-sm)", padding: 20, marginBottom: 16 }}>
<div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
<div style={{ width: 36, height: 36, borderRadius: 10, background: "var(--rose-deep)", display: "flex", alignItems: "center", justifyContent: "center", color: "white" }}><Icon d={icons.audio} size={16} /></div>
<div>
<div style={{ fontSize: 13, fontWeight: 600 }}>consultation_priya_sharma_20260310.wav</div>
<div style={{ fontSize: 11, color: "var(--muted)" }}>2m 34s · 4.8 MB · Tamil</div>
</div>
</div>
<div className="progress-bar"><div className="progress-fill" style={{ width: "100%" }} /></div>
<div style={{ fontSize: 11, color: "var(--muted)", marginTop: 6 }}>Translation complete</div>
</div>
<div className="info-box sage">
<Icon d={icons.check} size={16} stroke="var(--sage)" />
<div><div className="info-box-title">Translation Successful</div><div className="info-box-text">Audio translated from Tamil to English with 96.4% confidence. Ready for transcription.</div></div>
</div>
<button className="btn btn-primary" style={{ marginTop: 16 }} onClick={() => setStep(2)}>View Transcript →</button>
</div>
</div>
)}
{step === 2 && (
<div className="card">
<div className="card-header">
<div className="card-icon gold"><Icon d={icons.edit} size={18} /></div>
<div><div className="card-title">Clinical Transcript</div><div className="card-subtitle">AI-generated · Doctor review required</div></div>
<button className="btn btn-secondary btn-sm" style={{ marginLeft: "auto" }} onClick={() => setEditing(!editing)}><Icon d={icons.edit} size={13} /> {editing ? "Save" : "Edit"}</button>
</div>
<div className="card-body">
<div style={{ display: "flex", gap: 10, marginBottom: 14 }}>
{[{ l: "Confidence", v: "96.4%", c: "sage" }, { l: "Words", v: "142", c: "blue" }, { l: "Duration", v: "2m 34s", c: "gold" }].map((b, i) => (
<span key={i} className={`badge ${b.c}`}>{b.l}: {b.v}</span>
))}
</div>
{editing ? (
<textarea value={transcript} onChange={e => setTranscript(e.target.value)}
style={{ width: "100%", minHeight: 200, border: "1.5px solid var(--rose-soft)", borderRadius: "var(--radius-sm)", padding: "14px 16px", fontSize: 13.5, lineHeight: 1.7, fontFamily: "'DM Sans', sans-serif", color: "var(--charcoal)", outline: "none", resize: "vertical" }} />
) : (
<div style={{ background: "var(--blush-light)", borderRadius: "var(--radius-sm)", padding: "16px 20px", fontSize: 13.5, lineHeight: 1.8, color: "var(--charcoal)", fontStyle: "italic" }}>
" {transcript} "
</div>
)}
<div className="info-box gold" style={{ marginTop: 14 }}>
<Icon d={icons.sparkle} size={16} stroke="var(--gold)" />
<div><div className="info-box-title">Doctor Review Pending</div><div className="info-box-text">Please review and confirm the transcript before proceeding to AI medication suggestions.</div></div>
</div>
<div style={{ marginTop: 16, display: "flex", gap: 10 }}>
<button className="btn btn-secondary"><Icon d={icons.check} size={14} /> Mark Reviewed</button>
<button className="btn btn-primary" onClick={() => { setStep(3); handleAI(); }}><Icon d={icons.brain} size={14} /> Generate AI Suggestions →</button>
</div>
</div>
</div>
)}
{step === 3 && (
<div>
{aiLoading ? (
<div className="ai-panel" style={{ textAlign: "center", padding: 40 }}>
<div style={{ marginBottom: 16 }}>
<div style={{ width: 60, height: 60, borderRadius: "50%", background: "linear-gradient(135deg, var(--rose-mid), var(--gold))", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 16px", animation: "pulse 1.5s ease-in-out infinite" }}>
<Icon d={icons.brain} size={28} stroke="white" />
</div>
</div>
<div style={{ fontFamily: "Cormorant Garamond", fontSize: 22, color: "white", marginBottom: 8 }}>AI is analyzing...</div>
<div style={{ fontSize: 13, color: "rgba(255,255,255,0.5)" }}>Searching medical literature and generating recommendations</div>
</div>
) : aiResponse ? (
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div className="ai-panel">
<div className="ai-header">
<span className="ai-badge">✦ AI-POWERED ANALYSIS</span>
</div>
<div style={{ position: "relative", zIndex: 1, fontSize: 13.5, color: "rgba(255,255,255,0.85)", lineHeight: 1.7, background: "rgba(255,255,255,0.06)", borderRadius: "var(--radius-sm)", padding: 16 }}>
{aiResponse.diagnosis_summary}
</div>
</div>
{aiResponse.medications && aiResponse.medications.length > 0 && (
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.pill} size={18} /></div><div><div className="card-title">Medication Protocol</div></div></div>
<div className="card-body">
{aiResponse.medications.map((med, i) => (
<div key={i} className="drug-card" style={{ marginBottom: 10 }}>
<div className="drug-icon" style={{ background: i % 2 === 0 ? "var(--blush-light)" : "var(--gold-pale)", color: i % 2 === 0 ? "var(--rose-mid)" : "var(--gold)" }}>
<Icon d={icons.pill} size={18} />
</div>
<div style={{ flex: 1 }}>
<div className="drug-name">{med.name}</div>
<div className="drug-detail">{med.dose} · {med.route} · {med.duration}</div>
<div style={{ fontSize: 11, color: "var(--charcoal-mid)", marginTop: 4 }}>{med.rationale}</div>
</div>
</div>
))}
</div>
</div>
)}
{aiResponse.monitoring_plan && (
<div className="card">
<div className="card-header"><div className="card-icon sage"><Icon d={icons.calendar} size={18} /></div><div><div className="card-title">Monitoring Plan</div></div></div>
<div className="card-body">
<p style={{ fontSize: 13.5, lineHeight: 1.7, color: "var(--charcoal)" }}>{aiResponse.monitoring_plan}</p>
</div>
</div>
)}
<div className="info-box rose">
<Icon d={icons.sparkle} size={16} stroke="var(--rose-mid)" />
<div><div className="info-box-title">Saved to Patient Record</div><div className="info-box-text">Audio, translation, transcript, and AI recommendations saved under {patient.name}'s profile.</div></div>
</div>
</div>
) : (
<div className="card">
<div className="card-body" style={{ textAlign: "center", padding: 40 }}>
<button className="btn btn-primary" onClick={handleAI}><Icon d={icons.brain} size={16} /> Generate AI Suggestions</button>
</div>
</div>
)}
</div>
)}
</div>
);
}
// ─── COMPONENT: PHARMACY ──────────────────────────────────────────────────────
function Pharmacy() {
return (
<div>
<div className="section-header">
<div><div className="section-title">Pharmacy & Drugs</div><div className="section-subtitle">Fertility medication inventory & e-prescriptions</div></div>
<button className="btn btn-primary"><Icon d={icons.plus} size={15} /> Add Drug</button>
</div>
<div className="stats-grid" style={{ gridTemplateColumns: "repeat(3,1fr)", marginBottom: 20 }}>
{[{ label: "Total SKUs", value: "48", type: "rose" }, { label: "Low Stock Alerts", value: "3", type: "gold" }, { label: "Cold Chain Items", value: "12", type: "sage" }].map((s, i) => <div key={i} className={`stat-card ${s.type}`}><div className="stat-label">{s.label}</div><div className="stat-value">{s.value}</div></div>)}
</div>
<div className="card">
<div className="card-header"><div className="card-icon rose"><Icon d={icons.pharmacy} size={18} /></div><div><div className="card-title">Drug Inventory</div></div></div>
<div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 10 }}>
{drugs.map((d, i) => (
<div key={i} className="drug-card">
<div className="drug-icon" style={{ background: d.cold ? "rgba(127,200,232,0.12)" : "var(--blush-light)", color: d.cold ? "#1B6FA8" : "var(--rose-mid)" }}>
<Icon d={icons.pill} size={18} />
</div>
<div style={{ flex: 1 }}>
<div className="drug-name">{d.name}</div>
<div className="drug-detail">{d.category}{d.cold ? " · ❄ Cold Chain" : ""} · Exp: {d.expiry}</div>
</div>
<div className="drug-stock">
<div className="drug-qty" style={{ color: d.alert ? "var(--rose-mid)" : "var(--charcoal)" }}>{d.stock}</div>
<div className="drug-unit">{d.unit}</div>
</div>
{d.alert && <span className="badge red" style={{ marginLeft: 10 }}>Low</span>}
</div>
))}
</div>
</div>
</div>
);
}
// ─── COMPONENT: CRYOSTORAGE ───────────────────────────────────────────────────
function CryoStorage() {
const tanks = [
{ name: "Tank A", capacity: 120, used: 94, temp: -196, status: "Normal" },
{ name: "Tank B", capacity: 80, used: 52, temp: -196, status: "Normal" },
{ name: "Tank C", capacity: 60, used: 18, temp: -192, status: "Check" },
];
return (
<div>
<div className="section-header">
<div><div className="section-title">Cryopreservation Bank</div><div className="section-subtitle">LN₂ Tank Management · Embryo & Gamete Storage</div></div>
<button className="btn btn-secondary"><Icon d={icons.analytics} size={14} /> Export Report</button>
</div>
<div className="grid-3" style={{ marginBottom: 24 }}>
{tanks.map((t, i) => (
<div key={i} className="card">
<div className="card-body" style={{ textAlign: "center" }}>
<div style={{ width: 60, height: 60, borderRadius: "50%", background: t.status === "Normal" ? "rgba(127,200,232,0.15)" : "var(--blush-light)", margin: "0 auto 12px", display: "flex", alignItems: "center", justifyContent: "center", color: t.status === "Normal" ? "#1B6FA8" : "var(--rose-mid)" }}>
<Icon d={icons.freeze} size={26} />
</div>
<div style={{ fontFamily: "Cormorant Garamond", fontSize: 20, fontWeight: 600 }}>{t.name}</div>
<div style={{ fontSize: 13, color: "var(--muted)", margin: "4px 0 12px" }}>{t.temp}°C · LN₂</div>
<div className="progress-bar" style={{ marginBottom: 8 }}>
<div className="progress-fill" style={{ width: `${(t.used / t.capacity) * 100}%`, background: t.used / t.capacity > 0.85 ? "linear-gradient(90deg, var(--rose-mid), var(--rose-soft))" : "linear-gradient(90deg, #5B9BD5, #7FC8E8)" }} />
</div>
<div style={{ fontSize: 12, color: "var(--muted)" }}>{t.used}/{t.capacity} straws used</div>
<span className={`badge ${t.status === "Normal" ? "sage" : "gold"}`} style={{ marginTop: 10 }}>{t.status}</span>
</div>
</div>
))}
</div>
<div className="card">
<div className="card-header"><div className="card-icon" style={{ background: "rgba(127,200,232,0.12)", color: "#1B6FA8" }}><Icon d={icons.freeze} size={18} /></div><div><div className="card-title">Straw Registry</div><div className="card-subtitle">Individual straw tracking with barcode</div></div></div>
<div className="table-wrap">
<table>
<thead><tr><th>Straw ID</th><th>Patient</th><th>Type</th><th>Grade</th><th>Tank/Canister</th><th>Freeze Date</th><th>Status</th></tr></thead>
<tbody>
{[
{ id: "STW-2024-001", patient: "Priya Sharma", type: "Embryo", grade: "4AA", loc: "A/C3/R2", date: "Jan 12, 2024", status: "Stored" },
{ id: "STW-2024-002", patient: "Priya Sharma", type: "Embryo", grade: "4AB", loc: "A/C3/R3", date: "Jan 12, 2024", status: "Stored" },
{ id: "STW-2024-015", patient: "Ritu Verma", type: "Embryo", grade: "3BB", loc: "B/C1/R5", date: "Mar 8, 2024", status: "Stored" },
{ id: "STW-2024-028", patient: "Kavitha Nair", type: "Sperm", grade: "N/A", loc: "B/C4/R1", date: "Feb 5, 2024", status: "Stored" },
].map((s, i) => (
<tr key={i}>
<td><code style={{ fontSize: 12, background: "var(--blush-light)", padding: "2px 8px", borderRadius: 4 }}>{s.id}</code></td>
<td>{s.patient}</td>
<td><span className={`badge ${s.type === "Embryo" ? "rose" : "blue"}`}>{s.type}</span></td>
<td style={{ fontWeight: 600 }}>{s.grade}</td>
<td style={{ color: "var(--muted)", fontSize: 12 }}>{s.loc}</td>
<td style={{ color: "var(--muted)" }}>{s.date}</td>
<td><span className="badge sage">{s.status}</span></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
// ─── COMPONENT: BILLING ───────────────────────────────────────────────────────
function Billing() {
return (
<div>
<div className="section-header">
<div><div className="section-title">Finance & Billing</div><div className="section-subtitle">Package billing · Storage fees · Insurance</div></div>
<button className="btn btn-primary"><Icon d={icons.plus} size={15} /> New Invoice</button>
</div>
<div className="stats-grid" style={{ marginBottom: 24 }}>
{[
{ label: "Revenue (March)", value: "₹18.4L", type: "rose" },
{ label: "Pending Invoices", value: "12", type: "gold" },
{ label: "Insurance Claims", value: "5", type: "sage" },
{ label: "Cycle Packages Sold", value: "47", type: "purple" },
].map((s, i) => <div key={i} className={`stat-card ${s.type}`}><div className="stat-label">{s.label}</div><div className="stat-value">{s.value}</div></div>)}
</div>
<div className="card">
<div className="card-header"><div className="card-icon gold"><Icon d={icons.billing} size={18} /></div><div><div className="card-title">Recent Invoices</div></div></div>
<div className="table-wrap">
<table>
<thead><tr><th>Invoice</th><th>Patient</th><th>Package</th><th>Amount</th><th>Insurance</th><th>Status</th></tr></thead>
<tbody>
{[
{ inv: "INV-2026-047", patient: "Priya Sharma", pkg: "IVF Cycle Package", amount: "₹1,85,000", insurance: "Star Health", status: "Paid" },
{ inv: "INV-2026-048", patient: "Ananya Pillai", pkg: "IUI with Monitoring", amount: "₹32,000", insurance: "Self Pay", status: "Pending" },
{ inv: "INV-2026-049", patient: "Ritu Verma", pkg: "FET Cycle", amount: "₹65,000", insurance: "HDFC Ergo", status: "Claim Sent" },
{ inv: "INV-2026-050", patient: "Kavitha Nair", pkg: "ICSI Cycle + Storage", amount: "₹2,10,000", insurance: "Self Pay", status: "Partial" },
].map((inv, i) => (
<tr key={i}>
<td><code style={{ fontSize: 12, background: "var(--blush-light)", padding: "2px 8px", borderRadius: 4 }}>{inv.inv}</code></td>
<td style={{ fontWeight: 600 }}>{inv.patient}</td>
<td>{inv.pkg}</td>
<td style={{ fontWeight: 700, color: "var(--charcoal)" }}>{inv.amount}</td>
<td style={{ color: "var(--muted)" }}>{inv.insurance}</td>
<td><span className={`badge ${inv.status === "Paid" ? "sage" : inv.status === "Pending" ? "gold" : inv.status === "Partial" ? "purple" : "blue"}`}>{inv.status}</span></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
// ─── COMPONENT: ADD HOSPITAL MODAL ────────────────────────────────────────────
function AddHospitalModal({ onClose }) {
return (
<div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
<div className="modal">
<div className="modal-header">
<div className="modal-title">Add New Hospital</div>
<button className="icon-btn" onClick={onClose}><Icon d={icons.close} size={18} /></button>
</div>
<div className="modal-body">
<div className="form-row cols-2">
<div className="form-group"><label className="form-label">Hospital Name *</label><input className="form-input" placeholder="e.g. Bloom IVF Centre" /></div>
<div className="form-group"><label className="form-label">City *</label><input className="form-input" placeholder="e.g. Mumbai" /></div>
</div>
<div className="form-row cols-2">
<div className="form-group"><label className="form-label">Phone</label><input className="form-input" placeholder="+91 9876543210" /></div>
<div className="form-group"><label className="form-label">Email</label><input className="form-input" placeholder="admin@hospital.com" /></div>
</div>
<div className="form-group"><label className="form-label">Address</label><input className="form-input" placeholder="Full address" /></div>
<div className="form-row cols-2">
<div className="form-group"><label className="form-label">License Number</label><input className="form-input" placeholder="ART/MH/2024/0001" /></div>
<div className="form-group"><label className="form-label">Modules Access</label>
<select className="form-select"><option>Full Access</option><option>Clinical Only</option><option>Custom</option></select>
</div>
</div>
<div className="info-box sage" style={{ marginTop: 4 }}>
<Icon d={icons.sparkle} size={16} stroke="var(--sage)" />
<div><div className="info-box-title">Auto-provisioning</div><div className="info-box-text">A super-admin login will be auto-generated and sent to the hospital admin email.</div></div>
</div>
</div>
<div className="modal-footer">
<button className="btn btn-secondary" onClick={onClose}>Cancel</button>
<button className="btn btn-primary" onClick={onClose}><Icon d={icons.plus} size={14} /> Add Hospital</button>
</div>
</div>
</div>
);
}
// ─── COMPONENT: ADD PATIENT MODAL ─────────────────────────────────────────────
function AddPatientModal({ onClose }) {
return (
<div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
<div className="modal" style={{ maxWidth: 700 }}>
<div className="modal-header">
<div className="modal-title">Register New Patient (Couple)</div>
<button className="icon-btn" onClick={onClose}><Icon d={icons.close} size={18} /></button>
</div>
<div className="modal-body">
<div style={{ fontSize: 12, fontWeight: 700, letterSpacing: 1, textTransform: "uppercase", color: "var(--rose-mid)", marginBottom: 12 }}>Female Partner</div>
<div className="form-row cols-3">
<div className="form-group"><label className="form-label">First Name *</label><input className="form-input" placeholder="Priya" /></div>
<div className="form-group"><label className="form-label">Last Name *</label><input className="form-input" placeholder="Sharma" /></div>
<div className="form-group"><label className="form-label">Date of Birth *</label><input className="form-input" type="date" /></div>
</div>
<div className="form-row cols-3">
<div className="form-group"><label className="form-label">Phone</label><input className="form-input" placeholder="+91 XXXXXXXXXX" /></div>
<div className="form-group"><label className="form-label">Blood Group</label><select className="form-select"><option>A+</option><option>B+</option><option>O+</option><option>AB+</option></select></div>
<div className="form-group"><label className="form-label">AMH (ng/mL)</label><input className="form-input" placeholder="1.8" /></div>
</div>
<div className="divider" />
<div style={{ fontSize: 12, fontWeight: 700, letterSpacing: 1, textTransform: "uppercase", color: "var(--charcoal-mid)", marginBottom: 12 }}>Male Partner</div>
<div className="form-row cols-3">
<div className="form-group"><label className="form-label">First Name *</label><input className="form-input" placeholder="Rohan" /></div>
<div className="form-group"><label className="form-label">Last Name *</label><input className="form-input" placeholder="Sharma" /></div>
<div className="form-group"><label className="form-label">Date of Birth</label><input className="form-input" type="date" /></div>
</div>
<div className="divider" />
<div style={{ fontSize: 12, fontWeight: 700, letterSpacing: 1, textTransform: "uppercase", color: "var(--charcoal-mid)", marginBottom: 12 }}>Clinical Info</div>
<div className="form-row cols-3">
<div className="form-group"><label className="form-label">Treatment Type *</label><select className="form-select"><option>IVF</option><option>IUI</option><option>FET</option><option>ICSI</option><option>TESA</option></select></div>
<div className="form-group"><label className="form-label">Assigned Doctor *</label><select className="form-select"><option>Dr. Meera Iyer</option><option>Dr. Sonal Gupta</option><option>Dr. Priya Reddy</option></select></div>
<div className="form-group"><label className="form-label">Referral Source</label><input className="form-input" placeholder="Dr. / Hospital / Self" /></div>
</div>
</div>
<div className="modal-footer">
<button className="btn btn-secondary" onClick={onClose}>Cancel</button>
<button className="btn btn-primary" onClick={onClose}><Icon d={icons.check} size={14} /> Register Patient</button>
</div>
</div>
</div>
);
}
// ─── MAIN APP ──────────────────────────────────────────────────────────────────
export default function App() {
const [activePage, setActivePage] = useState("dashboard");
const [showModal, setShowModal] = useState(null);
const navItems = [
{ section: "Overview", items: [
{ id: "dashboard", label: "Dashboard", icon: icons.dashboard },
{ id: "hospitals", label: "Hospitals", icon: icons.hospital },
]},
{ section: "Clinical", items: [
{ id: "patients", label: "Patients", icon: icons.users, badge: "4" },
{ id: "artcycle", label: "ART Cycles", icon: icons.activity },
{ id: "lab", label: "Lab & Embryology", icon: icons.lab },
{ id: "cryo", label: "Cryostorage", icon: icons.freeze },
]},
{ section: "Operations", items: [
{ id: "pharmacy", label: "Pharmacy", icon: icons.pharmacy, badge: "3" },
{ id: "inventory", label: "Inventory", icon: icons.inventory },
{ id: "billing", label: "Finance & Billing", icon: icons.billing },
]},
{ section: "Advanced", items: [
{ id: "donor", label: "Donor & Surrogacy", icon: icons.donor },
{ id: "telemedicine", label: "Telemedicine", icon: icons.telemedicine },
{ id: "analytics", label: "Analytics & SART", icon: icons.analytics },
]},
];
const pageTitles = {
dashboard: ["Good Morning", "Dashboard"],
hospitals: ["Hospital", "Network"],
patients: ["Patient", "Management"],
artcycle: ["ART", "Cycles"],
lab: ["Lab &", "Embryology"],
cryo: ["Cryo", "Storage"],
pharmacy: ["Pharmacy &", "Drugs"],
inventory: ["Inventory &", "Procurement"],
billing: ["Finance &", "Billing"],
donor: ["Donor &", "Surrogacy"],
telemedicine: ["Tele", "medicine"],
analytics: ["Analytics &", "SART"],
};
const renderPage = () => {
switch (activePage) {
case "dashboard": return <Dashboard />;
case "hospitals": return <Hospitals onShowModal={() => setShowModal("hospital")} />;
case "patients": return <Patients onShowModal={() => setShowModal("patient")} />;
case "pharmacy": return <Pharmacy />;
case "cryo": return <CryoStorage />;
case "billing": return <Billing />;
default: return (
<div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "60vh", flexDirection: "column", gap: 12 }}>
<div style={{ width: 64, height: 64, borderRadius: "50%", background: "var(--blush-light)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--rose-mid)" }}>
<Icon d={icons[activePage === "donor" ? "donor" : activePage === "telemedicine" ? "telemedicine" : "analytics"] || icons.activity} size={28} />
</div>
<div style={{ fontFamily: "Cormorant Garamond", fontSize: 22, color: "var(--charcoal)" }}>{pageTitles[activePage]?.join(" ")} Module</div>
<div style={{ fontSize: 13, color: "var(--muted)" }}>This module is available in the full version</div>
<button className="btn btn-primary btn-sm">Coming Soon</button>
</div>
);
}
};
const [pt] = pageTitles[activePage] || ["", ""];
const [pt2] = pageTitles[activePage]?.slice(1) || [""];
return (
<>
<style>{styles}</style>
<div className="app">
{/* SIDEBAR */}
<aside className="sidebar">
<div className="sidebar-logo">
<div className="logo-mark">
<div className="logo-icon"><Icon d={icons.heart} size={20} fill="white" stroke="white" /></div>
<div className="logo-text">
<div className="logo-name">Thulir Care</div>
<div className="logo-sub">Fertility Management</div>
</div>
</div>
</div>
<div className="sidebar-role">
<div className="role-label">Logged in as</div>
<div className="role-name">Super Administrator</div>
</div>
<nav className="sidebar-nav">
{navItems.map(section => (
<div key={section.section}>
<div className="nav-section">{section.section}</div>
{section.items.map(item => (
<div key={item.id} className={`nav-item ${activePage === item.id ? "active" : ""}`} onClick={() => setActivePage(item.id)}>
<span className="nav-icon"><Icon d={item.icon} size={16} /></span>
{item.label}
{item.badge && <span className="nav-badge">{item.badge}</span>}
</div>
))}
</div>
))}
</nav>
<div className="sidebar-footer">
<div className="user-card">
<div className="user-avatar">SA</div>
<div className="user-info">
<div className="user-name">Super Admin</div>
<div className="user-email">admin@thulircare.com</div>
</div>
<div className="logout-btn"><Icon d={icons.logout} size={16} /></div>
</div>
</div>
</aside>
{/* MAIN */}
<main className="main">
<header className="topbar">
<div className="topbar-title">
{pageTitles[activePage]?.[0]} <span>{pageTitles[activePage]?.[1]}</span>
</div>
<div className="search-bar">
<Icon d={icons.search} size={15} stroke="var(--muted)" />
<input placeholder="Search patients, records..." />
</div>
<div className="topbar-actions">
<div className="icon-btn">
<Icon d={icons.bell} size={17} />
<div className="notif-dot" />
</div>
<div className="icon-btn">
<Icon d={icons.settings} size={17} />
</div>
<div style={{ display: "flex", alignItems: "center", gap: 8, background: "white", border: "1px solid var(--border)", borderRadius: 10, padding: "6px 12px", cursor: "pointer" }}>
<div style={{ width: 26, height: 26, borderRadius: 7, background: "linear-gradient(135deg, var(--rose-mid), var(--rose-deep))", display: "flex", alignItems: "center", justifyContent: "center", color: "white", fontSize: 11, fontWeight: 700 }}>BM</div>
<div>
<div style={{ fontSize: 12, fontWeight: 600, color: "var(--charcoal)" }}>Bloom IVF</div>
<div style={{ fontSize: 10, color: "var(--muted)" }}>Mumbai</div>
</div>
<Icon d={icons.chevronDown} size={14} stroke="var(--muted)" />
</div>
</div>
</header>
<div className="content">
{renderPage()}
</div>
</main>
{/* MODALS */}
{showModal === "hospital" && <AddHospitalModal onClose={() => setShowModal(null)} />}
{showModal === "patient" && <AddPatientModal onClose={() => setShowModal(null)} />}
</div>
</>
);
}