From 20ec0862c419cdcc5f1071f25f155588b23bf471 Mon Sep 17 00:00:00 2001 From: Aditya Shah Date: Fri, 12 Dec 2025 10:44:54 +0530 Subject: [PATCH 1/4] adds css and theme file for quicklab --- client/src/quicklab-theme.js | 79 +++++++++ client/src/quicklab.css | 159 ++++++++++++++++++ client/src/shared-base.css | 21 +++ .../QuickLab/labReportController.js | 2 - 4 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 client/src/quicklab-theme.js create mode 100644 client/src/quicklab.css create mode 100644 client/src/shared-base.css diff --git a/client/src/quicklab-theme.js b/client/src/quicklab-theme.js new file mode 100644 index 0000000..3bcbb03 --- /dev/null +++ b/client/src/quicklab-theme.js @@ -0,0 +1,79 @@ +// quicklab-theme.js + +export const colors = { + primary: '#eab308', // yellow-500 + primaryDark: '#ca8a04', // yellow-600 + primaryLight: '#facc15', // yellow-400 + secondary: '#1e293b', // black-800 + accent: '#3b82f6', // blue-500 + accentDark: '#2563eb', // blue-600 + light: '#f8fafc', // slate-50 + dark: '#000000', // pure black + darkSurface: '#0f172a', // slate-900 + success: '#22c55e', // green (from QuickMed) + warning: '#f59e0b', // amber + danger: '#ef4444', // red + info: '#3b82f6', // blue + text: { + light: '#0f172a', + dark: '#f8fafc', + muted: { + light: '#64748b', + dark: '#94a3b8', + }, + }, + border: { + light: '#e2e8f0', + dark: '#1e293b', + }, +}; + +export const spacing = { + xs: '0.25rem', + sm: '0.5rem', + md: '1rem', + lg: '1.5rem', + xl: '2rem', + '2xl': '3rem', +}; + +export const breakpoints = { + sm: '640px', + md: '768px', + lg: '1024px', + xl: '1280px', + '2xl': '1536px', +}; + +export const shadows = { + sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', + md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)', + lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)', + xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)', + yellow: '0 4px 14px 0 rgba(234, 179, 8, 0.39)', // yellow glow + blue: '0 4px 14px 0 rgba(59, 130, 246, 0.39)', // blue glow +}; + +export const transitions = { + fast: '150ms ease-in-out', + normal: '200ms ease-in-out', + slow: '300ms ease-in-out', +}; + +// Theme toggle functionality +export const initTheme = () => { + const theme = localStorage.getItem('quicklab-theme') || 'light'; + document.documentElement.classList.toggle('dark', theme === 'dark'); + return theme; +}; + +export const toggleTheme = () => { + const isDark = document.documentElement.classList.toggle('dark'); + localStorage.setItem('quicklab-theme', isDark ? 'dark' : 'light'); + return isDark ? 'dark' : 'light'; +}; + +export const setTheme = (theme) => { + document.documentElement.classList.toggle('dark', theme === 'dark'); + localStorage.setItem('quicklab-theme', theme); +}; diff --git a/client/src/quicklab.css b/client/src/quicklab.css new file mode 100644 index 0000000..88132f4 --- /dev/null +++ b/client/src/quicklab.css @@ -0,0 +1,159 @@ +@import 'tailwindcss'; + +/* Enable dark mode with class selector */ +@custom-variant dark (&:where(.dark, .dark *)); + +@theme { + /* QuickLab Light Mode Colors - Yellow/Gold Spectrum */ + --color-lab-yellow-50: #fefce8; + --color-lab-yellow-100: #fef9c3; + --color-lab-yellow-200: #fef08a; + --color-lab-yellow-300: #fde047; + --color-lab-yellow-400: #facc15; + --color-lab-yellow-500: #eab308; + --color-lab-yellow-600: #ca8a04; + --color-lab-yellow-700: #a16207; + --color-lab-yellow-800: #854d0e; + --color-lab-yellow-900: #713f12; + + /* QuickLab Black/Gray Spectrum */ + --color-lab-black-50: #f8fafc; + --color-lab-black-100: #f1f5f9; + --color-lab-black-200: #e2e8f0; + --color-lab-black-300: #cbd5e1; + --color-lab-black-400: #94a3b8; + --color-lab-black-500: #64748b; + --color-lab-black-600: #475569; + --color-lab-black-700: #334155; + --color-lab-black-800: #1e293b; + --color-lab-black-900: #0f172a; + + /* QuickLab Blue Accent */ + --color-lab-blue-400: #60a5fa; + --color-lab-blue-500: #3b82f6; + --color-lab-blue-600: #2563eb; + --color-lab-blue-700: #1d4ed8; + + /* Light Mode Base Colors */ + --color-lab-background: #ffffff; + --color-lab-surface: #f8fafc; + --color-lab-text: #0f172a; + --color-lab-text-muted: #64748b; + --color-lab-border: #e2e8f0; + --color-lab-primary: #eab308; + --color-lab-primary-dark: #ca8a04; + --color-lab-secondary: #1e293b; + --color-lab-accent: #3b82f6; +} + +/* Dark Mode Overrides */ +@layer base { + .dark { + --color-lab-yellow-500: #facc15; + --color-lab-yellow-600: #eab308; + --color-lab-yellow-700: #ca8a04; + --color-lab-blue-500: #60a5fa; + --color-lab-blue-600: #3b82f6; + + /* Dark Mode Base Colors */ + --color-lab-background: #000000; + --color-lab-surface: #0f172a; + --color-lab-text: #f8fafc; + --color-lab-text-muted: #94a3b8; + --color-lab-border: #1e293b; + --color-lab-primary: #facc15; + --color-lab-primary-dark: #eab308; + --color-lab-secondary: #f8fafc; + --color-lab-accent: #60a5fa; + } +} + +/* Custom Component Classes */ +@layer components { + /* Primary Button */ + .btn-quicklab-primary { + background-color: var(--color-lab-primary); + color: var(--color-lab-black-900); + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + transition: background-color 0.2s; + font-weight: 600; + } + + .btn-quicklab-primary:hover { + background-color: var(--color-lab-primary-dark); + } + + /* Secondary Button (Black) */ + .btn-quicklab-secondary { + background-color: var(--color-lab-secondary); + color: var(--color-lab-yellow-400); + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + transition: all 0.2s; + font-weight: 600; + border: 2px solid var(--color-lab-primary); + } + + .btn-quicklab-secondary:hover { + background-color: var(--color-lab-black-800); + border-color: var(--color-lab-yellow-500); + } + + /* Blue Accent Button */ + .btn-quicklab-accent { + background-color: var(--color-lab-accent); + color: white; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + transition: background-color 0.2s; + font-weight: 600; + } + + .btn-quicklab-accent:hover { + background-color: var(--color-lab-blue-600); + } + + /* Card Component */ + .card-quicklab { + background-color: var(--color-lab-surface); + border: 1px solid var(--color-lab-border); + border-radius: 0.75rem; + padding: 1.5rem; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + transition: all 0.2s; + } + + .card-quicklab:hover { + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + border-color: var(--color-lab-primary); + } + + /* Badge Component */ + .badge-quicklab { + background-color: var(--color-lab-yellow-100); + color: var(--color-lab-yellow-800); + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.875rem; + font-weight: 600; + } + + .dark .badge-quicklab { + background-color: var(--color-lab-yellow-900); + color: var(--color-lab-yellow-300); + } + + /* Alert Component */ + .alert-quicklab { + background-color: var(--color-lab-blue-50); + border-left: 4px solid var(--color-lab-accent); + padding: 1rem; + border-radius: 0.5rem; + } + + .dark .alert-quicklab { + background-color: var(--color-lab-blue-900); + border-left-color: var(--color-lab-blue-500); + } +} diff --git a/client/src/shared-base.css b/client/src/shared-base.css new file mode 100644 index 0000000..40ec3b6 --- /dev/null +++ b/client/src/shared-base.css @@ -0,0 +1,21 @@ +/* shared-base.css */ +:root { + --transition-speed: 0.2s; + --border-radius-sm: 0.5rem; + --border-radius-md: 0.75rem; + --border-radius-lg: 1rem; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + transition: + background-color var(--transition-speed), + color var(--transition-speed); +} diff --git a/server/Controllers/QuickLab/labReportController.js b/server/Controllers/QuickLab/labReportController.js index 3eb9415..b84db20 100644 --- a/server/Controllers/QuickLab/labReportController.js +++ b/server/Controllers/QuickLab/labReportController.js @@ -1,5 +1,3 @@ -// controllers/labReportController.js -import mongoose from 'mongoose'; import LabReport from '../../models/Lab/LabReport.js'; import LabAppointment from '../../models/Lab/LabAppointment.js'; import { uploadToCloudinary } from '../../services/uploadService.js'; From b377a5da758e07ae5ee0936724147d05688ebeee Mon Sep 17 00:00:00 2001 From: Aditya Shah Date: Mon, 15 Dec 2025 09:54:26 +0530 Subject: [PATCH 2/4] adds css file for quicklabs --- client/src/quicklab.css | 102 +++++++++++++++------------------------- 1 file changed, 39 insertions(+), 63 deletions(-) diff --git a/client/src/quicklab.css b/client/src/quicklab.css index 88132f4..447f199 100644 --- a/client/src/quicklab.css +++ b/client/src/quicklab.css @@ -33,38 +33,17 @@ --color-lab-blue-500: #3b82f6; --color-lab-blue-600: #2563eb; --color-lab-blue-700: #1d4ed8; - - /* Light Mode Base Colors */ - --color-lab-background: #ffffff; - --color-lab-surface: #f8fafc; - --color-lab-text: #0f172a; - --color-lab-text-muted: #64748b; - --color-lab-border: #e2e8f0; - --color-lab-primary: #eab308; - --color-lab-primary-dark: #ca8a04; - --color-lab-secondary: #1e293b; - --color-lab-accent: #3b82f6; } /* Dark Mode Overrides */ @layer base { .dark { + --color-lab-yellow-400: #facc15; --color-lab-yellow-500: #facc15; --color-lab-yellow-600: #eab308; --color-lab-yellow-700: #ca8a04; --color-lab-blue-500: #60a5fa; --color-lab-blue-600: #3b82f6; - - /* Dark Mode Base Colors */ - --color-lab-background: #000000; - --color-lab-surface: #0f172a; - --color-lab-text: #f8fafc; - --color-lab-text-muted: #94a3b8; - --color-lab-border: #1e293b; - --color-lab-primary: #facc15; - --color-lab-primary-dark: #eab308; - --color-lab-secondary: #f8fafc; - --color-lab-accent: #60a5fa; } } @@ -72,67 +51,77 @@ @layer components { /* Primary Button */ .btn-quicklab-primary { - background-color: var(--color-lab-primary); - color: var(--color-lab-black-900); + background-color: rgb(234 179 8); /* yellow-500 */ + color: rgb(15 23 42); /* black-900 */ padding: 0.75rem 1.5rem; border-radius: 0.5rem; transition: background-color 0.2s; font-weight: 600; } + .dark .btn-quicklab-primary { + background-color: rgb(250 204 21); /* yellow-400 */ + color: rgb(15 23 42); /* black-900 - stays dark */ + } + .btn-quicklab-primary:hover { - background-color: var(--color-lab-primary-dark); + background-color: rgb(202 138 4); /* yellow-600 */ + } + + .dark .btn-quicklab-primary:hover { + background-color: rgb(234 179 8); /* yellow-500 */ } /* Secondary Button (Black) */ .btn-quicklab-secondary { - background-color: var(--color-lab-secondary); - color: var(--color-lab-yellow-400); + background-color: rgb(30 41 59); /* black-800 */ + color: rgb(250 204 21); /* yellow-400 */ padding: 0.75rem 1.5rem; border-radius: 0.5rem; transition: all 0.2s; font-weight: 600; - border: 2px solid var(--color-lab-primary); + border: 2px solid rgb(234 179 8); /* yellow-500 */ } - .btn-quicklab-secondary:hover { - background-color: var(--color-lab-black-800); - border-color: var(--color-lab-yellow-500); + .dark .btn-quicklab-secondary { + background-color: rgb(248 250 252); /* light in dark mode */ + color: rgb(30 41 59); /* dark text */ + border-color: rgb(250 204 21); /* yellow-400 */ } - /* Blue Accent Button */ - .btn-quicklab-accent { - background-color: var(--color-lab-accent); - color: white; - padding: 0.75rem 1.5rem; - border-radius: 0.5rem; - transition: background-color 0.2s; - font-weight: 600; - } - - .btn-quicklab-accent:hover { - background-color: var(--color-lab-blue-600); + .btn-quicklab-secondary:hover { + background-color: rgb(15 23 42); /* black-900 */ + border-color: rgb(234 179 8); /* yellow-500 */ } /* Card Component */ .card-quicklab { - background-color: var(--color-lab-surface); - border: 1px solid var(--color-lab-border); + background-color: rgb(248 250 252); /* surface light */ + border: 1px solid rgb(226 232 240); /* border light */ border-radius: 0.75rem; padding: 1.5rem; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); transition: all 0.2s; } + .dark .card-quicklab { + background-color: rgb(15 23 42); /* surface dark */ + border-color: rgb(30 41 59); /* border dark */ + } + .card-quicklab:hover { box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); - border-color: var(--color-lab-primary); + border-color: rgb(234 179 8); /* yellow-500 */ + } + + .dark .card-quicklab:hover { + border-color: rgb(250 204 21); /* yellow-400 */ } /* Badge Component */ .badge-quicklab { - background-color: var(--color-lab-yellow-100); - color: var(--color-lab-yellow-800); + background-color: rgb(254 249 195); /* yellow-100 */ + color: rgb(133 77 14); /* yellow-800 */ padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.875rem; @@ -140,20 +129,7 @@ } .dark .badge-quicklab { - background-color: var(--color-lab-yellow-900); - color: var(--color-lab-yellow-300); - } - - /* Alert Component */ - .alert-quicklab { - background-color: var(--color-lab-blue-50); - border-left: 4px solid var(--color-lab-accent); - padding: 1rem; - border-radius: 0.5rem; - } - - .dark .alert-quicklab { - background-color: var(--color-lab-blue-900); - border-left-color: var(--color-lab-blue-500); + background-color: rgb(113 63 18); /* yellow-900 */ + color: rgb(253 224 71); /* yellow-300 */ } } From 2692ff1a3678d4e3e502b8868278de83eb8555f6 Mon Sep 17 00:00:00 2001 From: Aditya Shah Date: Mon, 15 Dec 2025 09:54:48 +0530 Subject: [PATCH 3/4] adds navbar for quicklab --- .../src/components/quicklab/DesktopNavbar.jsx | 51 ++++++++++++++ .../src/components/quicklab/MobileNavbar.jsx | 69 +++++++++++++++++++ client/src/components/quicklab/Navbar.jsx | 18 +++++ 3 files changed, 138 insertions(+) create mode 100644 client/src/components/quicklab/DesktopNavbar.jsx create mode 100644 client/src/components/quicklab/MobileNavbar.jsx create mode 100644 client/src/components/quicklab/Navbar.jsx diff --git a/client/src/components/quicklab/DesktopNavbar.jsx b/client/src/components/quicklab/DesktopNavbar.jsx new file mode 100644 index 0000000..09907e7 --- /dev/null +++ b/client/src/components/quicklab/DesktopNavbar.jsx @@ -0,0 +1,51 @@ +// DesktopNavbar.jsx +import { Search } from 'lucide-react'; +import DarkModeToggle from '../ui/DarkModeToggle'; + +export default function DesktopNavbar({ searchQuery, setSearchQuery }) { + return ( + + ); +} diff --git a/client/src/components/quicklab/MobileNavbar.jsx b/client/src/components/quicklab/MobileNavbar.jsx new file mode 100644 index 0000000..f5768d9 --- /dev/null +++ b/client/src/components/quicklab/MobileNavbar.jsx @@ -0,0 +1,69 @@ +// MobileNavbar.jsx +import { Search, Home, BookOpen, User } from 'lucide-react'; +import DarkModeToggle from '../ui/DarkModeToggle'; + +export default function MobileNavbar({ searchQuery, setSearchQuery }) { + return ( + <> + {/* Top Bar - Search Only */} +
+
+ {/* Logo */} +
+
+ Quick + Labs +
+
+ +
+
+ +
+ setSearchQuery(e.target.value)} + placeholder="Search labs..." + className="block w-full pl-10 pr-3 py-2 border border-slate-300 dark:border-slate-700 rounded-lg bg-slate-50 dark:bg-slate-900 text-slate-900 dark:text-slate-50 placeholder-slate-500 dark:placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-yellow-500 dark:focus:ring-yellow-400 focus:border-transparent transition-all" + /> +
+
+
+ + {/* Bottom Navigation Bar */} +
+
+ {/* Home/Labs */} + + + {/* Labs */} + + + {/* Dark Mode Toggle */} +
+ + + Theme + +
+ + {/* Login/Account */} + +
+
+ + {/* Spacer for fixed navbars */} +
+ + ); +} diff --git a/client/src/components/quicklab/Navbar.jsx b/client/src/components/quicklab/Navbar.jsx new file mode 100644 index 0000000..c31687e --- /dev/null +++ b/client/src/components/quicklab/Navbar.jsx @@ -0,0 +1,18 @@ +// Navbar.jsx +import { useState } from 'react'; +import DesktopNavbar from './DesktopNavbar'; +import MobileNavbar from './MobileNavbar'; + +export default function Navbar() { + const [searchQuery, setSearchQuery] = useState(''); + + return ( + <> + {/* Desktop Navbar - Hidden on mobile */} + + + {/* Mobile Navbar - Hidden on desktop */} + + + ); +} From ffcc00ea459f49e8a906149c87d98848b2aec38e Mon Sep 17 00:00:00 2001 From: Aditya Shah Date: Mon, 15 Dec 2025 09:55:31 +0530 Subject: [PATCH 4/4] add routes for quicklab --- client/src/App.jsx | 5 +++++ client/src/routes/QuickLabRoutes.jsx | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 client/src/routes/QuickLabRoutes.jsx diff --git a/client/src/App.jsx b/client/src/App.jsx index 20b4ea6..c96cd82 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -12,6 +12,7 @@ import PatientRoutes from './routes/PatientRoutes'; import PublicRoutes from './routes/PublicRoutes'; import getDashboardPath from './utility/getDashboardPath'; import QuickmedRoutes from './routes/QuickmedRoutes'; +import QuickLabRoutes from './routes/QuickLabRoutes'; // App.jsx - Updated AppInner component function AppInner() { @@ -43,9 +44,13 @@ function AppInner() { const renderRoutes = () => { console.log('Auth state:', { isAuthenticated, isLoading, user, pathname: location.pathname }); const quickMedPath = location.pathname.startsWith('/quick-med'); + const quickLabPath = location.pathname.startsWith('/quick-lab'); if (quickMedPath) { return ; } + if (quickLabPath) { + return ; + } // For authenticated users if (isAuthenticated && user) { switch (user.role) { diff --git a/client/src/routes/QuickLabRoutes.jsx b/client/src/routes/QuickLabRoutes.jsx new file mode 100644 index 0000000..8a53883 --- /dev/null +++ b/client/src/routes/QuickLabRoutes.jsx @@ -0,0 +1,13 @@ +import { Routes, Route } from 'react-router-dom'; +import NotFoundPage from '../components/ui/NotFoundPage'; +import Navbar from '../components/quicklab/Navbar'; +export default function QuickLabRoutes() { + return ( + <> + + + } /> + + + ); +}