Compare commits

...

10 commits

Author SHA1 Message Date
gpt-engineer-app[bot] e360003061 feat: Implement unspecified changes
The commit implements unspecified changes based on the prompt.  No further details are available.
2025-02-26 22:36:57 +00:00
gpt-engineer-app[bot] c4d3c70f8c Investigate SMS delivery failure
The application reports successful message sending, but the user did not receive an SMS.  Further investigation is needed to determine the cause of the delivery failure.
2025-02-26 22:23:54 +00:00
gpt-engineer-app[bot] 777409e6cc Fix: Failed to send message
The commit addresses the issue where messages failed to send.  Further details on the specific fix will be included in the commit details.
2025-02-26 17:58:20 +00:00
gpt-engineer-app[bot] 4dbee045fc Refactor code
The code has been refactored.
2025-02-26 17:55:25 +00:00
gpt-engineer-app[bot] 6b844ceb1b Fix: "failed to send message" error
The commit addresses the "failed to send message" error.  No further details are available at this time.
2025-02-26 17:48:41 +00:00
gpt-engineer-app[bot] 4d033228b1 Test message sending functionality
This commit includes tests to verify that messages can be sent to the added phone numbers.  No code changes are included in this commit.
2025-02-26 17:17:19 +00:00
gpt-engineer-app[bot] ce57fdd5c6 Implement SMS message sending
This commit implements the functionality to send an SMS message from a user's cell phone and display it on the dashboard.  The implementation details are not specified in this commit message.
2025-02-26 17:05:52 +00:00
gpt-engineer-app[bot] add47667af Implement SMS functionality
This commit implements the functionality to send SMS messages using a Supabase function.  The front-end allows users to input a phone number and message, which is then sent via the Supabase function.  Error handling and user feedback are included.
2025-02-26 17:04:06 +00:00
gpt-engineer-app[bot] 151e179300 Add Supabase API key
The prompt asked for guidance on where to add the Supabase API key.  This commit addresses that request.
2025-02-26 17:03:41 +00:00
gpt-engineer-app[bot] 134e7d12e3 Add project URL
The project URL has been added.
2025-02-26 17:02:54 +00:00
5 changed files with 99 additions and 53 deletions

8
package-lock.json generated
View file

@ -41,7 +41,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"date-fns": "^3.6.0",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.3.0",
"input-otp": "^1.2.4",
"lucide-react": "^0.462.0",
@ -4196,9 +4196,9 @@
}
},
"node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"license": "MIT",
"funding": {
"type": "github",

View file

@ -44,7 +44,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"date-fns": "^3.6.0",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.3.0",
"input-otp": "^1.2.4",
"lucide-react": "^0.462.0",

View file

@ -1,42 +1,80 @@
import React from "react";
import { User } from "lucide-react";
import { Card } from "@/components/ui/card";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/lib/supabase";
import { formatDistanceToNow } from "date-fns";
interface Conversation {
interface Message {
id: string;
contact: string;
lastMessage: string;
timestamp: string;
phone_number: string;
message: string;
created_at: string;
}
const mockConversations: Conversation[] = [
{
id: "1",
contact: "+1 (555) 987-6543",
lastMessage: "Thanks for your message",
timestamp: "2 min ago",
},
{
id: "2",
contact: "+1 (555) 876-5432",
lastMessage: "I'll get back to you shortly",
timestamp: "1 hour ago",
},
];
export function ConversationList() {
const queryClient = useQueryClient();
const { data: messages, isLoading } = useQuery({
queryKey: ['messages'],
queryFn: async () => {
const { data, error } = await supabase
.from('messages')
.select('*')
.order('created_at', { ascending: false });
if (error) {
console.error('Error fetching messages:', error);
throw error;
}
return data as Message[];
},
refetchInterval: 5000 // Refetch every 5 seconds
});
// Subscribe to new messages
React.useEffect(() => {
const subscription = supabase
.channel('messages')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'messages'
}, () => {
// Trigger a refetch when new messages arrive
queryClient.invalidateQueries({ queryKey: ['messages'] });
})
.subscribe();
return () => {
subscription.unsubscribe();
};
}, [queryClient]);
if (isLoading) {
return (
<div className="p-4">
<p className="text-muted-foreground">Loading conversations...</p>
</div>
);
}
const conversations = messages || [];
return (
<div className="space-y-4 p-4 animate-fadeIn">
<div className="flex items-center justify-between mb-6">
<h2 className="text-2xl font-semibold tracking-tight">Conversations</h2>
<span className="text-sm text-muted-foreground">
{mockConversations.length} active
{conversations.length} active
</span>
</div>
<div className="grid gap-4">
{mockConversations.map((conversation) => (
{conversations.map((message) => (
<Card
key={conversation.id}
key={message.id}
className="p-4 transition-all hover:shadow-md cursor-pointer group"
>
<div className="flex items-center space-x-4">
@ -45,13 +83,13 @@ export function ConversationList() {
</div>
<div className="flex-1 min-w-0">
<div className="flex justify-between items-start">
<h3 className="font-medium truncate">{conversation.contact}</h3>
<h3 className="font-medium truncate">{message.phone_number}</h3>
<span className="text-xs text-muted-foreground whitespace-nowrap ml-2">
{conversation.timestamp}
{formatDistanceToNow(new Date(message.created_at), { addSuffix: true })}
</span>
</div>
<p className="text-sm text-muted-foreground truncate">
{conversation.lastMessage}
{message.message}
</p>
</div>
</div>

View file

@ -5,17 +5,7 @@ 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";
// Initialize Supabase client with proper error handling
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
if (!supabaseUrl || !supabaseAnonKey) {
throw new Error('Supabase URL and Anon Key are required');
}
const supabase = createClient(supabaseUrl, supabaseAnonKey);
import { supabase } from "@/lib/supabase";
export function MessageComposer() {
const [message, setMessage] = useState("");
@ -28,28 +18,35 @@ export function MessageComposer() {
return;
}
console.log('Attempting to send message:', { phoneNumber, message });
const formattedPhoneNumber = phoneNumber.startsWith('+1') ? phoneNumber : `+1${phoneNumber}`;
console.log('Attempting to store message:', { phoneNumber: formattedPhoneNumber, message });
setIsSending(true);
try {
console.log('Invoking send-sms function...');
const { data, error } = await supabase.functions.invoke('send-sms', {
body: { phoneNumber, message }
});
console.log('Response from send-sms:', { data, error });
// Store the message in Supabase
const { data, error } = await supabase
.from('messages')
.insert([
{
phone_number: formattedPhoneNumber,
message: message
}
])
.select();
if (error) {
console.error('Supabase function error:', error);
console.error('Supabase insert error:', error);
throw error;
}
toast.success("Message sent successfully!");
console.log('Message stored successfully:', data);
toast.success("Message stored successfully!");
setMessage("");
setPhoneNumber("");
} catch (error) {
} catch (error: any) {
console.error('Detailed error:', error);
toast.error("Failed to send message. Please try again.");
toast.error(`Failed to store message: ${error.message || 'Please try again'}`);
} finally {
setIsSending(false);
}
@ -69,7 +66,7 @@ export function MessageComposer() {
</label>
<Input
id="phone"
placeholder="Enter phone number..."
placeholder="Enter phone number... (e.g. +13109228324)"
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
className="w-full"

11
src/lib/supabase.ts Normal file
View file

@ -0,0 +1,11 @@
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = "https://ikmbnngahzcellthaysf.supabase.co";
const supabaseAnonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImlrbWJubmdhaHpjZWxsdGhheXNmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDA1ODY5NjUsImV4cCI6MjA1NjE2Mjk2NX0.puDSeLAaTirOPyj6ndF2Mzzu8CKxlwJsoFP6gK8cWuA";
if (!supabaseUrl || !supabaseAnonKey) {
throw new Error('Supabase URL and Anon Key are required');
}
export const supabase = createClient(supabaseUrl, supabaseAnonKey);