Auto-cancel expired consulting orders and prefill re-booking
**Features Implemented:**
1. **Auto-Cancel Expired Consulting Orders:**
- New edge function: cancel-expired-consulting-orders
- Changes order status from 'pending' → 'cancelled'
- Cancels all associated consulting_sessions
- Deletes calendar events via delete-calendar-event
- Releases consulting_time_slots (deletes booked slots)
- Properly cleans up all resources
2. **Smart Re-Booking with Pre-filled Data:**
- OrderDetail.tsx stores expired order data in sessionStorage:
- fromExpiredOrder flag
- Original orderId
- topicCategory
- notes
- ConsultingBooking.tsx retrieves and pre-fills form on mount
- Auto-clears sessionStorage after use
3. **Improved UX for Expired Orders:**
- Clear message: "Order ini telah dibatalkan secara otomatis"
- Helpful hint: "Kategori dan catatan akan terisi otomatis"
- One-click re-booking with pre-filled data
- Member only needs to select new time slot
**How It Works:**
Flow:
1. QRIS expires → Order shows expired message
2. Member clicks "Buat Booking Baru"
3. Data stored in sessionStorage (category, notes)
4. Navigates to /consulting
5. Form auto-fills with previous data
6. Member selects new time → Books new session
**Edge Function Details:**
- Finds orders where: payment_status='pending' AND qr_expires_at < NOW()
- Cancels order status
- Cancels consulting_sessions
- Deletes consulting_time_slots
- Invokes delete-calendar-event for each session
- Returns count of processed orders
**To Deploy:**
1. Deploy cancel-expired-consulting-orders edge function
2. Set up cron job to run every 5-15 minutes:
`curl -X POST https://your-domain/functions/v1/cancel-expired-consulting-orders`
**Benefits:**
✅ Orders properly cancelled when QR expires
✅ Time slots released for other users
✅ Calendar events cleaned up
✅ Easy re-booking without re-typing data
✅ Better UX for expired payment situations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,31 @@ export default function ConsultingBooking() {
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
|
||||
// Check for pre-filled data from expired order
|
||||
const expiredOrderData = sessionStorage.getItem('expiredConsultingOrder');
|
||||
if (expiredOrderData) {
|
||||
try {
|
||||
const data = JSON.parse(expiredOrderData);
|
||||
if (data.fromExpiredOrder) {
|
||||
// Prefill form with expired order data
|
||||
if (data.topicCategory) setSelectedCategory(data.topicCategory);
|
||||
if (data.notes) setNotes(data.notes);
|
||||
|
||||
// Show notification to user
|
||||
setTimeout(() => {
|
||||
// You could add a toast notification here if you have toast set up
|
||||
console.log('Pre-filled data from expired order:', data);
|
||||
}, 100);
|
||||
|
||||
// Clear the stored data after using it
|
||||
sessionStorage.removeItem('expiredConsultingOrder');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error parsing expired order data:', err);
|
||||
sessionStorage.removeItem('expiredConsultingOrder');
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -449,15 +449,32 @@ export default function OrderDetail() {
|
||||
</Alert>
|
||||
|
||||
{isConsultingOrder ? (
|
||||
// Consulting order - show booking button
|
||||
// Consulting order - show booking button with pre-filled data
|
||||
<div className="text-center space-y-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Order ini telah dibatalkan secara otomatis karena waktu pembayaran habis.
|
||||
</p>
|
||||
<Button onClick={() => navigate("/consulting")} className="shadow-sm">
|
||||
<Button
|
||||
onClick={() => {
|
||||
// Pass expired order data to prefill the booking form
|
||||
const expiredData = {
|
||||
fromExpiredOrder: true,
|
||||
orderId: order.id,
|
||||
topicCategory: consultingSlots[0]?.topic_category || '',
|
||||
notes: consultingSlots[0]?.notes || ''
|
||||
};
|
||||
// Store in sessionStorage for the booking page to retrieve
|
||||
sessionStorage.setItem('expiredConsultingOrder', JSON.stringify(expiredData));
|
||||
navigate("/consulting");
|
||||
}}
|
||||
className="shadow-sm"
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-2" />
|
||||
Buat Booking Baru
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kategori dan catatan akan terisi otomatis dari order sebelumnya
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
// Product order - show regenerate button
|
||||
|
||||
Reference in New Issue
Block a user