Files
HOA_Financial_Platform/frontend/src/components/ideas/IdeaModal.tsx
JoeBot 140cd7acb7 feat: add ideation feature with per-tenant toggle
Adds idea submission capability gated by a per-tenant feature flag.
Super admins can enable/disable ideation for specific tenants via the
admin tenant detail drawer. Users see a lightbulb icon in the header
when enabled, opening a modal to submit ideas (title + description).
Ideas are stored in shared schema for cross-tenant backlog querying.

- Database: shared.ideas table (018-ideas.sql migration)
- Backend: Ideas NestJS module (entity, service, controller)
- Admin API: GET /admin/ideas, PUT /admin/ideas/:id/status,
  PUT /admin/organizations/:id/settings
- Frontend: IdeaModal component, lightbulb ActionIcon in header
- Admin UI: Feature Toggles card with ideation Switch in drawer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 17:20:37 -04:00

70 lines
1.9 KiB
TypeScript

import { useState } from 'react';
import { Modal, TextInput, Textarea, Button, Stack } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { useMutation } from '@tanstack/react-query';
import api from '../../services/api';
interface IdeaModalProps {
opened: boolean;
onClose: () => void;
}
export function IdeaModal({ opened, onClose }: IdeaModalProps) {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const submitIdea = useMutation({
mutationFn: async () => {
const { data } = await api.post('/ideas', { title, description });
return data;
},
onSuccess: () => {
notifications.show({ message: 'Idea submitted — thank you!', color: 'green' });
setTitle('');
setDescription('');
onClose();
},
onError: (err: any) => {
notifications.show({
message: err.response?.data?.message || 'Failed to submit idea',
color: 'red',
});
},
});
const handleClose = () => {
setTitle('');
setDescription('');
onClose();
};
return (
<Modal opened={opened} onClose={handleClose} title="Submit an Idea" size="md">
<Stack>
<TextInput
label="Title"
placeholder="Brief summary of your idea"
required
value={title}
onChange={(e) => setTitle(e.currentTarget.value)}
maxLength={255}
/>
<Textarea
label="Description"
placeholder="Describe your idea in more detail (optional)"
minRows={4}
value={description}
onChange={(e) => setDescription(e.currentTarget.value)}
/>
<Button
onClick={() => submitIdea.mutate()}
loading={submitIdea.isPending}
disabled={!title.trim()}
>
Submit Idea
</Button>
</Stack>
</Modal>
);
}