fix(ux): resolve tickets #59 #66 #67 — project feedback and demand summary

#66: Project detail "Open Demands" summary incorrectly counted COMPLETED
demands as open. Fix: add `status !== "COMPLETED"` to the activeDemands
filter in /projects/[id]/page.tsx.

#59/#67: Project creation and edit had two bugs:
1. Both invalidated `project.list` but the page queries `project.listWithCosts`
   — the list never refreshed after a save.
2. Success toasts were either absent (ProjectModal) or mounted inside the
   wizard component that unmounts before the toast finishes.
Fix: correct invalidation key to listWithCosts; add optional onSuccess prop
to both ProjectWizard and ProjectModal; ProjectsClient wires onSuccess to a
persistent SuccessToast rendered outside the modals.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-03 16:05:29 +02:00
parent b7bb6d05af
commit 2da29c8191
4 changed files with 39 additions and 8 deletions
@@ -95,9 +95,10 @@ function projectToForm(project: Project): FormState {
interface ProjectModalProps {
project?: Project | null;
onClose: () => void;
onSuccess?: (name: string) => void;
}
export function ProjectModal({ project, onClose }: ProjectModalProps) {
export function ProjectModal({ project, onClose, onSuccess }: ProjectModalProps) {
const isEdit = !!project;
const utils = trpc.useUtils();
@@ -116,7 +117,8 @@ export function ProjectModal({ project, onClose }: ProjectModalProps) {
// @ts-ignore TS2589: tRPC infers union type too deeply for CreateProjectSchema with .refine()
const createMutation = trpc.project.create.useMutation({
onSuccess: async () => {
await utils.project.list.invalidate();
await utils.project.listWithCosts.invalidate();
onSuccess?.(form.name.trim());
onClose();
},
onError: (err) => {
@@ -126,7 +128,8 @@ export function ProjectModal({ project, onClose }: ProjectModalProps) {
const updateMutation = trpc.project.update.useMutation({
onSuccess: async () => {
await utils.project.list.invalidate();
await utils.project.listWithCosts.invalidate();
onSuccess?.(form.name.trim());
onClose();
},
onError: (err) => {