Fix booking search, shrink time picker
This commit is contained in:
@@ -453,7 +453,7 @@ func GetAllAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add ordering and pagination (NO GROUP BY needed here)
|
// Add ordering and pagination (NO GROUP BY needed here)
|
||||||
baseQuery += " ORDER BY b.start_time ASC"
|
baseQuery += " ORDER BY b.start_time DESC"
|
||||||
if req.PerPage > 0 {
|
if req.PerPage > 0 {
|
||||||
baseQuery += fmt.Sprintf(" LIMIT $%d OFFSET $%d", paramCount, paramCount+1)
|
baseQuery += fmt.Sprintf(" LIMIT $%d OFFSET $%d", paramCount, paramCount+1)
|
||||||
args = append(args, req.PerPage, (req.Page-1)*req.PerPage)
|
args = append(args, req.PerPage, (req.Page-1)*req.PerPage)
|
||||||
@@ -954,7 +954,7 @@ func SearchAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
JOIN services s ON bs.service_id = s.id
|
JOIN services s ON bs.service_id = s.id
|
||||||
WHERE bs.booking_id = b.id AND s.name ILIKE $1 ESCAPE '\'
|
WHERE bs.booking_id = b.id AND s.name ILIKE $1 ESCAPE '\'
|
||||||
)
|
)
|
||||||
ORDER BY b.start_time ASC
|
ORDER BY b.start_time DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@@ -136,43 +136,40 @@
|
|||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/admin/bookings/search?q=${encodeURIComponent(bookingQuery)}`,
|
`/api/admin/bookings/search?q=${encodeURIComponent(bookingQuery)}`,
|
||||||
{
|
{
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${authStore.currentToken}`
|
Authorization: `Bearer ${authStore.currentToken}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
bookings = data.bookings.map((b: any) => ({
|
// HTTP error (400 / 401 / 500 etc)
|
||||||
id: b.id,
|
if (!response.ok) {
|
||||||
start_time: b.start_time,
|
const message = await response.text();
|
||||||
status: b.status,
|
throw new Error(message || `Request failed (${response.status})`);
|
||||||
notes: b.notes,
|
|
||||||
created_at: b.created_at,
|
|
||||||
updated_at: b.updated_at,
|
|
||||||
created_by: b.created_by,
|
|
||||||
user: b.user
|
|
||||||
? {
|
|
||||||
id: b.user.id,
|
|
||||||
full_name: b.user.full_name
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
services: b.services || [],
|
|
||||||
total_amount: b.total_amount || 0,
|
|
||||||
amount_paid: b.amount_paid || 0,
|
|
||||||
amount_due: b.amount_due || 0,
|
|
||||||
duration_minutes: b.duration_minutes || 0
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
const text = await response.text();
|
|
||||||
toast.error('Failed to search bookings: ' + text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
const bookingsData = Array.isArray(data.bookings) ? data.bookings : [];
|
||||||
|
|
||||||
|
bookings = bookingsData.map((b: any) => ({
|
||||||
|
id: b.id,
|
||||||
|
start_time: b.start_time,
|
||||||
|
status: b.status,
|
||||||
|
notes: b.notes,
|
||||||
|
created_at: b.created_at,
|
||||||
|
updated_at: b.updated_at,
|
||||||
|
created_by: b.created_by,
|
||||||
|
user: b.user ? { id: b.user.id, full_name: b.user.full_name } : undefined,
|
||||||
|
services: b.services || [],
|
||||||
|
total_amount: b.total_amount || 0,
|
||||||
|
amount_paid: b.amount_paid || 0,
|
||||||
|
amount_due: b.amount_due || 0,
|
||||||
|
duration_minutes: b.duration_minutes || 0
|
||||||
|
}));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error searching bookings:', err);
|
console.error('Search bookings failed:', err);
|
||||||
toast.error('Network error searching bookings');
|
|
||||||
|
toast.error(err instanceof Error ? err.message : 'Unexpected error searching bookings');
|
||||||
} finally {
|
} finally {
|
||||||
loadingSearch = false;
|
loadingSearch = false;
|
||||||
}
|
}
|
||||||
@@ -297,9 +294,6 @@
|
|||||||
</Card.Title>
|
</Card.Title>
|
||||||
<Card.Description>Search and manage booking history.</Card.Description>
|
<Card.Description>Search and manage booking history.</Card.Description>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium">
|
|
||||||
<span class="text-xs font-semibold">{bookings.length}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="space-y-4">
|
<Card.Content class="space-y-4">
|
||||||
|
|||||||
@@ -783,7 +783,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="no-scrollbar inset-y-0 right-0 flex max-h-48 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t p-6 md:absolute md:max-h-none md:w-56 md:border-t-0 md:border-l"
|
class="no-scrollbar inset-y-0 right-0 flex max-h-40 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t p-6 md:absolute md:max-h-none md:w-56 md:border-t-0 md:border-l"
|
||||||
>
|
>
|
||||||
{#if (loadingWorkingHours || loadingAvailableHours) && selectedDate}
|
{#if (loadingWorkingHours || loadingAvailableHours) && selectedDate}
|
||||||
<div class="text-center text-sm text-gray-500">Loading available times...</div>
|
<div class="text-center text-sm text-gray-500">Loading available times...</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user