Implemented a comprehensive CMS for managing platform homepage and content pages: - Platform homepage manager with template selection (default, minimal, modern) - Content pages CRUD with platform defaults and vendor overrides - Sidebar navigation for Content Management section - Dedicated API endpoints for creating, updating, deleting pages - Template support for customizable homepage layouts - Header/footer navigation integration for content pages - Comprehensive documentation for platform homepage setup - Migration script for creating initial platform pages UI improvements: - Fixed action buttons styling in content pages table to match design system - Added proper hover states, rounded corners, and better contrast - Increased button size and padding for better usability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
312 lines
17 KiB
HTML
312 lines
17 KiB
HTML
{# app/templates/admin/partials/sidebar.html #}
|
|
<!-- Desktop sidebar -->
|
|
<aside class="z-20 hidden w-64 overflow-y-auto bg-white dark:bg-gray-800 md:block flex-shrink-0">
|
|
<div class="py-4 text-gray-500 dark:text-gray-400">
|
|
<a class="ml-6 text-lg font-bold text-gray-800 dark:text-gray-200" href="/admin/dashboard">
|
|
Admin Portal
|
|
</a>
|
|
<ul class="mt-6">
|
|
<!-- Dashboard -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'dashboard'" 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 === 'dashboard' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/dashboard">
|
|
<span x-html="$icon('home')"></span>
|
|
<span class="ml-4">Dashboard</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Main Navigation -->
|
|
<ul>
|
|
<!-- 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>
|
|
<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 === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/vendors">
|
|
<span x-html="$icon('shopping-bag')"></span>
|
|
<span class="ml-4">Vendors</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Users -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'users'" 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 === 'users' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/users">
|
|
<span x-html="$icon('users')"></span>
|
|
<span class="ml-4">Users</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- 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>
|
|
</ul>
|
|
|
|
<!-- Content Management 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">
|
|
Content Management
|
|
</p>
|
|
<ul class="mt-3">
|
|
<!-- Platform Homepage -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'platform-homepage'" 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 === 'platform-homepage' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/platform-homepage">
|
|
<span x-html="$icon('home')"></span>
|
|
<span class="ml-4">Platform Homepage</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Content Pages -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'content-pages'" 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 === 'content-pages' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/content-pages">
|
|
<span x-html="$icon('document-text')"></span>
|
|
<span class="ml-4">Content Pages</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Developer Tools 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">
|
|
Developer Tools
|
|
</p>
|
|
<ul class="mt-3">
|
|
<!-- Components -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'components'" 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 === 'components' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/components">
|
|
<span x-html="$icon('view-grid')"></span>
|
|
<span class="ml-4">Components</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Icons -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'icons'" 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 === 'icons' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/icons">
|
|
<span x-html="$icon('photograph')"></span>
|
|
<span class="ml-4">Icons</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Testing Hub -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'testing'" 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 === 'testing' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/testing">
|
|
<span x-html="$icon('beaker')"></span>
|
|
<span class="ml-4">Testing Hub</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Settings Section -->
|
|
<div class="px-6 my-6">
|
|
<hr class="border-gray-200 dark:border-gray-700" />
|
|
</div>
|
|
<ul>
|
|
<!-- Settings -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'settings'" 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 === 'settings' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/settings">
|
|
<span x-html="$icon('cog')"></span>
|
|
<span class="ml-4">Settings</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Mobile sidebar -->
|
|
<div x-show="isSideMenuOpen"
|
|
x-transition:enter="transition ease-in-out duration-150"
|
|
x-transition:enter-start="opacity-0"
|
|
x-transition:enter-end="opacity-100"
|
|
x-transition:leave="transition ease-in-out duration-150"
|
|
x-transition:leave-start="opacity-100"
|
|
x-transition:leave-end="opacity-0"
|
|
class="fixed inset-0 z-10 flex items-end bg-black bg-opacity-50 sm:items-center sm:justify-center"></div>
|
|
|
|
<aside class="fixed inset-y-0 z-20 flex-shrink-0 w-64 mt-16 overflow-y-auto bg-white dark:bg-gray-800 md:hidden"
|
|
x-show="isSideMenuOpen"
|
|
x-transition:enter="transition ease-in-out duration-150"
|
|
x-transition:enter-start="opacity-0 transform -translate-x-20"
|
|
x-transition:enter-end="opacity-100"
|
|
x-transition:leave="transition ease-in-out duration-150"
|
|
x-transition:leave-start="opacity-100"
|
|
x-transition:leave-end="opacity-0 transform -translate-x-20"
|
|
@click.away="closeSideMenu"
|
|
@keydown.escape="closeSideMenu">
|
|
<div class="py-4 text-gray-500 dark:text-gray-400">
|
|
<a class="ml-6 text-lg font-bold text-gray-800 dark:text-gray-200" href="/admin/dashboard">
|
|
Admin Portal
|
|
</a>
|
|
<ul class="mt-6">
|
|
<!-- Dashboard -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'dashboard'" 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 === 'dashboard' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/dashboard">
|
|
<span x-html="$icon('home')"></span>
|
|
<span class="ml-4">Dashboard</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Main Navigation -->
|
|
<ul>
|
|
<!-- 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>
|
|
<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 === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/vendors">
|
|
<span x-html="$icon('shopping-bag')"></span>
|
|
<span class="ml-4">Vendors</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Users -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'users'" 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 === 'users' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/users">
|
|
<span x-html="$icon('users')"></span>
|
|
<span class="ml-4">Users</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- 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>
|
|
</ul>
|
|
|
|
<!-- Content Management 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">
|
|
Content Management
|
|
</p>
|
|
<ul class="mt-3">
|
|
<!-- Platform Homepage -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'platform-homepage'" 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 === 'platform-homepage' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/platform-homepage">
|
|
<span x-html="$icon('home')"></span>
|
|
<span class="ml-4">Platform Homepage</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Content Pages -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'content-pages'" 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 === 'content-pages' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/content-pages">
|
|
<span x-html="$icon('document-text')"></span>
|
|
<span class="ml-4">Content Pages</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Developer Tools 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">
|
|
Developer Tools
|
|
</p>
|
|
<ul class="mt-3">
|
|
<!-- Components -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'components'" 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 === 'components' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/components">
|
|
<span x-html="$icon('view-grid')"></span>
|
|
<span class="ml-4">Components</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Icons -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'icons'" 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 === 'icons' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/icons">
|
|
<span x-html="$icon('photograph')"></span>
|
|
<span class="ml-4">Icons</span>
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Testing Hub -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'testing'" 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 === 'testing' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/testing">
|
|
<span x-html="$icon('beaker')"></span>
|
|
<span class="ml-4">Testing Hub</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Settings Section -->
|
|
<div class="px-6 my-6">
|
|
<hr class="border-gray-200 dark:border-gray-700" />
|
|
</div>
|
|
<ul>
|
|
<!-- Settings -->
|
|
<li class="relative px-6 py-3">
|
|
<span x-show="currentPage === 'settings'" 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 === 'settings' ? 'text-gray-800 dark:text-gray-100' : ''"
|
|
href="/admin/settings">
|
|
<span x-html="$icon('cog')"></span>
|
|
<span class="ml-4">Settings</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</aside> |