feat: add complete company management UI

- Create companies list page with stats (total, verified, active, vendor count)
- Add company creation form with owner account generation
- Implement companies.js with full CRUD operations (list, create, edit, delete)
- Add Companies menu item to admin sidebar (desktop + mobile)
- Create company admin page routes (/admin/companies, /admin/companies/create)
- Register companies API router in admin __init__.py

Features:
- List all companies with pagination
- Create company with automatic owner user creation
- Display temporary password for new owner accounts
- Edit company information
- Delete company (only if no vendors)
- Toggle active/verified status
- Show vendor count per company

UI Components:
- Stats cards (total companies, verified, active, total vendors)
- Company table with status badges
- Create form with validation
- Success/error messaging
- Responsive design with dark mode support
This commit is contained in:
2025-12-01 21:50:20 +01:00
parent 4ca738dc7f
commit 801510ecc6
6 changed files with 1045 additions and 13 deletions

View File

@@ -20,6 +20,17 @@
<!-- Main Navigation -->
<ul>
<!-- Companies -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'companies'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'companies' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/companies">
<span x-html="$icon('office-building')"></span>
<span class="ml-4">Companies</span>
</a>
</li>
<!-- Vendors -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendors'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
@@ -42,14 +53,14 @@
</a>
</li>
<!-- Import Jobs -->
<!-- Marketplace Import -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'imports'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<span x-show="currentPage === 'marketplace'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'imports' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/imports">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
:class="currentPage === 'marketplace' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/marketplace">
<span x-html="$icon('shopping-bag')"></span>
<span class="ml-4">Marketplace Import</span>
</a>
</li>
</ul>
@@ -83,6 +94,17 @@
<span class="ml-4">Content Pages</span>
</a>
</li>
<!-- Vendor Themes -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendor-theme'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'vendor-theme' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/vendor-themes">
<span x-html="$icon('color-swatch')"></span>
<span class="ml-4">Vendor Themes</span>
</a>
</li>
</ul>
<!-- Developer Tools Section -->
@@ -138,6 +160,37 @@
</li>
</ul>
<!-- Platform Monitoring Section -->
<div class="px-6 my-6">
<hr class="border-gray-200 dark:border-gray-700" />
</div>
<p class="px-6 text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase tracking-wider">
Platform Monitoring
</p>
<ul class="mt-3">
<!-- Import Jobs -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'imports'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'imports' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/imports">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
</a>
</li>
<!-- Application Logs -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'logs'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'logs' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/logs">
<span x-html="$icon('document-text')"></span>
<span class="ml-4">Application Logs</span>
</a>
</li>
</ul>
<!-- Settings Section -->
<div class="px-6 my-6">
<hr class="border-gray-200 dark:border-gray-700" />
@@ -196,6 +249,17 @@
<!-- Main Navigation -->
<ul>
<!-- Companies -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'companies'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'companies' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/companies">
<span x-html="$icon('office-building')"></span>
<span class="ml-4">Companies</span>
</a>
</li>
<!-- Vendors -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendors'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
@@ -218,14 +282,14 @@
</a>
</li>
<!-- Import Jobs -->
<!-- Marketplace Import -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'imports'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<span x-show="currentPage === 'marketplace'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'imports' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/imports">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
:class="currentPage === 'marketplace' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/marketplace">
<span x-html="$icon('shopping-bag')"></span>
<span class="ml-4">Marketplace Import</span>
</a>
</li>
</ul>
@@ -259,6 +323,17 @@
<span class="ml-4">Content Pages</span>
</a>
</li>
<!-- Vendor Themes -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendor-theme'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'vendor-theme' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/vendor-themes">
<span x-html="$icon('color-swatch')"></span>
<span class="ml-4">Vendor Themes</span>
</a>
</li>
</ul>
<!-- Developer Tools Section -->
@@ -314,6 +389,37 @@
</li>
</ul>
<!-- Platform Monitoring Section -->
<div class="px-6 my-6">
<hr class="border-gray-200 dark:border-gray-700" />
</div>
<p class="px-6 text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase tracking-wider">
Platform Monitoring
</p>
<ul class="mt-3">
<!-- Import Jobs -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'imports'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'imports' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/imports">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
</a>
</li>
<!-- Application Logs -->
<li class="relative px-6 py-3">
<span x-show="currentPage === 'logs'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'logs' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/logs">
<span x-html="$icon('document-text')"></span>
<span class="ml-4">Application Logs</span>
</a>
</li>
</ul>
<!-- Settings Section -->
<div class="px-6 my-6">
<hr class="border-gray-200 dark:border-gray-700" />