Fix calendar timezone and group consulting slots by order

Calendar Timezone Fix:
- Add +07:00 timezone offset to date strings in create-google-meet-event
- Fixes 13:00 appearing as 20:00 in Google Calendar
- Now treats times as Asia/Jakarta time explicitly

Single Calendar Event per Order:
- handle-order-paid now creates ONE event for all slots in an order
- Uses first slot's start time and last slot's end time
- Updates all slots with the same meet_link
- Prevents duplicate calendar events for multi-slot orders

Admin Consulting Page Improvements:
- Group consulting slots by order_id
- Display as single row with continuous time range (start-end)
- Show session count when multiple slots (e.g., "2 sesi")
- Consistent with member-facing ConsultingHistory component
- Updated both desktop table and mobile card layouts
- Updated both upcoming and past tabs

🤖 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-27 01:34:40 +07:00
parent 3f0acca658
commit 42d6bd98e2
3 changed files with 337 additions and 254 deletions

View File

@@ -113,42 +113,50 @@ serve(async (req: Request): Promise<Response> => {
}
if (consultingSlots && consultingSlots.length > 0) {
for (const slot of consultingSlots) {
try {
console.log("[HANDLE-PAID] Creating Google Meet for slot:", slot.id);
try {
console.log("[HANDLE-PAID] Creating Google Meet for order:", order_id);
const topic = "Konsultasi 1-on-1";
// Group slots by order - use first slot's start time and last slot's end time
const firstSlot = consultingSlots[0];
const lastSlot = consultingSlots[consultingSlots.length - 1];
const topic = "Konsultasi 1-on-1";
const meetResponse = await fetch(
`${supabaseUrl}/functions/v1/create-google-meet-event`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${Deno.env.get("SUPABASE_ANON_KEY")}`,
},
body: JSON.stringify({
slot_id: slot.id,
date: slot.date,
start_time: slot.start_time,
end_time: slot.end_time,
client_name: userName,
client_email: userEmail,
topic: topic,
}),
}
);
if (meetResponse.ok) {
const meetData = await meetResponse.json();
if (meetData.success) {
console.log("[HANDLE-PAID] Meet created:", meetData.meet_link);
}
const meetResponse = await fetch(
`${supabaseUrl}/functions/v1/create-google-meet-event`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${Deno.env.get("SUPABASE_ANON_KEY")}`,
},
body: JSON.stringify({
slot_id: firstSlot.id, // Use first slot ID
date: firstSlot.date,
start_time: firstSlot.start_time,
end_time: lastSlot.end_time, // Use last slot's end time for continuous block
client_name: userName,
client_email: userEmail,
topic: topic,
notes: `${consultingSlots.length} sesi: ${consultingSlots.map(s => s.start_time.substring(0, 5)).join(', ')}`,
}),
}
);
if (meetResponse.ok) {
const meetData = await meetResponse.json();
if (meetData.success) {
console.log("[HANDLE-PAID] Meet created:", meetData.meet_link);
// Update all slots with the same meet link
await supabase
.from("consulting_slots")
.update({ meet_link: meetData.meet_link })
.eq("order_id", order_id);
}
} catch (error) {
console.error("[HANDLE-PAID] Meet creation failed:", error);
// Don't fail the entire process
}
} catch (error) {
console.error("[HANDLE-PAID] Meet creation failed:", error);
// Don't fail the entire process
}
}