mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
183fe0a93c
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
136 lines
4.9 KiB
TypeScript
136 lines
4.9 KiB
TypeScript
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
|
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.39.3";
|
|
|
|
const corsHeaders = {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Headers":
|
|
"authorization, x-client-info, apikey, content-type, x-supabase-client-platform, x-supabase-client-platform-version, x-supabase-client-runtime, x-supabase-client-runtime-version",
|
|
};
|
|
|
|
serve(async (req) => {
|
|
if (req.method === "OPTIONS") {
|
|
return new Response(null, { headers: corsHeaders });
|
|
}
|
|
|
|
try {
|
|
const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
|
|
const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
|
|
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
|
|
|
const { booking_id, session_id } = await req.json();
|
|
|
|
if (!booking_id) {
|
|
return new Response(
|
|
JSON.stringify({ error: "Missing booking_id" }),
|
|
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
// Fetch booking
|
|
const { data: booking, error: bookingErr } = await supabase
|
|
.from("amenity_bookings")
|
|
.select("*")
|
|
.eq("id", booking_id)
|
|
.single();
|
|
|
|
if (bookingErr || !booking) {
|
|
return new Response(
|
|
JSON.stringify({ error: "Booking not found" }),
|
|
{ status: 404, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
// Only process if still pending_payment
|
|
if (booking.status !== "pending_payment") {
|
|
return new Response(
|
|
JSON.stringify({ success: true, message: "Already processed" }),
|
|
{ headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
// Update booking status to confirmed
|
|
await supabase
|
|
.from("amenity_bookings")
|
|
.update({ status: "confirmed" })
|
|
.eq("id", booking_id);
|
|
|
|
// Extract pin_id from notes
|
|
let pinId: string | null = null;
|
|
try {
|
|
const notes = typeof booking.notes === "string" ? JSON.parse(booking.notes) : booking.notes;
|
|
pinId = notes?.pin_id || null;
|
|
} catch { /* ignore */ }
|
|
|
|
// Mark pin as rented
|
|
if (pinId && booking.amenity_id) {
|
|
const { data: amenity } = await supabase
|
|
.from("amenities")
|
|
.select("map_config")
|
|
.eq("id", booking.amenity_id)
|
|
.single();
|
|
|
|
if (amenity?.map_config?.pins) {
|
|
const updatedPins = amenity.map_config.pins.map((pin: any) =>
|
|
pin.id === pinId ? { ...pin, status: "rented" } : pin
|
|
);
|
|
|
|
await supabase
|
|
.from("amenities")
|
|
.update({
|
|
map_config: { ...amenity.map_config, pins: updatedPins },
|
|
updated_at: new Date().toISOString(),
|
|
})
|
|
.eq("id", booking.amenity_id);
|
|
}
|
|
}
|
|
|
|
// Send confirmation email
|
|
if (booking.guest_email) {
|
|
try {
|
|
const { data: amenityRow } = await supabase
|
|
.from("amenities").select("name, association_id").eq("id", booking.amenity_id).single();
|
|
const { data: assocRow } = amenityRow?.association_id
|
|
? await supabase.from("associations").select("name").eq("id", amenityRow.association_id).single()
|
|
: { data: null };
|
|
const { data: pageRow } = amenityRow?.association_id
|
|
? await supabase.from("association_public_pages").select("slug").eq("association_id", amenityRow.association_id).maybeSingle()
|
|
: { data: null };
|
|
const origin = req.headers.get("origin") || "https://avria.cloud";
|
|
const dateObj = booking.booking_date ? new Date(`${booking.booking_date}T12:00:00`) : null;
|
|
const formattedDate = dateObj
|
|
? dateObj.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })
|
|
: "";
|
|
await supabase.functions.invoke("send-transactional-email", {
|
|
body: {
|
|
templateName: "amenity-booking-confirmation",
|
|
recipientEmail: booking.guest_email,
|
|
idempotencyKey: `amenity-booking-confirmed-${booking.id}`,
|
|
templateData: {
|
|
guestName: booking.guest_name,
|
|
amenityName: amenityRow?.name,
|
|
associationName: (assocRow as any)?.name,
|
|
bookingDate: formattedDate,
|
|
startTime: booking.start_time || "",
|
|
status: "confirmed",
|
|
confirmationLink: `${origin}/booking/${booking.id}`,
|
|
},
|
|
},
|
|
});
|
|
} catch (err) {
|
|
console.error("Failed to send confirmation email:", err);
|
|
}
|
|
}
|
|
|
|
return new Response(
|
|
JSON.stringify({ success: true }),
|
|
{ headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
} catch (err) {
|
|
console.error("Error in confirm-reservation-payment:", err);
|
|
return new Response(
|
|
JSON.stringify({ error: err.message || "Internal server error" }),
|
|
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
});
|