Fix time slot picker bugs for past dates
Fixed issues: - Added isAvailable parameter to handleSlotClick to prevent clicks on unavailable slots - Added validation to prevent selecting past dates in date picker - Added validation in handlePreviousDay to block navigating to past dates - Added warning message when trying to view past dates - Prevents the "slot is not defined" error when clicking disabled slots Now the modal properly: - Blocks selecting dates before today - Shows clear error messages for past dates - Prevents clicks on unavailable time slots - Handles edge cases like passed sessions being rescheduled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,10 @@ export function TimeSlotPickerModal({
|
|||||||
// Date navigation handlers
|
// Date navigation handlers
|
||||||
const handlePreviousDay = () => {
|
const handlePreviousDay = () => {
|
||||||
const newDate = addDays(currentDate, -1);
|
const newDate = addDays(currentDate, -1);
|
||||||
|
// Prevent going to past dates
|
||||||
|
if (isPast(newDate) && !isToday(newDate)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setCurrentDate(newDate);
|
setCurrentDate(newDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -131,6 +135,10 @@ export function TimeSlotPickerModal({
|
|||||||
const handleDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const newDate = parse(e.target.value, 'yyyy-MM-dd', new Date());
|
const newDate = parse(e.target.value, 'yyyy-MM-dd', new Date());
|
||||||
if (!isNaN(newDate.getTime())) {
|
if (!isNaN(newDate.getTime())) {
|
||||||
|
// Prevent selecting past dates
|
||||||
|
if (isPast(newDate) && !isToday(newDate)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setCurrentDate(newDate);
|
setCurrentDate(newDate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -208,8 +216,9 @@ export function TimeSlotPickerModal({
|
|||||||
const totalBlocks = getSlotsInRange().length;
|
const totalBlocks = getSlotsInRange().length;
|
||||||
const totalDuration = totalBlocks * (settings?.consulting_block_duration_minutes || 30);
|
const totalDuration = totalBlocks * (settings?.consulting_block_duration_minutes || 30);
|
||||||
|
|
||||||
const handleSlotClick = (slotStart: string) => {
|
const handleSlotClick = (slotStart: string, isAvailable: boolean) => {
|
||||||
if (!slot.available) return;
|
// Prevent clicking on unavailable slots
|
||||||
|
if (!isAvailable) return;
|
||||||
|
|
||||||
// No selection yet → Set as pending
|
// No selection yet → Set as pending
|
||||||
if (!selectedRange.start) {
|
if (!selectedRange.start) {
|
||||||
@@ -327,7 +336,13 @@ export function TimeSlotPickerModal({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info */}
|
{/* Info */}
|
||||||
{isToday(currentDate) && timeSlots.length === 0 ? (
|
{isPast(currentDate) && !isToday(currentDate) ? (
|
||||||
|
<div className="bg-destructive/10 border-2 border-destructive/20 p-4 rounded-lg text-center">
|
||||||
|
<p className="text-sm text-destructive font-medium">
|
||||||
|
Tidak dapat memilih tanggal yang sudah lewat. Silakan pilih tanggal hari ini atau tanggal yang akan datang.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : isToday(currentDate) && timeSlots.length === 0 ? (
|
||||||
<div className="bg-amber-50 dark:bg-amber-950 border-2 border-amber-200 dark:border-amber-800 p-4 rounded-lg text-center">
|
<div className="bg-amber-50 dark:bg-amber-950 border-2 border-amber-200 dark:border-amber-800 p-4 rounded-lg text-center">
|
||||||
<p className="text-sm text-amber-900 dark:text-amber-100">
|
<p className="text-sm text-amber-900 dark:text-amber-100">
|
||||||
Tidak ada slot tersedia untuk sisa hari ini. Silakan pilih tanggal lain.
|
Tidak ada slot tersedia untuk sisa hari ini. Silakan pilih tanggal lain.
|
||||||
@@ -367,7 +382,7 @@ export function TimeSlotPickerModal({
|
|||||||
!slot.available ? 'opacity-30 cursor-not-allowed' : ''
|
!slot.available ? 'opacity-30 cursor-not-allowed' : ''
|
||||||
}`}
|
}`}
|
||||||
disabled={!slot.available}
|
disabled={!slot.available}
|
||||||
onClick={() => handleSlotClick(slot.start)}
|
onClick={() => handleSlotClick(slot.start, slot.available)}
|
||||||
>
|
>
|
||||||
{slot.start}
|
{slot.start}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user