Disable dates with no availability on booking page
- Fetch availability for all dates on page load - Track which dates have available slots in state - Disable date buttons that have no availability - Add visual styling for disabled dates (reduced opacity, not-allowed cursor) - Prevent clicking on dates with no availability - Improves UX by showing which dates are bookable at a glance
This commit is contained in:
parent
7926e3ae4c
commit
63f40433cc
1 changed files with 52 additions and 4 deletions
|
|
@ -92,6 +92,12 @@ const pageStyles: Record<string, React.CSSProperties> = {
|
|||
background: "rgba(167, 139, 250, 0.15)",
|
||||
border: "1px solid #a78bfa",
|
||||
},
|
||||
dateButtonDisabled: {
|
||||
opacity: 0.4,
|
||||
cursor: "not-allowed",
|
||||
background: "rgba(255, 255, 255, 0.01)",
|
||||
border: "1px solid rgba(255, 255, 255, 0.04)",
|
||||
},
|
||||
dateWeekday: {
|
||||
color: "#fff",
|
||||
fontWeight: 500,
|
||||
|
|
@ -224,6 +230,8 @@ export default function BookingPage() {
|
|||
const [isBooking, setIsBooking] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||
const [datesWithAvailability, setDatesWithAvailability] = useState<Set<string>>(new Set());
|
||||
const [isLoadingAvailability, setIsLoadingAvailability] = useState(true);
|
||||
|
||||
const dates = getDateRange(minAdvanceDays, maxAdvanceDays);
|
||||
|
||||
|
|
@ -245,6 +253,36 @@ export default function BookingPage() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
// Fetch availability for all dates on mount
|
||||
useEffect(() => {
|
||||
if (!user || !isAuthorized) return;
|
||||
|
||||
const fetchAllAvailability = async () => {
|
||||
setIsLoadingAvailability(true);
|
||||
const availabilitySet = new Set<string>();
|
||||
|
||||
// Fetch availability for all dates in parallel
|
||||
const promises = dates.map(async (date) => {
|
||||
try {
|
||||
const dateStr = formatDate(date);
|
||||
const data = await api.get<AvailableSlotsResponse>(`/api/booking/slots?date=${dateStr}`);
|
||||
if (data.slots.length > 0) {
|
||||
availabilitySet.add(dateStr);
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently fail for individual dates - they'll just be marked as unavailable
|
||||
console.error(`Failed to fetch availability for ${formatDate(date)}:`, err);
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
setDatesWithAvailability(availabilitySet);
|
||||
setIsLoadingAvailability(false);
|
||||
};
|
||||
|
||||
fetchAllAvailability();
|
||||
}, [user, isAuthorized, dates]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDate && user && isAuthorized) {
|
||||
fetchSlots(selectedDate);
|
||||
|
|
@ -252,8 +290,12 @@ export default function BookingPage() {
|
|||
}, [selectedDate, user, isAuthorized, fetchSlots]);
|
||||
|
||||
const handleDateSelect = (date: Date) => {
|
||||
setSelectedDate(date);
|
||||
setSuccessMessage(null);
|
||||
const dateStr = formatDate(date);
|
||||
// Only allow selection if date has availability
|
||||
if (datesWithAvailability.has(dateStr)) {
|
||||
setSelectedDate(date);
|
||||
setSuccessMessage(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSlotSelect = (slot: BookableSlot) => {
|
||||
|
|
@ -329,14 +371,20 @@ export default function BookingPage() {
|
|||
<h2 style={styles.sectionTitle}>Select a Date</h2>
|
||||
<div style={styles.dateGrid}>
|
||||
{dates.map((date) => {
|
||||
const isSelected = selectedDate && formatDate(selectedDate) === formatDate(date);
|
||||
const dateStr = formatDate(date);
|
||||
const isSelected = selectedDate && formatDate(selectedDate) === dateStr;
|
||||
const hasAvailability = datesWithAvailability.has(dateStr);
|
||||
const isDisabled = !hasAvailability || isLoadingAvailability;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={formatDate(date)}
|
||||
key={dateStr}
|
||||
onClick={() => handleDateSelect(date)}
|
||||
disabled={isDisabled}
|
||||
style={{
|
||||
...styles.dateButton,
|
||||
...(isSelected ? styles.dateButtonSelected : {}),
|
||||
...(isDisabled ? styles.dateButtonDisabled : {}),
|
||||
}}
|
||||
>
|
||||
<div style={styles.dateWeekday}>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue