From 0fecd426f450aa93a5615888d4434491d3f87a4a Mon Sep 17 00:00:00 2001 From: Jamie Brunton Date: Sat, 8 Aug 2026 15:40:08 +0100 Subject: [PATCH] feat(dashboard): close legacy parity gaps --- .../conversations/conversation-api.ts | 17 ++++++ .../conversations/conversation-detail.tsx | 12 +++- .../conversations/conversation-queries.ts | 13 +++++ .../conversations/conversation-route.tsx | 24 ++++++-- .../conversations/conversations-page.tsx | 36 ++++++++---- .../conversations/processed-user-lookup.tsx | 28 ++++++++++ .../src/features/media/media-page.tsx | 16 ++++-- .../src/features/media/media-route.tsx | 32 +++++++++++ .../features/operations/live-console-model.ts | 5 +- .../src/features/operations/operations-api.ts | 18 +++++- .../features/operations/operations-page.tsx | 22 +++++++- .../features/operations/operations-queries.ts | 14 ++++- .../src/features/overview/overview-page.tsx | 2 + .../src/features/overview/recent-messages.tsx | 32 +++++++++++ packages/api-contracts/src/messages.ts | 15 +++++ .../api-contracts/tests/contracts.test.ts | 8 +++ tests/dashboard/app.test.tsx | 7 +++ tests/dashboard/conversations.test.tsx | 21 +++++++ tests/dashboard/live-console-model.test.ts | 16 ++++++ .../dashboard/performance-operations.test.tsx | 32 ++++++++++- tests/dashboard/route-filters.test.tsx | 55 +++++++++++++++++++ 21 files changed, 397 insertions(+), 28 deletions(-) create mode 100644 apps/dashboard/src/features/conversations/processed-user-lookup.tsx create mode 100644 apps/dashboard/src/features/media/media-route.tsx create mode 100644 apps/dashboard/src/features/overview/recent-messages.tsx create mode 100644 tests/dashboard/route-filters.test.tsx diff --git a/apps/dashboard/src/features/conversations/conversation-api.ts b/apps/dashboard/src/features/conversations/conversation-api.ts index 44ed190..d81379b 100644 --- a/apps/dashboard/src/features/conversations/conversation-api.ts +++ b/apps/dashboard/src/features/conversations/conversation-api.ts @@ -3,6 +3,7 @@ import { ConversationsResponseSchema, ConversationDetailResponseSchema, ErrorResponseSchema, + ProcessedPostsResponseSchema, SendReplyRequestSchema, StartConversationRequestSchema, StartConversationResponseSchema, @@ -10,6 +11,7 @@ import { SuggestedReplyResponseSchema, type ActiveChat, type ConversationDetailResponse, + type ProcessedPost, type SuccessResponse, } from '../../../../../packages/api-contracts/src/index.js'; @@ -30,6 +32,8 @@ export interface ConversationApi { list(): Promise; detail(id: string): Promise; suggestReply(id: string): Promise; + suggestMediaAsk(id: string): Promise; + processedPosts(username: string): Promise; sendReply(id: string, message: string): Promise; startConversation(username: string, message: string): Promise; } @@ -53,6 +57,19 @@ export function createConversationApi(fetchImplementation?: typeof fetch): Conve ); return response.suggestedReply; }, + async suggestMediaAsk(id) { + const response = await parseResponse( + await request(`${conversationPath(id)}/suggest-media-ask`, { method: 'POST' }), + SuggestedReplyResponseSchema, + ); + return response.suggestedReply; + }, + async processedPosts(username) { + return parseResponse( + await request(`/api/posts/by-author/${encodeURIComponent(username.trim().replace(/^u\//i, ''))}`), + ProcessedPostsResponseSchema, + ); + }, async sendReply(id, message) { const body = SendReplyRequestSchema.parse({ message: message.trim() }); return parseResponse( diff --git a/apps/dashboard/src/features/conversations/conversation-detail.tsx b/apps/dashboard/src/features/conversations/conversation-detail.tsx index d29e2bd..d573153 100644 --- a/apps/dashboard/src/features/conversations/conversation-detail.tsx +++ b/apps/dashboard/src/features/conversations/conversation-detail.tsx @@ -1,6 +1,6 @@ import { useCallback, useRef, useState } from 'react'; import type { ConversationDetailResponse } from '../../../../../packages/api-contracts/src/index.js'; -import { useConversationDetailQuery, useSendReplyMutation, useSuggestReplyMutation } from './conversation-queries.js'; +import { useConversationDetailQuery, useSendReplyMutation, useSuggestMediaAskMutation, useSuggestReplyMutation } from './conversation-queries.js'; import { SendConfirmationDialog } from './send-confirmation-dialog.js'; interface ConversationDetailProps { @@ -38,6 +38,7 @@ function ConversationComposer({ conversation }: { conversation: ConversationDeta const [wasSent, setWasSent] = useState(false); const sendButtonRef = useRef(null); const suggestionMutation = useSuggestReplyMutation(conversation.roomId ?? conversation.username); + const mediaAskMutation = useSuggestMediaAskMutation(conversation.roomId ?? conversation.username); const sendMutation = useSendReplyMutation(conversation.roomId ?? conversation.username); const canSend = draft.trim().length > 0 && !sendMutation.isPending; @@ -51,6 +52,11 @@ function ConversationComposer({ conversation }: { conversation: ConversationDeta suggestionMutation.mutate(undefined, { onSuccess: (suggestion) => setDraft(suggestion) }); } + function suggestMediaAsk() { + setWasSent(false); + mediaAskMutation.mutate(undefined, { onSuccess: (suggestion) => setDraft(suggestion) }); + } + function sendReply() { if (!canSend) return; sendMutation.mutate(draft, { @@ -69,6 +75,9 @@ function ConversationComposer({ conversation }: { conversation: ConversationDeta +