This document describes the database schema required for the BroCode application.
Stores user profile information.
CREATE TABLE profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
username TEXT UNIQUE NOT NULL,
email TEXT,
phone TEXT,
password TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
profile_pic_url TEXT,
location TEXT,
date_of_birth TEXT,
is_verified BOOLEAN DEFAULT false,
latitude NUMERIC,
longitude NUMERIC,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create unique index on username
CREATE UNIQUE INDEX profiles_username_unique ON profiles(username);
-- Enable Row Level Security (RLS)
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
-- Policy: Users can read all profiles
CREATE POLICY "Users can read all profiles" ON profiles
FOR SELECT USING (true);
-- Policy: Users can update their own profile
CREATE POLICY "Users can update own profile" ON profiles
FOR UPDATE USING (auth.uid() = id);Stores spot/meetup information.
CREATE TABLE spots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
date TIMESTAMP WITH TIME ZONE NOT NULL,
day TEXT NOT NULL,
timing TEXT NOT NULL,
budget NUMERIC NOT NULL DEFAULT 0,
location TEXT NOT NULL,
created_by UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
description TEXT,
feedback TEXT,
latitude NUMERIC,
longitude NUMERIC,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create index on date for faster queries
CREATE INDEX spots_date_idx ON spots(date);
-- Enable RLS
ALTER TABLE spots ENABLE ROW LEVEL SECURITY;
-- Policy: Everyone can read spots
CREATE POLICY "Everyone can read spots" ON spots
FOR SELECT USING (true);
-- Policy: Only admins can create spots
CREATE POLICY "Admins can create spots" ON spots
FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);
-- Policy: Only admins can update spots
CREATE POLICY "Admins can update spots" ON spots
FOR UPDATE USING (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);
-- Policy: Only admins can delete spots
CREATE POLICY "Admins can delete spots" ON spots
FOR DELETE USING (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);Stores RSVP invitations for spots.
CREATE TABLE invitations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
spot_id UUID NOT NULL REFERENCES spots(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('confirmed', 'pending', 'declined')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(spot_id, user_id)
);
-- Create indexes for faster queries
CREATE INDEX invitations_spot_id_idx ON invitations(spot_id);
CREATE INDEX invitations_user_id_idx ON invitations(user_id);
-- Enable RLS
ALTER TABLE invitations ENABLE ROW LEVEL SECURITY;
-- Policy: Everyone can read invitations
CREATE POLICY "Everyone can read invitations" ON invitations
FOR SELECT USING (true);
-- Policy: Users can create/update their own invitations
CREATE POLICY "Users can manage own invitations" ON invitations
FOR ALL USING (auth.uid() = user_id);Stores payment information for spots.
CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
spot_id UUID NOT NULL REFERENCES spots(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
status TEXT NOT NULL DEFAULT 'not_paid' CHECK (status IN ('paid', 'not_paid')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(spot_id, user_id)
);
-- Create indexes for faster queries
CREATE INDEX payments_spot_id_idx ON payments(spot_id);
CREATE INDEX payments_user_id_idx ON payments(user_id);
-- Enable RLS
ALTER TABLE payments ENABLE ROW LEVEL SECURITY;
-- Policy: Everyone can read payments
CREATE POLICY "Everyone can read payments" ON payments
FOR SELECT USING (true);
-- Policy: Admins can update payments
CREATE POLICY "Admins can update payments" ON payments
FOR UPDATE USING (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);
-- Policy: System can create payments (via service role)
CREATE POLICY "System can create payments" ON payments
FOR INSERT WITH CHECK (true);Stores chat messages.
CREATE TABLE chat_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
content_text TEXT,
content_image_urls TEXT[],
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
reactions JSONB DEFAULT '{}'::jsonb
);
-- Create index on created_at for faster queries
CREATE INDEX chat_messages_created_at_idx ON chat_messages(created_at);
-- Enable RLS
ALTER TABLE chat_messages ENABLE ROW LEVEL SECURITY;
-- Policy: Everyone can read messages
CREATE POLICY "Everyone can read messages" ON chat_messages
FOR SELECT USING (true);
-- Policy: Users can create their own messages
CREATE POLICY "Users can create own messages" ON chat_messages
FOR INSERT WITH CHECK (auth.uid() = user_id);
-- Policy: Users can delete their own messages
CREATE POLICY "Users can delete own messages" ON chat_messages
FOR DELETE USING (auth.uid() = user_id);Stores user moments/photos.
CREATE TABLE moments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
image_url TEXT NOT NULL,
caption TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create index on user_id and created_at
CREATE INDEX moments_user_id_idx ON moments(user_id);
CREATE INDEX moments_created_at_idx ON moments(created_at DESC);
-- Enable RLS
ALTER TABLE moments ENABLE ROW LEVEL SECURITY;
-- Policy: Everyone can read moments
CREATE POLICY "Everyone can read moments" ON moments
FOR SELECT USING (true);
-- Policy: Users can create their own moments
CREATE POLICY "Users can create own moments" ON moments
FOR INSERT WITH CHECK (auth.uid() = user_id);
-- Policy: Users can delete their own moments
CREATE POLICY "Users can delete own moments" ON moments
FOR DELETE USING (auth.uid() = user_id);Stores transaction history for payment tracking.
CREATE TABLE transactions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
spot_id UUID NOT NULL REFERENCES spots(id) ON DELETE CASCADE,
amount NUMERIC NOT NULL,
payment_method TEXT NOT NULL DEFAULT 'UPI',
status TEXT NOT NULL DEFAULT 'not_paid' CHECK (status IN ('paid', 'not_paid')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create indexes for faster queries
CREATE INDEX transactions_user_id_idx ON transactions(user_id);
CREATE INDEX transactions_spot_id_idx ON transactions(spot_id);
CREATE INDEX transactions_created_at_idx ON transactions(created_at DESC);
-- Enable RLS
ALTER TABLE transactions ENABLE ROW LEVEL SECURITY;
-- Policy: Users can read their own transactions
CREATE POLICY "Users can read own transactions" ON transactions
FOR SELECT USING (auth.uid() = user_id);
-- Policy: Admins can read all transactions
CREATE POLICY "Admins can read all transactions" ON transactions
FOR SELECT USING (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);
-- Policy: Admins can create transactions
CREATE POLICY "Admins can create transactions" ON transactions
FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);
-- Policy: Admins can update transactions
CREATE POLICY "Admins can update transactions" ON transactions
FOR UPDATE USING (
EXISTS (
SELECT 1 FROM profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'admin'
)
);Enable real-time for the following tables in Supabase Dashboard:
spots- for spot updatesinvitations- for RSVP updatespayments- for payment status updateschat_messages- for chat updatestransactions- for transaction history updates
After creating the tables, you can insert the admin user:
INSERT INTO profiles (id, name, username, email, phone, password, role, location, is_verified)
VALUES (
'admin',
'Ram',
'ramvj2005',
'ramvj2005@gmail.com',
'7826821130',
'ramkumar',
'admin',
'Attibele',
true
);- Make sure to enable Row Level Security (RLS) on all tables
- Adjust policies based on your security requirements
- The
usernamefield has a UNIQUE constraint to ensure uniqueness - All timestamps use
TIMESTAMP WITH TIME ZONEfor proper timezone handling - Foreign key constraints ensure data integrity
Stores a single sponsor assignment per spot.
CREATE TABLE spot_sponsors (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
spot_id UUID NOT NULL REFERENCES spots(id) ON DELETE CASCADE UNIQUE,
sponsor_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
amount_covered NUMERIC NOT NULL DEFAULT 0,
message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
ALTER TABLE profiles
ADD COLUMN is_sponsor BOOLEAN DEFAULT false,
ADD COLUMN sponsor_count INTEGER DEFAULT 0;
ALTER TABLE spots
ADD COLUMN is_sponsored BOOLEAN DEFAULT false,
ADD COLUMN sponsored_by UUID REFERENCES profiles(id) ON DELETE SET NULL;A trigger on spot_sponsors should permanently mark the sponsor profile and increment sponsor_count whenever a new sponsorship is inserted.