mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 18:19:39 +02:00
Move inactive projects out of active workspace: - bauntown (community website) - maerchenzauber (AI story generation) - memoro (voice memo app) - news (news aggregation) - nutriphi (nutrition tracking) - reader (reading app) - uload (URL shortener) - wisekeep (AI wisdom extraction) Update CLAUDE.md documentation: - Add presi to active projects - Document archived projects section - Update workspace configuration Archived apps can be re-activated by moving back to apps/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
4.5 KiB
PL/PgSQL
132 lines
4.5 KiB
PL/PgSQL
-- Feedback System Migration
|
|
-- Create tables for user feedback with voting functionality
|
|
|
|
-- Main Feedback Table
|
|
CREATE TABLE IF NOT EXISTS user_feedback (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id TEXT NOT NULL,
|
|
|
|
-- Content
|
|
title TEXT,
|
|
feedback_text TEXT NOT NULL,
|
|
category VARCHAR(50) DEFAULT 'feature' CHECK (category IN (
|
|
'bug', -- Bug Report
|
|
'feature', -- Feature Request
|
|
'improvement', -- Verbesserungsvorschlag
|
|
'question', -- Frage
|
|
'other' -- Sonstiges
|
|
)),
|
|
|
|
-- Status & Publishing
|
|
status VARCHAR(50) DEFAULT 'submitted' CHECK (status IN (
|
|
'submitted', -- Neu eingereicht
|
|
'under_review', -- Wird geprüft
|
|
'planned', -- Geplant
|
|
'in_progress', -- In Bearbeitung
|
|
'completed', -- Umgesetzt
|
|
'declined' -- Abgelehnt
|
|
)),
|
|
is_public BOOLEAN DEFAULT FALSE,
|
|
admin_response TEXT,
|
|
|
|
-- Voting
|
|
vote_count INTEGER DEFAULT 0,
|
|
upvote_count INTEGER DEFAULT 0,
|
|
|
|
-- Metadata
|
|
source VARCHAR(50) DEFAULT 'mobile',
|
|
device_info JSONB,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
|
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
|
published_at TIMESTAMPTZ,
|
|
completed_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- User Votes Table
|
|
CREATE TABLE IF NOT EXISTS feedback_votes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
feedback_id UUID NOT NULL REFERENCES user_feedback(id) ON DELETE CASCADE,
|
|
user_id TEXT NOT NULL,
|
|
vote_type VARCHAR(20) DEFAULT 'upvote' CHECK (vote_type IN ('upvote')),
|
|
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
|
UNIQUE(feedback_id, user_id)
|
|
);
|
|
|
|
-- Indices for performance
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_status ON user_feedback(status, is_public);
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_public ON user_feedback(is_public, published_at DESC)
|
|
WHERE is_public = true;
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_votes ON user_feedback(vote_count DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_user ON user_feedback(user_id, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_votes_feedback ON feedback_votes(feedback_id);
|
|
CREATE INDEX IF NOT EXISTS idx_votes_user ON feedback_votes(user_id);
|
|
|
|
-- Enable Row Level Security
|
|
ALTER TABLE user_feedback ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE feedback_votes ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- RLS Policies for user_feedback
|
|
-- Users can view their own feedback
|
|
CREATE POLICY "users_view_own_feedback" ON user_feedback
|
|
FOR SELECT USING (user_id = auth.uid()::text);
|
|
|
|
-- Users can view public feedback
|
|
CREATE POLICY "users_view_public_feedback" ON user_feedback
|
|
FOR SELECT USING (is_public = true);
|
|
|
|
-- Users can create feedback
|
|
CREATE POLICY "users_create_feedback" ON user_feedback
|
|
FOR INSERT WITH CHECK (user_id = auth.uid()::text);
|
|
|
|
-- RLS Policies for feedback_votes
|
|
-- Users can vote on public feedback
|
|
CREATE POLICY "users_vote_on_feedback" ON feedback_votes
|
|
FOR INSERT WITH CHECK (user_id = auth.uid()::text);
|
|
|
|
-- Users can delete their own votes
|
|
CREATE POLICY "users_delete_own_vote" ON feedback_votes
|
|
FOR DELETE USING (user_id = auth.uid()::text);
|
|
|
|
-- Users can view all votes
|
|
CREATE POLICY "users_view_votes" ON feedback_votes
|
|
FOR SELECT USING (true);
|
|
|
|
-- Trigger to update vote count automatically
|
|
CREATE OR REPLACE FUNCTION update_feedback_vote_count()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF TG_OP = 'INSERT' THEN
|
|
UPDATE user_feedback
|
|
SET
|
|
vote_count = vote_count + 1,
|
|
upvote_count = upvote_count + 1
|
|
WHERE id = NEW.feedback_id;
|
|
ELSIF TG_OP = 'DELETE' THEN
|
|
UPDATE user_feedback
|
|
SET
|
|
vote_count = vote_count - 1,
|
|
upvote_count = upvote_count - 1
|
|
WHERE id = OLD.feedback_id;
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER feedback_vote_count_trigger
|
|
AFTER INSERT OR DELETE ON feedback_votes
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_feedback_vote_count();
|
|
|
|
-- Trigger for updated_at timestamp
|
|
CREATE TRIGGER update_feedback_updated_at
|
|
BEFORE UPDATE ON user_feedback
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Comments
|
|
COMMENT ON TABLE user_feedback IS 'User feedback, feature requests, and bug reports';
|
|
COMMENT ON COLUMN user_feedback.is_public IS 'Set to true by admin to make feedback visible to all users';
|
|
COMMENT ON COLUMN user_feedback.status IS 'Current status of the feedback item';
|
|
COMMENT ON COLUMN user_feedback.vote_count IS 'Total number of upvotes (automatically updated by trigger)';
|