feat: rebrand to Curio and update ingress for curaflow.applaude.net
Build MCP Services / build-mcp-filesystem (push) Successful in 1m18s Details

This commit is contained in:
Antigravity 2026-05-13 14:50:37 -04:00
parent ce1edeba3a
commit 1e926f8072
23 changed files with 575 additions and 192 deletions

View File

@ -1,4 +1,4 @@
name: Build CuraFlow HMS name: Build Curio HMS
on: [push] on: [push]
jobs: jobs:
@ -16,8 +16,8 @@ jobs:
docker run --rm \ docker run --rm \
--volumes-from "$JOB_CONTAINER" \ --volumes-from "$JOB_CONTAINER" \
gcr.io/kaniko-project/executor:latest \ gcr.io/kaniko-project/executor:latest \
--context=dir://"$GITHUB_WORKSPACE/curaflow" \ --context=dir://"$GITHUB_WORKSPACE" \
--dockerfile="$GITHUB_WORKSPACE/curaflow/Dockerfile" \ --dockerfile="$GITHUB_WORKSPACE/Dockerfile" \
--destination=192.168.8.250:5000/agentic-os/curaflow:latest \ --destination=192.168.8.250:5000/Curio:latest \
--insecure \ --insecure \
--skip-tls-verify --skip-tls-verify

View File

@ -19,7 +19,7 @@ class BotLogic {
if (text.includes('hi') && !this.states[`${patientId}_lang`]) { if (text.includes('hi') && !this.states[`${patientId}_lang`]) {
this.states[patientId] = 'SELECT_LANG'; this.states[patientId] = 'SELECT_LANG';
return { return {
reply: "Welcome to CuraFlow! Please select your language / भाषा चुनें / భాషను ఎంచుకోండి:\n\n1. English\n2. Hindi (हिंदी)\n3. Telugu (తెలుగు)", reply: "Welcome to Curio! Please select your language / भाषा चुनें / భాషను ఎంచుకోండి:\n\n1. English\n2. Hindi (हिंदी)\n3. Telugu (తెలుగు)",
buttons: ["English", "Hindi", "Telugu"] buttons: ["English", "Hindi", "Telugu"]
}; };
} }
@ -56,7 +56,7 @@ class BotLogic {
this.states[patientId] = 'TRIAGE_START'; this.states[patientId] = 'TRIAGE_START';
return { return {
reply: i18n.t(lang, 'triage_ask', { token: result.token }) + reply: i18n.t(lang, 'triage_ask', { token: result.token }) +
` \n\n💳 *Payment Required*: Please pay ₹${result.fee} to activate your token: http://razorpay.me/curaflow_mock`, ` \n\n💳 *Payment Required*: Please pay ₹${result.fee} to activate your token: http://razorpay.me/Curio_mock`,
}; };
} else { } else {
return { return {

View File

@ -1,30 +1,46 @@
/** /**
* ConfigManager: Central configuration for hospital-wide pricing and slots. * ConfigManager: Central configuration for multi-tenant hospital settings and white-labeling.
*/ */
class ConfigManager { class ConfigManager {
constructor() { constructor() {
this.config = { this.tenants = {
consultationFee: 500, 'default': {
slotDuration: 30, // minutes name: "Curio Clinic",
onlineSlotLimit: 3, logo: "C",
walkinSlotLimit: 5, primaryColor: "#0F172A",
hospitalName: "Dr. Sharma's Clinic", secondaryColor: "#38BDF8",
currency: "₹" consultationFee: 500,
currency: "₹"
},
'sharma-clinic': {
name: "Dr. Sharma's Cardiology",
logo: "S",
primaryColor: "#1E3A8A", // Deep Blue
secondaryColor: "#60A5FA",
consultationFee: 800,
currency: "₹"
},
'apollo-hospitals': {
name: "Apollo Multispecialty",
logo: "A",
primaryColor: "#065F46", // Dark Green
secondaryColor: "#34D399",
consultationFee: 1200,
currency: "₹"
}
}; };
} }
get(key) { getTenantConfig(tenantId) {
return this.config[key]; return this.tenants[tenantId] || this.tenants['default'];
} }
set(key, value) { updateTenantConfig(tenantId, newConfig) {
this.config[key] = value; if (!this.tenants[tenantId]) {
console.log(`Config updated: ${key} = ${value}`); this.tenants[tenantId] = { ...this.tenants['default'] };
} }
this.tenants[tenantId] = { ...this.tenants[tenantId], ...newConfig };
getAll() {
return this.config;
} }
} }

View File

@ -1,5 +1,5 @@
/** /**
* i18n: Translation manager for CuraFlow WhatsApp Bot. * i18n: Translation manager for Curio WhatsApp Bot.
* Supports English (en), Hindi (hi), and Telugu (te). * Supports English (en), Hindi (hi), and Telugu (te).
*/ */

View File

@ -1,5 +1,5 @@
/** /**
* QueueManager: Handles the hybrid slot logic for CuraFlow * QueueManager: Handles the hybrid slot logic for Curio
* - 30-min slots * - 30-min slots
* - Max 3 online bookings (Hard Cap) * - Max 3 online bookings (Hard Cap)
* - 5 Walk-in slots * - 5 Walk-in slots
@ -9,65 +9,68 @@ const configManager = require('./configManager');
class QueueManager { class QueueManager {
constructor() { constructor() {
this.slots = {}; // Key: "YYYY-MM-DD:HH:mm" this.slots = {}; // Key: "tenantId:YYYY-MM-DD:HH:mm"
} }
getSlotKey(date, time) { getSlotKey(tenantId, date, time) {
// Round time to nearest slot duration const config = configManager.getTenantConfig(tenantId);
const duration = configManager.get('slotDuration'); const duration = config.slotDuration || 30;
const [hours, minutes] = time.split(':'); const [hours, minutes] = time.split(':');
const roundedMins = parseInt(minutes) < duration ? '00' : duration; const roundedMins = parseInt(minutes) < duration ? '00' : duration;
return `${date}:${hours}:${roundedMins}`; return `${tenantId}:${date}:${hours}:${roundedMins}`;
} }
getSlotStatus(date, time) { getSlotStatus(tenantId, date, time) {
const key = this.getSlotKey(date, time); const key = this.getSlotKey(tenantId, date, time);
if (!this.slots[key]) { if (!this.slots[key]) {
const config = configManager.getTenantConfig(tenantId);
this.slots[key] = { this.slots[key] = {
online: 0, online: 0,
walkin: 0, walkin: 0,
maxOnline: configManager.get('onlineSlotLimit'), maxOnline: config.onlineSlotLimit || 3,
maxWalkin: configManager.get('walkinSlotLimit') maxWalkin: config.walkinSlotLimit || 5
}; };
} }
return this.slots[key]; return this.slots[key];
} }
bookOnline(date, time) { bookOnline(date, time, tenantId = 'default') {
const status = this.getSlotStatus(date, time); const status = this.getSlotStatus(tenantId, date, time);
const config = configManager.getTenantConfig(tenantId);
if (status.online < status.maxOnline) { if (status.online < status.maxOnline) {
status.online++; status.online++;
return { return {
success: true, success: true,
token: `ON-${status.online}`, token: `ON-${status.online}`,
slot: this.getSlotKey(date, time), slot: this.getSlotKey(tenantId, date, time),
status: 'PENDING_PAYMENT', status: 'PENDING_PAYMENT',
fee: configManager.get('consultationFee') fee: config.consultationFee
}; };
} }
return { success: false, message: "Slot full for online booking. Try next slot." }; return { success: false, message: "Slot full for online booking. Try next slot." };
} }
bookWalkin(date, time) { bookWalkin(date, time, tenantId = 'default') {
const status = this.getSlotStatus(date, time); const status = this.getSlotStatus(tenantId, date, time);
const config = configManager.getTenantConfig(tenantId);
if (status.walkin < status.maxWalkin) { if (status.walkin < status.maxWalkin) {
status.walkin++; status.walkin++;
return { return {
success: true, success: true,
token: `WK-${status.walkin}`, token: `WK-${status.walkin}`,
status: 'PENDING_PAYMENT', status: 'PENDING_PAYMENT',
fee: configManager.get('consultationFee') fee: config.consultationFee
}; };
} }
return { success: false, message: "Clinic is at full capacity for this slot." }; return { success: false, message: "Clinic is at full capacity for this slot." };
} }
getDailyUpdates(patientId) { getDailyUpdates(patientId, tenantId = 'default') {
// Mock data for daily updates const config = configManager.getTenantConfig(tenantId);
return [ return [
"Good morning! Your appointment with Dr. Sharma is at 10:30 AM today.", `Good morning! Your appointment with ${config.name} is scheduled for today.`,
"Queue Update: The clinic is running 10 mins behind schedule. Please plan accordingly.", "Queue Update: The clinic is running 10 mins behind schedule. Please plan accordingly.",
"Reminder: Don't forget to bring your previous blood reports." "Reminder: Don't forget to bring your previous reports."
]; ];
} }
} }

View File

@ -1,6 +1,7 @@
const express = require('express'); const express = require('express');
const path = require('path'); const path = require('path');
const botLogic = require('./botLogic'); const botLogic = require('./botLogic');
const configManager = require('./configManager');
const app = express(); const app = express();
const port = 3000; const port = 3000;
@ -12,6 +13,12 @@ app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../login.html')); res.sendFile(path.join(__dirname, '../login.html'));
}); });
// Multi-tenant Config API
app.get('/api/config/:tenantId', (req, res) => {
const config = configManager.getTenantConfig(req.params.tenantId);
res.json(config);
});
// Mock WhatsApp Webhook // Mock WhatsApp Webhook
app.post('/whatsapp/webhook', async (req, res) => { app.post('/whatsapp/webhook', async (req, res) => {
const { from, body } = req.body; const { from, body } = req.body;
@ -28,5 +35,5 @@ app.post('/whatsapp/webhook', async (req, res) => {
}); });
app.listen(port, '0.0.0.0', () => { app.listen(port, '0.0.0.0', () => {
console.log(`CuraFlow WhatsApp Mock Server running at http://0.0.0.0:${port}`); console.log(`Curio WhatsApp Mock Server running at http://0.0.0.0:${port}`);
}); });

44
curaflow/backend_tests.js Normal file
View File

@ -0,0 +1,44 @@
const queueManager = require('./backend/queueManager');
const botLogic = require('./backend/botLogic');
const configManager = require('./backend/configManager');
console.log("=== STARTING BACKEND UNIT TESTS ===");
// 1. Test QueueManager - Online Booking Limits
console.log("\nTesting QueueManager: Online Booking Limits");
const date = "2026-05-13";
const time = "10:00";
for (let i = 0; i < 4; i++) {
const res = queueManager.bookOnline(date, time);
console.log(`Booking ${i+1}:`, res.success ? `Success - ${res.token}` : `Failed - ${res.message}`);
}
// 2. Test QueueManager - Walkin Booking
console.log("\nTesting QueueManager: Walk-in Booking");
const walkRes = queueManager.bookWalkin(date, time);
console.log("Walkin result:", walkRes.token);
// 3. Test Bot Logic - WhatsApp Simulation
console.log("\nTesting BotLogic: WhatsApp Interactions");
async function testBot() {
const msg1 = await botLogic.handleMessage("9876543210", "Hi");
console.log("User: Hi -> Bot:", msg1.reply);
const msg2 = await botLogic.handleMessage("9876543210", "Book Token");
console.log("User: Book Token -> Bot:", msg2.reply);
console.log("Buttons:", msg2.buttons);
}
testBot();
// 4. Test ConfigManager - Multi-tenancy
console.log("\nTesting ConfigManager: Multi-tenancy");
const sharmaConfig = configManager.getTenantConfig('sharma-clinic');
console.log("Sharma Clinic Name:", sharmaConfig.name);
// 5. Test Multi-tenant Booking
console.log("\nTesting Multi-tenant Booking (Sharma Clinic)");
const sharmaRes = queueManager.bookOnline(date, time, 'sharma-clinic');
console.log("Sharma Booking Result:", sharmaRes.success ? `Success - ${sharmaRes.token} (Fee: ${sharmaRes.fee})` : "Failed");

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Billing | Hospital Revenue & Accounts</title> <title>Curio Billing | Hospital Revenue & Accounts</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="billing.css"> <link rel="stylesheet" href="billing.css">
@ -13,7 +13,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html"><span>🏠</span> Overview</a> <a href="dashboard.html"><span>🏠</span> Overview</a>
@ -25,6 +25,14 @@
<a href="staff.html"><span>👔</span> Staff & Payroll</a> <a href="staff.html"><span>👔</span> Staff & Payroll</a>
<a href="settings.html"><span>⚙️</span> Settings</a> <a href="settings.html"><span>⚙️</span> Settings</a>
</nav> </nav>
<div class="user-profile">
<div class="avatar">BA</div>
<div class="info">
<strong>Billing Admin</strong>
<span>Staff</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div>
</div>
</aside> </aside>
<main class="dashboard-main"> <main class="dashboard-main">

View File

@ -3,21 +3,22 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Dashboard | Dr. Sharma's Clinic</title> <title>Dashboard | Curio</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet">
<script src="tenantLoader.js"></script>
</head> </head>
<body class="dashboard-body"> <body class="dashboard-body">
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text" data-tenant-name>Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html" class="active"><span>🏠</span> Overview</a> <a href="#" class="active" onclick="showSection('overview')"><span>🏠</span> Overview</a>
<a href="dashboard.html"><span>👥</span> Queue</a> <a href="#" onclick="showSection('queue')"><span>👥</span> Queue</a>
<a href="dashboard.html"><span>📂</span> Patients</a> <a href="#" onclick="showSection('patients')"><span>📂</span> Patients</a>
<a href="pharmacy.html"><span>💊</span> Pharmacy</a> <a href="pharmacy.html"><span>💊</span> Pharmacy</a>
<a href="lab.html"><span>🔬</span> Lab</a> <a href="lab.html"><span>🔬</span> Lab</a>
<a href="billing.html"><span>💳</span> Billing & Accounts</a> <a href="billing.html"><span>💳</span> Billing & Accounts</a>
@ -29,6 +30,7 @@
<div class="info"> <div class="info">
<strong>Dr. Sharma</strong> <strong>Dr. Sharma</strong>
<span>Cardiologist</span> <span>Cardiologist</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div> </div>
</div> </div>
</aside> </aside>
@ -44,101 +46,142 @@
</div> </div>
</header> </header>
<section class="stats-row"> <div id="overview-section">
<div class="stat-card"> <section class="stats-row">
<span>In Queue</span> <div class="stat-card">
<h3>12 Patients</h3> <span>In Queue</span>
<small class="text-accent">↑ 4 since last hour</small> <h3>12 Patients</h3>
</div> <small class="text-accent">↑ 4 since last hour</small>
<div class="stat-card quota-card"> </div>
<span>Current Slot (10:00-10:30)</span> <div class="stat-card quota-card">
<div class="quota-bars"> <span>Current Slot (10:00-10:30)</span>
<div class="quota-item closed"> <div class="quota-bars">
<small>Online: 3/3 (CLOSED)</small> <div class="quota-item closed">
<div class="bar"><div class="fill" style="width: 100%; background: var(--text-muted);"></div></div> <small>Online: 3/3 (CLOSED)</small>
</div> <div class="bar"><div class="fill" style="width: 100%; background: var(--text-muted);"></div></div>
<div class="quota-item"> </div>
<small>Walk-in: 4/5</small> <div class="quota-item">
<div class="bar"><div class="fill" style="width: 80%;"></div></div> <small>Walk-in: 4/5</small>
<div class="bar"><div class="fill" style="width: 80%;"></div></div>
</div>
</div> </div>
</div> </div>
</div> <div class="stat-card">
<div class="stat-card"> <span>Avg. Wait Time</span>
<span>Avg. Wait Time</span> <h3>18 Mins</h3>
<h3>18 Mins</h3> <small class="text-muted">Target: 15 Mins</small>
<small class="text-muted">Target: 15 Mins</small> </div>
</div> </section>
</section>
<section class="queue-section"> <section class="queue-section" id="queue-section">
<div class="section-card"> <div class="section-card">
<div class="card-header"> <div class="card-header">
<h2>Live Queue</h2> <h2>Live Queue</h2>
<div class="filters"> <div class="filters">
<span class="badge">All</span> <span class="badge">All</span>
<span class="badge muted">Appointments</span> <span class="badge muted">Appointments</span>
<span class="badge muted">Walk-ins</span> <span class="badge muted">Walk-ins</span>
</div>
</div> </div>
<table class="queue-table">
<thead>
<tr>
<th>Token</th>
<th>Patient Name</th>
<th>Source</th>
<th>Lang</th>
<th>Triage AI</th>
<th>Status</th>
<th>Arrival</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr class="active-row">
<td>#012</td>
<td><strong>Rahul Verma</strong></td>
<td><span class="source-tag online">Online</span></td>
<td><span class="lang-tag">HI</span></td>
<td><span class="triage-pill urgent">High Fever / Cough</span></td>
<td><span class="status-pill in-room">In Room</span></td>
<td>09:15 AM</td>
<td><button class="btn-small">Prescribe</button></td>
</tr>
<tr>
<td>#013</td>
<td><strong>Anjali Singh</strong></td>
<td><span class="source-tag walkin">Walk-in</span></td>
<td><span class="lang-tag">TE</span></td>
<td><span class="triage-pill moderate">General Checkup</span></td>
<td><span class="status-pill pending-pay">Unpaid (₹500)</span></td>
<td>09:30 AM</td>
<td><button class="btn-small secondary">Collect Pay</button></td>
</tr>
<tr>
<td>#014</td>
<td><strong>Suresh Kumar</strong></td>
<td><span class="source-tag online">Online</span></td>
<td><span class="lang-tag">EN</span></td>
<td><span class="triage-pill routine">Back Pain</span></td>
<td><span class="status-pill waiting">Paid (Waiting)</span></td>
<td>09:45 AM</td>
<td><button class="btn-small secondary">Notify</button></td>
</tr>
</tbody>
</table>
</div>
<div class="side-panel">
<div class="section-card ai-insights">
<h3>✨ AI Insights</h3>
<p>Predicted peak time: <strong>11:30 AM</strong>. Suggesting 5-min break for staff now.</p>
<div class="insight-item">
<small>No-show Alert</small>
<p>Token #015 (Vikram) hasn't replied to the 10-min reminder.</p>
</div>
</div>
</div>
</section>
</div>
<div id="patients-section" class="hidden">
<section class="section-card">
<div class="card-header">
<h2>Patient Records</h2>
<button class="btn-primary">+ Add New Patient</button>
</div> </div>
<table class="queue-table"> <table class="queue-table">
<thead> <thead>
<tr> <tr>
<th>Token</th> <th>Patient ID</th>
<th>Patient Name</th> <th>Name</th>
<th>Source</th> <th>WhatsApp</th>
<th>Lang</th> <th>Last Visit</th>
<th>Triage AI</th> <th>Visits</th>
<th>Status</th>
<th>Arrival</th>
<th>Actions</th> <th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="active-row"> <tr>
<td>#012</td> <td>CF-1001</td>
<td><strong>Rahul Verma</strong></td> <td><strong>Rahul Verma</strong></td>
<td><span class="source-tag online">Online</span></td> <td>+91 98765 43210</td>
<td><span class="lang-tag">HI</span></td> <td>12 May 2026</td>
<td><span class="triage-pill urgent">High Fever / Cough</span></td> <td>5</td>
<td><span class="status-pill in-room">In Room</span></td> <td><button class="btn-small secondary">View History</button></td>
<td>09:15 AM</td>
<td><button class="btn-small">Prescribe</button></td>
</tr> </tr>
<tr> <tr>
<td>#013</td> <td>CF-1002</td>
<td><strong>Anjali Singh</strong></td> <td><strong>Anjali Singh</strong></td>
<td><span class="source-tag walkin">Walk-in</span></td> <td>+91 98234 56789</td>
<td><span class="lang-tag">TE</span></td> <td>Today</td>
<td><span class="triage-pill moderate">General Checkup</span></td> <td>2</td>
<td><span class="status-pill pending-pay">Unpaid (₹500)</span></td> <td><button class="btn-small secondary">View History</button></td>
<td>09:30 AM</td>
<td><button class="btn-small secondary">Collect Pay</button></td>
</tr>
<tr>
<td>#014</td>
<td><strong>Suresh Kumar</strong></td>
<td><span class="source-tag online">Online</span></td>
<td><span class="lang-tag">EN</span></td>
<td><span class="triage-pill routine">Back Pain</span></td>
<td><span class="status-pill waiting">Paid (Waiting)</span></td>
<td>09:45 AM</td>
<td><button class="btn-small secondary">Notify</button></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </section>
</div>
<div class="side-panel">
<div class="section-card ai-insights">
<h3>✨ AI Insights</h3>
<p>Predicted peak time: <strong>11:30 AM</strong>. Suggesting 5-min break for staff now.</p>
<div class="insight-item">
<small>No-show Alert</small>
<p>Token #015 (Vikram) hasn't replied to the 10-min reminder.</p>
</div>
</div>
</div>
</section>
<div id="prescriptionModal" class="modal"> <div id="prescriptionModal" class="modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">

View File

@ -93,3 +93,28 @@ startRecordBtn.onclick = () => {
} }
}, 3000); }, 3000);
}; };
// Section Switching Logic
window.showSection = (sectionId) => {
// Hide all sections
document.getElementById('overview-section').classList.add('hidden');
document.getElementById('patients-section').classList.add('hidden');
// Show target section
if (sectionId === 'overview') {
document.getElementById('overview-section').classList.remove('hidden');
} else if (sectionId === 'queue') {
document.getElementById('overview-section').classList.remove('hidden');
document.getElementById('queue-section').scrollIntoView({ behavior: 'smooth' });
} else if (sectionId === 'patients') {
document.getElementById('patients-section').classList.remove('hidden');
}
// Update active state in nav
document.querySelectorAll('.side-nav a').forEach(link => {
link.classList.remove('active');
if (link.innerText.toLowerCase().includes(sectionId)) {
link.classList.add('active');
}
});
};

View File

@ -432,3 +432,111 @@ footer {
.chat-container { grid-template-columns: 1fr; } .chat-container { grid-template-columns: 1fr; }
.phone-mockup { margin: 0 auto; } .phone-mockup { margin: 0 auto; }
} }
/* Pricing Section */
.pricing-section {
padding: 100px 0;
background: var(--bg);
}
.pricing-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 4rem;
}
.pricing-card {
background: white;
padding: 3rem;
border-radius: 24px;
box-shadow: var(--shadow);
text-align: center;
border: 1px solid var(--border);
transition: transform 0.3s;
position: relative;
overflow: hidden;
}
.pricing-card.featured {
border-color: var(--secondary);
transform: scale(1.05);
}
.pricing-card.featured::after {
content: "Most Popular";
position: absolute;
top: 20px;
right: -35px;
background: var(--secondary);
color: white;
font-size: 0.75rem;
font-weight: 700;
padding: 0.5rem 3rem;
transform: rotate(45deg);
}
.pricing-card h3 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
.price {
font-size: 3rem;
font-weight: 700;
color: var(--primary);
margin-bottom: 2rem;
}
.price span {
font-size: 1rem;
color: var(--text-muted);
}
.pricing-features {
list-style: none;
text-align: left;
margin-bottom: 2.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.pricing-features li {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 0.95rem;
color: var(--text-muted);
}
.pricing-features li::before {
content: "✓";
color: var(--accent);
font-weight: 700;
}
/* Logout & Shared Nav Utilities */
.logout-btn {
margin-top: auto;
padding: 0.75rem 1rem;
color: #F87171;
text-decoration: none;
font-size: 0.875rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 8px;
transition: background 0.3s;
}
.logout-btn:hover {
background: rgba(239, 68, 68, 0.1);
}
.user-actions {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

View File

@ -3,25 +3,26 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow | WhatsApp-First Clinic Management</title> <title>Curio | WhatsApp-First Clinic Management</title>
<meta name="description" content="Revolutionizing Indian OPDs with WhatsApp-native queue management, AI triage, and digital patient records."> <meta name="description" content="Revolutionizing Indian OPDs with WhatsApp-native queue management, AI triage, and digital patient records.">
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="tenantLoader.js"></script>
</head> </head>
<body> <body>
<nav class="glass-nav"> <nav class="glass-nav">
<div class="container"> <div class="container">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<div class="nav-links"> <div class="nav-links">
<a href="#features">Features</a> <a href="#features">Features</a>
<a href="#whatsapp">WhatsApp Flow</a> <a href="#whatsapp">WhatsApp Flow</a>
<a href="#pricing">Pricing</a> <a href="#pricing">Pricing</a>
<button class="btn-primary">Get Started</button> <a href="register.html" class="btn-primary" style="text-decoration: none;">Get Started</a>
</div> </div>
</div> </div>
</nav> </nav>
@ -33,8 +34,8 @@
<h1>Chaotic OPDs are a thing of the <span class="text-gradient">past.</span></h1> <h1>Chaotic OPDs are a thing of the <span class="text-gradient">past.</span></h1>
<p>Manage tokens, appointments, and patient records entirely through WhatsApp. Reduce waiting room crowds and automate admin work with AI-powered triage.</p> <p>Manage tokens, appointments, and patient records entirely through WhatsApp. Reduce waiting room crowds and automate admin work with AI-powered triage.</p>
<div class="hero-btns"> <div class="hero-btns">
<button class="btn-primary btn-lg">Deploy to My Clinic</button> <a href="register.html" class="btn-primary btn-lg" style="text-decoration: none;">Deploy to My Clinic</a>
<button class="btn-secondary btn-lg">Watch Demo</button> <a href="#whatsapp" class="btn-secondary btn-lg" style="text-decoration: none;">Watch Demo</a>
</div> </div>
<div class="hero-stats"> <div class="hero-stats">
<div class="stat"> <div class="stat">
@ -49,7 +50,7 @@
</div> </div>
<div class="hero-visual"> <div class="hero-visual">
<div class="image-wrapper"> <div class="image-wrapper">
<img src="curaflow_hero_ui_1778636262274.png" alt="CuraFlow Dashboard Mockup"> <img src="Curio_hero_ui_1778636262274.png" alt="Curio Dashboard Mockup">
</div> </div>
</div> </div>
</div> </div>
@ -65,7 +66,7 @@
<div class="phone-mockup"> <div class="phone-mockup">
<div class="chat-header"> <div class="chat-header">
<div class="status-dot"></div> <div class="status-dot"></div>
<span>CuraFlow Clinic Assistant</span> <span>Curio Clinic Assistant</span>
</div> </div>
<div class="chat-body" id="chatBody"> <div class="chat-body" id="chatBody">
<div class="msg bot">Hello! Welcome to Dr. Sharma's Clinic. How can I help you today?</div> <div class="msg bot">Hello! Welcome to Dr. Sharma's Clinic. How can I help you today?</div>
@ -135,9 +136,53 @@
<p>Send Razorpay links directly on WhatsApp. Integrated GST billing for pharmacy & labs.</p> <p>Send Razorpay links directly on WhatsApp. Integrated GST billing for pharmacy & labs.</p>
</div> </div>
<div class="feature-item"> <div class="feature-item">
<div class="icon">📜</div> <div class="icon">🏢</div>
<h3>Digital Prescriptions</h3> <h3>Multi-Tenant Branding</h3>
<p>Doctors can generate prescriptions that are instantly sent to the patient's WhatsApp.</p> <p>Enterprise ready. Full white-label support for hospital chains with custom logos, themes, and domains.</p>
</div>
</div>
</div>
</section>
<section id="pricing" class="pricing-section">
<div class="container">
<div class="section-header">
<h2>Simple, Transparent Pricing</h2>
<p>Choose the plan that fits your clinic's volume.</p>
</div>
<div class="pricing-grid">
<div class="pricing-card">
<h3>Basic</h3>
<div class="price">₹1,499<span>/mo</span></div>
<ul class="pricing-features">
<li>Up to 500 tokens/mo</li>
<li>Basic WhatsApp Queue</li>
<li>Digital Prescriptions</li>
<li>Single Doctor Support</li>
</ul>
<a href="register.html" class="btn-secondary" style="display: block; text-decoration: none;">Choose Basic</a>
</div>
<div class="pricing-card featured">
<h3>Pro</h3>
<div class="price">₹3,999<span>/mo</span></div>
<ul class="pricing-features">
<li>Unlimited Tokens</li>
<li>AI Triage & Summaries</li>
<li>Pharmacy & Lab Integration</li>
<li>Multi-Doctor Support</li>
</ul>
<a href="register.html" class="btn-primary" style="display: block; text-decoration: none;">Get Started Pro</a>
</div>
<div class="pricing-card">
<h3>Enterprise</h3>
<div class="price">Custom</div>
<ul class="pricing-features">
<li>Multi-Clinic Chain</li>
<li>Custom AI Training</li>
<li>White-label WhatsApp Bot</li>
<li>Dedicated Account Manager</li>
</ul>
<a href="register.html" class="btn-secondary" style="display: block; text-decoration: none;">Contact Sales</a>
</div> </div>
</div> </div>
</div> </div>
@ -145,7 +190,7 @@
<footer> <footer>
<div class="container"> <div class="container">
<p>&copy; 2026 CuraFlow Technologies. Empowering healthcare in Bharat.</p> <p>&copy; 2026 Curio Technologies. Empowering healthcare in Bharat.</p>
</div> </div>
</footer> </footer>

View File

@ -47,7 +47,7 @@ function handleOptionClick() {
chatBody.appendChild(optDiv); chatBody.appendChild(optDiv);
bindOptions(); bindOptions();
} else if (userMsg === '10:00 AM' || userMsg === '10:30 AM') { } else if (userMsg === '10:00 AM' || userMsg === '10:30 AM') {
botDiv.innerHTML = `✅ Confirmed! Your token is *#ON-3* for the ${userMsg} slot.<br><br>💳 *Payment Required*: Please pay ₹500 to activate your token: <a href="#">razorpay.me/curaflow</a><br><br>Also, to help Dr. Sharma prepare, could you briefly describe your symptoms?`; botDiv.innerHTML = `✅ Confirmed! Your token is *#ON-3* for the ${userMsg} slot.<br><br>💳 *Payment Required*: Please pay ₹500 to activate your token: <a href="#">razorpay.me/Curio</a><br><br>Also, to help Dr. Sharma prepare, could you briefly describe your symptoms?`;
chatBody.appendChild(botDiv); chatBody.appendChild(botDiv);
} else if (userMsg === 'Check Queue' || userMsg === 'Check Queue Status') { } else if (userMsg === 'Check Queue' || userMsg === 'Check Queue Status') {
botDiv.innerText = "Current status: 5 people ahead of you. Estimated wait time: 25 minutes."; botDiv.innerText = "Current status: 5 people ahead of you. Estimated wait time: 25 minutes.";

View File

@ -0,0 +1,17 @@
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: curio-route
namespace: curaflow
spec:
http:
- name: Curio-rule
match:
hosts:
- curaflow.applaude.net
- curio.applaude.net
paths:
- /*
backends:
- serviceName: Curio-app
servicePort: 80

View File

@ -1,55 +1,35 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: curaflow-app name: curio-app
namespace: curaflow
spec: spec:
replicas: 2 replicas: 2
selector: selector:
matchLabels: matchLabels:
app: curaflow-app app: Curio-app
template: template:
metadata: metadata:
labels: labels:
app: curaflow-app app: Curio-app
spec: spec:
containers: containers:
- name: curaflow - name: Curio
image: 192.168.8.250:5000/agentic-os/curaflow:latest image: 192.168.8.250:5000/Curio:latest
ports: ports:
- containerPort: 3000 - containerPort: 3000
env: env:
- name: DATABASE_URL - name: DATABASE_URL
value: "postgres://postgres:curaflow_secret@curaflow-db:5432/curaflow" value: "postgres://postgres:Curio_secret@Curio-db:5432/Curio"
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: curaflow-app name: curio-app
namespace: curaflow
spec: spec:
selector: selector:
app: curaflow-app app: Curio-app
ports: ports:
- port: 80 - port: 80
targetPort: 3000 targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: curaflow-ingress
namespace: curaflow
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
k8s.apisix.apache.org/enable-websocket: "true"
spec:
ingressClassName: apisix
rules:
- host: curaflow.applaude.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: curaflow-app
port:
number: 80

View File

@ -1,33 +1,33 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: curaflow-db name: Curio-db
spec: spec:
selector: selector:
matchLabels: matchLabels:
app: curaflow-db app: Curio-db
template: template:
metadata: metadata:
labels: labels:
app: curaflow-db app: Curio-db
spec: spec:
containers: containers:
- name: postgres - name: postgres
image: postgres:15-alpine image: postgres:15-alpine
env: env:
- name: POSTGRES_PASSWORD - name: POSTGRES_PASSWORD
value: "curaflow_secret" value: "Curio_secret"
- name: POSTGRES_DB - name: POSTGRES_DB
value: "curaflow" value: "Curio"
ports: ports:
- containerPort: 5432 - containerPort: 5432
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: curaflow-db name: Curio-db
spec: spec:
selector: selector:
app: curaflow-db app: Curio-db
ports: ports:
- port: 5432 - port: 5432

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Lab | Diagnostics & Reports</title> <title>Curio Lab | Diagnostics & Reports</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="lab.css"> <link rel="stylesheet" href="lab.css">
@ -13,7 +13,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html"><span>🏠</span> Overview</a> <a href="dashboard.html"><span>🏠</span> Overview</a>
@ -25,6 +25,14 @@
<a href="staff.html"><span>👔</span> Staff & Payroll</a> <a href="staff.html"><span>👔</span> Staff & Payroll</a>
<a href="settings.html"><span>⚙️</span> Settings</a> <a href="settings.html"><span>⚙️</span> Settings</a>
</nav> </nav>
<div class="user-profile">
<div class="avatar">LT</div>
<div class="info">
<strong>Lab Tech</strong>
<span>Staff</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div>
</div>
</aside> </aside>
<main class="dashboard-main"> <main class="dashboard-main">

View File

@ -3,17 +3,18 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login | CuraFlow HMS</title> <title>Login | Curio HMS</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="login.css"> <link rel="stylesheet" href="login.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet">
<script src="tenantLoader.js"></script>
</head> </head>
<body class="auth-body"> <body class="auth-body">
<div class="auth-container"> <div class="auth-container">
<div class="auth-card"> <div class="auth-card">
<div class="auth-logo"> <div class="auth-logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<h1>CuraFlow</h1> <h1>Curio</h1>
</div> </div>
<h2>Welcome Back</h2> <h2>Welcome Back</h2>
<p>Login to manage your clinic OPD and accounts.</p> <p>Login to manage your clinic OPD and accounts.</p>
@ -30,14 +31,21 @@
<button type="submit" class="btn-primary auth-btn">Login to Dashboard</button> <button type="submit" class="btn-primary auth-btn">Login to Dashboard</button>
</form> </form>
<p class="auth-footer">New to CuraFlow? <a href="register.html">Register your clinic</a></p> <p class="auth-footer">New to Curio? <a href="register.html">Register your clinic</a></p>
</div> </div>
</div> </div>
<script> <script>
document.getElementById('loginForm').onsubmit = (e) => { document.getElementById('loginForm').onsubmit = (e) => {
e.preventDefault(); e.preventDefault();
window.location.href = 'dashboard.html'; const email = e.target.querySelector('input[type="text"]').value;
const password = e.target.querySelector('input[type="password"]').value;
if (email === 'deepkoluguri@gmail.com' && password === 'password123') {
window.location.href = 'dashboard.html';
} else {
alert('Invalid credentials. Hint: deepkoluguri@gmail.com / password123');
}
}; };
</script> </script>
</body> </body>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Pharmacy | Inventory & Billing</title> <title>Curio Pharmacy | Inventory & Billing</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="pharmacy.css"> <link rel="stylesheet" href="pharmacy.css">
@ -13,7 +13,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html"><span>🏠</span> Overview</a> <a href="dashboard.html"><span>🏠</span> Overview</a>
@ -25,6 +25,14 @@
<a href="staff.html"><span>👔</span> Staff & Payroll</a> <a href="staff.html"><span>👔</span> Staff & Payroll</a>
<a href="settings.html"><span>⚙️</span> Settings</a> <a href="settings.html"><span>⚙️</span> Settings</a>
</nav> </nav>
<div class="user-profile">
<div class="avatar">PH</div>
<div class="info">
<strong>Pharmacy Head</strong>
<span>Staff</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div>
</div>
</aside> </aside>
<main class="dashboard-main"> <main class="dashboard-main">

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clinic Registration | CuraFlow HMS</title> <title>Clinic Registration | Curio HMS</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="login.css"> <link rel="stylesheet" href="login.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap" rel="stylesheet">
@ -13,7 +13,7 @@
<div class="auth-card"> <div class="auth-card">
<div class="auth-logo"> <div class="auth-logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<h1>CuraFlow</h1> <h1>Curio</h1>
</div> </div>
<h2>Register Your Clinic</h2> <h2>Register Your Clinic</h2>
<p>Join Bharat's first WhatsApp-native HMS.</p> <p>Join Bharat's first WhatsApp-native HMS.</p>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Settings | Hospital Configuration</title> <title>Curio Settings | Hospital Configuration</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="settings.css"> <link rel="stylesheet" href="settings.css">
@ -13,7 +13,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html"><span>🏠</span> Overview</a> <a href="dashboard.html"><span>🏠</span> Overview</a>
@ -25,6 +25,14 @@
<a href="staff.html"><span>👔</span> Staff & Payroll</a> <a href="staff.html"><span>👔</span> Staff & Payroll</a>
<a href="settings.html" class="active"><span>⚙️</span> Settings</a> <a href="settings.html" class="active"><span>⚙️</span> Settings</a>
</nav> </nav>
<div class="user-profile">
<div class="avatar">AD</div>
<div class="info">
<strong>Admin</strong>
<span>Settings</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div>
</div>
</aside> </aside>
<main class="dashboard-main"> <main class="dashboard-main">

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow Staff | Personnel & Payroll</title> <title>Curio Staff | Personnel & Payroll</title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="dashboard.css"> <link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="staff.css"> <link rel="stylesheet" href="staff.css">
@ -13,7 +13,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="logo"> <div class="logo">
<span class="logo-icon">C</span> <span class="logo-icon">C</span>
<span class="logo-text">CuraFlow</span> <span class="logo-text">Curio</span>
</div> </div>
<nav class="side-nav"> <nav class="side-nav">
<a href="dashboard.html"><span>🏠</span> Overview</a> <a href="dashboard.html"><span>🏠</span> Overview</a>
@ -25,6 +25,14 @@
<a href="staff.html" class="active"><span>👔</span> Staff & Payroll</a> <a href="staff.html" class="active"><span>👔</span> Staff & Payroll</a>
<a href="settings.html"><span>⚙️</span> Settings</a> <a href="settings.html"><span>⚙️</span> Settings</a>
</nav> </nav>
<div class="user-profile">
<div class="avatar">SA</div>
<div class="info">
<strong>Staff Admin</strong>
<span>Staff</span>
<a href="login.html" class="logout-btn"><span>🚪</span> Logout</a>
</div>
</div>
</aside> </aside>
<main class="dashboard-main"> <main class="dashboard-main">

47
curaflow/tenantLoader.js Normal file
View File

@ -0,0 +1,47 @@
/**
* tenantLoader.js: Dynamically applies branding and multi-tenant settings.
*/
async function loadTenantBranding() {
// Determine tenant from URL (e.g., ?tenant=sharma-clinic) or localStorage
const urlParams = new URLSearchParams(window.location.search);
let tenantId = urlParams.get('tenant') || localStorage.getItem('Curio_tenant') || 'default';
// Save to localStorage for persistence across pages
localStorage.setItem('Curio_tenant', tenantId);
try {
const response = await fetch(`/api/config/${tenantId}`);
const config = await response.json();
applyBranding(config);
} catch (error) {
console.error("Failed to load tenant branding:", error);
}
}
function applyBranding(config) {
// 1. Apply CSS Variables for dynamic coloring
document.documentElement.style.setProperty('--primary', config.primaryColor);
document.documentElement.style.setProperty('--secondary', config.secondaryColor);
// 2. Update UI Elements (Logo, Name)
const logoIcons = document.querySelectorAll('.logo-icon');
const logoTexts = document.querySelectorAll('.logo-text, .header-title h1, .auth-logo h1');
const hospitalNames = document.querySelectorAll('.hospital-name, .logo-text');
logoIcons.forEach(icon => icon.innerText = config.logo);
// Update Document Title
document.title = `${config.name} | Curio`;
// Update instances of hospital name in text
document.querySelectorAll('[data-tenant-name]').forEach(el => {
el.innerText = config.name;
});
console.log(`Branding applied for: ${config.name}`);
}
// Auto-load on script include
document.addEventListener('DOMContentLoaded', loadTenantBranding);