feat: F025 button & action logic audit — global toast, confirm dialog, wired mutations
- Add ToastProvider (global MUI Snackbar stack) + toastStore (Zustand) - Add ConfirmDialog reusable component for destructive actions - Wire toast feedback to all async mutations: review status, AI output status, match approval, shortlist add/remove/title/finalize, signal review actions - Fix dead UserMenu buttons (Profil, Einstellungen) — show info toast - Migrate local Snackbar instances in AddToShortlistDialog and FutureSignalDetailPanel to global toast store Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
AIMonitoringEmptyState,
|
||||
} from '../../components/ai-monitoring'
|
||||
import { useAIOutputs, useUpdateAIOutputReviewStatus } from '../../hooks/useAIMonitoring'
|
||||
import { useToastStore } from '../../stores/toastStore'
|
||||
import type { AIOutput, AIOutputType } from '../../domain/aiOutput'
|
||||
import type { ReviewStatus } from '../../domain/enums'
|
||||
|
||||
@@ -58,6 +59,7 @@ export default function AIMonitoring() {
|
||||
const [filters, setFilters] = useState<Filters>({ type: '', reviewStatus: '', hasError: null })
|
||||
const [selectedOutput, setSelectedOutput] = useState<AIOutput | null>(null)
|
||||
|
||||
const showToast = useToastStore((s) => s.showToast)
|
||||
const { data: allOutputs = [], isLoading } = useAIOutputs()
|
||||
const updateStatus = useUpdateAIOutputReviewStatus()
|
||||
|
||||
@@ -66,11 +68,25 @@ export default function AIMonitoring() {
|
||||
const failedCount = allOutputs.filter(o => !!o.error).length
|
||||
const pendingCount = allOutputs.filter(o => o.reviewStatus === 'UNREVIEWED' || o.reviewStatus === 'FLAGGED').length
|
||||
|
||||
const STATUS_TOAST: Record<ReviewStatus, string> = {
|
||||
UNREVIEWED: 'Status zurückgesetzt.',
|
||||
IN_REVIEW: 'Output zur Prüfung markiert.',
|
||||
APPROVED: 'Output genehmigt.',
|
||||
REJECTED: 'Output abgelehnt.',
|
||||
FLAGGED: 'Output markiert.',
|
||||
}
|
||||
|
||||
const handleUpdateStatus = (status: ReviewStatus) => {
|
||||
if (!selectedOutput) return
|
||||
updateStatus.mutate(
|
||||
{ id: selectedOutput.id, status },
|
||||
{ onSuccess: (res) => setSelectedOutput(res.data) }
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
setSelectedOutput(res.data)
|
||||
showToast(STATUS_TOAST[status] ?? 'Status aktualisiert.')
|
||||
},
|
||||
onError: () => showToast('Statusänderung fehlgeschlagen.', 'error'),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '../../components/review'
|
||||
import { useReviewQueue, useUpdateReviewStatus, useAddReviewNote } from '../../hooks/useReviewQueue'
|
||||
import { useSessionStore } from '../../stores/sessionStore'
|
||||
import { useToastStore } from '../../stores/toastStore'
|
||||
import type { ReviewTask, ReviewTaskStatus } from '../../domain/review'
|
||||
import type { ReviewFilters } from '../../provider/IReviewProvider'
|
||||
|
||||
@@ -24,6 +25,7 @@ function filterTasks(tasks: ReviewTask[], filters: ReviewFilters): ReviewTask[]
|
||||
|
||||
export default function ReviewQueue() {
|
||||
const { currentUser } = useSessionStore()
|
||||
const showToast = useToastStore((s) => s.showToast)
|
||||
const userRole = currentUser?.role ?? 'REVIEWER'
|
||||
|
||||
const [filters, setFilters] = useState<ReviewFilters>({})
|
||||
@@ -40,6 +42,15 @@ export default function ReviewQueue() {
|
||||
const escalatedCount = allTasks.filter(t => t.status === 'ESCALATED').length
|
||||
const criticalCount = allTasks.filter(t => t.priority === 'CRITICAL' && (t.status === 'PENDING' || t.status === 'IN_REVIEW')).length
|
||||
|
||||
const STATUS_TOAST: Record<ReviewTaskStatus, string> = {
|
||||
PENDING: 'Status auf "Ausstehend" gesetzt.',
|
||||
IN_REVIEW: 'Aufgabe zur Prüfung übernommen.',
|
||||
APPROVED: 'Aufgabe genehmigt.',
|
||||
REJECTED: 'Aufgabe abgelehnt.',
|
||||
ESCALATED: 'Aufgabe eskaliert.',
|
||||
NEEDS_MORE_DATA: 'Weitere Daten angefordert.',
|
||||
}
|
||||
|
||||
const handleAction = (status: ReviewTaskStatus) => {
|
||||
if (!selectedTask) return
|
||||
updateStatus.mutate(
|
||||
@@ -47,7 +58,9 @@ export default function ReviewQueue() {
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
setSelectedTask(res.data)
|
||||
showToast(STATUS_TOAST[status] ?? 'Status aktualisiert.')
|
||||
},
|
||||
onError: () => showToast('Statusänderung fehlgeschlagen.', 'error'),
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -59,7 +72,9 @@ export default function ReviewQueue() {
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
setSelectedTask(res.data)
|
||||
showToast('Notiz hinzugefügt.')
|
||||
},
|
||||
onError: () => showToast('Notiz konnte nicht gespeichert werden.', 'error'),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user