# UI Components This document describes the reusable UI components and patterns used in the Wizamart admin panel. ## Page Layout Structure All admin list pages follow a consistent structure: ``` ┌─────────────────────────────────────────────────────┐ │ Page Header (Title + Action Button) │ ├─────────────────────────────────────────────────────┤ │ Stats Cards (4 columns on desktop) │ ├─────────────────────────────────────────────────────┤ │ Search & Filters Bar │ ├─────────────────────────────────────────────────────┤ │ Data Table │ │ ├── Table Header │ │ ├── Table Rows │ │ └── Pagination │ └─────────────────────────────────────────────────────┘ ``` ## Page Header The page header contains the page title and primary action button. ```html

Page Title

Create Resource
``` ## Stats Cards Stats cards display key metrics in a 4-column grid layout. ### Structure ```html

Label

0

``` ### Color Options | Color | Use Case | Example | |-------|----------|---------| | `blue` | Total counts | Total Users, Total Companies | | `green` | Positive status | Active, Verified | | `red` | Negative status | Inactive, Errors | | `orange` | Special/Admin | Admin users, Warnings | | `purple` | Primary/Vendors | Active vendors, Main metrics | ### Icon Style - Icons should be inside a **circular** container (`rounded-full`) - Icon size: `w-5 h-5` - Container padding: `p-3` ## Search & Filters Bar The search and filters bar provides filtering capabilities for list pages. ### Structure ```html
``` ### JavaScript Implementation ```javascript // State filters: { search: '', status: '', type: '' }, // Debounced search function debouncedSearch() { if (this._searchTimeout) { clearTimeout(this._searchTimeout); } this._searchTimeout = setTimeout(() => { this.pagination.page = 1; // Reset to first page this.loadData(); }, 300); }, // Load data with filters async loadData() { const params = new URLSearchParams(); params.append('page', this.pagination.page); params.append('per_page', this.pagination.per_page); if (this.filters.search) { params.append('search', this.filters.search); } if (this.filters.status) { params.append('status', this.filters.status); } const response = await apiClient.get(`/admin/resource?${params}`); // Handle response... } ``` ### Backend API Support The API endpoint should support these query parameters: | Parameter | Type | Description | |-----------|------|-------------| | `page` | int | Page number (1-based) | | `per_page` | int | Items per page | | `search` | string | Search term (searches multiple fields) | | `{filter}` | string | Filter by specific field | Example API implementation: ```python @router.get("", response_model=ListResponse) def get_all( page: int = Query(1, ge=1), per_page: int = Query(10, ge=1, le=100), search: str = Query("", description="Search term"), status: str = Query("", description="Filter by status"), db: Session = Depends(get_db), ): query = db.query(Model) # Apply search if search: search_term = f"%{search.lower()}%" query = query.filter( (Model.name.ilike(search_term)) | (Model.email.ilike(search_term)) ) # Apply filters if status: query = query.filter(Model.status == status) # Pagination total = query.count() items = query.offset((page - 1) * per_page).limit(per_page).all() return ListResponse(items=items, total=total, page=page, ...) ``` ## Data Table ### Structure ```html
Column Actions
``` ### Action Buttons Standard action buttons for table rows: ```html
``` ### Status Badges ```html ``` ## Loading & Error States ### Loading State ```html

Loading...

``` ### Error State ```html

Error loading data

``` ### Empty State ```html ``` ## Pages Using These Components | Page | Stats | Search | Filters | |------|-------|--------|---------| | `/admin/users` | Total, Active, Inactive, Admins | Name, Email, Username | Role, Status | | `/admin/companies` | Total, Verified, Active, Vendors | Name, Email, Owner | Status | | `/admin/vendors` | Total, Verified, Active, Products | Name, Code, Subdomain | Status, Company | ## JavaScript Module Structure Each list page follows this pattern: ```javascript function adminResourceList() { return { // Inherit base layout ...data(), // Page identifier (for sidebar highlighting) currentPage: 'resource-name', // State items: [], loading: false, error: null, filters: { search: '', status: '' }, stats: {}, pagination: { page: 1, per_page: 10, total: 0, pages: 0 }, // Initialize async init() { await this.loadItems(); await this.loadStats(); }, // Format helpers formatDate(dateString) { return dateString ? Utils.formatDate(dateString) : '-'; }, // Data loading async loadItems() { /* ... */ }, async loadStats() { /* ... */ }, // Search & filters debouncedSearch() { /* ... */ }, // Pagination nextPage() { /* ... */ }, previousPage() { /* ... */ }, // Actions async deleteItem(item) { /* ... */ } }; } ``` ## Related Documentation - [Icons Reference](./icons.md) - [Alpine.js Integration](./alpine-integration.md) - [Tailwind CSS](./tailwind-css.md)