feat: implement admin-users management with super admin restriction
- Add /admin/admin-users routes for managing admin users (super admin only) - Remove vendor role from user creation form (vendors created via company hierarchy) - Add admin-users.html and admin-user-detail.html templates - Add admin-users.js and admin-user-detail.js for frontend logic - Move database operations to admin_platform_service (list, get, create, delete, toggle status) - Update sidebar to show Admin Users section only for super admins - Add isSuperAdmin computed property to init-alpine.js - Fix /api/v1 prefix issues in JS files (apiClient already adds prefix) - Update architecture rule JS-012 to catch more variable patterns (url, endpoint, path) - Replace inline SVGs with $icon() helper in select-platform.html Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
{% extends "admin/base.html" %}
|
||||
{% from 'shared/macros/headers.html' import page_header %}
|
||||
|
||||
{% block title %}Create User{% endblock %}
|
||||
{% block title %}Create Admin User{% endblock %}
|
||||
|
||||
{% block alpine_data %}adminUserCreate(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ page_header('Create New User', subtitle='Add a new user to the platform', back_url='/admin/users', back_label='Back to Users') }}
|
||||
{{ page_header('Create Admin User', subtitle='Add a new admin user to manage platforms', back_url='/admin/admin-users', back_label='Back to Admin Users') }}
|
||||
|
||||
<!-- Create Form -->
|
||||
<form @submit.prevent="handleSubmit" class="px-4 py-3 mb-8 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
||||
@@ -74,29 +74,9 @@
|
||||
<span x-show="errors.password" class="text-xs text-red-600 dark:text-red-400 mt-1" x-text="errors.password"></span>
|
||||
</label>
|
||||
|
||||
<!-- Role -->
|
||||
<label class="block mb-4 text-sm">
|
||||
<span class="text-gray-700 dark:text-gray-400">
|
||||
Role <span class="text-red-600">*</span>
|
||||
</span>
|
||||
<select
|
||||
x-model="formData.role"
|
||||
@change="onRoleChange()"
|
||||
:disabled="saving"
|
||||
class="block w-full mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-select"
|
||||
>
|
||||
<option value="vendor">Vendor</option>
|
||||
<option value="admin">Admin</option>
|
||||
</select>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-400 mt-1">
|
||||
Vendor: Can own companies and manage stores. Admin: Platform management access.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<!-- Admin-specific options -->
|
||||
<template x-if="formData.role === 'admin'">
|
||||
<div class="mt-4 p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg border border-purple-200 dark:border-purple-800">
|
||||
<h4 class="text-sm font-medium text-purple-800 dark:text-purple-300 mb-3">Admin Settings</h4>
|
||||
<!-- Admin Settings -->
|
||||
<div class="mt-4 p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg border border-purple-200 dark:border-purple-800">
|
||||
<h4 class="text-sm font-medium text-purple-800 dark:text-purple-300 mb-3">Admin Settings</h4>
|
||||
|
||||
<!-- Super Admin Toggle -->
|
||||
<label class="flex items-center mb-4">
|
||||
@@ -114,37 +94,36 @@
|
||||
Super admins have access to all platforms and can manage other admins.
|
||||
</p>
|
||||
|
||||
<!-- Platform Assignment (only if not super admin) -->
|
||||
<template x-if="!formData.is_super_admin">
|
||||
<div>
|
||||
<label class="block text-sm">
|
||||
<span class="text-gray-700 dark:text-gray-400">
|
||||
Assigned Platforms <span class="text-red-600">*</span>
|
||||
</span>
|
||||
<div class="mt-2 space-y-2 max-h-48 overflow-y-auto">
|
||||
<template x-for="platform in platforms" :key="platform.id">
|
||||
<label class="flex items-center p-2 rounded hover:bg-purple-100 dark:hover:bg-purple-900/30 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
:value="platform.id"
|
||||
x-model="formData.platform_ids"
|
||||
:disabled="saving"
|
||||
class="w-4 h-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500 dark:border-gray-600 dark:bg-gray-700"
|
||||
>
|
||||
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300" x-text="platform.name"></span>
|
||||
<span class="ml-2 text-xs text-gray-500 dark:text-gray-400" x-text="'(' + platform.code + ')'"></span>
|
||||
</label>
|
||||
</template>
|
||||
</div>
|
||||
<p x-show="platforms.length === 0" class="text-sm text-gray-500 dark:text-gray-400 mt-2">
|
||||
No platforms available. Create a platform first.
|
||||
</p>
|
||||
<span x-show="errors.platform_ids" class="text-xs text-red-600 dark:text-red-400 mt-1" x-text="errors.platform_ids"></span>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<!-- Platform Assignment (only if not super admin) -->
|
||||
<template x-if="!formData.is_super_admin">
|
||||
<div>
|
||||
<label class="block text-sm">
|
||||
<span class="text-gray-700 dark:text-gray-400">
|
||||
Assigned Platforms <span class="text-red-600">*</span>
|
||||
</span>
|
||||
<div class="mt-2 space-y-2 max-h-48 overflow-y-auto">
|
||||
<template x-for="platform in platforms" :key="platform.id">
|
||||
<label class="flex items-center p-2 rounded hover:bg-purple-100 dark:hover:bg-purple-900/30 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
:value="platform.id"
|
||||
x-model="formData.platform_ids"
|
||||
:disabled="saving"
|
||||
class="w-4 h-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500 dark:border-gray-600 dark:bg-gray-700"
|
||||
>
|
||||
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300" x-text="platform.name"></span>
|
||||
<span class="ml-2 text-xs text-gray-500 dark:text-gray-400" x-text="'(' + platform.code + ')'"></span>
|
||||
</label>
|
||||
</template>
|
||||
</div>
|
||||
<p x-show="platforms.length === 0" class="text-sm text-gray-500 dark:text-gray-400 mt-2">
|
||||
No platforms available. Create a platform first.
|
||||
</p>
|
||||
<span x-show="errors.platform_ids" class="text-xs text-red-600 dark:text-red-400 mt-1" x-text="errors.platform_ids"></span>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Personal Info -->
|
||||
@@ -188,7 +167,7 @@
|
||||
<!-- Submit Button -->
|
||||
<div class="flex items-center justify-end gap-3 pt-6 border-t dark:border-gray-700">
|
||||
<a
|
||||
href="/admin/users"
|
||||
href="/admin/admin-users"
|
||||
class="px-4 py-2 text-sm font-medium leading-5 text-gray-700 transition-colors duration-150 bg-white border border-gray-300 rounded-lg dark:text-gray-400 dark:border-gray-600 dark:bg-gray-800 hover:border-gray-400 focus:outline-none">
|
||||
Cancel
|
||||
</a>
|
||||
@@ -198,7 +177,7 @@
|
||||
class="flex items-center px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!saving">
|
||||
<span x-html="$icon('user-plus', 'w-4 h-4 mr-2 inline')"></span>
|
||||
Create User
|
||||
Create Admin User
|
||||
</span>
|
||||
<span x-show="saving" class="flex items-center">
|
||||
<span x-html="$icon('spinner', 'w-4 h-4 mr-2')"></span>
|
||||
|
||||
Reference in New Issue
Block a user