5ca5e018ca
- [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
57 lines
1.9 KiB
TypeScript
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);
|
|
},
|
|
}));
|