Neolife Wellness Admin Dashboard

Syncing... Website: Live App: Live

Total Users

0

Admins

0

Doctors

0

Employees

0

Patients

0

Recent User Registrations

0 records
User Email Phone Role Last Platform Last Login

All Users List

0 users
User Email Phone Current Role Assign Role Platform Created Action

Latest Appointments

0 items
User Email Doctor Mode Date Time Status Action

Doctor Live Queue

0 items
Position Patient Consultation Priority Room Action

Doctor Appointment Listing

0 items
Patient Email Service Mode Date Time Status Action

Appointment Notifications

0 items
Recipient Type Message Status Date

E-commerce Orders

0 items
Order ID Customer Amount Status Items Date

Product Upload & Catalog Management

0 products
Upload a medicine image directly. The file is optimized in-browser before saving.
💊
Medicine photo placeholder
Add an image URL or upload a medicine image file to preview it here.

Admins and staff (employee role) can upload and manage products. Categories now support Patent Medicines, Neolife Products, and broader catalog groups. Data is saved in Firestore collection medicines and mirrored in local cache for offline fallback.

Product manager ready.
Product Category Price Stock Status Updated Action

Plain Text To Article Files

Article Input

This generates 3 files: {slug}.html, {slug}.css, and {slug}.js. If browser file-system access is available, files can be saved directly into both articles and hosting-public/articles.
Ready to generate article files.

Live Preview

Generate preview to see formatted content.

Latest Payments

0 items
User Email Amount Method Status Date

Ratings & Reviews

0 items
Customer Rating Review Doctor Verified Badge Status Date Action

Role Matrix

Admin: Full system access, role management, analytics and settings.

Doctor: Access to appointments and patient treatment workflows.

Employee: Operations support access (appointments, orders, notifications).

Patient: Standard portal access for appointments, medicines and profile.

Unknown: Users with missing role assignment. Assign immediately from "All Users".

Settings

Core admin functions are active. Use Website + App Control to configure platform operations, visibility, and critical workflows.

Website + App Full Control Center

Shared operations control for admin, doctor, and staff

Website Operations

App Operations

Emergency + Messaging

Operational Notes

These settings are saved to Firestore in platformControls/global and mirrored in browser cache for fallback. Website and app clients can read this document to enforce live/maintenance behavior in real time.

Control center ready.
`; } function buildArticleCardHtml(bundle) { const summary = bundle.summary.length > 132 ? `${bundle.summary.slice(0, 129)}...` : bundle.summary; return `
📘

${escapeHtml(bundle.title)}

${escapeHtml(summary)}

Read Article
`; } function injectArticleCardIntoIndex(indexHtml, bundle) { if (!indexHtml || indexHtml.includes(`href="${bundle.slug}.html"`)) { return indexHtml; } const cardHtml = buildArticleCardHtml(bundle); const marker = "

Add New Article

"; const markerPos = indexHtml.indexOf(marker); if (markerPos !== -1) { const articleStart = indexHtml.lastIndexOf("${escapeHtml(bundle.title)}

${escapeHtml(bundle.summary)}

${bundle.contentHtml}
`; if (badges) { badges.innerHTML = ` ${escapeHtml(bundle.slug)}.html ${escapeHtml(bundle.slug)}.css ${escapeHtml(bundle.slug)}.js `; } } async function writeTextToFile(directoryHandle, fileName, content) { const fileHandle = await directoryHandle.getFileHandle(fileName, { create: true }); const writable = await fileHandle.createWritable(); await writable.write(content); await writable.close(); } async function readTextFromFile(directoryHandle, fileName) { try { const fileHandle = await directoryHandle.getFileHandle(fileName); const file = await fileHandle.getFile(); return await file.text(); } catch (error) { return ""; } } async function saveArticleBundleToWebsiteFolder(bundle) { if (!window.showDirectoryPicker) { throw new Error("Browser file-system save is unavailable. Use Download Files and move them into articles folder."); } setArticleStudioStatus("Select your Website root folder to save article files."); const root = await window.showDirectoryPicker({ mode: "readwrite" }); const articlesDir = await root.getDirectoryHandle("articles", { create: true }); await writeTextToFile(articlesDir, `${bundle.slug}.html`, bundle.html); await writeTextToFile(articlesDir, `${bundle.slug}.css`, bundle.css); await writeTextToFile(articlesDir, `${bundle.slug}.js`, bundle.js); const sourceIndex = await readTextFromFile(articlesDir, "index.html"); if (sourceIndex) { const updatedSourceIndex = injectArticleCardIntoIndex(sourceIndex, bundle); if (updatedSourceIndex !== sourceIndex) { await writeTextToFile(articlesDir, "index.html", updatedSourceIndex); } } let hostedSaved = false; try { const hostingPublicDir = await root.getDirectoryHandle("hosting-public"); const hostingArticlesDir = await hostingPublicDir.getDirectoryHandle("articles", { create: true }); await writeTextToFile(hostingArticlesDir, `${bundle.slug}.html`, bundle.html); await writeTextToFile(hostingArticlesDir, `${bundle.slug}.css`, bundle.css); await writeTextToFile(hostingArticlesDir, `${bundle.slug}.js`, bundle.js); const hostedIndex = await readTextFromFile(hostingArticlesDir, "index.html"); if (hostedIndex) { const updatedHostedIndex = injectArticleCardIntoIndex(hostedIndex, bundle); if (updatedHostedIndex !== hostedIndex) { await writeTextToFile(hostingArticlesDir, "index.html", updatedHostedIndex); } } hostedSaved = true; } catch (error) { hostedSaved = false; } if (window.db && typeof window.db.collection === "function") { try { await window.db.collection("articleDrafts").add({ title: bundle.title, slug: bundle.slug, category: bundle.category, author: bundle.author, summary: bundle.summary, status: "generated", source: "admin-article-studio", createdByRole: currentActorRole, createdAt: new Date(), updatedAt: new Date() }); } catch (error) { console.warn("Article draft metadata sync skipped", error); } } const hostedText = hostedSaved ? " and hosting-public/articles" : ""; setArticleStudioStatus(`Saved ${bundle.slug}.html/.css/.js to articles${hostedText}.`, "success"); } function downloadSingleTextFile(fileName, content) { const blob = new Blob([content], { type: "text/plain;charset=utf-8" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); } function downloadArticleBundle(bundle) { downloadSingleTextFile(`${bundle.slug}.html`, bundle.html); setTimeout(() => downloadSingleTextFile(`${bundle.slug}.css`, bundle.css), 140); setTimeout(() => downloadSingleTextFile(`${bundle.slug}.js`, bundle.js), 280); setArticleStudioStatus(`Downloaded ${bundle.slug}.html/.css/.js. Move files to articles folder if needed.`, "success"); } async function fullRefresh() { setSyncStatus("Syncing...", true); await Promise.allSettled([ runSyncTask("Users", loadUsers), runSyncTask("Appointments", loadAppointments), runSyncTask("Notifications", loadNotifications), runSyncTask("Ecommerce orders", loadOrders), runSyncTask("Products", loadProductsForManagement), runSyncTask("Payments", loadPayments), runSyncTask("Reviews", loadReviews), runSyncTask("Control center", loadControlCenter) ]); setSyncStatus("Live", true); } async function boot() { if (!enforceAdminAccess()) { return; } if (typeof window.initializeFirebase === "function") { window.initializeFirebase(); } if ((!window.db || !window.auth) && typeof window.initFirebaseDirect === "function") { try { await window.initFirebaseDirect(); } catch (error) { console.error("Direct Firebase bootstrap failed:", error); } } attachNavigationHandlers(); initFilters(); initActions(); try { await fullRefresh(); } catch (error) { console.error(error); setSyncStatus("Connected", true); } } document.addEventListener("DOMContentLoaded", boot);