diff --git a/docs/frontend/shared/pagination-quick-start.md b/docs/frontend/shared/pagination-quick-start.md index 22150f2d..bdf00515 100644 --- a/docs/frontend/shared/pagination-quick-start.md +++ b/docs/frontend/shared/pagination-quick-start.md @@ -1,201 +1,178 @@ -╔══════════════════════════════════════════════════════════════════╗ -║ PAGINATION FEATURE - QUICK START ║ -╚══════════════════════════════════════════════════════════════════╝ +# Pagination & Search - Quick Start Guide -✨ WHAT'S NEW -═════════════════════════════════════════════════════════════════ +## Overview -1. ✅ Edit Button - Pencil icon already present in table -2. ✅ Pagination - Smart pagination with 10 items per page -3. ✅ Page Navigation - Previous/Next buttons + page numbers -4. ✅ Smart Display - Shows "..." for large page ranges +All admin list pages use consistent **server-side pagination** with search and filters. +**Pages using this pattern:** +- `/admin/vendors` - Vendor Management +- `/admin/companies` - Company Management +- `/admin/users` - User Management -📦 INSTALLATION (3 STEPS) -═════════════════════════════════════════════════════════════════ +--- -Step 1: Backup current files - $ cp templates/admin/vendors.html templates/admin/vendors.html.backup - $ cp static/admin/js/vendors.js static/admin/js/vendors.js.backup +## Visual Layout -Step 2: Replace with new versions - $ cp vendors.html templates/admin/vendors.html - $ cp vendors.js static/admin/js/vendors.js +``` +┌──────────────────────────────────────────────────────────────────┐ +│ Page Title [+ Create Button] │ +├──────────────────────────────────────────────────────────────────┤ +│ [Stat 1] [Stat 2] [Stat 3] [Stat 4] ← Stats Cards │ +├──────────────────────────────────────────────────────────────────┤ +│ [🔍 Search... ] [Filter ▼] [Filter ▼] [Refresh] ← Search Bar │ +├──────────────────────────────────────────────────────────────────┤ +│ Column 1 │ Column 2 │ Column 3 │ Actions │ +├──────────┼──────────┼──────────┼─────────────────────────────────┤ +│ Row 1 │ ... │ ... │ 👁 ✏️ 🗑 │ +│ Row 2 │ ... │ ... │ 👁 ✏️ 🗑 │ +│ ... │ ... │ ... │ ... │ +├──────────────────────────────────────────────────────────────────┤ +│ Showing 1-10 of 45 ← 1 2 [3] 4 ... 9 → │ +└──────────────────────────────────────────────────────────────────┘ +``` -Step 3: Clear cache and test - - Hard refresh: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac) - - Test with >10 vendors to see pagination +--- +## Key Features -🎨 VISUAL PREVIEW -═════════════════════════════════════════════════════════════════ +| Feature | Description | +|---------|-------------| +| Server-side pagination | Uses `skip`/`limit` API params | +| Debounced search | 300ms delay before API call | +| Filter dropdowns | Status, Verification, Role filters | +| Smart page numbers | Shows ellipsis for large page ranges | +| Refresh button | Manually reload data | +| Contextual empty state | Different message when filters applied | -Before (No Pagination): -┌────────────────────────────────────────────────────────────┐ -│ Vendor │ Subdomain │ Status │ Created │ Actions │ -├────────┼───────────┼────────┼─────────┼───────────────────┤ -│ Vendor1│ vendor1 │ ✓ │ Jan 1 │ 👁 🗑 │ ❌ No edit -│ Vendor2│ vendor2 │ ⏰ │ Jan 2 │ 👁 🗑 │ -│ ...50 more vendors... │ -│ Vendor52│vendor52 │ ✓ │ Jan 52 │ 👁 🗑 │ -└────────────────────────────────────────────────────────────┘ -❌ All vendors on one page (hard to scroll through!) +--- +## State Structure -After (With Pagination): -┌────────────────────────────────────────────────────────────┐ -│ Vendor │ Subdomain │ Status │ Created │ Actions │ -├────────┼───────────┼────────┼─────────┼───────────────────┤ -│ Vendor1│ vendor1 │ ✓ │ Jan 1 │ 👁 ✏️ 🗑 │ ✅ Edit added! -│ Vendor2│ vendor2 │ ⏰ │ Jan 2 │ 👁 ✏️ 🗑 │ -│ ...8 more vendors... │ -│Vendor10│ vendor10 │ ✓ │ Jan 10 │ 👁 ✏️ 🗑 │ -├────────────────────────────────────────────────────────────┤ -│ Showing 1-10 of 52 ← 1 [2] 3 4 5 ... 9 → │ ✅ Pagination! -└────────────────────────────────────────────────────────────┘ +### JavaScript State +```javascript +// Filters +filters: { + search: '', + is_active: '', // 'true', 'false', or '' + is_verified: '', // 'true', 'false', or '' +} +// Pagination +pagination: { + page: 1, + per_page: 10, + total: 0, + pages: 0 +} +``` -🎯 ACTION BUTTONS (3 BUTTONS PER ROW) -═════════════════════════════════════════════════════════════ +--- -1. 👁 View (Blue) ─────────→ View vendor details -2. ✏️ Edit (Purple) ⭐ NEW → Edit vendor form -3. 🗑 Delete (Red) ────────→ Delete with confirmation +## Computed Properties +| Property | Purpose | +|----------|---------| +| `totalPages` | Total number of pages | +| `startIndex` | First item number on current page | +| `endIndex` | Last item number on current page | +| `pageNumbers` | Array of page numbers with '...' | -🔢 PAGINATION CONTROLS -═════════════════════════════════════════════════════════════ +--- -Page 1 of 10: - [←] 1 2 3 4 5 ... 9 10 [→] - ^ ^ ^ ^ ^ - | | | | └─ Next button - | | | └──── Last page - | | └─────── Ellipsis (...) - | └───────────────────── Page numbers - └──────────────────────── Previous button (disabled) +## Methods -Page 5 of 10: - [←] 1 ... 4 [5] 6 ... 10 [→] - ↑ ↑ ↑ - | | └─ Next page - | └───── Current page (purple) - └───────── Previous pages +| Method | Purpose | +|--------|---------| +| `debouncedSearch()` | Triggers search after 300ms | +| `previousPage()` | Go to previous page | +| `nextPage()` | Go to next page | +| `goToPage(num)` | Jump to specific page | +--- -📊 HOW IT WORKS -═════════════════════════════════════════════════════════════ +## Page Number Display -1. Template displays: paginatedVendors (not all vendors) -2. Alpine.js computes: Which 10 vendors to show -3. User clicks page: currentPage updates -4. Template refreshes: Shows new 10 vendors +**Few pages (7 or less):** +``` +← 1 2 3 4 5 6 7 → +``` -Simple and reactive! 🎉 +**Many pages, at start:** +``` +← [1] 2 3 ... 10 → +``` +**Many pages, in middle:** +``` +← 1 ... 4 [5] 6 ... 10 → +``` -⚙️ CONFIGURATION -═════════════════════════════════════════════════════════════ +**Many pages, at end:** +``` +← 1 ... 8 9 [10] → +``` -Change items per page in vendors.js: +--- -// Find this line: -itemsPerPage: 10, +## API Integration -// Change to any number: -itemsPerPage: 25, // Show 25 per page -itemsPerPage: 50, // Show 50 per page +### Request +``` +GET /admin/vendors?skip=0&limit=10&search=acme&is_active=true +``` +### Response +```json +{ + "vendors": [...], + "total": 45, + "skip": 0, + "limit": 10 +} +``` -🧪 TESTING CHECKLIST -═════════════════════════════════════════════════════════════ +--- -After installation: +## Configuration -□ Vendors page loads -□ If <10 vendors: No pagination shows (correct!) -□ If >10 vendors: Pagination appears -□ Can click page numbers to navigate -□ Can click ← → arrows -□ "Showing X-Y of Z" updates correctly -□ Edit button (pencil icon) appears -□ Edit button navigates to edit page -□ View button still works -□ Delete button still works -□ Dark mode works -□ Pagination styling matches theme +### Change Items Per Page +Edit in JavaScript file: +```javascript +pagination: { + page: 1, + per_page: 25, // Change from 10 + total: 0, + pages: 0 +} +``` -🎨 FEATURES -═════════════════════════════════════════════════════════════ +--- -✅ Smart pagination (10 per page) -✅ Edit button added (purple pencil) -✅ Dynamic page numbers with "..." -✅ Previous/Next disabled at boundaries -✅ Shows "X-Y of Total" count -✅ Dark mode compatible -✅ Windmill theme styling -✅ Fully responsive -✅ Client-side pagination (fast!) -✅ Auto-reset to page 1 after data reload +## Files Reference +| Page | Template | JavaScript | +|------|----------|------------| +| Vendors | `templates/admin/vendors.html` | `static/admin/js/vendors.js` | +| Companies | `templates/admin/companies.html` | `static/admin/js/companies.js` | +| Users | `templates/admin/users.html` | `static/admin/js/users.js` | -💡 TIPS -═════════════════════════════════════════════════════════════ +--- -1. Need more vendors per page? - Change itemsPerPage in vendors.js +## Adding to a New Page -2. Want server-side pagination? - For 1000+ vendors, consider API pagination +1. **Add state** to JavaScript: +```javascript +filters: { search: '', is_active: '' }, +pagination: { page: 1, per_page: 10, total: 0, pages: 0 } +``` -3. Want to preserve page on refresh? - Add localStorage for currentPage +2. **Add computed properties**: `totalPages`, `startIndex`, `endIndex`, `pageNumbers` -4. Want to add search/filter? - Filter vendors array first, then paginate +3. **Add methods**: `debouncedSearch()`, `previousPage()`, `nextPage()`, `goToPage()` -5. Page numbers look weird? - Check you have enough vendors (need >10 to see pagination) +4. **Update load function** to use query params +5. **Add HTML** for search bar and pagination footer -🆘 TROUBLESHOOTING -═════════════════════════════════════════════════════════════ - -Problem: Pagination not showing -→ Need more than 10 vendors to see it -→ Check itemsPerPage value - -Problem: Edit button doesn't work -→ Check backend route exists: /admin/vendors/{code}/edit -→ Check browser console for errors - -Problem: Page numbers stuck -→ Clear browser cache (Ctrl+Shift+R) -→ Check Alpine.js loaded correctly - -Problem: "Showing 0-0 of 0" -→ Vendors not loading from API -→ Check API endpoint /admin/vendors - - -📁 FILES INCLUDED -═════════════════════════════════════════════════════════════ - -vendors.html ................. Updated template with pagination -vendors.js ................... Updated script with pagination logic -PAGINATION_DOCUMENTATION.md .. Full technical documentation -PAGINATION_QUICK_START.txt ... This file (quick reference) - - -📖 LEARN MORE -═════════════════════════════════════════════════════════════ - -For detailed technical explanation, see: -→ PAGINATION_DOCUMENTATION.md - - -══════════════════════════════════════════════════════════════ - Pagination made easy! 📖✨ -══════════════════════════════════════════════════════════════ +See `docs/frontend/shared/pagination.md` for full implementation details. diff --git a/docs/frontend/shared/pagination.md b/docs/frontend/shared/pagination.md index 13b82521..0ac06631 100644 --- a/docs/frontend/shared/pagination.md +++ b/docs/frontend/shared/pagination.md @@ -1,297 +1,351 @@ -# Vendor Page Pagination Implementation +# Admin List Pages - Pagination & Search Implementation -## 🎯 What's New +## Overview -Your vendors page now includes: -1. ✅ **Edit button** - Already present (pencil icon next to view icon) -2. ✅ **Pagination** - New pagination controls at the bottom of the table +All admin list pages (Vendors, Companies, Users) share a consistent pagination and search pattern using **server-side pagination** with Alpine.js. --- -## 📦 Files Updated +## Files Using This Pattern -### 1. vendors.html -**Changes:** -- Changed `x-for="vendor in vendors"` → `x-for="vendor in paginatedVendors"` -- Added pagination footer with controls -- Added "Showing X-Y of Z" results display - -### 2. vendors.js -**Changes:** -- Added pagination state: `currentPage`, `itemsPerPage` -- Added computed properties: - - `paginatedVendors` - Returns current page's vendors - - `totalPages` - Calculates total number of pages - - `startIndex` / `endIndex` - For "Showing X-Y" display - - `pageNumbers` - Generates smart page number array with ellipsis -- Added pagination methods: - - `goToPage(page)` - Navigate to specific page - - `nextPage()` - Go to next page - - `previousPage()` - Go to previous page +| Page | HTML Template | JavaScript | +|------|---------------|------------| +| Vendors | `templates/admin/vendors.html` | `static/admin/js/vendors.js` | +| Companies | `templates/admin/companies.html` | `static/admin/js/companies.js` | +| Users | `templates/admin/users.html` | `static/admin/js/users.js` | --- -## 🎨 Pagination Features +## State Structure -### Smart Page Number Display -The pagination intelligently shows page numbers: +### Filters Object +```javascript +filters: { + search: '', // Search query string + is_active: '', // 'true', 'false', or '' (all) + is_verified: '' // 'true', 'false', or '' (all) - vendors/companies only + role: '' // 'admin', 'vendor', or '' (all) - users only +} +``` -**Example 1: Few pages (≤7)** +### Pagination Object +```javascript +pagination: { + page: 1, // Current page number + per_page: 10, // Items per page + total: 0, // Total items from API + pages: 0 // Total pages (calculated) +} +``` + +--- + +## Computed Properties + +All three pages implement these computed properties: + +### `paginatedVendors` / `paginatedCompanies` / `users` +Returns the items array (already paginated from server): +```javascript +get paginatedVendors() { + return this.vendors; +} +``` + +### `totalPages` +```javascript +get totalPages() { + return this.pagination.pages; +} +``` + +### `startIndex` +```javascript +get startIndex() { + if (this.pagination.total === 0) return 0; + return (this.pagination.page - 1) * this.pagination.per_page + 1; +} +``` + +### `endIndex` +```javascript +get endIndex() { + const end = this.pagination.page * this.pagination.per_page; + return end > this.pagination.total ? this.pagination.total : end; +} +``` + +### `pageNumbers` +Generates smart page number array with ellipsis: +```javascript +get pageNumbers() { + const pages = []; + const totalPages = this.totalPages; + const current = this.pagination.page; + + if (totalPages <= 7) { + for (let i = 1; i <= totalPages; i++) { + pages.push(i); + } + } else { + pages.push(1); + if (current > 3) pages.push('...'); + + const start = Math.max(2, current - 1); + const end = Math.min(totalPages - 1, current + 1); + for (let i = start; i <= end; i++) { + pages.push(i); + } + + if (current < totalPages - 2) pages.push('...'); + pages.push(totalPages); + } + return pages; +} +``` + +--- + +## Methods + +### `debouncedSearch()` +Triggers search after 300ms delay: +```javascript +debouncedSearch() { + if (this._searchTimeout) { + clearTimeout(this._searchTimeout); + } + this._searchTimeout = setTimeout(() => { + this.pagination.page = 1; + this.loadVendors(); // or loadCompanies(), loadUsers() + }, 300); +} +``` + +### Pagination Methods +```javascript +previousPage() { + if (this.pagination.page > 1) { + this.pagination.page--; + this.loadVendors(); + } +} + +nextPage() { + if (this.pagination.page < this.totalPages) { + this.pagination.page++; + this.loadVendors(); + } +} + +goToPage(pageNum) { + if (pageNum !== '...' && pageNum >= 1 && pageNum <= this.totalPages) { + this.pagination.page = pageNum; + this.loadVendors(); + } +} +``` + +--- + +## API Integration + +### Building Query Parameters +```javascript +async loadVendors() { + const params = new URLSearchParams(); + params.append('skip', (this.pagination.page - 1) * this.pagination.per_page); + params.append('limit', this.pagination.per_page); + + if (this.filters.search) { + params.append('search', this.filters.search); + } + if (this.filters.is_active !== '') { + params.append('is_active', this.filters.is_active); + } + if (this.filters.is_verified !== '') { + params.append('is_verified', this.filters.is_verified); + } + + const response = await apiClient.get(`/admin/vendors?${params}`); + + this.vendors = response.vendors; + this.pagination.total = response.total; + this.pagination.pages = Math.ceil(response.total / this.pagination.per_page); +} +``` + +### API Response Format +```json +{ + "vendors": [...], + "total": 45, + "skip": 0, + "limit": 10 +} +``` + +--- + +## HTML Template Structure + +### Search & Filters Bar +```html +
+
+ +
+
+ + + + +
+
+ + +
+ + + + + +
+
+
+``` + +### Pagination Footer +```html +
+ + + Showing - + of + + + + + + + +
+``` + +--- + +## Page Number Display Examples + +**Few pages (<=7):** ``` ← 1 2 3 4 5 6 7 → ``` -**Example 2: Many pages, current = 1** +**Many pages, current = 1:** ``` -← 1 2 3 ... 9 10 → +← [1] 2 3 ... 10 → ``` -**Example 3: Many pages, current = 5** +**Many pages, current = 5:** ``` -← 1 ... 4 5 6 ... 10 → +← 1 ... 4 [5] 6 ... 10 → ``` -**Example 4: Many pages, current = 10** +**Many pages, current = 10:** ``` -← 1 ... 8 9 10 → -``` - -### Configurable Items Per Page -Default: 10 vendors per page - -To change, edit in `vendors.js`: -```javascript -itemsPerPage: 10, // Change this number +← 1 ... 8 9 [10] → ``` --- -## 🔧 How It Works +## Visual Layout -### 1. Computed Properties (Alpine.js) -Alpine.js computes these values reactively: - -```javascript -get paginatedVendors() { - const start = (this.currentPage - 1) * this.itemsPerPage; - const end = start + this.itemsPerPage; - return this.vendors.slice(start, end); -} ``` - -When `currentPage` changes, `paginatedVendors` automatically updates! - -### 2. Template Binding -The HTML template uses the computed property: -```html - -``` - -### 3. Pagination Controls -Buttons call the pagination methods: -```html -