-- Create users table CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, phone VARCHAR(20), role VARCHAR(20) NOT NULL CHECK (role IN ('customer', 'barber', 'admin')), photo TEXT, loyalty_points INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Create services table CREATE TABLE services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, description TEXT, duration INTEGER NOT NULL, -- in minutes price DECIMAL(10,2) NOT NULL, image TEXT, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Create barbers table CREATE TABLE barbers ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, specialty VARCHAR(255) NOT NULL, bio TEXT, rating DECIMAL(3,2) DEFAULT 0.0 CHECK (rating >= 0 AND rating <= 5), availability JSONB DEFAULT '{}', -- JSON object with days and time slots is_active BOOLEAN DEFAULT true, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id) ); -- Create bookings table CREATE TABLE bookings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), customer_id UUID REFERENCES users(id) ON DELETE CASCADE, barber_id UUID REFERENCES barbers(id) ON DELETE CASCADE, service_id UUID REFERENCES services(id) ON DELETE CASCADE, booking_date DATE NOT NULL, booking_time TIME NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'completed', 'cancelled')), notes TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Create reviews table CREATE TABLE reviews ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, barber_id UUID REFERENCES barbers(id) ON DELETE CASCADE, booking_id UUID REFERENCES bookings(id) ON DELETE SET NULL, rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5), comment TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id, barber_id, booking_id) ); -- Create promotions table CREATE TABLE promotions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, description TEXT, discount_percentage INTEGER NOT NULL CHECK (discount_percentage > 0 AND discount_percentage <= 100), service_id UUID REFERENCES services(id) ON DELETE CASCADE, is_active BOOLEAN DEFAULT true, start_date DATE NOT NULL, end_date DATE NOT NULL, image TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Create indexes for better performance CREATE INDEX idx_barbers_user_id ON barbers(user_id); CREATE INDEX idx_bookings_customer_id ON bookings(customer_id); CREATE INDEX idx_bookings_barber_id ON bookings(barber_id); CREATE INDEX idx_bookings_service_id ON bookings(service_id); CREATE INDEX idx_bookings_date_time ON bookings(booking_date, booking_time); CREATE INDEX idx_reviews_user_id ON reviews(user_id); CREATE INDEX idx_reviews_barber_id ON reviews(barber_id); CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_users_role ON users(role); -- Create function to update updated_at timestamp CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; -- Create triggers for updated_at CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_services_updated_at BEFORE UPDATE ON services FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_barbers_updated_at BEFORE UPDATE ON barbers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_bookings_updated_at BEFORE UPDATE ON bookings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_reviews_updated_at BEFORE UPDATE ON reviews FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_promotions_updated_at BEFORE UPDATE ON promotions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- Insert sample data INSERT INTO services (name, description, duration, price, image) VALUES ('Classic Haircut', 'Traditional haircut with scissors and clippers', 30, 25.00, 'https://images.unsplash.com/photo-1560069007-67cba843241f?w=400'), ('Beard Trim', 'Professional beard shaping and trimming', 20, 15.00, 'https://images.unsplash.com/photo-1622286342621-4bd786c2447c?w=400'), ('Hot Towel Shave', 'Luxurious hot towel straight razor shave', 45, 35.00, 'https://images.unsplash.com/photo-1596468138837-0c38f5fca1b3?w=400'), ('Haircut & Beard', 'Complete haircut and beard trim package', 45, 35.00, 'https://images.unsplash.com/photo-1585747860715-1ba5b1b0ba72?w=400'), ('Kids Haircut', 'Haircut for children under 12', 25, 20.00, 'https://images.unsplash.com/photo-1503931975084-1a8352b4c66d?w=400'); -- Enable Row Level Security (RLS) ALTER TABLE users ENABLE ROW LEVEL SECURITY; ALTER TABLE barbers ENABLE ROW LEVEL SECURITY; ALTER TABLE services ENABLE ROW LEVEL SECURITY; ALTER TABLE bookings ENABLE ROW LEVEL SECURITY; ALTER TABLE reviews ENABLE ROW LEVEL SECURITY; ALTER TABLE promotions ENABLE ROW LEVEL SECURITY; -- Create RLS policies -- Users can view all users but only update their own profile CREATE POLICY "Users can view all users" ON users FOR SELECT USING (true); CREATE POLICY "Users can update own profile" ON users FOR UPDATE USING (auth.uid() = id); -- Anyone can view active services CREATE POLICY "Services are viewable by everyone" ON services FOR SELECT USING (is_active = true); -- Barbers can be viewed by everyone CREATE POLICY "Barbers are viewable by everyone" ON barbers FOR SELECT USING (is_active = true); -- Users can view their own bookings and barbers can view bookings assigned to them CREATE POLICY "Users can view own bookings" ON bookings FOR SELECT USING (auth.uid() = customer_id); CREATE POLICY "Barbers can view their bookings" ON bookings FOR SELECT USING ( EXISTS (SELECT 1 FROM barbers WHERE barbers.id = barber_id AND barbers.user_id = auth.uid()) ); CREATE POLICY "Users can create bookings" ON bookings FOR INSERT WITH CHECK (auth.uid() = customer_id); -- Reviews can be viewed by everyone CREATE POLICY "Reviews are viewable by everyone" ON reviews FOR SELECT USING (true); CREATE POLICY "Users can create reviews" ON reviews FOR INSERT WITH CHECK (auth.uid() = user_id); -- Active promotions can be viewed by everyone CREATE POLICY "Active promotions are viewable by everyone" ON promotions FOR SELECT USING (is_active = true);