Fix: Connected
The prompt indicated a connection issue needed to be addressed. This commit addresses that issue.
This commit is contained in:
parent
dc6fafb0ef
commit
a149662806
|
@ -5,21 +5,41 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
import { toast } from "sonner";
|
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() {
|
export function MessageComposer() {
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [phoneNumber, setPhoneNumber] = useState("");
|
const [phoneNumber, setPhoneNumber] = useState("");
|
||||||
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
|
||||||
const handleSend = () => {
|
const handleSend = async () => {
|
||||||
if (!message.trim() || !phoneNumber.trim()) {
|
if (!message.trim() || !phoneNumber.trim()) {
|
||||||
toast.error("Please enter both phone number and message");
|
toast.error("Please enter both phone number and message");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock send functionality
|
setIsSending(true);
|
||||||
|
try {
|
||||||
|
const { data, error } = await supabase.functions.invoke('send-sms', {
|
||||||
|
body: { phoneNumber, message }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
toast.success("Message sent successfully!");
|
toast.success("Message sent successfully!");
|
||||||
setMessage("");
|
setMessage("");
|
||||||
setPhoneNumber("");
|
setPhoneNumber("");
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error sending message:', error);
|
||||||
|
toast.error("Failed to send message. Please try again.");
|
||||||
|
} finally {
|
||||||
|
setIsSending(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -40,6 +60,7 @@ export function MessageComposer() {
|
||||||
value={phoneNumber}
|
value={phoneNumber}
|
||||||
onChange={(e) => setPhoneNumber(e.target.value)}
|
onChange={(e) => setPhoneNumber(e.target.value)}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
disabled={isSending}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
@ -55,14 +76,16 @@ export function MessageComposer() {
|
||||||
value={message}
|
value={message}
|
||||||
onChange={(e) => setMessage(e.target.value)}
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
disabled={isSending}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSend}
|
onClick={handleSend}
|
||||||
className="w-full group hover:shadow-md transition-all"
|
className="w-full group hover:shadow-md transition-all"
|
||||||
|
disabled={isSending}
|
||||||
>
|
>
|
||||||
<Send className="mr-2 h-4 w-4 group-hover:scale-110 transition-transform" />
|
<Send className="mr-2 h-4 w-4 group-hover:scale-110 transition-transform" />
|
||||||
Send Message
|
{isSending ? "Sending..." : "Send Message"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
5
supabase/functions/_shared/cors.ts
Normal file
5
supabase/functions/_shared/cors.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
export const corsHeaders = {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||||
|
}
|
47
supabase/functions/send-sms/index.ts
Normal file
47
supabase/functions/send-sms/index.ts
Normal file
|
@ -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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in a new issue