/** * Supabase Backend Demo Page * Demonstrates Supabase integration patterns */ import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { supabase } from '@/utils/supabase'; interface Todo { id: string; title: string; completed: boolean; created_at: string; } export default function SupabaseDemo() { const [todos, setTodos] = useState([]); const [newTodo, setNewTodo] = useState(''); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [realtimeStatus, setRealtimeStatus] = useState<'connected' | 'disconnected'>('disconnected'); // Fetch todos const fetchTodos = async () => { setLoading(true); const { data, error } = await supabase .from('todos') .select('*') .order('created_at', { ascending: false }) .limit(10) .returns(); if (error) { setError(error.message); } else { setTodos(data || []); } setLoading(false); }; // Create todo const createTodo = async (e: React.FormEvent) => { e.preventDefault(); if (!newTodo.trim()) return; const { error } = await supabase .from('todos') .insert([{ title: newTodo.trim(), completed: false }]); if (error) { setError(error.message); } else { setNewTodo(''); fetchTodos(); } }; // Toggle todo const toggleTodo = async (id: string, completed: boolean) => { const { error } = await supabase .from('todos') .update({ completed: !completed }) .eq('id', id); if (error) { setError(error.message); } else { fetchTodos(); } }; // Delete todo const deleteTodo = async (id: string) => { const { error } = await supabase .from('todos') .delete() .eq('id', id); if (error) { setError(error.message); } else { fetchTodos(); } }; // Setup realtime subscription useEffect(() => { let ignore = false; const loadTodos = async () => { setLoading(true); const { data, error } = await supabase .from('todos') .select('*') .order('created_at', { ascending: false }) .limit(10) .returns(); if (!ignore) { if (error) { setError(error.message); } else { setTodos(data || []); } setLoading(false); } }; loadTodos(); const channel = supabase .channel('todos-changes') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'todos' }, (payload) => { console.log('Realtime update:', payload); // Refetch on realtime update - this is in a callback, not sync in effect fetchTodos(); } ) .subscribe((status) => { if (!ignore) { setRealtimeStatus(status === 'SUBSCRIBED' ? 'connected' : 'disconnected'); } }); return () => { ignore = true; supabase.removeChannel(channel); }; }, []); return (
← Back to Home

Supabase Backend Demo

PostgreSQL database with real-time subscriptions.

{/* Connection Status */}

Connection Status

Realtime: {realtimeStatus}
Database: connected
{/* CRUD Operations */}

CRUD Operations

{/* Create */}
setNewTodo(e.target.value)} placeholder="Add a new todo..." className="input flex-1" />
{error && (
{error}
)} {/* Read */} {loading ? (
Loading...
) : todos.length === 0 ? (
No todos yet
) : (
    {todos.map((todo) => (
  • {/* Update (toggle) */} {todo.title}
    {/* Delete */}
  • ))}
)}
{/* Code Examples */}

Query Examples

SELECT (Read)

{`const { data, error } = await supabase
  .from('todos')
  .select('*')
  .order('created_at', { ascending: false })
  .limit(10);`}
              

INSERT (Create)

{`const { error } = await supabase
  .from('todos')
  .insert([{ title: 'New todo', completed: false }]);`}
              

UPDATE

{`const { error } = await supabase
  .from('todos')
  .update({ completed: true })
  .eq('id', todoId);`}
              

DELETE

{`const { error } = await supabase
  .from('todos')
  .delete()
  .eq('id', todoId);`}
              

Realtime Subscription

{`const channel = supabase
  .channel('todos-changes')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'todos' },
    (payload) => {
      console.log('Change:', payload);
      refetchData();
    }
  )
  .subscribe();`}
              
); }