CREATE TABLE public.form_inbox ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), source_type TEXT NOT NULL, source_id UUID NOT NULL, association_id UUID REFERENCES public.associations(id), title TEXT NOT NULL, submitter_name TEXT, submitter_email TEXT, summary TEXT, status TEXT NOT NULL DEFAULT 'new', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), reviewed_by UUID, reviewed_at TIMESTAMPTZ ); ALTER TABLE public.form_inbox ENABLE ROW LEVEL SECURITY; CREATE POLICY "Admins and managers can view form inbox" ON public.form_inbox FOR SELECT TO authenticated USING ( public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') ); CREATE POLICY "Admins and managers can update form inbox" ON public.form_inbox FOR UPDATE TO authenticated USING ( public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') ); CREATE POLICY "Anyone can insert into form inbox" ON public.form_inbox FOR INSERT WITH CHECK (true); -- Trigger to auto-create inbox entry for public form submissions CREATE OR REPLACE FUNCTION public.create_form_inbox_entry_from_submission() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ BEGIN INSERT INTO public.form_inbox (source_type, source_id, association_id, title, submitter_name, submitter_email, summary) SELECT 'public_form', NEW.id, NEW.association_id, COALESCE(t.title, 'Form Submission'), NEW.submitter_name, NEW.submitter_email, t.title FROM public.public_form_templates t WHERE t.id = NEW.template_id; RETURN NEW; END; $$; CREATE TRIGGER trg_form_inbox_from_submission AFTER INSERT ON public.public_form_submissions FOR EACH ROW EXECUTE FUNCTION public.create_form_inbox_entry_from_submission(); -- Trigger for violation responses CREATE OR REPLACE FUNCTION public.create_form_inbox_entry_from_violation_response() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE v_assoc_id UUID; v_title TEXT; BEGIN SELECT v.association_id, 'Violation Response - ' || COALESCE(vt.category, 'Unknown') INTO v_assoc_id, v_title FROM public.violations v LEFT JOIN public.violation_types vt ON v.violation_type_id = vt.id WHERE v.id = NEW.violation_id; INSERT INTO public.form_inbox (source_type, source_id, association_id, title, submitter_name, submitter_email, summary) VALUES ('violation_response', NEW.id, v_assoc_id, v_title, NEW.respondent_name, NEW.respondent_email, LEFT(NEW.response_text, 200)); RETURN NEW; END; $$; CREATE TRIGGER trg_form_inbox_from_violation_response AFTER INSERT ON public.violation_responses FOR EACH ROW EXECUTE FUNCTION public.create_form_inbox_entry_from_violation_response(); -- Trigger for client requests CREATE OR REPLACE FUNCTION public.create_form_inbox_entry_from_client_request() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ BEGIN INSERT INTO public.form_inbox (source_type, source_id, association_id, title, submitter_name, submitter_email, summary) VALUES ('client_request', NEW.id, NEW.association_id, NEW.title, NEW.requester_name, NEW.requester_email, LEFT(NEW.description, 200)); RETURN NEW; END; $$; CREATE TRIGGER trg_form_inbox_from_client_request AFTER INSERT ON public.client_requests FOR EACH ROW EXECUTE FUNCTION public.create_form_inbox_entry_from_client_request(); -- Enable realtime ALTER PUBLICATION supabase_realtime ADD TABLE public.form_inbox;