feat: add platform selection frontend for platform admins

Frontend implementation of platform admin flow:
- Update login.js to check for platform selection after login
- Add platform selection page (/admin/select-platform)
- Add platform context indicator in admin header
- Add is_super_admin to UserResponse schema
- Show "Super Admin" badge or platform name with switch option

Platform admins now:
1. Login normally at /admin/login
2. Get redirected to /admin/select-platform if they have multiple platforms
3. See current platform in header with option to switch

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-24 18:54:59 +01:00
parent 53e05dd497
commit 300f49c5a1
6 changed files with 406 additions and 3 deletions

View File

@@ -20,6 +20,27 @@
</div>
<ul class="flex items-center flex-shrink-0 space-x-6">
<!-- Platform Context Indicator (for platform admins) -->
<li class="flex" x-data="platformContext()">
<template x-if="platform && !isSuperAdmin">
<div class="flex items-center space-x-2">
<span class="px-3 py-1 text-xs font-medium text-purple-700 bg-purple-100 dark:text-purple-300 dark:bg-purple-900/30 rounded-full">
<span x-text="platform.name"></span>
</span>
<a href="/admin/select-platform"
class="text-xs text-gray-500 hover:text-purple-600 dark:text-gray-400 dark:hover:text-purple-400"
title="Switch platform">
<span x-html="$icon('switch-horizontal', 'w-4 h-4')"></span>
</a>
</div>
</template>
<template x-if="isSuperAdmin">
<span class="px-3 py-1 text-xs font-medium text-green-700 bg-green-100 dark:text-green-300 dark:bg-green-900/30 rounded-full">
Super Admin
</span>
</template>
</li>
<!-- Theme toggler -->
<li class="flex">
<button class="rounded-md focus:outline-none focus:shadow-outline-purple"
@@ -182,6 +203,53 @@
<!-- Header notifications and logout handler script -->
<script>
// Platform context component for header
function platformContext() {
return {
platform: null,
isSuperAdmin: false,
init() {
// Try to get platform from localStorage
const storedPlatform = localStorage.getItem('admin_platform');
if (storedPlatform) {
try {
this.platform = JSON.parse(storedPlatform);
} catch (e) {
console.warn('Failed to parse stored platform:', e);
}
}
// Check if user is super admin
const storedUser = localStorage.getItem('admin_user');
if (storedUser) {
try {
const user = JSON.parse(storedUser);
this.isSuperAdmin = user.is_super_admin === true;
} catch (e) {
console.warn('Failed to parse stored user:', e);
}
}
}
};
}
// Header messages component
function headerMessages() {
return {
unreadCount: 0,
async init() {
try {
const response = await apiClient.get('/admin/messages/unread-count');
this.unreadCount = response.count || 0;
} catch (error) {
// Silently fail - messages count is not critical
}
}
};
}
// Header notifications component
function headerNotifications() {
return {
@@ -288,6 +356,7 @@ document.addEventListener('alpine:init', () => {
// Keep admin_last_visited_page so user returns to same page after login
localStorage.removeItem('admin_token');
localStorage.removeItem('admin_user');
localStorage.removeItem('admin_platform');
// Note: Do NOT use localStorage.clear() - it would clear vendor/customer tokens too
window.location.href = '/admin/login';
});