Files
dumpsterChat/web/src/stores/featureRequest.ts
T
hobokenchicken 5ca5e018ca feat: feature requests board with voting
- [FEATURES] tab next to PINNED in channel header
- Create, vote/unvote, filter by status (open/planned/done/rejected)
- Sort by vote count (most voted first)
- Status selector for moderation
- DB: feature_requests + feature_request_votes tables
- Backend: full CRUD + vote endpoints under /servers/{id}/feature-requests
2026-07-02 13:11:52 -04:00

57 lines
1.9 KiB
TypeScript

import { create } from "zustand";
import api from "../lib/api.ts";
export interface FeatureRequest {
id: string;
server_id: string;
channel_id: string;
author_id: string;
title: string;
description: string;
status: "open" | "planned" | "done" | "rejected";
vote_count: number;
voters: string[];
created_at: string;
updated_at: string;
}
interface FeatureRequestStore {
requestsByServer: Record<string, FeatureRequest[]>;
fetchRequests: (serverId: string) => Promise<void>;
createRequest: (serverId: string, title: string, description: string, channelId?: string) => Promise<void>;
vote: (serverId: string, requestId: string) => Promise<void>;
unvote: (serverId: string, requestId: string) => Promise<void>;
updateStatus: (serverId: string, requestId: string, status: string) => Promise<void>;
}
export const useFeatureRequestStore = create<FeatureRequestStore>((set, get) => ({
requestsByServer: {},
fetchRequests: async (serverId: string) => {
const data = await api.get<FeatureRequest[]>(`/servers/${serverId}/feature-requests`);
set((s) => ({
requestsByServer: { ...s.requestsByServer, [serverId]: data },
}));
},
createRequest: async (serverId, title, description, channelId) => {
await api.post(`/servers/${serverId}/feature-requests`, { title, description, channel_id: channelId });
await get().fetchRequests(serverId);
},
vote: async (serverId, requestId) => {
await api.post(`/servers/${serverId}/feature-requests/${requestId}/vote`);
await get().fetchRequests(serverId);
},
unvote: async (serverId, requestId) => {
await api.delete(`/servers/${serverId}/feature-requests/${requestId}/vote`);
await get().fetchRequests(serverId);
},
updateStatus: async (serverId, requestId, status) => {
await api.patch(`/servers/${serverId}/feature-requests/${requestId}/status`, { status });
await get().fetchRequests(serverId);
},
}));