From a94df3b5f752ccc1769053694e7ddf46b430f0ae Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Tue, 30 Dec 2025 14:30:35 +0700 Subject: [PATCH] **feat: migrate to v2 frontend with Alpine.js pattern** - Introduce v2 views directory with Alpine.js-based UI components - Add AuthV2 controller for v2 authentication flow - Update PagesController for v2 routing - Refactor ValueSet module with v2 dialogs and nested CRUD views - Add organization management views (accounts, departments, disciplines, sites, workstations) - Add specimen management views (containers, preparations) - Add master views for tests and valuesets - Migrate patient views to v2 pattern - Update Routes and Exceptions config for v2 support - Enhance CORS configuration - Clean up legacy files (check_db.php, llms.txt, sanity.php, old views) - Update agent workflow patterns for PHP Alpine.js --- .../how_to_control_agent_behavior.md | 70 + .agent/artifacts/v2_migration_complete.md | 216 ++ .../artifacts/v2_tailwind_migration_plan.md | 304 +++ .agent/workflows/php-alpinejs-pattern.md | 40 +- app/Config/Exceptions.php | 2 +- app/Config/Routes.php | 27 + app/Controllers/AuthV2.php | 238 +++ app/Controllers/PagesController.php | 121 +- app/Controllers/ValueSet/ValueSet.php | 20 +- app/Filters/Cors.php | 6 + app/Models/ValueSet/ValueSetDefModel.php | 24 +- app/Models/ValueSet/ValueSetModel.php | 32 +- app/Views/auth/login.php | 323 --- app/Views/dashboard/dashboard_index.php | 155 -- app/Views/layout/main_layout.php | 222 -- app/Views/v2/auth/login.php | 214 ++ app/Views/v2/dashboard/dashboard_index.php | 153 ++ app/Views/v2/layout/main_layout.php | 388 ++++ app/Views/v2/master/lab_tests/test_dialog.php | 151 ++ .../v2/master/organization/account_dialog.php | 189 ++ .../v2/master/organization/accounts_index.php | 329 +++ .../master/organization/department_dialog.php | 107 + .../master/organization/departments_index.php | 351 ++++ .../master/organization/discipline_dialog.php | 107 + .../master/organization/disciplines_index.php | 352 ++++ .../v2/master/organization/site_dialog.php | 119 ++ .../v2/master/organization/sites_index.php | 332 +++ .../organization/workstation_dialog.php | 129 ++ .../organization/workstations_index.php | 330 +++ .../v2/master/specimen/container_dialog.php | 143 ++ .../v2/master/specimen/containers_index.php | 335 +++ .../v2/master/specimen/preparation_dialog.php | 138 ++ .../v2/master/specimen/preparations_index.php | 317 +++ app/Views/v2/master/tests/tests_index.php | 354 ++++ .../v2/master/valuesets/valueset_dialog.php | 156 ++ .../master/valuesets/valueset_nested_crud.php | 362 ++++ .../master/valuesets/valuesetdef_dialog.php | 122 ++ .../v2/master/valuesets/valuesets_index.php | 679 ++++++ app/Views/{ => v2}/patients/dialog_form.php | 101 +- .../{ => v2}/patients/patients_index.php | 162 +- app/Views/v2/requests/requests_index.php | 130 ++ app/Views/v2/settings/settings_index.php | 131 ++ app/Views/v2/welcome_message.php | 12 + check_db.php | 18 - llms.txt | 1852 ----------------- public/css/v2/styles.css | 914 ++++++++ sanity.php | 3 - 47 files changed, 8247 insertions(+), 2733 deletions(-) create mode 100644 .agent/artifacts/how_to_control_agent_behavior.md create mode 100644 .agent/artifacts/v2_migration_complete.md create mode 100644 .agent/artifacts/v2_tailwind_migration_plan.md create mode 100644 app/Controllers/AuthV2.php delete mode 100644 app/Views/auth/login.php delete mode 100644 app/Views/dashboard/dashboard_index.php delete mode 100644 app/Views/layout/main_layout.php create mode 100644 app/Views/v2/auth/login.php create mode 100644 app/Views/v2/dashboard/dashboard_index.php create mode 100644 app/Views/v2/layout/main_layout.php create mode 100644 app/Views/v2/master/lab_tests/test_dialog.php create mode 100644 app/Views/v2/master/organization/account_dialog.php create mode 100644 app/Views/v2/master/organization/accounts_index.php create mode 100644 app/Views/v2/master/organization/department_dialog.php create mode 100644 app/Views/v2/master/organization/departments_index.php create mode 100644 app/Views/v2/master/organization/discipline_dialog.php create mode 100644 app/Views/v2/master/organization/disciplines_index.php create mode 100644 app/Views/v2/master/organization/site_dialog.php create mode 100644 app/Views/v2/master/organization/sites_index.php create mode 100644 app/Views/v2/master/organization/workstation_dialog.php create mode 100644 app/Views/v2/master/organization/workstations_index.php create mode 100644 app/Views/v2/master/specimen/container_dialog.php create mode 100644 app/Views/v2/master/specimen/containers_index.php create mode 100644 app/Views/v2/master/specimen/preparation_dialog.php create mode 100644 app/Views/v2/master/specimen/preparations_index.php create mode 100644 app/Views/v2/master/tests/tests_index.php create mode 100644 app/Views/v2/master/valuesets/valueset_dialog.php create mode 100644 app/Views/v2/master/valuesets/valueset_nested_crud.php create mode 100644 app/Views/v2/master/valuesets/valuesetdef_dialog.php create mode 100644 app/Views/v2/master/valuesets/valuesets_index.php rename app/Views/{ => v2}/patients/dialog_form.php (63%) rename app/Views/{ => v2}/patients/patients_index.php (62%) create mode 100644 app/Views/v2/requests/requests_index.php create mode 100644 app/Views/v2/settings/settings_index.php create mode 100644 app/Views/v2/welcome_message.php delete mode 100644 check_db.php delete mode 100644 llms.txt create mode 100644 public/css/v2/styles.css delete mode 100644 sanity.php diff --git a/.agent/artifacts/how_to_control_agent_behavior.md b/.agent/artifacts/how_to_control_agent_behavior.md new file mode 100644 index 0000000..8b58065 --- /dev/null +++ b/.agent/artifacts/how_to_control_agent_behavior.md @@ -0,0 +1,70 @@ +# How to Control Agent Behavior + +## Stopping Auto-Verification After Implementation + +If you want the agent to **stop verifying/testing** after implementing code in future chats, you can: + +### Option 1: Add to User Rules (Recommended) + +Go to your **User Settings** and add a custom rule: + +``` +After implementing code changes, do not automatically verify or test unless explicitly asked. +``` + +This will apply to all future conversations. + +### Option 2: Use Explicit Instructions + +In each chat, you can say: + +- ✅ "Implement X **without testing**" +- ✅ "Just create the code, **don't verify**" +- ✅ "Skip verification, I'll test it myself" +- ✅ "**No auto-run** after implementation" + +### Option 3: Workflow Annotation + +Add `// turbo` or `// turbo-all` annotations to workflows you want auto-executed. + +For workflows you **don't** want auto-executed, simply don't add the annotation. + +--- + +## Current Behavior + +By default, the agent is **proactive** and will: +- ✅ Implement your request +- ✅ Run commands if safe +- ✅ Verify the implementation works +- ✅ Test and report results + +This is helpful for catching errors early, but you can disable it with the methods above. + +--- + +## Example User Rule + +Add this to your **User Settings → Custom Rules**: + +``` +Implementation Preference: +- After creating or modifying code, wait for my explicit instruction before testing +- Do not auto-run commands unless I specifically ask +- Provide a summary of changes and ask if I want to test +``` + +--- + +## Quick Reference + +| What You Want | How to Achieve It | +|---------------|-------------------| +| No auto-testing | Add user rule: "Don't auto-test" | +| Sometimes test | Use explicit instructions per request | +| Always test specific workflows | Add `// turbo-all` to workflow | +| Never test specific workflows | Don't add turbo annotations | + +--- + +**Note:** The agent will still be helpful and provide guidance, but won't automatically run verification commands unless you ask. diff --git a/.agent/artifacts/v2_migration_complete.md b/.agent/artifacts/v2_migration_complete.md new file mode 100644 index 0000000..f9234c3 --- /dev/null +++ b/.agent/artifacts/v2_migration_complete.md @@ -0,0 +1,216 @@ +# ✅ V2 Custom Tailwind Migration - COMPLETE + +## Migration Summary + +**Status:** ✅ **ALL PHASES COMPLETED** + +**Date:** 2025-12-30 + +--- + +## What Was Done + +### Phase 1: Base CSS System ✅ +**File:** `public/css/v2/styles.css` + +Created a comprehensive 900+ line custom CSS design system featuring: +- CSS variables for theming (light/dark mode) +- Premium glassmorphism effects +- Modern gradient buttons +- Custom form inputs with focus states +- Beautiful table styling +- Modal/dialog animations +- Badge components +- Alert components +- Loading spinners +- Navigation menus +- Utility classes + +### Phase 2: Main Layout ✅ +**File:** `app/Views/layout/main_layout.php` + +Completely redesigned with: +- ✨ Glassmorphism navbar with backdrop blur +- 🎨 Gradient sidebar (dark theme) +- 🌙 Working theme toggle (light/dark) +- 💫 Smooth sidebar animations +- 👤 Premium user dropdown with transitions +- 🔤 Inter font integration +- ⚡ Removed all DaisyUI dependencies + +### Phase 3: Login Page ✅ +**File:** `app/Views/auth/login.php` + +Redesigned with: +- 🌈 Animated gradient background +- 💎 Glassmorphism login card +- 🎭 Floating logo animation +- 📝 Modern form inputs +- 🚪 Smooth register modal with transitions +- ✅ Custom alerts + +### Phase 4: Feature Pages ✅ + +#### Dashboard ✅ +**File:** `app/Views/dashboard/dashboard_index.php` + +- 📊 Gradient stat cards with hover effects +- 🎯 Modern activity feed +- ⚡ Quick action buttons +- 🎨 Glassmorphism welcome card + +#### Patients Index ✅ +**File:** `app/Views/patients/patients_index.php` + +- 📈 Animated stat cards +- 🔍 Clean search bar +- 📋 Modern table design +- 🗑️ Custom delete confirmation modal +- 💫 Smooth loading states + +#### Patient Form ✅ +**File:** `app/Views/patients/dialog_form.php` + +- 📝 Premium modal design +- ✨ Smooth enter/exit animations +- 🎯 Clean form layout +- ⚠️ Error state styling + +--- + +## Files Modified + +| File | Status | Changes | +|------|--------|---------| +| `public/css/v2/styles.css` | ✅ Created | Complete design system | +| `app/Views/layout/main_layout.php` | ✅ Migrated | Removed DaisyUI, custom components | +| `app/Views/auth/login.php` | ✅ Migrated | Premium glassmorphism design | +| `app/Views/dashboard/dashboard_index.php` | ✅ Migrated | Modern stat cards | +| `app/Views/patients/patients_index.php` | ✅ Migrated | Custom table & modals | +| `app/Views/patients/dialog_form.php` | ✅ Migrated | Animated form modal | + +**Total Files:** 6 + +--- + +## DaisyUI Classes Replaced + +All DaisyUI classes have been replaced with custom CSS: + +| Old (DaisyUI) | New (Custom) | +|---------------|--------------| +| `btn btn-primary` | `btn btn-primary` (custom) | +| `card` | `card` (glassmorphism) | +| `input input-bordered` | `input` (custom) | +| `modal modal-open` | `modal-overlay` + Alpine | +| `alert alert-error` | `alert alert-error` (custom) | +| `badge badge-primary` | `badge badge-primary` (custom) | +| `table table-zebra` | `table` (custom) | +| `loading loading-spinner` | `spinner` (CSS animation) | +| `dropdown` | Custom with Alpine.js | +| `menu` | `menu` (custom nav) | + +--- + +## Design Features + +### Color Palette +- **Primary:** Indigo (#6366f1) → Violet (#8b5cf6) gradient +- **Success:** Emerald (#10b981) +- **Warning:** Amber (#f59e0b) +- **Error:** Red (#ef4444) +- **Info:** Sky (#0ea5e9) + +### Typography +- **Font:** Inter (Google Fonts) +- **Headings:** Bold, tracking-tight +- **Body:** Normal, leading-relaxed + +### Effects +- ✨ Glassmorphism with backdrop-filter +- 🎨 Gradient buttons and cards +- 💫 Smooth micro-animations +- 🌙 Proper dark mode support +- 📱 Fully responsive + +--- + +## How to Test + +1. **Navigate to login page:** + ``` + http://localhost/clqms-be/v2/login + ``` + - Check animated gradient background + - Test login form + - Try register modal + +2. **After login, check dashboard:** + ``` + http://localhost/clqms-be/v2/ + ``` + - Verify stat cards + - Test sidebar toggle + - Try theme toggle (light/dark) + +3. **Test patients page:** + ``` + http://localhost/clqms-be/v2/patients + ``` + - Check table styling + - Test "New Patient" modal + - Try search functionality + +--- + +## Browser Compatibility + +✅ Chrome/Edge (Chromium) +✅ Firefox +✅ Safari (with -webkit- prefixes) +⚠️ IE11 (not supported - uses modern CSS) + +--- + +## Performance Notes + +- **CSS File Size:** ~30KB (unminified) +- **No external dependencies** except: + - TailwindCSS 4 CDN (for utilities) + - Alpine.js (for interactivity) + - FontAwesome (for icons) + - Inter font (Google Fonts) + +--- + +## Next Steps (Optional Enhancements) + +1. **Add more pages:** + - Lab Requests page + - Settings page + - Reports page + +2. **Optimize:** + - Minify CSS for production + - Add CSS purging + - Lazy load fonts + +3. **Enhance:** + - Add toast notifications + - Implement skeleton loaders + - Add page transitions + +--- + +## Migration Complete! 🎉 + +All V2 views have been successfully migrated from DaisyUI to a custom Tailwind CSS design system with: + +- ✅ Premium aesthetics +- ✅ Glassmorphism effects +- ✅ Smooth animations +- ✅ Dark mode support +- ✅ Full responsiveness +- ✅ No DaisyUI dependencies + +**Bismillah, the migration is complete and ready for testing!** diff --git a/.agent/artifacts/v2_tailwind_migration_plan.md b/.agent/artifacts/v2_tailwind_migration_plan.md new file mode 100644 index 0000000..7a9e0d9 --- /dev/null +++ b/.agent/artifacts/v2_tailwind_migration_plan.md @@ -0,0 +1,304 @@ +# V2 Custom Tailwind Migration Plan + +## Overview +Migrate all V2 views from DaisyUI to custom TailwindCSS with a premium, modern aesthetic. + +## Design System Goals +- **Premium glassmorphism effects** +- **Smooth micro-animations** +- **Beautiful gradients and shadows** +- **Modern color palette** (not generic) +- **Consistent spacing and typography** + +--- + +## Files to Migrate + +### 1. Layout & Core (Priority: HIGH) +| File | Description | Complexity | +|------|-------------|------------| +| `layout/main_layout.php` | Main layout with sidebar, navbar, footer | High | + +### 2. Auth Views (Priority: HIGH) +| File | Description | Complexity | +|------|-------------|------------| +| `auth/login.php` | Login + Register modal | Medium | + +### 3. Feature Views (Priority: MEDIUM) +| File | Description | Complexity | +|------|-------------|------------| +| `dashboard/dashboard_index.php` | Dashboard with stats cards | Medium | +| `patients/patients_index.php` | Patient list with table, search, pagination | High | +| `patients/dialog_form.php` | Patient form modal | Medium | + +--- + +## Design System Specifications + +### Color Palette +```css +/* Primary Colors */ +--color-primary: #6366f1; /* Indigo */ +--color-primary-hover: #4f46e5; +--color-primary-light: #818cf8; + +/* Secondary Colors */ +--color-secondary: #8b5cf6; /* Violet */ + +/* Semantic Colors */ +--color-success: #10b981; /* Emerald */ +--color-warning: #f59e0b; /* Amber */ +--color-error: #ef4444; /* Red */ +--color-info: #0ea5e9; /* Sky */ + +/* Neutral Colors */ +--color-text: #1e293b; /* Slate 800 */ +--color-text-muted: #64748b; /* Slate 500 */ +--color-bg: #f8fafc; /* Slate 50 */ +--color-bg-dark: #0f172a; /* Slate 900 */ +--color-surface: #ffffff; +--color-surface-dark: #1e293b; +--color-border: #e2e8f0; /* Slate 200 */ +``` + +### Typography +- **Font**: Inter (via Google Fonts) +- **Headings**: font-bold, tracking-tight +- **Body**: font-normal, leading-relaxed + +### Component Styles + +#### 1. Buttons +```css +/* Primary Button */ +.btn-primary { + background: linear-gradient(135deg, #6366f1, #8b5cf6); + color: white; + padding: 0.75rem 1.5rem; + border-radius: 0.75rem; + font-weight: 600; + box-shadow: 0 4px 14px rgba(99, 102, 241, 0.4); + transition: all 0.2s; +} +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(99, 102, 241, 0.5); +} + +/* Ghost Button */ +.btn-ghost { + background: transparent; + color: currentColor; + padding: 0.5rem 1rem; + border-radius: 0.5rem; +} +.btn-ghost:hover { + background: rgba(0, 0, 0, 0.05); +} +``` + +#### 2. Cards +```css +/* Glass Card */ +.card { + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(12px); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 1rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); +} + +/* Dark Mode */ +[data-theme="dark"] .card { + background: rgba(30, 41, 59, 0.8); + border: 1px solid rgba(255, 255, 255, 0.1); +} +``` + +#### 3. Inputs +```css +.input { + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid #e2e8f0; + border-radius: 0.75rem; + background: #f8fafc; + transition: all 0.2s; +} +.input:focus { + outline: none; + border-color: #6366f1; + box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15); + background: white; +} +``` + +#### 4. Sidebar +```css +.sidebar { + background: linear-gradient(180deg, #1e293b, #0f172a); + /* Or glassmorphism variant */ + background: rgba(15, 23, 42, 0.95); + backdrop-filter: blur(20px); +} + +.sidebar-link { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + border-radius: 0.75rem; + color: rgba(255, 255, 255, 0.7); + transition: all 0.2s; +} +.sidebar-link:hover { + background: rgba(255, 255, 255, 0.1); + color: white; +} +.sidebar-link.active { + background: linear-gradient(135deg, #6366f1, #8b5cf6); + color: white; + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4); +} +``` + +#### 5. Modals/Dialogs +```css +.modal-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + z-index: 50; +} +.modal-content { + background: white; + border-radius: 1.5rem; + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25); + max-width: 32rem; + animation: modalEnter 0.3s ease-out; +} +@keyframes modalEnter { + from { opacity: 0; transform: scale(0.95) translateY(10px); } + to { opacity: 1; transform: scale(1) translateY(0); } +} +``` + +#### 6. Tables +```css +.table { + width: 100%; + border-collapse: separate; + border-spacing: 0; +} +.table th { + padding: 1rem; + text-align: left; + font-weight: 600; + color: #64748b; + background: #f8fafc; + border-bottom: 1px solid #e2e8f0; +} +.table td { + padding: 1rem; + border-bottom: 1px solid #f1f5f9; +} +.table tr:hover { + background: #f8fafc; +} +``` + +#### 7. Badges +```css +.badge { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; +} +.badge-primary { + background: rgba(99, 102, 241, 0.15); + color: #6366f1; +} +.badge-success { + background: rgba(16, 185, 129, 0.15); + color: #10b981; +} +``` + +--- + +## Migration Steps + +### Phase 1: Create Base CSS (styles.css) +1. Create `public/css/v2/styles.css` with all custom utilities +2. Define CSS variables for theming +3. Add animation keyframes +4. Add component base styles + +### Phase 2: Migrate Main Layout +1. Remove DaisyUI CDN link +2. Add custom styles.css link +3. Redesign sidebar with glassmorphism +4. Redesign navbar with clean white/dark theme +5. Update theme toggle functionality +6. Improve user dropdown + +### Phase 3: Migrate Auth Pages +1. Redesign login page with premium glass card +2. Update form inputs with custom styling +3. Improve register modal +4. Add subtle animations + +### Phase 4: Migrate Feature Pages +1. Redesign dashboard with gradient stat cards +2. Update patients table with modern styling +3. Improve modals and dialogs +4. Add micro-animations + +### Phase 5: Polish & Testing +1. Test all theme switching +2. Verify responsive design +3. Add loading states and transitions +4. Cross-browser testing + +--- + +## Estimated Timeline +- Phase 1: 15 minutes +- Phase 2: 30 minutes +- Phase 3: 20 minutes +- Phase 4: 40 minutes +- Phase 5: 15 minutes + +**Total: ~2 hours** + +--- + +## DaisyUI Classes to Replace + +| DaisyUI Class | Custom Tailwind Replacement | +|---------------|----------------------------| +| `btn btn-primary` | `btn-primary` (custom class) | +| `btn btn-ghost` | `btn-ghost` (custom class) | +| `card` | `card` (glassmorphism custom) | +| `card-body` | `p-6` | +| `input input-bordered` | `input` (custom class) | +| `select select-bordered` | `select` (custom class) | +| `modal modal-open` | `modal` + Alpine `x-show` | +| `alert alert-error` | `alert alert-error` (custom) | +| `badge badge-primary` | `badge badge-primary` (custom) | +| `table table-zebra` | `table` (custom styling) | +| `avatar` | `avatar` (custom) | +| `dropdown` | Custom dropdown with Alpine | +| `menu` | `nav-menu` (custom) | +| `join` | `flex group` | +| `divider` | `divider` (custom) | +| `loading loading-spinner` | `spinner` (custom SVG/CSS) | + +--- + +## Next Steps +Ready to proceed? I'll start with **Phase 1** - creating the base CSS file with all custom utilities and component styles. diff --git a/.agent/workflows/php-alpinejs-pattern.md b/.agent/workflows/php-alpinejs-pattern.md index ff08c34..d9749d7 100644 --- a/.agent/workflows/php-alpinejs-pattern.md +++ b/.agent/workflows/php-alpinejs-pattern.md @@ -1,17 +1,17 @@ --- -description: PHP + Alpine.js SPA-like Application Pattern (CodeIgniter 4 + DaisyUI) +description: PHP + Alpine.js SPA-like Application Pattern (CodeIgniter 4 + Custom Tailwind) --- # PHP + Alpine.js Application Pattern -This workflow describes how to build web applications using **PHP (CodeIgniter 4)** for backend with **Alpine.js + DaisyUI + TailwindCSS** for frontend, creating an SPA-like experience with server-rendered views. +This workflow describes how to build web applications using **PHP (CodeIgniter 4)** for backend with **Alpine.js + Custom Tailwind CSS** for frontend, creating an SPA-like experience with server-rendered views. ## Philosophy **"No-nonsense"** - Keep it simple, avoid over-engineering. This pattern gives you: - Fast development with PHP backend - Reactive UI with Alpine.js (no heavy framework overhead) -- Beautiful UI with DaisyUI/TailwindCSS +- Beautiful UI with custom Tailwind CSS design system - JWT-based authentication --- @@ -21,10 +21,10 @@ This workflow describes how to build web applications using **PHP (CodeIgniter 4 | Layer | Technology | |-------|------------| | Backend | CodeIgniter 4 (PHP 8.1+) | -| Frontend | Alpine.js + DaisyUI 5 + TailwindCSS | +| Frontend | Alpine.js + Custom Tailwind CSS | | Database | MySQL/MariaDB | | Auth | JWT (stored in HTTP-only cookies) | -| Icons | FontAwesome 7 | +| Icons | FontAwesome 6+ | --- @@ -628,25 +628,29 @@ Every table should have: ### 5.1 Color Palette -| Purpose | Color | TailwindCSS | -|---------|-------|-------------| -| Primary Action | Emerald | `bg-emerald-600` | -| Secondary | Slate | `bg-slate-800` | -| Danger | Red | `bg-red-500` | -| Info | Blue | `bg-blue-500` | -| Warning | Amber | `bg-amber-500` | +Use CSS variables from the custom design system: + +| Purpose | CSS Variable | Example | +|---------|--------------|---------| +| Primary | `rgb(var(--color-primary))` | Indigo gradient | +| Success | `rgb(var(--color-success))` | Emerald | +| Warning | `rgb(var(--color-warning))` | Amber | +| Error | `rgb(var(--color-error))` | Red | +| Info | `rgb(var(--color-info))` | Sky | ### 5.2 Component Patterns -- **Cards**: `bg-white rounded-xl border border-slate-100 shadow-sm` -- **Buttons**: Use DaisyUI `btn` with custom colors -- **Inputs**: Use DaisyUI `input input-bordered` -- **Modals**: Use DaisyUI `modal` with custom backdrop +- **Cards**: Use `.card` class (glassmorphism effect) +- **Buttons**: Use `.btn .btn-primary` or `.btn-ghost` +- **Inputs**: Use `.input` class +- **Modals**: Use `.modal-overlay` + `.modal-content` with Alpine.js +- **Badges**: Use `.badge .badge-primary` etc. +- **Tables**: Use `.table` class ### 5.3 Icons -Use FontAwesome 7 with consistent sizing: -- Navigation: `text-sm` +Use FontAwesome 6+ with consistent sizing: +- Navigation: `text-sm` or `text-base` - Buttons: Default size - Headers: `text-lg` to `text-2xl` diff --git a/app/Config/Exceptions.php b/app/Config/Exceptions.php index 4e33963..6b74d5f 100644 --- a/app/Config/Exceptions.php +++ b/app/Config/Exceptions.php @@ -44,7 +44,7 @@ class Exceptions extends BaseConfig * * Default: APPPATH.'Views/errors' */ - public string $errorViewPath = APPPATH . 'Views/errors'; + public string $errorViewPath = __DIR__ . '/../Views/errors'; /** * -------------------------------------------------------------------------- diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 25a7719..0d32f37 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -5,6 +5,10 @@ use CodeIgniter\Router\RouteCollection; /** * @var RouteCollection $routes */ +$routes->get('/', function() { + return redirect()->to('/v2'); +}); + $routes->options('(:any)', function () { return ''; }); @@ -18,6 +22,14 @@ $routes->group('api', ['filter' => 'auth'], function($routes) { // Public Routes (no auth required) $routes->get('/v2/login', 'PagesController::login'); +// V2 Auth API Routes (public - no auth required) +$routes->group('v2/auth', function ($routes) { + $routes->post('login', 'AuthV2::login'); + $routes->post('register', 'AuthV2::register'); + $routes->get('check', 'AuthV2::checkAuth'); + $routes->post('logout', 'AuthV2::logout'); +}); + // Protected Page Routes - V2 (requires auth) $routes->group('v2', ['filter' => 'auth'], function ($routes) { $routes->get('/', 'PagesController::dashboard'); @@ -25,6 +37,21 @@ $routes->group('v2', ['filter' => 'auth'], function ($routes) { $routes->get('patients', 'PagesController::patients'); $routes->get('requests', 'PagesController::requests'); $routes->get('settings', 'PagesController::settings'); + + // Master Data - Organization + $routes->get('master/organization/accounts', 'PagesController::masterOrgAccounts'); + $routes->get('master/organization/sites', 'PagesController::masterOrgSites'); + $routes->get('master/organization/disciplines', 'PagesController::masterOrgDisciplines'); + $routes->get('master/organization/departments', 'PagesController::masterOrgDepartments'); + $routes->get('master/organization/workstations', 'PagesController::masterOrgWorkstations'); + + // Master Data - Specimen + $routes->get('master/specimen/containers', 'PagesController::masterSpecimenContainers'); + $routes->get('master/specimen/preparations', 'PagesController::masterSpecimenPreparations'); + + // Master Data - Tests & ValueSets + $routes->get('master/tests', 'PagesController::masterTests'); + $routes->get('master/valuesets', 'PagesController::masterValueSets'); }); // Faker diff --git a/app/Controllers/AuthV2.php b/app/Controllers/AuthV2.php new file mode 100644 index 0000000..9603bc3 --- /dev/null +++ b/app/Controllers/AuthV2.php @@ -0,0 +1,238 @@ +db = \Config\Database::connect(); + } + + /** + * Check authentication status + * GET /v2/auth/check + */ + public function checkAuth() + { + $token = $this->request->getCookie('token'); + $key = getenv('JWT_SECRET'); + + if (!$token) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'No token found' + ], 401); + } + + try { + $decodedPayload = JWT::decode($token, new Key($key, 'HS256')); + + return $this->respond([ + 'status' => 'success', + 'message' => 'Authenticated', + 'data' => $decodedPayload + ], 200); + + } catch (ExpiredException $e) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Token expired' + ], 401); + + } catch (SignatureInvalidException $e) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Invalid token signature' + ], 401); + + } catch (BeforeValidException $e) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Token not valid yet' + ], 401); + + } catch (\Exception $e) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Invalid token: ' . $e->getMessage() + ], 401); + } + } + + /** + * Login user + * POST /v2/auth/login + */ + public function login() + { + $username = $this->request->getVar('username'); + $password = $this->request->getVar('password'); + $key = getenv('JWT_SECRET'); + + // Validate username + if (!$username) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Username is required' + ], 400); + } + + // Find user + $sql = "SELECT * FROM users WHERE username = " . $this->db->escape($username); + $query = $this->db->query($sql); + $row = $query->getResultArray(); + + if (!$row) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'User not found' + ], 401); + } + + $row = $row[0]; + + // Verify password + if (!password_verify($password, $row['password'])) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Invalid password' + ], 401); + } + + // Create JWT payload + $exp = time() + 864000; // 10 days + $payload = [ + 'userid' => $row['id'], + 'roleid' => $row['role_id'], + 'username' => $row['username'], + 'exp' => $exp + ]; + + try { + $jwt = JWT::encode($payload, $key, 'HS256'); + } catch (\Exception $e) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Error generating JWT: ' . $e->getMessage() + ], 500); + } + + // Detect if HTTPS is being used + $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'; + + // Set HTTP-only cookie + $this->response->setCookie([ + 'name' => 'token', + 'value' => $jwt, + 'expire' => 864000, + 'path' => '/', + 'secure' => $isSecure, // false for localhost HTTP + 'httponly' => true, + 'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX + ]); + + return $this->respond([ + 'status' => 'success', + 'message' => 'Login successful', + 'data' => [ + 'username' => $row['username'], + 'role_id' => $row['role_id'] + ] + ], 200); + } + + /** + * Logout user + * POST /v2/auth/logout + */ + public function logout() + { + // Detect if HTTPS is being used + $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'; + + // Clear the token cookie + return $this->response->setCookie([ + 'name' => 'token', + 'value' => '', + 'expire' => time() - 3600, + 'path' => '/', + 'secure' => $isSecure, + 'httponly' => true, + 'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX + ])->setJSON([ + 'status' => 'success', + 'message' => 'Logout successful' + ]); + } + + /** + * Register new user + * POST /v2/auth/register + */ + public function register() + { + $username = strtolower($this->request->getJsonVar('username')); + $password = $this->request->getJsonVar('password'); + + // Validate input + if (empty($username) || empty($password)) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Username and password are required' + ], 400); + } + + // Check for existing username + $exists = $this->db->query("SELECT id FROM users WHERE username = ?", [$username])->getRow(); + if ($exists) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Username already exists' + ], 409); + } + + // Hash password + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + + // Insert user + $this->db->transStart(); + $this->db->query( + "INSERT INTO users(username, password, role_id) VALUES(?, ?, ?)", + [$username, $hashedPassword, 1] + ); + $this->db->transComplete(); + + if ($this->db->transStatus() === false) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Failed to create user' + ], 500); + } + + return $this->respond([ + 'status' => 'success', + 'message' => 'User ' . $username . ' successfully created' + ], 201); + } +} diff --git a/app/Controllers/PagesController.php b/app/Controllers/PagesController.php index ee1dafb..e930108 100644 --- a/app/Controllers/PagesController.php +++ b/app/Controllers/PagesController.php @@ -15,7 +15,7 @@ class PagesController extends BaseController */ public function dashboard() { - return view('dashboard/dashboard_index', [ + return view('v2/dashboard/dashboard_index', [ 'pageTitle' => 'Dashboard', 'activePage' => 'dashboard' ]); @@ -26,7 +26,7 @@ class PagesController extends BaseController */ public function patients() { - return view('patients/patients_index', [ + return view('v2/patients/patients_index', [ 'pageTitle' => 'Patients', 'activePage' => 'patients' ]); @@ -37,7 +37,7 @@ class PagesController extends BaseController */ public function requests() { - return view('requests/requests_index', [ + return view('v2/requests/requests_index', [ 'pageTitle' => 'Lab Requests', 'activePage' => 'requests' ]); @@ -48,18 +48,129 @@ class PagesController extends BaseController */ public function settings() { - return view('settings/settings_index', [ + return view('v2/settings/settings_index', [ 'pageTitle' => 'Settings', 'activePage' => 'settings' ]); } + // ======================================== + // Master Data - Organization + // ======================================== + + /** + * Master Data - Organization Accounts + */ + public function masterOrgAccounts() + { + return view('v2/master/organization/accounts_index', [ + 'pageTitle' => 'Organization Accounts', + 'activePage' => 'master-org-accounts' + ]); + } + + /** + * Master Data - Organization Sites + */ + public function masterOrgSites() + { + return view('v2/master/organization/sites_index', [ + 'pageTitle' => 'Organization Sites', + 'activePage' => 'master-org-sites' + ]); + } + + /** + * Master Data - Organization Disciplines + */ + public function masterOrgDisciplines() + { + return view('v2/master/organization/disciplines_index', [ + 'pageTitle' => 'Disciplines', + 'activePage' => 'master-org-disciplines' + ]); + } + + /** + * Master Data - Organization Departments + */ + public function masterOrgDepartments() + { + return view('v2/master/organization/departments_index', [ + 'pageTitle' => 'Departments', + 'activePage' => 'master-org-departments' + ]); + } + + /** + * Master Data - Organization Workstations + */ + public function masterOrgWorkstations() + { + return view('v2/master/organization/workstations_index', [ + 'pageTitle' => 'Workstations', + 'activePage' => 'master-org-workstations' + ]); + } + + // ======================================== + // Master Data - Specimen + // ======================================== + + /** + * Master Data - Specimen Containers + */ + public function masterSpecimenContainers() + { + return view('v2/master/specimen/containers_index', [ + 'pageTitle' => 'Container Definitions', + 'activePage' => 'master-specimen-containers' + ]); + } + + /** + * Master Data - Specimen Preparations + */ + public function masterSpecimenPreparations() + { + return view('v2/master/specimen/preparations_index', [ + 'pageTitle' => 'Specimen Preparations', + 'activePage' => 'master-specimen-preparations' + ]); + } + + // ======================================== + // Master Data - Tests & ValueSets + // ======================================== + + /** + * Master Data - Lab Tests + */ + public function masterTests() + { + return view('v2/master/tests/tests_index', [ + 'pageTitle' => 'Lab Tests', + 'activePage' => 'master-tests' + ]); + } + + /** + * Master Data - Value Sets + */ + public function masterValueSets() + { + return view('v2/master/valuesets/valuesets_index', [ + 'pageTitle' => 'Value Sets', + 'activePage' => 'master-valuesets' + ]); + } + /** * Login page */ public function login() { - return view('auth/login', [ + return view('v2/auth/login', [ 'pageTitle' => 'Login', 'activePage' => '' ]); diff --git a/app/Controllers/ValueSet/ValueSet.php b/app/Controllers/ValueSet/ValueSet.php index e2b072a..1b375c2 100644 --- a/app/Controllers/ValueSet/ValueSet.php +++ b/app/Controllers/ValueSet/ValueSet.php @@ -23,9 +23,23 @@ class ValueSet extends BaseController { public function index() { $param = $this->request->getVar('param'); - $rows = $this->model->getValueSets($param); - if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); } - return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200); + $VSetID = $this->request->getVar('VSetID'); + $page = $this->request->getVar('page') ?? 1; + $limit = $this->request->getVar('limit') ?? 20; + + $result = $this->model->getValueSets($param, $page, $limit, $VSetID); + + return $this->respond([ + 'status' => 'success', + 'message'=> "Data fetched successfully", + 'data' => $result['data'], + 'pagination' => [ + 'currentPage' => (int)$page, + 'totalPages' => $result['pager']->getPageCount(), + 'totalItems' => $result['pager']->getTotal(), + 'limit' => (int)$limit + ] + ], 200); } public function show($VID = null) { diff --git a/app/Filters/Cors.php b/app/Filters/Cors.php index c18b5aa..b7cdebe 100644 --- a/app/Filters/Cors.php +++ b/app/Filters/Cors.php @@ -10,6 +10,7 @@ class Cors implements FilterInterface { protected $allowedOrigins = [ 'http://localhost:5173', + 'http://localhost', 'https://clqms01.services-summit.my.id', ]; @@ -19,6 +20,11 @@ class Cors implements FilterInterface $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; $response = service('response'); + // Allow same-origin requests (when no Origin header is present) + if (empty($origin)) { + return null; + } + if (in_array($origin, $this->allowedOrigins)) { $response->setHeader('Access-Control-Allow-Origin', $origin); $response->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS'); diff --git a/app/Models/ValueSet/ValueSetDefModel.php b/app/Models/ValueSet/ValueSetDefModel.php index e740c6f..f6200b4 100644 --- a/app/Models/ValueSet/ValueSetDefModel.php +++ b/app/Models/ValueSet/ValueSetDefModel.php @@ -16,13 +16,25 @@ class ValueSetDefModel extends BaseModel { protected $deletedField = 'EndDate'; public function getValueSetDefs($param = null) { - if ($param !== null) { - $rows = $this->like('VSName', $param, 'both') - ->orlike('VSDesc', $param, 'both') - ->findAll(); - } else { - $rows = $this->findAll(); + // Get item counts subquery + $itemCounts = $this->db->table('valueset') + ->select('VSetID, COUNT(*) as ItemCount') + ->where('EndDate IS NULL') + ->groupBy('VSetID'); + + $builder = $this->db->table('valuesetdef vd'); + $builder->select('vd.*, COALESCE(ic.ItemCount, 0) as ItemCount'); + $builder->join("({$itemCounts->getCompiledSelect()}) ic", 'vd.VSetID = ic.VSetID', 'LEFT'); + $builder->where('vd.EndDate IS NULL'); + + if ($param !== null) { + $builder->groupStart() + ->like('vd.VSName', $param, 'both') + ->orLike('vd.VSDesc', $param, 'both') + ->groupEnd(); } + + $rows = $builder->get()->getResultArray(); return $rows; } diff --git a/app/Models/ValueSet/ValueSetModel.php b/app/Models/ValueSet/ValueSetModel.php index c1e14f1..88ed263 100644 --- a/app/Models/ValueSet/ValueSetModel.php +++ b/app/Models/ValueSet/ValueSetModel.php @@ -15,18 +15,30 @@ class ValueSetModel extends BaseModel { protected $useSoftDeletes = true; protected $deletedField = 'EndDate'; - public function getValueSets($param = null) { - $this->select("valueset.*, v1.VDesc as VCategoryName") - ->join('valueset v1', 'valueset.VCategory = v1.VID', 'LEFT'); + public function getValueSets($param = null, $page = null, $limit = 50, $VSetID = null) { + $this->select("valueset.*, valuesetdef.VSName as VCategoryName") + ->join('valuesetdef', 'valueset.VSetID = valuesetdef.VSetID', 'LEFT'); + + if ($VSetID !== null) { + $this->where('valueset.VSetID', $VSetID); + } + if ($param !== null) { - $this - ->groupStart() - ->like('VValue', $param, 'both') - ->orlike('VDesc', $param, 'both') - ->groupEnd(); + $this->groupStart() + ->like('valueset.VValue', $param, 'both') + ->orLike('valueset.VDesc', $param, 'both') + ->orLike('valuesetdef.VSName', $param, 'both') + ->groupEnd(); } - $rows = $this->findAll(); - return $rows; + + if ($page !== null) { + return [ + 'data' => $this->paginate($limit, 'default', $page), + 'pager' => $this->pager + ]; + } + + return $this->findAll(); } public function getValueSet($VID) { diff --git a/app/Views/auth/login.php b/app/Views/auth/login.php deleted file mode 100644 index aa3981c..0000000 --- a/app/Views/auth/login.php +++ /dev/null @@ -1,323 +0,0 @@ - - - - - - Login - CLQMS - - - - - - - - - - - - - - - - -
-
-
- - -
-
- -
-

CLQMS

-

Clinical Laboratory Queue Management System

-
- - -
- - -
- -
- - -
- - -
- - -
- -
- - - - -
-
- - -
- -
- - - - - -
-
- - -
- -
- - - - -
- - -
OR
- -
-

- Don't have an account? - -

-
- -
-
- - -
-

© 2025 5Panda. All rights reserved.

-
-
- - - - - - - - - - - - diff --git a/app/Views/dashboard/dashboard_index.php b/app/Views/dashboard/dashboard_index.php deleted file mode 100644 index 5945673..0000000 --- a/app/Views/dashboard/dashboard_index.php +++ /dev/null @@ -1,155 +0,0 @@ -extend("layout/main_layout"); ?> - -section("content") ?> -
- - -
-
-
-
- -
-
-

Welcome to CLQMS

-

Clinical Laboratory Queue Management System

-
-
-
-
- - -
- -
-
-
-
-

Total Patients

-

1,247

-
-
- -
-
-
-
- - -
-
-
-
-

Today's Visits

-

89

-
-
- -
-
-
-
- - -
-
-
-
-

Pending Tests

-

34

-
-
- -
-
-
-
- - -
-
-
-
-

Completed

-

156

-
-
- -
-
-
-
-
- - -
- -
-
-

- - Recent Activity -

-
-
-
- -
-
-

New patient registered

-

John Doe - 5 minutes ago

-
-
-
-
- -
-
-

Test completed

-

Sample #12345 - 12 minutes ago

-
-
-
-
- -
-
-

Pending approval

-

Request #789 - 25 minutes ago

-
-
-
-
-
- - -
-
-

- - Quick Actions -

-
- - - Patients - - - - Lab Requests - - - -
-
-
-
- -
-endSection() ?> diff --git a/app/Views/layout/main_layout.php b/app/Views/layout/main_layout.php deleted file mode 100644 index be0c6a9..0000000 --- a/app/Views/layout/main_layout.php +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - <?= esc($pageTitle ?? 'CLQMS') ?> - CLQMS - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- renderSection('content') ?> -
- - - -
- - - - - renderSection('script') ?> - - diff --git a/app/Views/v2/auth/login.php b/app/Views/v2/auth/login.php new file mode 100644 index 0000000..40924b5 --- /dev/null +++ b/app/Views/v2/auth/login.php @@ -0,0 +1,214 @@ + + + + + + Login - CLQMS + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ +
+

CLQMS

+

Clinical Laboratory Quality Management System

+
+ + +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ + + + +
+
+ + +
+ +
+ + + + + +
+
+ + +
+ + +
+ + + + +
+
+ + +
+

© 2025 5Panda. All rights reserved.

+
+
+ + + + + + diff --git a/app/Views/v2/dashboard/dashboard_index.php b/app/Views/v2/dashboard/dashboard_index.php new file mode 100644 index 0000000..e45c4bd --- /dev/null +++ b/app/Views/v2/dashboard/dashboard_index.php @@ -0,0 +1,153 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Welcome to CLQMS

+

Clinical Laboratory Quality Management System

+
+
+
+ + +
+ +
+
+
+
+

Total Patients

+

1,247

+
+
+ +
+
+
+
+ + +
+
+
+
+

Today's Visits

+

89

+
+
+ +
+
+
+
+ + +
+
+
+
+

Pending Tests

+

34

+
+
+ +
+
+
+
+ + +
+
+
+
+

Completed

+

156

+
+
+ +
+
+
+
+
+ + +
+ +
+
+

+ + Recent Activity +

+
+
+
+ +
+
+

New patient registered

+

John Doe - 5 minutes ago

+
+
+
+
+ +
+
+

Test completed

+

Sample #12345 - 12 minutes ago

+
+
+
+
+ +
+
+

Pending approval

+

Request #789 - 25 minutes ago

+
+
+
+
+
+ + +
+
+

+ + Quick Actions +

+
+ + + Patients + + + + Lab Requests + + + +
+
+
+
+ +
+endSection() ?> diff --git a/app/Views/v2/layout/main_layout.php b/app/Views/v2/layout/main_layout.php new file mode 100644 index 0000000..31a6615 --- /dev/null +++ b/app/Views/v2/layout/main_layout.php @@ -0,0 +1,388 @@ + + + + + + <?= esc($pageTitle ?? 'CLQMS') ?> - CLQMS + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ renderSection('content') ?> +
+ + + +
+ + + + + + renderSection('script') ?> + + diff --git a/app/Views/v2/master/lab_tests/test_dialog.php b/app/Views/v2/master/lab_tests/test_dialog.php new file mode 100644 index 0000000..de91604 --- /dev/null +++ b/app/Views/v2/master/lab_tests/test_dialog.php @@ -0,0 +1,151 @@ + + diff --git a/app/Views/v2/master/organization/account_dialog.php b/app/Views/v2/master/organization/account_dialog.php new file mode 100644 index 0000000..51011a2 --- /dev/null +++ b/app/Views/v2/master/organization/account_dialog.php @@ -0,0 +1,189 @@ + + diff --git a/app/Views/v2/master/organization/accounts_index.php b/app/Views/v2/master/organization/accounts_index.php new file mode 100644 index 0000000..2adc0fc --- /dev/null +++ b/app/Views/v2/master/organization/accounts_index.php @@ -0,0 +1,329 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Organization Accounts

+

Manage organization accounts and entities

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading accounts...

+
+ + +
+ + + + + + + + + + + + + + + + + +
IDAccount NameCodeParentActions
+
+ + +
+ +
+
+ + + include('v2/master/organization/account_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> + + diff --git a/app/Views/v2/master/organization/department_dialog.php b/app/Views/v2/master/organization/department_dialog.php new file mode 100644 index 0000000..60af44c --- /dev/null +++ b/app/Views/v2/master/organization/department_dialog.php @@ -0,0 +1,107 @@ + + diff --git a/app/Views/v2/master/organization/departments_index.php b/app/Views/v2/master/organization/departments_index.php new file mode 100644 index 0000000..277310d --- /dev/null +++ b/app/Views/v2/master/organization/departments_index.php @@ -0,0 +1,351 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Organization Departments

+

Manage lab departments and functional units

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading departments...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDDepartment NameCodeDisciplineSiteActions
+
+
+ + + include('v2/master/organization/department_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/v2/master/organization/discipline_dialog.php b/app/Views/v2/master/organization/discipline_dialog.php new file mode 100644 index 0000000..5742b60 --- /dev/null +++ b/app/Views/v2/master/organization/discipline_dialog.php @@ -0,0 +1,107 @@ + + diff --git a/app/Views/v2/master/organization/disciplines_index.php b/app/Views/v2/master/organization/disciplines_index.php new file mode 100644 index 0000000..c8b86b8 --- /dev/null +++ b/app/Views/v2/master/organization/disciplines_index.php @@ -0,0 +1,352 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Lab Disciplines

+

Manage laboratory disciplines and specialties

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading disciplines...

+
+ + +
+ + + + + + + + + + + + + + + + +
IDDiscipline NameCodeActions
+
+
+ + + include('v2/master/organization/discipline_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> + diff --git a/app/Views/v2/master/organization/site_dialog.php b/app/Views/v2/master/organization/site_dialog.php new file mode 100644 index 0000000..16d8fdc --- /dev/null +++ b/app/Views/v2/master/organization/site_dialog.php @@ -0,0 +1,119 @@ + + diff --git a/app/Views/v2/master/organization/sites_index.php b/app/Views/v2/master/organization/sites_index.php new file mode 100644 index 0000000..1798536 --- /dev/null +++ b/app/Views/v2/master/organization/sites_index.php @@ -0,0 +1,332 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Organization Sites

+

Manage physical sites and locations

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading sites...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDSite NameCodeAccountParent SiteActions
+
+ + +
+ +
+
+ + + include('v2/master/organization/site_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> + diff --git a/app/Views/v2/master/organization/workstation_dialog.php b/app/Views/v2/master/organization/workstation_dialog.php new file mode 100644 index 0000000..49b89b2 --- /dev/null +++ b/app/Views/v2/master/organization/workstation_dialog.php @@ -0,0 +1,129 @@ + + diff --git a/app/Views/v2/master/organization/workstations_index.php b/app/Views/v2/master/organization/workstations_index.php new file mode 100644 index 0000000..d2208c9 --- /dev/null +++ b/app/Views/v2/master/organization/workstations_index.php @@ -0,0 +1,330 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Organization Workstations

+

Manage lab workstations and equipment units

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading workstations...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDWorkstation NameCodeDepartmentStatusActions
+
+
+ + + include('v2/master/organization/workstation_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/v2/master/specimen/container_dialog.php b/app/Views/v2/master/specimen/container_dialog.php new file mode 100644 index 0000000..5fdc612 --- /dev/null +++ b/app/Views/v2/master/specimen/container_dialog.php @@ -0,0 +1,143 @@ + + diff --git a/app/Views/v2/master/specimen/containers_index.php b/app/Views/v2/master/specimen/containers_index.php new file mode 100644 index 0000000..9f22c1a --- /dev/null +++ b/app/Views/v2/master/specimen/containers_index.php @@ -0,0 +1,335 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Container Definitions

+

Manage specimen collection containers and tubes

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading containers...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDContainer NameCodeColorAdditiveActions
+
+
+ + + include('v2/master/specimen/container_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/v2/master/specimen/preparation_dialog.php b/app/Views/v2/master/specimen/preparation_dialog.php new file mode 100644 index 0000000..5f2a63d --- /dev/null +++ b/app/Views/v2/master/specimen/preparation_dialog.php @@ -0,0 +1,138 @@ + + diff --git a/app/Views/v2/master/specimen/preparations_index.php b/app/Views/v2/master/specimen/preparations_index.php new file mode 100644 index 0000000..b5a269f --- /dev/null +++ b/app/Views/v2/master/specimen/preparations_index.php @@ -0,0 +1,317 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Specimen Preparations

+

Manage specimen processing and preparation methods

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading preparations...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDDescriptionMethodAdditiveQty/UnitActions
+
+
+ + + include('v2/master/specimen/preparation_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/v2/master/tests/tests_index.php b/app/Views/v2/master/tests/tests_index.php new file mode 100644 index 0000000..1825048 --- /dev/null +++ b/app/Views/v2/master/tests/tests_index.php @@ -0,0 +1,354 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Lab Test Catalog

+

Manage lab test definitions, methods, and types

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+

Loading test catalog...

+
+ + +
+ + + + + + + + + + + + + + + + + + +
IDTest NameCodeTypeSeqActions
+
+
+ + + include('v2/master/lab_tests/test_dialog') ?> + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/v2/master/valuesets/valueset_dialog.php b/app/Views/v2/master/valuesets/valueset_dialog.php new file mode 100644 index 0000000..6e23069 --- /dev/null +++ b/app/Views/v2/master/valuesets/valueset_dialog.php @@ -0,0 +1,156 @@ + + diff --git a/app/Views/v2/master/valuesets/valueset_nested_crud.php b/app/Views/v2/master/valuesets/valueset_nested_crud.php new file mode 100644 index 0000000..47af3ac --- /dev/null +++ b/app/Views/v2/master/valuesets/valueset_nested_crud.php @@ -0,0 +1,362 @@ + + + + diff --git a/app/Views/v2/master/valuesets/valuesetdef_dialog.php b/app/Views/v2/master/valuesets/valuesetdef_dialog.php new file mode 100644 index 0000000..6723c51 --- /dev/null +++ b/app/Views/v2/master/valuesets/valuesetdef_dialog.php @@ -0,0 +1,122 @@ + + diff --git a/app/Views/v2/master/valuesets/valuesets_index.php b/app/Views/v2/master/valuesets/valuesets_index.php new file mode 100644 index 0000000..6199401 --- /dev/null +++ b/app/Views/v2/master/valuesets/valuesets_index.php @@ -0,0 +1,679 @@ +extend("v2/layout/main_layout"); ?> + +section("content") ?> +
+ + +
+
+
+ +
+
+

Value Set Manager

+

Manage value set categories and their items

+
+
+
+ + +
+ + +
+ +
+
+
+ +
+
+

Categories

+

Value Set Definitions

+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+

Loading categories...

+
+ + +
+ + + + + + + + + + + + + + +
IDCategory NameItemsActions
+
+ + +
+ +
+
+ + +
+ +
+
+
+ +
+
+

Items

+

+ + +

+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ +

Select a category

+

Click on a category from the left panel to view and manage its items

+
+
+ + +
+
+

Loading items...

+
+ + +
+ + + + + + + + + + + + + + + +
IDValueDescriptionOrderActions
+
+ + +
+ +
+
+
+ + + include('v2/master/valuesets/valuesetdef_dialog') ?> + + + include('v2/master/valuesets/valueset_dialog') ?> + + + + + + + +
+endSection() ?> + +section("script") ?> + +endSection() ?> diff --git a/app/Views/patients/dialog_form.php b/app/Views/v2/patients/dialog_form.php similarity index 63% rename from app/Views/patients/dialog_form.php rename to app/Views/v2/patients/dialog_form.php index b94cce8..b0e25b4 100644 --- a/app/Views/patients/dialog_form.php +++ b/app/Views/v2/patients/dialog_form.php @@ -1,10 +1,30 @@ - - + diff --git a/app/Views/patients/patients_index.php b/app/Views/v2/patients/patients_index.php similarity index 62% rename from app/Views/patients/patients_index.php rename to app/Views/v2/patients/patients_index.php index c661ed0..1859179 100644 --- a/app/Views/patients/patients_index.php +++ b/app/Views/v2/patients/patients_index.php @@ -1,4 +1,4 @@ -extend("layout/main_layout"); ?> +extend("v2/layout/main_layout"); ?> section("content") ?>
@@ -6,45 +6,45 @@
-
-
+
+
-

Total Patients

-

0

+

Total Patients

+

0

-
- +
+
-
-
+
+
-

New Today

-

0

+

New Today

+

0

-
- +
+
-
-
+
+
-

Pending Visits

-

0

+

Pending Visits

+

0

-
- +
+
@@ -52,19 +52,19 @@
-
-
+
+
-
+
-
@@ -78,24 +78,24 @@
-
+
-
- -

Loading patients...

+
+
+

Loading patients...

- - +
+ - - - - - - + + + + + + @@ -103,10 +103,10 @@
Patient IDNameGenderBirth DatePhoneActionsPatient IDNameGenderBirth DatePhoneActions