this push will conclude the majority of pulls. this repos will now, not be actively be managed or any further code pushes will not be frequent.
186 lines
7.6 KiB
HTML
186 lines
7.6 KiB
HTML
{{ define "content" }}
|
|
<div class="flex-1 flex flex-col overflow-hidden">
|
|
<!-- Toolbar -->
|
|
<div class="bg-white border-b border-gray-200 px-4 md:px-6 py-4">
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
|
<!-- Search -->
|
|
<div class="relative w-full sm:w-auto">
|
|
<i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 text-sm"></i>
|
|
<input
|
|
type="text"
|
|
placeholder="Search appointments..."
|
|
x-model="search"
|
|
class="w-full sm:w-80 pl-10 pr-4 py-2 text-sm border border-gray-200 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{{ if .Pagination }}
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-center gap-4 w-full sm:w-auto">
|
|
<div class="flex items-center gap-2">
|
|
<label for="pageSize" class="text-sm text-gray-600 whitespace-nowrap">Per page:</label>
|
|
<select
|
|
id="pageSize"
|
|
onchange="changePageSize(this.value)"
|
|
class="px-3 py-2 text-sm border border-gray-200 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
>
|
|
<option value="20" {{if eq .Pagination.PageSize 20}}selected{{end}}>20</option>
|
|
<option value="50" {{if eq .Pagination.PageSize 50}}selected{{end}}>50</option>
|
|
<option value="100" {{if eq .Pagination.PageSize 100}}selected{{end}}>100</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2">
|
|
<button
|
|
onclick="goToPage({{.Pagination.PreviousPage}})"
|
|
{{if not .Pagination.HasPrevious}}disabled{{end}}
|
|
class="px-3 py-2 text-sm border border-gray-200 rounded-lg {{if .Pagination.HasPrevious}}hover:bg-gray-50 text-gray-700{{else}}text-gray-400 cursor-not-allowed{{end}} transition-colors"
|
|
>
|
|
<i class="fas fa-chevron-left"></i>
|
|
</button>
|
|
<span class="px-3 py-2 text-sm text-gray-600 whitespace-nowrap">
|
|
{{.Pagination.CurrentPage}} / {{.Pagination.TotalPages}}
|
|
</span>
|
|
<button
|
|
onclick="goToPage({{.Pagination.NextPage}})"
|
|
{{if not .Pagination.HasNext}}disabled{{end}}
|
|
class="px-3 py-2 text-sm border border-gray-200 rounded-lg {{if .Pagination.HasNext}}hover:bg-gray-50 text-gray-700{{else}}text-gray-400 cursor-not-allowed{{end}} transition-colors"
|
|
>
|
|
<i class="fas fa-chevron-right"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table Container -->
|
|
<div class="flex-1 p-4 md:p-6 overflow-auto" x-data="{ search: '' }">
|
|
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
|
|
|
<!-- Desktop Table -->
|
|
<div class="hidden lg:block overflow-x-auto">
|
|
<table class="w-full min-w-full">
|
|
<thead class="bg-gray-50 border-b border-gray-200">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Poll</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Address</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Appointment</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-100">
|
|
{{ range .Appointments }}
|
|
<tr
|
|
class="hover:bg-gray-50"
|
|
x-show="
|
|
'{{ .Address }} {{ .PollButtonText }} {{ .AppointmentDate.Format "2006-01-02" }}'
|
|
.toLowerCase()
|
|
.includes(search.toLowerCase())
|
|
"
|
|
>
|
|
<!-- Poll -->
|
|
<td class="px-6 py-4">
|
|
{{ if .HasPollResponse }}
|
|
<span class="{{ .PollButtonClass }}">{{ .PollButtonText }}</span>
|
|
{{ else }}
|
|
<a href="/poll?address_id={{ .AddressID }}" class="{{ .PollButtonClass }}">
|
|
{{ .PollButtonText }}
|
|
</a>
|
|
{{ end }}
|
|
</td>
|
|
|
|
<!-- Address -->
|
|
<td class="px-6 py-4">
|
|
<a
|
|
href="https://www.google.com/maps/search/?api=1&query={{ .Latitude }},{{ .Longitude }}"
|
|
target="_blank"
|
|
class="text-blue-600 hover:text-blue-800 text-sm hover:underline"
|
|
>
|
|
{{ .Address }}
|
|
</a>
|
|
</td>
|
|
|
|
<!-- Appointment -->
|
|
<td class="px-6 py-4 text-sm text-gray-700">
|
|
({{ .AppointmentDate.Format "2006-01-02" }} @ {{ .AppointmentTime.Format "15:04" }})
|
|
</td>
|
|
</tr>
|
|
{{ else }}
|
|
<tr>
|
|
<td colspan="3" class="px-6 py-8 text-center text-gray-500">No appointments found</td>
|
|
</tr>
|
|
{{ end }}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Mobile Cards -->
|
|
<div class="lg:hidden">
|
|
<div class="space-y-4 p-4">
|
|
{{ range .Appointments }}
|
|
<div class="bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden">
|
|
<!-- Card Header -->
|
|
<div class="bg-gray-50 px-4 py-3 border-b border-gray-200 flex items-center justify-between">
|
|
<span class="text-sm font-semibold text-gray-900">Appointment</span>
|
|
{{ if .HasPollResponse }}
|
|
<span class="inline-flex items-center px-2 py-1 text-xs font-medium bg-green-100 text-green-700 rounded-full">
|
|
{{ .PollButtonText }}
|
|
</span>
|
|
{{ else }}
|
|
<a
|
|
href="/poll?address_id={{ .AddressID }}"
|
|
class="inline-flex items-center px-2 py-1 text-xs font-medium bg-blue-100 text-blue-700 rounded-full"
|
|
>
|
|
{{ .PollButtonText }}
|
|
</a>
|
|
{{ end }}
|
|
</div>
|
|
|
|
<!-- Card Content -->
|
|
<div class="p-4 space-y-3">
|
|
<div class="flex flex-col">
|
|
<span class="text-sm font-medium text-gray-900">{{ .Address }}</span>
|
|
</div>
|
|
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-sm text-gray-500">Date</span>
|
|
<span class="text-sm text-gray-900">{{ .AppointmentDate.Format "2006-01-02" }}</span>
|
|
</div>
|
|
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-sm text-gray-500">Time</span>
|
|
<span class="text-sm text-gray-900">{{ .AppointmentTime.Format "15:04" }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{ else }}
|
|
<div class="text-center py-12">
|
|
<div class="text-gray-400 mb-4">
|
|
<i class="fas fa-calendar-times text-4xl"></i>
|
|
</div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">No appointments found</h3>
|
|
<p class="text-gray-500">Try adjusting your search criteria.</p>
|
|
</div>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function goToPage(page) {
|
|
var urlParams = new URLSearchParams(window.location.search);
|
|
urlParams.set("page", page);
|
|
window.location.search = urlParams.toString();
|
|
}
|
|
|
|
function changePageSize(pageSize) {
|
|
var urlParams = new URLSearchParams(window.location.search);
|
|
urlParams.set("pageSize", pageSize);
|
|
urlParams.set("page", 1);
|
|
window.location.search = urlParams.toString();
|
|
}
|
|
</script>
|
|
{{ end }}
|