- Add platform detail and edit admin pages with templates and JS - Add ContentPageService methods: list_all_platform_pages, list_all_vendor_defaults - Deprecate /admin/platform-homepage route (redirects to /admin/platforms) - Add migration to fix content_page nullable columns - Refine platform and vendor context middleware - Add platform context middleware unit tests - Update platforms.js with improved functionality - Add section-based homepage plan documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
140 lines
4.0 KiB
JavaScript
140 lines
4.0 KiB
JavaScript
/**
|
|
* Platform Detail - Alpine.js Component
|
|
*
|
|
* Displays platform overview, stats, and quick actions.
|
|
*/
|
|
|
|
const platformDetailLog = window.LogConfig.createLogger('PLATFORM_DETAIL');
|
|
|
|
function platformDetail() {
|
|
return {
|
|
// Inherit base layout functionality from init-alpine.js
|
|
...data(),
|
|
|
|
// Page identification
|
|
currentPage: 'platform-detail',
|
|
|
|
// State
|
|
platform: null,
|
|
stats: null,
|
|
recentPages: [],
|
|
loading: true,
|
|
error: null,
|
|
platformCode: null,
|
|
|
|
// Lifecycle
|
|
async init() {
|
|
platformDetailLog.info('=== PLATFORM DETAIL PAGE INITIALIZING ===');
|
|
|
|
// Duplicate initialization guard
|
|
if (window._platformDetailInitialized) {
|
|
platformDetailLog.warn('Platform detail page already initialized, skipping...');
|
|
return;
|
|
}
|
|
window._platformDetailInitialized = true;
|
|
|
|
try {
|
|
// Extract platform code from URL
|
|
const path = window.location.pathname;
|
|
const match = path.match(/\/admin\/platforms\/([^\/]+)$/);
|
|
|
|
if (match) {
|
|
this.platformCode = match[1];
|
|
platformDetailLog.info('Viewing platform:', this.platformCode);
|
|
await Promise.all([
|
|
this.loadPlatform(),
|
|
this.loadRecentPages(),
|
|
]);
|
|
} else {
|
|
platformDetailLog.error('No platform code in URL');
|
|
this.error = 'Platform code not found in URL';
|
|
this.loading = false;
|
|
}
|
|
|
|
platformDetailLog.info('=== PLATFORM DETAIL PAGE INITIALIZATION COMPLETE ===');
|
|
} catch (error) {
|
|
window.LogConfig.logError(error, 'Platform Detail Init');
|
|
this.error = 'Failed to initialize page';
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
// API Methods
|
|
async loadPlatform() {
|
|
try {
|
|
const response = await apiClient.get(`/admin/platforms/${this.platformCode}`);
|
|
this.platform = response;
|
|
platformDetailLog.info(`Loaded platform: ${this.platformCode}`);
|
|
} catch (err) {
|
|
platformDetailLog.error('Error loading platform:', err);
|
|
this.error = err.message || 'Failed to load platform';
|
|
throw err;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async loadRecentPages() {
|
|
try {
|
|
// Load recent content pages for this platform
|
|
const response = await apiClient.get(`/admin/content-pages?platform_code=${this.platformCode}&limit=5`);
|
|
this.recentPages = response.items || response || [];
|
|
platformDetailLog.info(`Loaded ${this.recentPages.length} recent pages`);
|
|
} catch (err) {
|
|
platformDetailLog.error('Error loading recent pages:', err);
|
|
// Non-fatal - don't throw
|
|
this.recentPages = [];
|
|
}
|
|
},
|
|
|
|
// Helper Methods
|
|
getPlatformIcon(code) {
|
|
const icons = {
|
|
main: 'home',
|
|
oms: 'clipboard-list',
|
|
loyalty: 'star',
|
|
sitebuilder: 'template',
|
|
};
|
|
return icons[code] || 'globe-alt';
|
|
},
|
|
|
|
getPageTypeLabel(page) {
|
|
if (page.is_platform_page) return 'Marketing';
|
|
if (page.vendor_id) return 'Vendor Override';
|
|
return 'Vendor Default';
|
|
},
|
|
|
|
getPageTypeBadgeClass(page) {
|
|
if (page.is_platform_page) {
|
|
return 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200';
|
|
}
|
|
if (page.vendor_id) {
|
|
return 'bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-200';
|
|
}
|
|
return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200';
|
|
},
|
|
|
|
formatDate(dateString) {
|
|
if (!dateString) return '—';
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString('fr-LU', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric',
|
|
});
|
|
},
|
|
|
|
getPlatformUrl() {
|
|
if (!this.platform) return '#';
|
|
if (this.platform.domain) {
|
|
return `https://${this.platform.domain}`;
|
|
}
|
|
// Development URL
|
|
if (this.platform.code === 'main') {
|
|
return '/';
|
|
}
|
|
return `/platforms/${this.platform.code}/`;
|
|
},
|
|
};
|
|
}
|