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.
682 lines
28 KiB
HTML
682 lines
28 KiB
HTML
{{ define "content" }}
|
|
<div class="flex-1 flex flex-col overflow-hidden" x-data="volunteerTable()">
|
|
<!-- 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 & Filters -->
|
|
<div
|
|
class="flex flex-col sm:flex-row items-start sm:items-center gap-4 w-full sm:w-auto"
|
|
>
|
|
<!-- 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"
|
|
x-model="searchTerm"
|
|
placeholder="Search volunteers..."
|
|
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>
|
|
|
|
<!-- Role Filter -->
|
|
<div class="flex items-center gap-2">
|
|
<label
|
|
for="roleFilter"
|
|
class="text-sm text-gray-600 whitespace-nowrap"
|
|
>Role:</label
|
|
>
|
|
<select
|
|
x-model="roleFilter"
|
|
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="">All Roles</option>
|
|
<option value="1">Admin</option>
|
|
<option value="2">Team Leader</option>
|
|
<option value="3">Volunteer</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Clear Filters -->
|
|
<button
|
|
@click="clearFilters()"
|
|
class="px-3 py-2 text-sm text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded-lg transition-colors"
|
|
>
|
|
<i class="fas fa-times mr-1"></i>Clear
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Actions & Results -->
|
|
<div
|
|
class="flex flex-col sm:flex-row items-start sm:items-center gap-4 w-full sm:w-auto"
|
|
>
|
|
<button
|
|
class="px-6 py-2.5 bg-green-600 text-white text-sm font-medium hover:bg-green-700 transition-colors rounded-lg"
|
|
onclick="openAddVolunteerPanel()"
|
|
>
|
|
<i class="fas fa-user-plus mr-2"></i>Add Volunteer
|
|
</button>
|
|
|
|
<!-- Results Count -->
|
|
<div class="text-sm text-gray-600 whitespace-nowrap">
|
|
Showing <span x-text="filteredVolunteers.length"></span> of
|
|
<span x-text="volunteers.length"></span> volunteers
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table Container -->
|
|
<div class="flex-1 p-4 md:p-6 overflow-auto">
|
|
<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 whitespace-nowrap"
|
|
>
|
|
<div
|
|
class="flex items-center gap-2 cursor-pointer"
|
|
@click="sortBy('UserID')"
|
|
>
|
|
ID
|
|
<i
|
|
class="fas"
|
|
:class="getSortIcon('UserID')"
|
|
></i>
|
|
</div>
|
|
</th>
|
|
<th
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
<div
|
|
class="flex items-center gap-2 cursor-pointer"
|
|
@click="sortBy('FirstName')"
|
|
>
|
|
Name
|
|
<i
|
|
class="fas"
|
|
:class="getSortIcon('FirstName')"
|
|
></i>
|
|
</div>
|
|
</th>
|
|
<th
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
<div
|
|
class="flex items-center gap-2 cursor-pointer"
|
|
@click="sortBy('Email')"
|
|
>
|
|
Contact
|
|
<i
|
|
class="fas"
|
|
:class="getSortIcon('Email')"
|
|
></i>
|
|
</div>
|
|
</th>
|
|
<th
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap"
|
|
>
|
|
<div
|
|
class="flex items-center gap-2 cursor-pointer"
|
|
@click="sortBy('RoleID')"
|
|
>
|
|
Role
|
|
<i
|
|
class="fas"
|
|
:class="getSortIcon('RoleID')"
|
|
></i>
|
|
</div>
|
|
</th>
|
|
<th
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
Actions
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-100">
|
|
<template
|
|
x-for="volunteer in filteredVolunteers"
|
|
:key="volunteer.UserID"
|
|
>
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-6 py-4">
|
|
<div
|
|
class="text-sm font-medium text-gray-900"
|
|
x-text="volunteer.UserID"
|
|
></div>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<div
|
|
class="text-sm font-medium text-gray-900"
|
|
x-text="volunteer.FirstName + ' ' + volunteer.LastName"
|
|
></div>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<div
|
|
class="text-sm text-gray-900"
|
|
x-text="volunteer.Email"
|
|
></div>
|
|
<div
|
|
class="text-sm text-gray-500"
|
|
x-text="volunteer.Phone"
|
|
></div>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span
|
|
class="inline-flex items-center px-2 py-1 text-xs font-medium rounded-full"
|
|
:class="getRoleBadgeClass(volunteer.RoleID)"
|
|
x-text="getRoleName(volunteer.RoleID)"
|
|
></span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<div class="flex items-center space-x-2">
|
|
<button
|
|
class="text-blue-600 hover:text-blue-800 p-1"
|
|
@click="editVolunteer(volunteer)"
|
|
title="Edit volunteer"
|
|
>
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button
|
|
class="text-red-600 hover:text-red-800 p-1"
|
|
@click="deleteVolunteer(volunteer.UserID)"
|
|
title="Delete volunteer"
|
|
>
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- No Results - Desktop -->
|
|
<div
|
|
x-show="filteredVolunteers.length === 0"
|
|
class="px-6 py-8 text-center text-gray-500"
|
|
>
|
|
No volunteers found
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Cards -->
|
|
<div class="lg:hidden">
|
|
<div class="space-y-4 p-4">
|
|
<template
|
|
x-for="volunteer in filteredVolunteers"
|
|
:key="volunteer.UserID"
|
|
>
|
|
<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"
|
|
>
|
|
<div class="flex items-center space-x-2">
|
|
<i class="fas fa-user text-gray-400"></i>
|
|
<span
|
|
class="text-sm font-semibold text-gray-900"
|
|
>Volunteer #<span
|
|
x-text="volunteer.UserID"
|
|
></span
|
|
></span>
|
|
</div>
|
|
<span
|
|
class="inline-flex items-center px-2 py-1 text-xs font-medium rounded-full"
|
|
:class="getRoleBadgeClass(volunteer.RoleID)"
|
|
x-text="getRoleName(volunteer.RoleID)"
|
|
></span>
|
|
</div>
|
|
|
|
<!-- Card Content -->
|
|
<div class="p-4 space-y-3">
|
|
<!-- Name -->
|
|
<div class="flex flex-col">
|
|
<span
|
|
class="text-sm font-medium text-gray-900"
|
|
x-text="volunteer.FirstName + ' ' + volunteer.LastName"
|
|
></span>
|
|
</div>
|
|
|
|
<!-- Email -->
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-sm text-gray-500"
|
|
>Email</span
|
|
>
|
|
<span
|
|
class="text-sm text-gray-900"
|
|
x-text="volunteer.Email"
|
|
></span>
|
|
</div>
|
|
|
|
<!-- Phone -->
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-sm text-gray-500"
|
|
>Phone</span
|
|
>
|
|
<span
|
|
class="text-sm text-gray-900"
|
|
x-text="volunteer.Phone"
|
|
></span>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div
|
|
class="flex justify-center space-x-4 pt-3 border-t border-gray-100"
|
|
>
|
|
<button
|
|
class="flex-1 px-4 py-2 bg-blue-500 text-white text-sm rounded-md hover:bg-blue-600 transition-colors font-medium"
|
|
@click="editVolunteer(volunteer)"
|
|
>
|
|
<i class="fas fa-edit mr-1"></i> Edit
|
|
</button>
|
|
<button
|
|
class="px-4 py-2 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-md transition-colors text-sm font-medium"
|
|
@click="deleteVolunteer(volunteer.UserID)"
|
|
>
|
|
<i class="fas fa-trash mr-1"></i> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- No Results - Mobile -->
|
|
<div
|
|
x-show="filteredVolunteers.length === 0"
|
|
class="text-center py-12"
|
|
>
|
|
<div class="text-gray-400 mb-4">
|
|
<i class="fas fa-users text-4xl"></i>
|
|
</div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">
|
|
No volunteers found
|
|
</h3>
|
|
<p class="text-gray-500">
|
|
Try adjusting your search or filter criteria.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Panel Overlay -->
|
|
<div
|
|
id="volunteerPanelOverlay"
|
|
class="fixed inset-0 bg-black bg-opacity-50 hidden z-40"
|
|
></div>
|
|
|
|
<!-- Add/Edit Volunteer Panel -->
|
|
<div
|
|
id="volunteerPanel"
|
|
class="fixed top-0 right-0 h-full w-full max-w-md bg-white shadow-xl transform translate-x-full transition-transform duration-300 ease-in-out z-50 flex flex-col"
|
|
>
|
|
<!-- Panel Header -->
|
|
<div
|
|
class="flex justify-between items-center px-6 py-4 border-b border-gray-200 bg-gray-50"
|
|
>
|
|
<div class="flex items-center space-x-2">
|
|
<i class="fas fa-user-plus text-blue-500" id="panelIcon"></i>
|
|
<h2 class="text-lg font-semibold text-gray-900" id="panelTitle">
|
|
Add Volunteer
|
|
</h2>
|
|
</div>
|
|
<button
|
|
onclick="closeVolunteerPanel()"
|
|
class="text-gray-400 hover:text-gray-600 focus:outline-none p-1"
|
|
>
|
|
<i class="fas fa-times text-xl"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Panel Body -->
|
|
<form
|
|
id="volunteerForm"
|
|
method="POST"
|
|
action="/volunteer/add"
|
|
class="flex-1 overflow-y-auto p-6 space-y-6"
|
|
>
|
|
<input type="hidden" name="id" id="volunteerId" />
|
|
|
|
<!-- First Name -->
|
|
<div>
|
|
<label
|
|
for="firstName"
|
|
class="block text-sm font-medium text-gray-700 mb-2"
|
|
>
|
|
<i class="fas fa-user mr-2 text-gray-400"></i>First Name
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="firstName"
|
|
name="first_name"
|
|
required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Last Name -->
|
|
<div>
|
|
<label
|
|
for="lastName"
|
|
class="block text-sm font-medium text-gray-700 mb-2"
|
|
>
|
|
<i class="fas fa-user mr-2 text-gray-400"></i>Last Name
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="lastName"
|
|
name="last_name"
|
|
required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Email -->
|
|
<div>
|
|
<label
|
|
for="email"
|
|
class="block text-sm font-medium text-gray-700 mb-2"
|
|
>
|
|
<i class="fas fa-envelope mr-2 text-gray-400"></i>Email
|
|
</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Phone -->
|
|
<div>
|
|
<label
|
|
for="phone"
|
|
class="block text-sm font-medium text-gray-700 mb-2"
|
|
>
|
|
<i class="fas fa-phone mr-2 text-gray-400"></i>Phone
|
|
</label>
|
|
<input
|
|
type="tel"
|
|
id="phone"
|
|
name="phone"
|
|
required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Role Selection -->
|
|
<div>
|
|
<label
|
|
for="role"
|
|
class="block text-sm font-medium text-gray-700 mb-2"
|
|
>
|
|
<i class="fas fa-user-tag mr-2 text-gray-400"></i>Role
|
|
</label>
|
|
<select
|
|
name="role_id"
|
|
id="role"
|
|
required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
<option value="">-- Select Role --</option>
|
|
<option value="1">Admin</option>
|
|
<option value="2">Team Leader</option>
|
|
<option value="3">Volunteer</option>
|
|
</select>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Panel Footer -->
|
|
<div
|
|
class="flex justify-end gap-3 px-6 py-4 border-t border-gray-200 bg-gray-50"
|
|
>
|
|
<button
|
|
type="button"
|
|
onclick="closeVolunteerPanel()"
|
|
class="px-6 py-2 border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded-lg font-medium transition-colors"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
form="volunteerForm"
|
|
id="submitBtn"
|
|
class="px-6 py-2 bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded-lg font-medium transition-colors"
|
|
>
|
|
<i class="fas fa-check mr-2"></i>
|
|
<span id="submitText">Add Volunteer</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script
|
|
src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"
|
|
defer
|
|
></script>
|
|
<script>
|
|
function volunteerTable() {
|
|
return {
|
|
searchTerm: '',
|
|
roleFilter: '',
|
|
sortColumn: '',
|
|
sortDirection: 'asc',
|
|
volunteers: [
|
|
{{ range .Users }}
|
|
{
|
|
UserID: {{ .UserID }},
|
|
FirstName: "{{ .FirstName }}",
|
|
LastName: "{{ .LastName }}",
|
|
Email: "{{ .Email }}",
|
|
Phone: "{{ .Phone }}",
|
|
RoleID: {{ .RoleID }}
|
|
},
|
|
{{ end }}
|
|
],
|
|
|
|
get filteredVolunteers() {
|
|
let filtered = this.volunteers.filter(volunteer => {
|
|
// Search filter
|
|
const searchMatch = !this.searchTerm ||
|
|
volunteer.FirstName.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
volunteer.LastName.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
volunteer.Email.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
volunteer.Phone.includes(this.searchTerm);
|
|
|
|
// Role filter
|
|
const roleMatch = !this.roleFilter || volunteer.RoleID.toString() === this.roleFilter;
|
|
|
|
return searchMatch && roleMatch;
|
|
});
|
|
|
|
// Sort filtered results
|
|
if (this.sortColumn) {
|
|
filtered.sort((a, b) => {
|
|
let aValue = a[this.sortColumn];
|
|
let bValue = b[this.sortColumn];
|
|
|
|
// Handle string comparison
|
|
if (typeof aValue === 'string') {
|
|
aValue = aValue.toLowerCase();
|
|
bValue = bValue.toLowerCase();
|
|
}
|
|
|
|
let comparison = 0;
|
|
if (aValue > bValue) comparison = 1;
|
|
if (aValue < bValue) comparison = -1;
|
|
|
|
return this.sortDirection === 'asc' ? comparison : -comparison;
|
|
});
|
|
}
|
|
|
|
return filtered;
|
|
},
|
|
|
|
sortBy(column) {
|
|
if (this.sortColumn === column) {
|
|
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
|
|
} else {
|
|
this.sortColumn = column;
|
|
this.sortDirection = 'asc';
|
|
}
|
|
},
|
|
|
|
getSortIcon(column) {
|
|
if (this.sortColumn !== column) {
|
|
return 'fa-sort text-gray-400';
|
|
}
|
|
return this.sortDirection === 'asc' ? 'fa-sort-up text-blue-600' : 'fa-sort-down text-blue-600';
|
|
},
|
|
|
|
getRoleName(roleId) {
|
|
switch (roleId) {
|
|
case 1: return 'Admin';
|
|
case 2: return 'Team Leader';
|
|
case 3: return 'Volunteer';
|
|
default: return 'Unknown';
|
|
}
|
|
},
|
|
|
|
getRoleBadgeClass(roleId) {
|
|
switch (roleId) {
|
|
case 1: return 'bg-red-100 text-red-700'; // Admin - Red
|
|
case 2: return 'bg-blue-100 text-blue-700'; // Team Leader - Blue
|
|
case 3: return 'bg-green-100 text-green-700'; // Volunteer - Green
|
|
default: return 'bg-gray-100 text-gray-700';
|
|
}
|
|
},
|
|
|
|
clearFilters() {
|
|
this.searchTerm = '';
|
|
this.roleFilter = '';
|
|
this.sortColumn = '';
|
|
this.sortDirection = 'asc';
|
|
},
|
|
|
|
editVolunteer(volunteer) {
|
|
openEditVolunteerPanel(volunteer);
|
|
},
|
|
|
|
deleteVolunteer(volunteerId) {
|
|
if (confirm('Are you sure you want to delete this volunteer?')) {
|
|
// Create and submit form for deletion
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = '/volunteer/delete';
|
|
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'id';
|
|
input.value = volunteerId;
|
|
|
|
form.appendChild(input);
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Panel functions
|
|
function openAddVolunteerPanel() {
|
|
document.getElementById('panelTitle').textContent = 'Add Volunteer';
|
|
document.getElementById('panelIcon').className = 'fas fa-user-plus text-blue-500';
|
|
document.getElementById('submitText').textContent = 'Add Volunteer';
|
|
document.getElementById('volunteerForm').action = '/volunteer/add';
|
|
document.getElementById('volunteerForm').reset();
|
|
document.getElementById('volunteerId').value = '';
|
|
|
|
showPanel();
|
|
}
|
|
|
|
function openEditVolunteerPanel(volunteer) {
|
|
document.getElementById('panelTitle').textContent = 'Edit Volunteer';
|
|
document.getElementById('panelIcon').className = 'fas fa-user-edit text-blue-500';
|
|
document.getElementById('submitText').textContent = 'Update Volunteer';
|
|
document.getElementById('volunteerForm').action = '/volunteer/edit';
|
|
|
|
// Populate form
|
|
document.getElementById('volunteerId').value = volunteer.UserID;
|
|
document.getElementById('firstName').value = volunteer.FirstName;
|
|
document.getElementById('lastName').value = volunteer.LastName;
|
|
document.getElementById('email').value = volunteer.Email;
|
|
document.getElementById('phone').value = volunteer.Phone;
|
|
document.getElementById('role').value = volunteer.RoleID;
|
|
|
|
showPanel();
|
|
}
|
|
|
|
function showPanel() {
|
|
document.getElementById('volunteerPanelOverlay').classList.remove('hidden');
|
|
document.getElementById('volunteerPanel').classList.remove('translate-x-full');
|
|
|
|
setTimeout(() => {
|
|
document.getElementById('firstName').focus();
|
|
}, 100);
|
|
}
|
|
|
|
function closeVolunteerPanel() {
|
|
document.getElementById('volunteerPanel').classList.add('translate-x-full');
|
|
document.getElementById('volunteerPanelOverlay').classList.add('hidden');
|
|
|
|
setTimeout(() => {
|
|
document.getElementById('volunteerForm').reset();
|
|
}, 300);
|
|
}
|
|
|
|
// Event listeners
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Close panel when clicking overlay
|
|
document.getElementById('volunteerPanelOverlay').addEventListener('click', closeVolunteerPanel);
|
|
|
|
// Close panel on Escape key
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') {
|
|
const overlay = document.getElementById('volunteerPanelOverlay');
|
|
if (!overlay.classList.contains('hidden')) {
|
|
closeVolunteerPanel();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
/* Consistent styling */
|
|
input,
|
|
select,
|
|
button {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
button {
|
|
font-weight: 500;
|
|
letter-spacing: 0.025em;
|
|
}
|
|
|
|
/* Mobile responsive adjustments */
|
|
@media (max-width: 640px) {
|
|
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
|
--tw-space-x-reverse: 0;
|
|
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
|
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
|
}
|
|
}
|
|
</style>
|
|
|
|
{{ end }}
|