diff --git a/src/components/panel/MessageComposer.tsx b/src/components/panel/MessageComposer.tsx
index 386e40b..4cd3298 100644
--- a/src/components/panel/MessageComposer.tsx
+++ b/src/components/panel/MessageComposer.tsx
@@ -5,21 +5,41 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card } from "@/components/ui/card";
import { toast } from "sonner";
+import { createClient } from "@supabase/supabase-js";
+
+const supabase = createClient(
+ import.meta.env.VITE_SUPABASE_URL,
+ import.meta.env.VITE_SUPABASE_ANON_KEY
+);
export function MessageComposer() {
const [message, setMessage] = useState("");
const [phoneNumber, setPhoneNumber] = useState("");
+ const [isSending, setIsSending] = useState(false);
- const handleSend = () => {
+ const handleSend = async () => {
if (!message.trim() || !phoneNumber.trim()) {
toast.error("Please enter both phone number and message");
return;
}
-
- // Mock send functionality
- toast.success("Message sent successfully!");
- setMessage("");
- setPhoneNumber("");
+
+ setIsSending(true);
+ try {
+ const { data, error } = await supabase.functions.invoke('send-sms', {
+ body: { phoneNumber, message }
+ });
+
+ if (error) throw error;
+
+ toast.success("Message sent successfully!");
+ setMessage("");
+ setPhoneNumber("");
+ } catch (error) {
+ console.error('Error sending message:', error);
+ toast.error("Failed to send message. Please try again.");
+ } finally {
+ setIsSending(false);
+ }
};
return (
@@ -40,6 +60,7 @@ export function MessageComposer() {
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
className="w-full"
+ disabled={isSending}
/>
@@ -55,14 +76,16 @@ export function MessageComposer() {
value={message}
onChange={(e) => setMessage(e.target.value)}
className="w-full"
+ disabled={isSending}
/>
diff --git a/supabase/functions/_shared/cors.ts b/supabase/functions/_shared/cors.ts
new file mode 100644
index 0000000..765bfe2
--- /dev/null
+++ b/supabase/functions/_shared/cors.ts
@@ -0,0 +1,5 @@
+
+export const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
+}
diff --git a/supabase/functions/send-sms/index.ts b/supabase/functions/send-sms/index.ts
new file mode 100644
index 0000000..f42a253
--- /dev/null
+++ b/supabase/functions/send-sms/index.ts
@@ -0,0 +1,47 @@
+
+import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
+import { corsHeaders } from '../_shared/cors.ts'
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
+
+serve(async (req) => {
+ // Handle CORS
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders })
+ }
+
+ try {
+ const { phoneNumber, message } = await req.json()
+ const twilioAccountSid = Deno.env.get('TWILIO_ACCOUNT_SID')
+ const twilioAuthToken = Deno.env.get('TWILIO_AUTH_TOKEN')
+ const twilioPhoneNumber = Deno.env.get('TWILIO_PHONE_NUMBER')
+
+ if (!twilioAccountSid || !twilioAuthToken || !twilioPhoneNumber) {
+ throw new Error('Missing Twilio credentials')
+ }
+
+ const twilioUrl = `https://api.twilio.com/2010-04/Accounts/${twilioAccountSid}/Messages.json`
+ const response = await fetch(twilioUrl, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Authorization: `Basic ${btoa(`${twilioAccountSid}:${twilioAuthToken}`)}`,
+ },
+ body: new URLSearchParams({
+ To: phoneNumber,
+ From: twilioPhoneNumber,
+ Body: message,
+ }),
+ })
+
+ const result = await response.json()
+ return new Response(JSON.stringify(result), {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ status: 200,
+ })
+ } catch (error) {
+ return new Response(JSON.stringify({ error: error.message }), {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ status: 400,
+ })
+ }
+})