Compare commits

..

No commits in common. "e3600030617a55dc61ae5c11a780b2bb1b887cd1" and "bd29eefcef7555dfa2c76c96ded8a53cc6b2c21e" have entirely different histories.

5 changed files with 53 additions and 99 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": "^4.1.0",
"date-fns": "^3.6.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": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"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": "^4.1.0",
"date-fns": "^3.6.0",
"embla-carousel-react": "^8.3.0",
"input-otp": "^1.2.4",
"lucide-react": "^0.462.0",

View file

@ -1,80 +1,42 @@
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 Message {
interface Conversation {
id: string;
phone_number: string;
message: string;
created_at: string;
contact: string;
lastMessage: string;
timestamp: 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">
{conversations.length} active
{mockConversations.length} active
</span>
</div>
<div className="grid gap-4">
{conversations.map((message) => (
{mockConversations.map((conversation) => (
<Card
key={message.id}
key={conversation.id}
className="p-4 transition-all hover:shadow-md cursor-pointer group"
>
<div className="flex items-center space-x-4">
@ -83,13 +45,13 @@ export function ConversationList() {
</div>
<div className="flex-1 min-w-0">
<div className="flex justify-between items-start">
<h3 className="font-medium truncate">{message.phone_number}</h3>
<h3 className="font-medium truncate">{conversation.contact}</h3>
<span className="text-xs text-muted-foreground whitespace-nowrap ml-2">
{formatDistanceToNow(new Date(message.created_at), { addSuffix: true })}
{conversation.timestamp}
</span>
</div>
<p className="text-sm text-muted-foreground truncate">
{message.message}
{conversation.lastMessage}
</p>
</div>
</div>

View file

@ -5,7 +5,17 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card } from "@/components/ui/card";
import { toast } from "sonner";
import { supabase } from "@/lib/supabase";
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);
export function MessageComposer() {
const [message, setMessage] = useState("");
@ -18,35 +28,28 @@ export function MessageComposer() {
return;
}
const formattedPhoneNumber = phoneNumber.startsWith('+1') ? phoneNumber : `+1${phoneNumber}`;
console.log('Attempting to store message:', { phoneNumber: formattedPhoneNumber, message });
console.log('Attempting to send message:', { phoneNumber, message });
setIsSending(true);
try {
// Store the message in Supabase
const { data, error } = await supabase
.from('messages')
.insert([
{
phone_number: formattedPhoneNumber,
message: message
}
])
.select();
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 });
if (error) {
console.error('Supabase insert error:', error);
console.error('Supabase function error:', error);
throw error;
}
console.log('Message stored successfully:', data);
toast.success("Message stored successfully!");
toast.success("Message sent successfully!");
setMessage("");
setPhoneNumber("");
} catch (error: any) {
} catch (error) {
console.error('Detailed error:', error);
toast.error(`Failed to store message: ${error.message || 'Please try again'}`);
toast.error("Failed to send message. Please try again.");
} finally {
setIsSending(false);
}
@ -66,7 +69,7 @@ export function MessageComposer() {
</label>
<Input
id="phone"
placeholder="Enter phone number... (e.g. +13109228324)"
placeholder="Enter phone number..."
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
className="w-full"

View file

@ -1,11 +0,0 @@
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);