aggiornato per uso di taiwind

This commit is contained in:
fabio
2026-02-23 13:46:44 +01:00
parent 275d3df3f1
commit 3fc01cc4f7
39 changed files with 5743 additions and 1381 deletions

View File

@@ -0,0 +1,32 @@
{{define "content"}}
<section class="space-y-6">
<h1 class="text-3xl font-bold text-gray-900">Audit Logs</h1>
<div class="mb-4 border-b border-gray-200">
<ul class="-mb-px flex flex-wrap text-center text-sm font-medium" id="audit-tab" data-tabs-toggle="#audit-tab-content" role="tablist">
<li class="me-2" role="presentation">
<button class="inline-block rounded-t-lg border-b-2 p-4" id="activity-tab" data-tabs-target="#activity" type="button" role="tab" aria-controls="activity" aria-selected="true">Activity</button>
</li>
<li class="me-2" role="presentation">
<button class="inline-block rounded-t-lg border-b-2 p-4" id="security-tab" data-tabs-target="#security" type="button" role="tab" aria-controls="security" aria-selected="false">Security</button>
</li>
</ul>
</div>
<div id="audit-tab-content">
<div class="hidden rounded-lg border border-gray-200 bg-white p-4 shadow-sm" id="activity" role="tabpanel" aria-labelledby="activity-tab">
<div class="relative overflow-x-auto">
<table class="w-full text-left text-sm text-gray-500">
<thead class="bg-gray-50 text-xs uppercase text-gray-700">
<tr><th class="px-6 py-3">Timestamp</th><th class="px-6 py-3">Actor</th><th class="px-6 py-3">Action</th></tr>
</thead>
<tbody><tr class="border-b bg-white"><td class="px-6 py-4">-</td><td class="px-6 py-4">-</td><td class="px-6 py-4">-</td></tr></tbody>
</table>
</div>
</div>
<div class="hidden rounded-lg border border-gray-200 bg-white p-4 shadow-sm" id="security" role="tabpanel" aria-labelledby="security-tab">
<p class="text-sm text-gray-600">Security logs placeholder.</p>
</div>
</div>
</section>
{{end}}

View File

@@ -1,9 +1,29 @@
{{define "content"}}
<div class="space-y-3">
<h1 class="text-2xl font-semibold">Admin Dashboard</h1>
<p class="muted">Area amministrazione.</p>
<div class="row">
<a href="/admin/users" class="rounded-lg border border-slate-300 px-4 py-2 hover:bg-slate-50">Gestione utenti</a>
<section class="space-y-6">
<div>
<h1 class="text-3xl font-bold text-gray-900">Admin Dashboard</h1>
<p class="text-gray-600">Area amministrazione.</p>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
<p class="text-sm font-medium text-gray-500">Utenti</p>
<p class="mt-2 text-3xl font-semibold text-gray-900">{{if .PageData}}{{.PageData.Total}}{{else}}-{{end}}</p>
</article>
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
<p class="text-sm font-medium text-gray-500">Ruolo corrente</p>
<p class="mt-2">
{{if and .CurrentUser (eq .CurrentUser.Role "admin")}}
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">admin</span>
{{else}}
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">user</span>
{{end}}
</p>
</article>
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
<p class="text-sm font-medium text-gray-500">Navigazione</p>
<a href="/admin/users" class="mt-2 inline-flex rounded-lg bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-800">Gestione utenti</a>
</article>
</div>
</section>
{{end}}

View File

@@ -0,0 +1,8 @@
{{define "content"}}
<section class="space-y-4">
<h1 class="text-3xl font-bold text-gray-900">Admin Users</h1>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm">
<p class="text-gray-600">Template pagina utenti admin in stile Flowbite.</p>
</div>
</section>
{{end}}

View File

@@ -1,13 +1,36 @@
{{define "users_modal"}}
<div style="padding:16px;">
<h3 style="margin-top:0;">Dettaglio utente #{{.User.ID}}</h3>
<p><strong>Name:</strong> {{if .User.Name}}{{.User.Name}}{{else}}-{{end}}</p>
<p><strong>Email:</strong> {{.User.Email}}</p>
<p><strong>Role:</strong> {{.User.Role}}</p>
<p><strong>Verified:</strong> {{if .User.EmailVerified}}yes{{else}}no{{end}}</p>
<p><strong>Created:</strong> {{.User.CreatedAt}}</p>
<div class="row">
<button type="button" onclick="document.getElementById('userModal').removeAttribute('open')">Chiudi</button>
<div class="grid gap-3 text-sm text-gray-700 sm:grid-cols-2">
<div>
<span class="font-semibold text-gray-900">ID:</span>
<span>{{.User.ID}}</span>
</div>
<div>
<span class="font-semibold text-gray-900">Role:</span>
{{if eq .User.Role "admin"}}
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">admin</span>
{{else}}
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">user</span>
{{end}}
</div>
<div class="sm:col-span-2">
<span class="font-semibold text-gray-900">Name:</span>
<span>{{if .User.Name}}{{.User.Name}}{{else}}-{{end}}</span>
</div>
<div class="sm:col-span-2">
<span class="font-semibold text-gray-900">Email:</span>
<span>{{.User.Email}}</span>
</div>
<div>
<span class="font-semibold text-gray-900">Verified:</span>
<span>{{if .User.EmailVerified}}yes{{else}}no{{end}}</span>
</div>
<div>
<span class="font-semibold text-gray-900">Created:</span>
<span>{{.User.CreatedAt}}</span>
</div>
</div>
<div class="mt-5">
<button type="button" class="rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800" data-modal-hide="userModal">Chiudi</button>
</div>
{{end}}

View File

@@ -1,47 +1,53 @@
{{define "users_table"}}
{{ $p := .PageData }}
<table style="width:100%;border-collapse:collapse;margin-top:16px;">
<thead>
<tr>
<th style="text-align:left;border-bottom:1px solid #e5e7eb;padding:8px;">
<a href="#" hx-get="/admin/users/table?q={{$p.Q}}&sort=id&dir={{if and (eq $p.Sort "id") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">ID</a>
</th>
<th style="text-align:left;border-bottom:1px solid #e5e7eb;padding:8px;">
<a href="#" hx-get="/admin/users/table?q={{$p.Q}}&sort=name&dir={{if and (eq $p.Sort "name") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Name</a>
</th>
<th style="text-align:left;border-bottom:1px solid #e5e7eb;padding:8px;">
<a href="#" hx-get="/admin/users/table?q={{$p.Q}}&sort=email&dir={{if and (eq $p.Sort "email") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Email</a>
</th>
<th style="text-align:left;border-bottom:1px solid #e5e7eb;padding:8px;">Role</th>
<th style="text-align:left;border-bottom:1px solid #e5e7eb;padding:8px;">Azioni</th>
</tr>
</thead>
<tbody>
{{range $u := $p.Users}}
<tr>
<td style="border-bottom:1px solid #f1f5f9;padding:8px;">{{$u.ID}}</td>
<td style="border-bottom:1px solid #f1f5f9;padding:8px;">{{if $u.Name}}{{$u.Name}}{{else}}-{{end}}</td>
<td style="border-bottom:1px solid #f1f5f9;padding:8px;">{{$u.Email}}</td>
<td style="border-bottom:1px solid #f1f5f9;padding:8px;">{{$u.Role}}</td>
<td style="border-bottom:1px solid #f1f5f9;padding:8px;">
<button
hx-get="/admin/users/{{$u.ID}}/modal"
hx-target="#userModalContent"
hx-swap="innerHTML"
>Apri</button>
</td>
</tr>
{{else}}
<tr><td colspan="5" style="padding:12px;">Nessun utente trovato.</td></tr>
{{end}}
</tbody>
</table>
<div class="relative overflow-x-auto">
<table class="w-full text-left text-sm text-gray-500 rtl:text-right">
<thead class="bg-gray-50 text-xs uppercase text-gray-700">
<tr>
<th scope="col" class="px-6 py-3">
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=id&dir={{if and (eq $p.Sort "id") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">ID</button>
</th>
<th scope="col" class="px-6 py-3">
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=name&dir={{if and (eq $p.Sort "name") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Name</button>
</th>
<th scope="col" class="px-6 py-3">
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=email&dir={{if and (eq $p.Sort "email") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Email</button>
</th>
<th scope="col" class="px-6 py-3">Role</th>
<th scope="col" class="px-6 py-3">Azioni</th>
</tr>
</thead>
<tbody>
{{range $u := $p.Users}}
<tr class="border-b bg-white hover:bg-gray-50">
<td class="px-6 py-4">{{$u.ID}}</td>
<td class="px-6 py-4 font-medium text-gray-900">{{if $u.Name}}{{$u.Name}}{{else}}-{{end}}</td>
<td class="px-6 py-4">{{$u.Email}}</td>
<td class="px-6 py-4">
{{if eq $u.Role "admin"}}
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">admin</span>
{{else}}
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">user</span>
{{end}}
</td>
<td class="px-6 py-4">
<button type="button" class="rounded-lg bg-blue-700 px-3 py-2 text-xs font-medium text-white hover:bg-blue-800" data-modal-target="userModal" data-modal-toggle="userModal" hx-get="/admin/users/{{$u.ID}}/modal" hx-target="#userModalContent" hx-swap="innerHTML">Apri</button>
</td>
</tr>
{{else}}
<tr class="bg-white">
<td colspan="5" class="px-6 py-4 text-center text-gray-500">Nessun utente trovato.</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="row" style="margin-top:12px;align-items:center;justify-content:space-between;">
<div class="muted">Totale: {{$p.Total}} utenti. Pagina {{$p.Page}}{{if gt $p.TotalPages 0}} / {{$p.TotalPages}}{{end}}</div>
<div class="row">
<button {{if not $p.HasPrev}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.PrevPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Prev</button>
<button {{if not $p.HasNext}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.NextPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Next</button>
<div class="mt-4 flex flex-wrap items-center justify-between gap-3">
<div class="text-sm text-gray-600">Totale: {{$p.Total}} utenti. Pagina {{$p.Page}}{{if gt $p.TotalPages 0}} / {{$p.TotalPages}}{{end}}</div>
<div class="inline-flex gap-2">
<button type="button" class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-900 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50" {{if not $p.HasPrev}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.PrevPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Prev</button>
<button type="button" class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-900 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50" {{if not $p.HasNext}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.NextPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML">Next</button>
</div>
</div>
{{end}}

View File

@@ -1,36 +1,74 @@
{{define "content"}}
<h1>Users</h1>
<p class="muted">Ricerca, ordinamento e paging server-side via HTMX.</p>
<section class="space-y-6">
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<h1 class="text-3xl font-bold text-gray-900">Users</h1>
<p class="text-gray-600">Ricerca, ordinamento e paging server-side via HTMX.</p>
</div>
<button type="button" data-modal-target="newUserModal" data-modal-toggle="newUserModal" class="inline-flex items-center rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">
Nuovo Utente
</button>
</div>
<form id="usersFilters" class="row" hx-get="/admin/users/table" hx-target="#usersTableContainer" hx-swap="innerHTML">
<input type="text" name="q" placeholder="Cerca nome o email" value="{{.PageData.Q}}">
<input type="number" name="pageSize" min="1" max="100" value="{{.PageData.PageSize}}" style="max-width:120px;">
<input type="hidden" name="sort" value="{{.PageData.Sort}}">
<input type="hidden" name="dir" value="{{.PageData.Dir}}">
<input type="hidden" name="page" value="1">
<button type="submit">Cerca</button>
</form>
<form id="usersFilters" class="grid gap-3 rounded-lg border border-gray-200 bg-white p-4 shadow-sm md:grid-cols-4" hx-get="/admin/users/table" hx-target="#usersTableContainer" hx-swap="innerHTML">
<div class="md:col-span-2">
<label for="users-q" class="mb-2 block text-sm font-medium text-gray-900">Search</label>
<input id="users-q" type="text" name="q" placeholder="Cerca nome o email" value="{{.PageData.Q}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500">
</div>
<div>
<label for="users-size" class="mb-2 block text-sm font-medium text-gray-900">Page size</label>
<input id="users-size" type="number" name="pageSize" min="1" max="100" value="{{.PageData.PageSize}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500">
</div>
<div class="flex items-end">
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">Cerca</button>
</div>
<input type="hidden" name="sort" value="{{.PageData.Sort}}">
<input type="hidden" name="dir" value="{{.PageData.Dir}}">
<input type="hidden" name="page" value="1">
</form>
<div id="usersTableContainer" hx-get="/admin/users/table?q={{.PageData.Q}}&sort={{.PageData.Sort}}&dir={{.PageData.Dir}}&page={{.PageData.Page}}&pageSize={{.PageData.PageSize}}" hx-trigger="load" hx-swap="innerHTML">
{{template "users_table" .}}
<div id="usersTableContainer" class="rounded-lg border border-gray-200 bg-white p-2 shadow-sm md:p-4" hx-get="/admin/users/table?q={{.PageData.Q}}&sort={{.PageData.Sort}}&dir={{.PageData.Dir}}&page={{.PageData.Page}}&pageSize={{.PageData.PageSize}}" hx-trigger="load" hx-swap="innerHTML">
{{template "users_table" .}}
</div>
</section>
<div id="userModal" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
<div class="relative max-h-full w-full max-w-2xl">
<div class="relative rounded-lg bg-white shadow-sm">
<div class="flex items-start justify-between rounded-t border-b p-4 md:p-5">
<h3 class="text-xl font-semibold text-gray-900">Dettaglio utente</h3>
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900" data-modal-hide="userModal" aria-label="Close modal">
<span class="sr-only">Close modal</span>
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
</button>
</div>
<div id="userModalContent" class="space-y-4 p-4 md:p-5"></div>
</div>
</div>
</div>
<ui-modal id="userModal" title="Dettaglio utente">
<div
id="userModalContent"
hx-on:htmx:after-swap="document.getElementById('userModal').setAttribute('open','')"
></div>
</ui-modal>
<script>
(function () {
var modal = document.getElementById('userModal');
var content = document.getElementById('userModalContent');
if (!modal || !content || modal.dataset.closeBound === '1') return;
modal.dataset.closeBound = '1';
modal.addEventListener('ui:close', function () {
content.innerHTML = '';
});
})();
</script>
<div id="newUserModal" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
<div class="relative max-h-full w-full max-w-xl">
<div class="relative rounded-lg bg-white shadow-sm">
<div class="flex items-start justify-between rounded-t border-b p-4 md:p-5">
<h3 class="text-xl font-semibold text-gray-900">Nuovo utente</h3>
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900" data-modal-hide="newUserModal" aria-label="Close modal">
<span class="sr-only">Close modal</span>
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
</button>
</div>
<div class="space-y-4 p-4 md:p-5">
<p class="text-sm text-gray-600">Placeholder UI Flowbite. La creazione utente può essere collegata a una route backend quando disponibile.</p>
<div>
<label for="new-user-email" class="mb-2 block text-sm font-medium text-gray-900">Email</label>
<input id="new-user-email" type="email" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900" placeholder="name@company.com" disabled>
</div>
</div>
</div>
</div>
</div>
{{end}}

View File

@@ -0,0 +1,13 @@
{{define "flowbite_collapse"}}
<button data-collapse-toggle="collapseExample" type="button" class="flex w-full items-center justify-between rounded-lg bg-gray-100 px-5 py-2.5 text-left text-sm font-medium text-gray-500 hover:bg-gray-200" aria-expanded="false" aria-controls="collapseExample">
<span>Toggle collapse</span>
<svg data-accordion-icon class="h-3 w-3 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5 5 1 1 5"/>
</svg>
</button>
<div id="collapseExample" class="hidden">
<div class="rounded-b-lg border border-gray-200 p-5">
<p class="text-sm text-gray-500">Collapsed content.</p>
</div>
</div>
{{end}}

View File

@@ -0,0 +1,16 @@
{{define "flowbite_dropdown"}}
<button id="dropdownDefaultButton" data-dropdown-toggle="dropdown" class="inline-flex items-center rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800" type="button">
Dropdown
<svg class="ms-3 h-2.5 w-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</button>
<div id="dropdown" class="z-10 hidden w-44 divide-y divide-gray-100 rounded-lg bg-white shadow-sm">
<ul class="py-2 text-sm text-gray-700" aria-labelledby="dropdownDefaultButton">
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Dashboard</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Settings</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Sign out</a></li>
</ul>
</div>
{{end}}

View File

@@ -0,0 +1,17 @@
{{define "flowbite_flash"}}
{{if .FlashSuccess}}
<div class="mb-4 flex items-center rounded-lg border border-green-200 bg-green-50 p-4 text-green-800" role="alert">
<span class="text-sm font-medium">{{.FlashSuccess}}</span>
</div>
{{end}}
{{if .FlashError}}
<div class="mb-4 flex items-center rounded-lg border border-red-200 bg-red-50 p-4 text-red-800" role="alert">
<span class="text-sm font-medium">{{.FlashError}}</span>
</div>
{{end}}
{{if .FlashWarning}}
<div class="mb-4 flex items-center rounded-lg border border-yellow-200 bg-yellow-50 p-4 text-yellow-800" role="alert">
<span class="text-sm font-medium">{{.FlashWarning}}</span>
</div>
{{end}}
{{end}}

View File

@@ -0,0 +1,25 @@
{{define "flowbite_modal"}}
<div id="{{.ModalID}}" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
<div class="relative max-h-full w-full max-w-2xl">
<div class="relative rounded-lg bg-white shadow-sm">
<div class="flex items-start justify-between rounded-t border-b p-4 md:p-5">
<h3 class="text-xl font-semibold text-gray-900">{{.ModalTitle}}</h3>
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900" data-modal-hide="{{.ModalID}}" aria-label="Close modal">
<span class="sr-only">Close modal</span>
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
</button>
</div>
<div class="space-y-4 p-4 md:p-5">
{{template .ModalBodyTemplate .}}
</div>
{{if .ModalFooterTemplate}}
<div class="flex items-center rounded-b border-t border-gray-200 p-4 md:p-5">
{{template .ModalFooterTemplate .}}
</div>
{{end}}
</div>
</div>
</div>
{{end}}

View File

@@ -0,0 +1,21 @@
{{define "flowbite_navbar"}}
<nav class="border-gray-200 bg-white">
<div class="mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4">
<a href="#" class="flex items-center space-x-3 rtl:space-x-reverse">
<span class="self-center whitespace-nowrap text-2xl font-semibold">Trustcontact</span>
</a>
<button data-collapse-toggle="navbar-default" type="button" class="inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 md:hidden" aria-controls="navbar-default" aria-expanded="false">
<span class="sr-only">Open main menu</span>
<svg class="h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
</svg>
</button>
<div class="hidden w-full md:block md:w-auto" id="navbar-default">
<ul class="mt-4 flex flex-col rounded-lg border border-gray-100 bg-gray-50 p-4 font-medium md:mt-0 md:flex-row md:space-x-8 md:border-0 md:bg-white md:p-0 rtl:space-x-reverse">
<li><a href="#" class="block rounded-sm bg-blue-700 px-3 py-2 text-white md:bg-transparent md:p-0 md:text-blue-700" aria-current="page">Home</a></li>
<li><a href="#" class="block rounded-sm px-3 py-2 text-gray-900 hover:bg-gray-100 md:p-0 md:hover:bg-transparent md:hover:text-blue-700">About</a></li>
</ul>
</div>
</div>
</nav>
{{end}}

View File

@@ -0,0 +1,20 @@
{{define "flowbite_tabs"}}
<div class="mb-4 border-b border-gray-200">
<ul class="-mb-px flex flex-wrap text-center text-sm font-medium" id="default-tab" data-tabs-toggle="#default-tab-content" role="tablist">
<li class="me-2" role="presentation">
<button class="inline-block rounded-t-lg border-b-2 p-4" id="profile-tab" data-tabs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="me-2" role="presentation">
<button class="inline-block rounded-t-lg border-b-2 p-4" id="dashboard-tab" data-tabs-target="#dashboard" type="button" role="tab" aria-controls="dashboard" aria-selected="false">Dashboard</button>
</li>
</ul>
</div>
<div id="default-tab-content">
<div class="hidden rounded-lg bg-gray-50 p-4" id="profile" role="tabpanel" aria-labelledby="profile-tab">
<p class="text-sm text-gray-500">Profile tab content.</p>
</div>
<div class="hidden rounded-lg bg-gray-50 p-4" id="dashboard" role="tabpanel" aria-labelledby="dashboard-tab">
<p class="text-sm text-gray-500">Dashboard tab content.</p>
</div>
</div>
{{end}}

View File

@@ -5,38 +5,85 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{.Title}}</title>
<link rel="stylesheet" href="/static/css/app.css?v={{.BuildHash}}">
<link rel="stylesheet" href="/static/ui/ui.css?v={{.BuildHash}}">
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<script type="module" src="/static/ui/ui.esm.js?v={{.BuildHash}}"></script>
<script src="/static/vendor/htmx.min.js"></script>
<script src="/static/vendor/flowbite.js"></script>
</head>
<body>
<nav class="relative flex items-center justify-between border-b border-gray-300 bg-white px-6 py-4 transition-all md:px-16 lg:px-24 xl:px-32">
<a href="/" class="text-lg font-semibold text-slate-800">Trustcontact</a>
<div class="hidden items-center gap-8 sm:flex">
{{if and .CurrentUser (eq .CurrentUser.Role "admin")}}
<a href="/admin" class="text-slate-700 hover:text-slate-900 {{if eq .NavSection "admin"}}font-semibold{{end}}">Admin</a>
{{end}}
{{if .CurrentUser}}
<form action="/logout" method="post">
<button type="submit" class="cursor-pointer rounded-full bg-indigo-500 px-8 py-2 text-white transition hover:bg-indigo-600">
Logout
</button>
</form>
{{else}}
<a href="/login" class="cursor-pointer rounded-full bg-indigo-500 px-8 py-2 text-white transition hover:bg-indigo-600">
Login
<body class="bg-gray-50 text-gray-900 antialiased">
<nav class="border-b border-gray-200 bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between p-4">
<a href="/" class="flex items-center space-x-3 rtl:space-x-reverse">
<span class="self-center whitespace-nowrap text-xl font-semibold">Trustcontact</span>
</a>
{{end}}
<button data-collapse-toggle="navbar-main" type="button" class="inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 md:hidden" aria-controls="navbar-main" aria-expanded="false">
<span class="sr-only">Apri menu principale</span>
<svg class="h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
</svg>
</button>
<div class="hidden w-full items-center justify-between md:order-1 md:flex md:w-auto" id="navbar-main">
<ul class="mt-4 flex flex-col gap-2 rounded-lg border border-gray-100 bg-gray-50 p-4 text-sm font-medium md:mt-0 md:flex-row md:items-center md:gap-1 md:border-0 md:bg-transparent md:p-0">
{{if .CurrentUser}}
<li>
<a href="/welcome" class="block rounded-lg px-3 py-2 {{if eq .NavSection "private"}}bg-blue-100 text-blue-700{{else}}text-gray-700 hover:bg-gray-100{{end}}">Dashboard</a>
</li>
<li>
<a href="/admin/users" class="block rounded-lg px-3 py-2 {{if eq .NavSection "users"}}bg-blue-100 text-blue-700{{else}}text-gray-700 hover:bg-gray-100{{end}}">Users</a>
</li>
{{if eq .CurrentUser.Role "admin"}}
<li>
<a href="/admin" class="block rounded-lg px-3 py-2 {{if eq .NavSection "admin"}}bg-blue-100 text-blue-700{{else}}text-gray-700 hover:bg-gray-100{{end}}">Admin</a>
</li>
{{end}}
{{else}}
<li>
<a href="/login" class="block rounded-lg px-3 py-2 {{if eq .NavSection "login"}}bg-blue-100 text-blue-700{{else}}text-gray-700 hover:bg-gray-100{{end}}">Login</a>
</li>
<li>
<a href="/signup" class="block rounded-lg px-3 py-2 {{if eq .NavSection "signup"}}bg-blue-100 text-blue-700{{else}}text-gray-700 hover:bg-gray-100{{end}}">Signup</a>
</li>
{{end}}
</ul>
{{if .CurrentUser}}
<div class="relative mt-4 md:mt-0 md:ms-4">
<button type="button" class="flex items-center rounded-full bg-gray-800 text-sm focus:ring-4 focus:ring-gray-300 md:me-0" id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown" data-dropdown-placement="bottom">
<span class="sr-only">Apri menu utente</span>
<span class="inline-flex h-9 w-9 items-center justify-center rounded-full bg-blue-600 font-semibold text-white">
{{if .CurrentUser.Name}}{{printf "%.1s" .CurrentUser.Name}}{{else}}{{printf "%.1s" .CurrentUser.Email}}{{end}}
</span>
</button>
<div class="z-50 my-4 hidden w-56 list-none divide-y divide-gray-100 rounded-lg bg-white text-base shadow-sm" id="user-dropdown">
<div class="px-4 py-3">
<span class="block truncate text-sm text-gray-900">{{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}Utente{{end}}</span>
<span class="block truncate text-sm text-gray-500">{{.CurrentUser.Email}}</span>
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
<li><a href="/welcome" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a></li>
<li><a href="/admin/users" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Users</a></li>
</ul>
<div class="py-2">
<form action="/logout" method="post" class="px-2">
<button type="submit" class="block w-full rounded-lg px-2 py-2 text-left text-sm text-red-700 hover:bg-red-50">Logout</button>
</form>
</div>
</div>
</div>
{{end}}
</div>
</div>
</nav>
<div class="mx-auto my-5 max-w-5xl px-4">
<main class="mx-auto max-w-7xl p-6">
{{template "_flash.html" .}}
<div class="rounded-xl bg-white p-5 shadow-sm">
{{template "content" .}}
{{template "content" .}}
</main>
<footer class="border-t border-gray-200 bg-white">
<div class="mx-auto max-w-7xl px-6 py-4 text-sm text-gray-500">
Trustcontact
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,49 @@
{{define "content"}}
<section class="space-y-6">
<div class="flex items-center justify-between">
<h1 class="text-3xl font-bold text-gray-900">Users</h1>
<button type="button" class="rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800" data-modal-target="privateUserModal" data-modal-toggle="privateUserModal">Nuovo Utente</button>
</div>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm">
<label for="private-users-search" class="mb-2 block text-sm font-medium text-gray-900">Search</label>
<input id="private-users-search" type="text" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900" placeholder="Cerca utenti">
</div>
<div class="relative overflow-x-auto rounded-lg border border-gray-200 bg-white shadow-sm">
<table class="w-full text-left text-sm text-gray-500">
<thead class="bg-gray-50 text-xs uppercase text-gray-700">
<tr>
<th class="px-6 py-3">Name</th>
<th class="px-6 py-3">Email</th>
<th class="px-6 py-3">Role</th>
</tr>
</thead>
<tbody>
<tr class="border-b bg-white hover:bg-gray-50">
<td class="px-6 py-4">-</td>
<td class="px-6 py-4">-</td>
<td class="px-6 py-4"><span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">user</span></td>
</tr>
</tbody>
</table>
</div>
</section>
<div id="privateUserModal" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
<div class="relative max-h-full w-full max-w-xl">
<div class="relative rounded-lg bg-white shadow-sm">
<div class="flex items-start justify-between rounded-t border-b p-4 md:p-5">
<h3 class="text-xl font-semibold text-gray-900">Nuovo utente</h3>
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900" data-modal-hide="privateUserModal" aria-label="Close modal">
<span class="sr-only">Close modal</span>
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" /></svg>
</button>
</div>
<div class="p-4 md:p-5">
<p class="text-sm text-gray-600">Template Flowbite pronto per integrazione backend.</p>
</div>
</div>
</div>
</div>
{{end}}

View File

@@ -1,16 +1,20 @@
{{define "content"}}
<div class="space-y-5">
<div>
<h1 class="text-2xl font-semibold">Welcome</h1>
<section class="grid gap-6 md:grid-cols-3">
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm md:col-span-2">
<h1 class="mb-2 text-2xl font-bold text-gray-900">Dashboard</h1>
{{if .CurrentUser}}
<p class="muted">Bentornato {{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}{{.CurrentUser.Email}}{{end}}.</p>
<p class="text-gray-600">Bentornato {{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}{{.CurrentUser.Email}}{{end}}.</p>
{{else}}
<p class="muted">Benvenuto.</p>
<p class="text-gray-600">Benvenuto.</p>
{{end}}
</div>
</article>
{{if and .CurrentUser (ne .CurrentUser.Role "admin")}}
<p class="muted">Non hai privilegi admin.</p>
{{end}}
</div>
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
<h2 class="mb-3 text-lg font-semibold text-gray-900">Quick Links</h2>
<div class="space-y-2">
<a href="/welcome" class="block rounded-lg px-3 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a>
<a href="/admin/users" class="block rounded-lg px-3 py-2 text-sm text-gray-700 hover:bg-gray-100">Users</a>
</div>
</article>
</section>
{{end}}

View File

@@ -1,6 +1,26 @@
{{define "_flash.html"}}
{{if .FlashSuccess}}
<div style="background:#dcfce7;color:#166534;padding:12px;border-radius:8px;margin:0 0 12px;">{{.FlashSuccess}}</div>
<div class="mb-4 flex items-center rounded-lg border border-green-200 bg-green-50 p-4 text-green-800" role="alert">
<svg class="me-3 inline h-4 w-4 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 0a10 10 0 1 0 10 10A10 10 0 0 0 10 0Zm3.707 8.707-4 4a1 1 0 0 1-1.414 0l-2-2 1.414-1.414L9 10.586l3.293-3.293Z"/>
</svg>
<span class="text-sm font-medium">{{.FlashSuccess}}</span>
</div>
{{end}}
{{if .FlashError}}
<div style="background:#fee2e2;color:#991b1b;padding:12px;border-radius:8px;margin:0 0 12px;">{{.FlashError}}</div>
<div class="mb-4 flex items-center rounded-lg border border-red-200 bg-red-50 p-4 text-red-800" role="alert">
<svg class="me-3 inline h-4 w-4 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 0a10 10 0 1 0 10 10A10 10 0 0 0 10 0Zm1 14H9v-2h2Zm0-4H9V5h2Z"/>
</svg>
<span class="text-sm font-medium">{{.FlashError}}</span>
</div>
{{end}}
{{if .FlashWarning}}
<div class="mb-4 flex items-center rounded-lg border border-yellow-200 bg-yellow-50 p-4 text-yellow-800" role="alert">
<svg class="me-3 inline h-4 w-4 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l6.518 11.596c.75 1.334-.213 2.99-1.742 2.99H3.48c-1.53 0-2.492-1.656-1.743-2.99L8.257 3.1ZM11 13H9v2h2v-2Zm0-6H9v5h2V7Z"/>
</svg>
<span class="text-sm font-medium">{{.FlashWarning}}</span>
</div>
{{end}}
{{end}}

View File

@@ -1,25 +1,19 @@
{{define "content"}}
<div class="mx-auto w-full max-w-96 rounded-xl border border-gray-200 px-6 py-8">
<div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-amber-100">
<svg class="h-8 w-8 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c0 1.657-1.343 3-3 3S6 12.657 6 11s1.343-3 3-3 3 1.343 3 3zm0 0V9a4 4 0 118 0v2m-8 0h8m-8 0H4m16 0v8a2 2 0 01-2 2H6a2 2 0 01-2-2v-8"></path>
</svg>
<div class="flex min-h-screen items-center justify-center">
<div class="w-full max-w-md rounded-lg border border-gray-200 bg-white p-6 shadow-sm md:p-8">
<h1 class="mb-1 text-2xl font-bold text-gray-900">Forgot Password</h1>
<p class="mb-6 text-sm text-gray-500">Inserisci la tua email per ricevere il link di reset.</p>
<form action="/forgot-password" method="post" class="space-y-5">
<div>
<label for="forgot-email" class="mb-2 block text-sm font-medium text-gray-900">Email</label>
<input id="forgot-email" type="email" name="email" value="{{.Email}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">Invia link reset</button>
<p class="text-center text-sm text-gray-600"><a href="/login" class="text-blue-700 hover:underline">Torna al login</a></p>
</form>
</div>
<h3 class="mb-3 text-center text-xl font-bold text-gray-800">Forgot Password</h3>
<p class="mb-6 text-center text-sm text-gray-500">Inserisci la tua email. Se l'account esiste e risulta verificato, invieremo un link di reset.</p>
<form action="/forgot-password" method="post">
<div class="mb-6">
<label class="mb-1 block text-sm font-medium text-gray-700">Email</label>
<input type="email" name="email" value="{{.Email}}" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-amber-500 focus:ring-2 focus:ring-amber-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-amber-500 px-4 py-2 font-medium text-white transition duration-300 hover:bg-amber-600">Invia link reset</button>
<div class="mt-4 text-center">
<a href="/login" class="text-sm text-slate-600 hover:text-slate-800">Torna al login</a>
</div>
</form>
</div>
{{end}}

View File

@@ -1,10 +1,10 @@
{{define "content"}}
<div class="space-y-3">
<h1 class="text-2xl font-semibold">Trustcontact</h1>
<p class="muted">Accedi o registrati per continuare.</p>
<div class="row">
<a class="rounded-lg border border-slate-300 px-4 py-2 hover:bg-slate-50" href="/login">Accedi</a>
<a class="rounded-lg border border-slate-300 px-4 py-2 hover:bg-slate-50" href="/signup">Registrati</a>
<section class="rounded-lg border border-gray-200 bg-white p-8 shadow-sm">
<h1 class="mb-2 text-3xl font-bold text-gray-900">Trustcontact</h1>
<p class="mb-6 text-gray-600">Accedi o registrati per continuare.</p>
<div class="flex flex-wrap gap-3">
<a class="rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800" href="/login">Accedi</a>
<a class="rounded-lg border border-gray-300 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100" href="/signup">Registrati</a>
</div>
</div>
</section>
{{end}}

View File

@@ -1,32 +1,27 @@
{{define "content"}}
<div class="mx-auto w-full max-w-96 rounded-xl border border-gray-200 px-6 py-8">
<div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-blue-100">
<svg class="h-8 w-8 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
</svg>
<div class="flex min-h-screen items-center justify-center">
<div class="w-full max-w-md rounded-lg border border-gray-200 bg-white p-6 shadow-sm md:p-8">
<h1 class="mb-1 text-2xl font-bold text-gray-900">Login</h1>
<p class="mb-6 text-sm text-gray-500">Accedi al tuo account.</p>
<form action="/login" method="post" class="space-y-5">
<div>
<label for="email" class="mb-2 block text-sm font-medium text-gray-900">Email</label>
<input id="email" type="text" name="email" value="{{.Email}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<div>
<label for="password" class="mb-2 block text-sm font-medium text-gray-900">Password</label>
<input id="password" type="password" name="password" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">Sign in</button>
<div class="flex items-center justify-between text-sm">
<a href="/forgot-password" class="text-blue-700 hover:underline">Forgot password?</a>
<a href="/signup" class="text-gray-600 hover:underline">Create account</a>
</div>
</form>
</div>
<h3 class="mb-6 text-center text-xl font-bold text-gray-800">Quick Login</h3>
<form action="/login" method="post">
<div class="mb-4">
<label class="mb-1 block text-sm font-medium text-gray-700">Email or Patient ID</label>
<input type="text" name="email" value="{{.Email}}" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500" required />
</div>
<div class="mb-6">
<label class="mb-1 block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="password" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-blue-500 px-4 py-2 font-medium text-white transition duration-300 hover:bg-blue-600">Sign In</button>
<div class="mt-4 text-center">
<a href="/forgot-password" class="text-sm text-blue-500 hover:text-blue-600">Forgot Password?</a>
</div>
<div class="mt-3 text-center">
<a href="/signup" class="text-sm text-slate-600 hover:text-slate-800">Non hai un account? Registrati</a>
</div>
</form>
</div>
{{end}}

View File

@@ -1,24 +1,21 @@
{{define "content"}}
<div class="mx-auto w-full max-w-96 rounded-xl border border-gray-200 px-6 py-8">
<div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-violet-100">
<svg class="h-8 w-8 text-violet-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 11V7a4 4 0 118 0v4m-8 0h8m-8 0H5m14 0v8a2 2 0 01-2 2H7a2 2 0 01-2-2v-8"></path>
</svg>
<div class="flex min-h-screen items-center justify-center">
<div class="w-full max-w-md rounded-lg border border-gray-200 bg-white p-6 shadow-sm md:p-8">
<h1 class="mb-1 text-2xl font-bold text-gray-900">Reset Password</h1>
<p class="mb-6 text-sm text-gray-500">Imposta una nuova password.</p>
{{if .Token}}
<form action="/reset-password?token={{.Token}}" method="post" class="space-y-5">
<div>
<label for="reset-password" class="mb-2 block text-sm font-medium text-gray-900">Nuova password</label>
<input id="reset-password" type="password" name="password" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">Aggiorna password</button>
</form>
{{else}}
<div class="rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-800" role="alert">Token mancante o non valido.</div>
{{end}}
</div>
<h3 class="mb-6 text-center text-xl font-bold text-gray-800">Reset Password</h3>
{{if .Token}}
<form action="/reset-password?token={{.Token}}" method="post">
<div class="mb-6">
<label class="mb-1 block text-sm font-medium text-gray-700">Nuova password</label>
<input type="password" name="password" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-violet-500 focus:ring-2 focus:ring-violet-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-violet-500 px-4 py-2 font-medium text-white transition duration-300 hover:bg-violet-600">Aggiorna password</button>
</form>
{{else}}
<p class="text-center text-sm text-gray-500">Token mancante o non valido.</p>
{{end}}
</div>
{{end}}

View File

@@ -1,29 +1,24 @@
{{define "content"}}
<div class="mx-auto w-full max-w-96 rounded-xl border border-gray-200 px-6 py-8">
<div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-emerald-100">
<svg class="h-8 w-8 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3M5 7h8M5 11h4m1 10h8a2 2 0 002-2V5a2 2 0 00-2-2H6a2 2 0 00-2 2v14a2 2 0 002 2h4z"></path>
</svg>
<div class="flex min-h-screen items-center justify-center">
<div class="w-full max-w-md rounded-lg border border-gray-200 bg-white p-6 shadow-sm md:p-8">
<h1 class="mb-1 text-2xl font-bold text-gray-900">Signup</h1>
<p class="mb-6 text-sm text-gray-500">Crea il tuo account.</p>
<form action="/signup" method="post" class="space-y-5">
<div>
<label for="signup-email" class="mb-2 block text-sm font-medium text-gray-900">Email</label>
<input id="signup-email" type="email" name="email" value="{{.Email}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<div>
<label for="signup-password" class="mb-2 block text-sm font-medium text-gray-900">Password</label>
<input id="signup-password" type="password" name="password" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300">Sign up</button>
<p class="text-center text-sm text-gray-600">Hai già un account? <a href="/login" class="text-blue-700 hover:underline">Accedi</a></p>
</form>
</div>
<h3 class="mb-6 text-center text-xl font-bold text-gray-800">Create Account</h3>
<form action="/signup" method="post">
<div class="mb-4">
<label class="mb-1 block text-sm font-medium text-gray-700">Email</label>
<input type="email" name="email" value="{{.Email}}" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500" required />
</div>
<div class="mb-6">
<label class="mb-1 block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="password" class="w-full rounded-lg border border-gray-300 px-3 py-2 transition outline-none focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500" required />
</div>
<button type="submit" class="w-full rounded-lg bg-emerald-500 px-4 py-2 font-medium text-white transition duration-300 hover:bg-emerald-600">Sign Up</button>
<div class="mt-4 text-center">
<a href="/login" class="text-sm text-slate-600 hover:text-slate-800">Hai già un account? Accedi</a>
</div>
</form>
</div>
{{end}}

View File

@@ -1,6 +1,8 @@
{{define "content"}}
<h1>Verifica email</h1>
<p class="muted">Controlla la casella di posta e apri il link di verifica ricevuto.</p>
<p class="muted">Se il link è scaduto, ripeti la registrazione o contatta supporto.</p>
<p><a href="/login">Vai al login</a></p>
<section class="rounded-lg border border-blue-200 bg-blue-50 p-8 shadow-sm" role="status" aria-live="polite">
<h1 class="mb-2 text-2xl font-bold text-blue-900">Verifica email</h1>
<p class="mb-2 text-blue-800">Controlla la casella di posta e apri il link di verifica ricevuto.</p>
<p class="mb-4 text-blue-800">Se il link è scaduto, ripeti la registrazione o contatta supporto.</p>
<a href="/login" class="inline-flex rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800">Vai al login</a>
</section>
{{end}}