mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-22 21:47:56 +00:00
e1d4d9d8a2
Added: - useGovernance hook: Fetches live proposals and referenda from blockchain - useTreasury hook: Fetches live treasury balance and proposals - TreasuryOverview: Now uses real blockchain data with loading/error states - Forum database schema: Admin announcements, categories, discussions, replies, reactions Features: - Live data badge shows active blockchain connection - Automatic refresh every 30 seconds for treasury data - Secure RLS policies for forum access control - Admin announcements system with priority and expiry - Forum reactions (upvote/downvote) support Next: Complete forum UI with admin banner and moderation panel
217 lines
7.2 KiB
PL/PgSQL
217 lines
7.2 KiB
PL/PgSQL
-- Forum Tables for Pezkuwi Governance
|
|
|
|
-- Admin Announcements Table
|
|
CREATE TABLE IF NOT EXISTS public.admin_announcements (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'info', -- 'info', 'warning', 'success', 'critical'
|
|
is_active BOOLEAN DEFAULT true,
|
|
priority INTEGER DEFAULT 0, -- Higher priority shows first
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Forum Categories
|
|
CREATE TABLE IF NOT EXISTS public.forum_categories (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL UNIQUE,
|
|
description TEXT,
|
|
icon TEXT,
|
|
color TEXT,
|
|
display_order INTEGER DEFAULT 0,
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Forum Discussions
|
|
CREATE TABLE IF NOT EXISTS public.forum_discussions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
category_id UUID REFERENCES public.forum_categories(id) ON DELETE SET NULL,
|
|
proposal_id TEXT, -- Link to blockchain proposal if applicable
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
author_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
author_name TEXT NOT NULL,
|
|
author_address TEXT, -- Blockchain address
|
|
is_pinned BOOLEAN DEFAULT false,
|
|
is_locked BOOLEAN DEFAULT false,
|
|
views_count INTEGER DEFAULT 0,
|
|
replies_count INTEGER DEFAULT 0,
|
|
tags TEXT[],
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
last_activity_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Forum Replies
|
|
CREATE TABLE IF NOT EXISTS public.forum_replies (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
discussion_id UUID REFERENCES public.forum_discussions(id) ON DELETE CASCADE,
|
|
parent_reply_id UUID REFERENCES public.forum_replies(id) ON DELETE CASCADE, -- For nested replies
|
|
content TEXT NOT NULL,
|
|
author_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
author_name TEXT NOT NULL,
|
|
author_address TEXT,
|
|
is_edited BOOLEAN DEFAULT false,
|
|
edited_at TIMESTAMP WITH TIME ZONE,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Discussion Reactions (upvotes/downvotes)
|
|
CREATE TABLE IF NOT EXISTS public.forum_reactions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
discussion_id UUID REFERENCES public.forum_discussions(id) ON DELETE CASCADE,
|
|
reply_id UUID REFERENCES public.forum_replies(id) ON DELETE CASCADE,
|
|
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
reaction_type TEXT NOT NULL, -- 'upvote', 'downvote', 'helpful', etc.
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(discussion_id, user_id, reaction_type),
|
|
UNIQUE(reply_id, user_id, reaction_type)
|
|
);
|
|
|
|
-- Create Indexes
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_active ON public.admin_announcements(is_active, priority DESC, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_discussions_category ON public.forum_discussions(category_id);
|
|
CREATE INDEX IF NOT EXISTS idx_discussions_proposal ON public.forum_discussions(proposal_id);
|
|
CREATE INDEX IF NOT EXISTS idx_discussions_pinned ON public.forum_discussions(is_pinned DESC, last_activity_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_replies_discussion ON public.forum_replies(discussion_id, created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_discussion ON public.forum_reactions(discussion_id);
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_reply ON public.forum_reactions(reply_id);
|
|
|
|
-- RLS Policies
|
|
|
|
-- Admin Announcements
|
|
ALTER TABLE public.admin_announcements ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Anyone can view active announcements"
|
|
ON public.admin_announcements FOR SELECT
|
|
USING (is_active = true AND (expires_at IS NULL OR expires_at > NOW()));
|
|
|
|
CREATE POLICY "Admins can manage announcements"
|
|
ON public.admin_announcements FOR ALL
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Forum Categories
|
|
ALTER TABLE public.forum_categories ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Anyone can view active categories"
|
|
ON public.forum_categories FOR SELECT
|
|
USING (is_active = true);
|
|
|
|
CREATE POLICY "Admins can manage categories"
|
|
ON public.forum_categories FOR ALL
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Forum Discussions
|
|
ALTER TABLE public.forum_discussions ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Anyone can view discussions"
|
|
ON public.forum_discussions FOR SELECT
|
|
USING (true);
|
|
|
|
CREATE POLICY "Authenticated users can create discussions"
|
|
ON public.forum_discussions FOR INSERT
|
|
WITH CHECK (auth.uid() IS NOT NULL);
|
|
|
|
CREATE POLICY "Authors and admins can update discussions"
|
|
ON public.forum_discussions FOR UPDATE
|
|
USING (
|
|
author_id = auth.uid() OR
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Authors and admins can delete discussions"
|
|
ON public.forum_discussions FOR DELETE
|
|
USING (
|
|
author_id = auth.uid() OR
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Forum Replies
|
|
ALTER TABLE public.forum_replies ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Anyone can view replies"
|
|
ON public.forum_replies FOR SELECT
|
|
USING (true);
|
|
|
|
CREATE POLICY "Authenticated users can create replies"
|
|
ON public.forum_replies FOR INSERT
|
|
WITH CHECK (auth.uid() IS NOT NULL);
|
|
|
|
CREATE POLICY "Authors and admins can update replies"
|
|
ON public.forum_replies FOR UPDATE
|
|
USING (
|
|
author_id = auth.uid() OR
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Authors and admins can delete replies"
|
|
ON public.forum_replies FOR DELETE
|
|
USING (
|
|
author_id = auth.uid() OR
|
|
EXISTS (
|
|
SELECT 1 FROM public.admin_roles
|
|
WHERE user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Forum Reactions
|
|
ALTER TABLE public.forum_reactions ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Anyone can view reactions"
|
|
ON public.forum_reactions FOR SELECT
|
|
USING (true);
|
|
|
|
CREATE POLICY "Authenticated users can manage own reactions"
|
|
ON public.forum_reactions FOR ALL
|
|
USING (user_id = auth.uid());
|
|
|
|
-- Insert Default Categories
|
|
INSERT INTO public.forum_categories (name, description, icon, color, display_order) VALUES
|
|
('Treasury', 'Discussions about treasury proposals and funding', '💰', '#10B981', 1),
|
|
('Technical', 'Technical discussions and protocol upgrades', '⚙️', '#3B82F6', 2),
|
|
('Governance', 'Governance proposals and voting discussions', '🗳️', '#8B5CF6', 3),
|
|
('Community', 'Community initiatives and general discussions', '👥', '#F59E0B', 4),
|
|
('Support', 'Help and support for using Pezkuwi', '❓', '#6B7280', 5)
|
|
ON CONFLICT (name) DO NOTHING;
|
|
|
|
-- Function to update last_activity
|
|
CREATE OR REPLACE FUNCTION update_discussion_activity()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
UPDATE public.forum_discussions
|
|
SET
|
|
last_activity_at = NOW(),
|
|
replies_count = replies_count + 1
|
|
WHERE id = NEW.discussion_id;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER on_reply_created
|
|
AFTER INSERT ON public.forum_replies
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_discussion_activity();
|