add htmx web frontend with templates and session auth

This commit is contained in:
2026-01-18 21:11:23 +01:00
parent 1bc112047d
commit 01a0ac68a4
11 changed files with 969 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
{{define "app_list"}}
{{if .Apps}}
{{range .Apps}}
<a href="/apps/{{.ID}}" class="block px-6 py-4 hover:bg-gray-50 transition-colors">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<div class="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center">
<svg class="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/>
</svg>
</div>
<div>
<h3 class="text-sm font-medium text-gray-900">{{.Name}}</h3>
<p class="text-sm text-gray-500">{{.PackageID}}</p>
</div>
</div>
<div class="flex items-center space-x-6">
{{if eq .Status "published"}}
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
Published
</span>
{{else if eq .Status "draft"}}
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
Draft
</span>
{{else if eq .Status "review"}}
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
In Review
</span>
{{else}}
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
{{.Status}}
</span>
{{end}}
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
</div>
</a>
{{end}}
{{else}}
<div class="px-6 py-12 text-center">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/>
</svg>
<h3 class="mt-2 text-sm font-medium text-gray-900">No apps yet</h3>
<p class="mt-1 text-sm text-gray-500">Get started by creating your first app.</p>
<div class="mt-6">
<a href="/apps/new" class="inline-flex items-center px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
New App
</a>
</div>
</div>
{{end}}
{{end}}

View File

@@ -0,0 +1,55 @@
{{define "navbar"}}
<nav class="bg-white shadow-sm border-b border-gray-200">
<div class="container mx-auto px-4">
<div class="flex justify-between items-center h-16">
<!-- Logo -->
<a href="/dashboard" class="flex items-center space-x-2">
<svg class="w-8 h-8 text-indigo-600" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>
</svg>
<span class="font-bold text-xl text-gray-900">Mosis</span>
</a>
<!-- Navigation Links -->
<div class="hidden md:flex items-center space-x-8">
<a href="/dashboard" class="text-gray-600 hover:text-gray-900 {{if eq .ActiveNav "dashboard"}}text-indigo-600 font-medium{{end}}">
Dashboard
</a>
<a href="/apps" class="text-gray-600 hover:text-gray-900 {{if eq .ActiveNav "apps"}}text-indigo-600 font-medium{{end}}">
Apps
</a>
<a href="/docs" class="text-gray-600 hover:text-gray-900 {{if eq .ActiveNav "docs"}}text-indigo-600 font-medium{{end}}">
Docs
</a>
<a href="/settings" class="text-gray-600 hover:text-gray-900 {{if eq .ActiveNav "settings"}}text-indigo-600 font-medium{{end}}">
Settings
</a>
</div>
<!-- User Menu -->
<div class="flex items-center space-x-4">
<div class="relative" x-data="{ open: false }">
<button class="flex items-center space-x-2 text-gray-600 hover:text-gray-900">
{{if .Developer.AvatarURL}}
<img src="{{.Developer.AvatarURL}}" alt="{{.Developer.Name}}" class="w-8 h-8 rounded-full">
{{else}}
<div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center">
<span class="text-indigo-600 font-medium text-sm">{{slice .Developer.Name 0 1}}</span>
</div>
{{end}}
<span class="hidden md:inline">{{.Developer.Name}}</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
</div>
<a href="/auth/logout" class="text-gray-500 hover:text-gray-700">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
</svg>
</a>
</div>
</div>
</div>
</nav>
{{end}}