compiling project documentation

This commit is contained in:
2025-10-26 19:59:53 +01:00
parent d79817f069
commit 99863ad80b
45 changed files with 24278 additions and 0 deletions

View File

@@ -0,0 +1,331 @@
# Alpine.js Page Template - Quick Reference
## ✅ Correct Page Structure
```javascript
// static/admin/js/your-page.js
// 1. Setup logging (optional but recommended)
const YOUR_PAGE_LOG_LEVEL = 3;
const yourPageLog = {
error: (...args) => YOUR_PAGE_LOG_LEVEL >= 1 && console.error('❌ [YOUR_PAGE ERROR]', ...args),
warn: (...args) => YOUR_PAGE_LOG_LEVEL >= 2 && console.warn('⚠️ [YOUR_PAGE WARN]', ...args),
info: (...args) => YOUR_PAGE_LOG_LEVEL >= 3 && console.info(' [YOUR_PAGE INFO]', ...args),
debug: (...args) => YOUR_PAGE_LOG_LEVEL >= 4 && console.log('🔍 [YOUR_PAGE DEBUG]', ...args)
};
// 2. Create your Alpine.js component
function yourPageComponent() {
return {
// ✅ CRITICAL: Inherit base layout functionality
...data(),
// ✅ CRITICAL: Set page identifier
currentPage: 'your-page',
// Your page-specific state
items: [],
loading: false,
error: null,
// ✅ CRITICAL: Proper initialization with guard
async init() {
yourPageLog.info('=== YOUR PAGE INITIALIZING ===');
// Prevent multiple initializations
if (window._yourPageInitialized) {
yourPageLog.warn('Page already initialized, skipping...');
return;
}
window._yourPageInitialized = true;
// Load your data
await this.loadData();
yourPageLog.info('=== YOUR PAGE INITIALIZATION COMPLETE ===');
},
// Your methods
async loadData() {
yourPageLog.info('Loading data...');
this.loading = true;
this.error = null;
try {
const startTime = Date.now();
// ✅ CRITICAL: Use lowercase apiClient
const response = await apiClient.get('/your/endpoint');
const duration = Date.now() - startTime;
this.items = response.items || [];
yourPageLog.info(`Data loaded in ${duration}ms`, {
count: this.items.length
});
} catch (error) {
yourPageLog.error('Failed to load data:', error);
this.error = error.message;
Utils.showToast('Failed to load data', 'error');
} finally {
this.loading = false;
}
},
// Format date helper (if needed)
formatDate(dateString) {
if (!dateString) return '-';
return Utils.formatDate(dateString);
},
// Your other methods...
};
}
yourPageLog.info('Your page module loaded');
```
---
## 🎯 Checklist for New Pages
### HTML Template
```jinja2
{# app/templates/admin/your-page.html #}
{% extends "admin/base.html" %}
{% block title %}Your Page{% endblock %}
{# ✅ CRITICAL: Link to your Alpine.js component #}
{% block alpine_data %}yourPageComponent(){% endblock %}
{% block content %}
<!-- Your page content -->
{% endblock %}
{% block extra_scripts %}
{# ✅ CRITICAL: Load your JavaScript file #}
<script src="{{ url_for('static', path='admin/js/your-page.js') }}"></script>
{% endblock %}
```
### JavaScript File Checklist
- [ ] ✅ Logging setup (optional)
- [ ] ✅ Function name matches `alpine_data` in template
- [ ]`...data(),` at start of return object
- [ ]`currentPage: 'your-page'` set
- [ ] ✅ Initialization guard in `init()`
- [ ] ✅ Use lowercase `apiClient` for API calls
- [ ] ✅ Use your custom logger (not `Logger`)
- [ ] ✅ Performance tracking with `Date.now()` (optional)
- [ ] ✅ Module loaded log at end
---
## ❌ Common Mistakes to Avoid
### 1. Missing Base Inheritance
```javascript
// ❌ WRONG
function myPage() {
return {
items: [],
// Missing ...data()
};
}
// ✅ CORRECT
function myPage() {
return {
...data(), // Must be first!
items: [],
};
}
```
### 2. Wrong API Client Name
```javascript
// ❌ WRONG - Capital letters
await ApiClient.get('/endpoint');
await API_CLIENT.get('/endpoint');
// ✅ CORRECT - lowercase
await apiClient.get('/endpoint');
```
### 3. Missing Init Guard
```javascript
// ❌ WRONG
async init() {
await this.loadData();
}
// ✅ CORRECT
async init() {
if (window._myPageInitialized) return;
window._myPageInitialized = true;
await this.loadData();
}
```
### 4. Missing currentPage
```javascript
// ❌ WRONG
return {
...data(),
items: [],
// Missing currentPage
};
// ✅ CORRECT
return {
...data(),
currentPage: 'my-page', // Must set this!
items: [],
};
```
---
## 🔧 API Client Pattern
### GET Request
```javascript
try {
const response = await apiClient.get('/endpoint');
this.data = response;
} catch (error) {
console.error('Failed:', error);
Utils.showToast('Failed to load', 'error');
}
```
### POST Request
```javascript
try {
const response = await apiClient.post('/endpoint', {
name: 'value',
// ... data
});
Utils.showToast('Created successfully', 'success');
} catch (error) {
console.error('Failed:', error);
Utils.showToast('Failed to create', 'error');
}
```
### PUT Request
```javascript
try {
const response = await apiClient.put('/endpoint/123', {
name: 'updated value'
});
Utils.showToast('Updated successfully', 'success');
} catch (error) {
console.error('Failed:', error);
Utils.showToast('Failed to update', 'error');
}
```
### DELETE Request
```javascript
try {
await apiClient.delete('/endpoint/123');
Utils.showToast('Deleted successfully', 'success');
await this.reloadData();
} catch (error) {
console.error('Failed:', error);
Utils.showToast('Failed to delete', 'error');
}
```
---
## 🎨 Common UI Patterns
### Loading State
```javascript
async loadData() {
this.loading = true;
try {
const data = await apiClient.get('/endpoint');
this.items = data;
} finally {
this.loading = false;
}
}
```
### Error Handling
```javascript
async loadData() {
this.loading = true;
this.error = null;
try {
const data = await apiClient.get('/endpoint');
this.items = data;
} catch (error) {
this.error = error.message;
Utils.showToast('Failed to load', 'error');
} finally {
this.loading = false;
}
}
```
### Refresh/Reload
```javascript
async refresh() {
console.info('Refreshing...');
await this.loadData();
Utils.showToast('Refreshed successfully', 'success');
}
```
---
## 📚 Available Utilities
### From `init-alpine.js` (via `...data()`)
- `this.dark` - Dark mode state
- `this.toggleTheme()` - Toggle theme
- `this.isSideMenuOpen` - Side menu state
- `this.toggleSideMenu()` - Toggle side menu
- `this.closeSideMenu()` - Close side menu
- `this.isNotificationsMenuOpen` - Notifications menu state
- `this.toggleNotificationsMenu()` - Toggle notifications
- `this.closeNotificationsMenu()` - Close notifications
- `this.isProfileMenuOpen` - Profile menu state
- `this.toggleProfileMenu()` - Toggle profile menu
- `this.closeProfileMenu()` - Close profile menu
- `this.isPagesMenuOpen` - Pages menu state
- `this.togglePagesMenu()` - Toggle pages menu
### From `Utils` (global)
- `Utils.showToast(message, type, duration)` - Show toast notification
- `Utils.formatDate(dateString)` - Format date for display
- `Utils.confirm(message, title)` - Show confirmation dialog (if available)
### From `apiClient` (global)
- `apiClient.get(url)` - GET request
- `apiClient.post(url, data)` - POST request
- `apiClient.put(url, data)` - PUT request
- `apiClient.delete(url)` - DELETE request
---
## 🚀 Quick Start Template Files
Copy these to create a new page:
1. Copy `dashboard.js` → rename to `your-page.js`
2. Replace function name: `adminDashboard()``yourPageComponent()`
3. Update logging prefix: `dashLog``yourPageLog`
4. Update init flag: `_dashboardInitialized``_yourPageInitialized`
5. Update `currentPage`: `'dashboard'``'your-page'`
6. Replace data loading logic with your endpoints
7. Update HTML template to use your function name
Done! ✅