Add calendar event lifecycle management and "Add to Calendar" feature

- Migrate consulting_slots to consulting_sessions structure
- Add calendar_event_id to track Google Calendar events
- Create delete-calendar-event edge function for auto-cleanup
- Add "Tambah ke Kalender" button for members (OrderDetail, ConsultingHistory)
- Update create-google-meet-event to store calendar event ID
- Update handle-order-paid to use consulting_sessions table
- Remove deprecated create-meet-link function
- Add comprehensive documentation (CALENDAR_INTEGRATION.md, MIGRATION_GUIDE.md)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2025-12-28 13:54:16 +07:00
parent 952bb209cf
commit 5ab4e6b974
11 changed files with 1303 additions and 554 deletions

View File

@@ -311,27 +311,15 @@ serve(async (req: Request): Promise<Response> => {
if (meetLink) {
log(`Meet link found: ${meetLink}`);
// If this is part of a multi-slot order, update all slots with the same order_id
// First, check if this slot has an order_id
const { data: slotData } = await supabase
.from("consulting_slots")
.select("order_id")
.eq("id", body.slot_id)
.single();
if (slotData?.order_id) {
log(`Updating all slots in order ${slotData.order_id} with meet_link`);
await supabase
.from("consulting_slots")
.update({ meet_link: meetLink })
.eq("order_id", slotData.order_id);
} else {
log(`No order_id found, updating only slot ${body.slot_id}`);
await supabase
.from("consulting_slots")
.update({ meet_link: meetLink })
.eq("id", body.slot_id);
}
// Update consulting_sessions with meet_link and event_id
log(`Updating session ${body.slot_id} with meet_link and calendar_event_id`);
await supabase
.from("consulting_sessions")
.update({
meet_link: meetLink,
calendar_event_id: eventDataResult.id
})
.eq("id", body.slot_id);
log("Successfully completed");
return new Response(
@@ -351,26 +339,15 @@ serve(async (req: Request): Promise<Response> => {
if (eventDataResult.hangoutLink) {
log(`Using hangoutLink: ${eventDataResult.hangoutLink}`);
// If this is part of a multi-slot order, update all slots with the same order_id
const { data: slotData } = await supabase
.from("consulting_slots")
.select("order_id")
.eq("id", body.slot_id)
.single();
if (slotData?.order_id) {
log(`Updating all slots in order ${slotData.order_id} with meet_link`);
await supabase
.from("consulting_slots")
.update({ meet_link: eventDataResult.hangoutLink })
.eq("order_id", slotData.order_id);
} else {
log(`No order_id found, updating only slot ${body.slot_id}`);
await supabase
.from("consulting_slots")
.update({ meet_link: eventDataResult.hangoutLink })
.eq("id", body.slot_id);
}
// Update consulting_sessions with meet_link and event_id
log(`Updating session ${body.slot_id} with meet_link and calendar_event_id`);
await supabase
.from("consulting_sessions")
.update({
meet_link: eventDataResult.hangoutLink,
calendar_event_id: eventDataResult.id
})
.eq("id", body.slot_id);
log("Successfully completed");
return new Response(