- 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
305 lines
7.0 KiB
Markdown
305 lines
7.0 KiB
Markdown
# 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.
|