From f47426d4f2d1847ee96366eae77d7d11f579cbd3 Mon Sep 17 00:00:00 2001 From: dextmorgn <64375473+dextmorgn@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:21:08 +0200 Subject: [PATCH] fix(frontend): type the chat-service API boundary Same treatment as the other *-service files. getById turned out to return a different shape than the list endpoints (messages inlined), now modeled as ChatDetail extends Chat rather than folded into one loose type. Also types chat-history.tsx's props (deleteChatMutation as the actual UseMutationResult, confirm against the exported ConfirmProps, setView/ handleCreateNewChat/switchToChat against their real signatures) since they were all any purely because nothing upstream forced them to be. --- flowsint-app/src/api/chat-service.ts | 11 +++++----- .../src/components/chat/chat-history.tsx | 20 ++++++++++--------- .../src/components/use-confirm-dialog.tsx | 2 +- flowsint-app/src/types/chat.ts | 5 +++++ 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/flowsint-app/src/api/chat-service.ts b/flowsint-app/src/api/chat-service.ts index 449411e6..822fe35f 100644 --- a/flowsint-app/src/api/chat-service.ts +++ b/flowsint-app/src/api/chat-service.ts @@ -1,28 +1,29 @@ import { fetchWithAuth } from './api' +import type { Chat, ChatDetail } from '@/types/chat' export const chatCRUDService = { - get: async (): Promise => { + get: async (): Promise => { return fetchWithAuth('/api/chats', { method: 'GET' }) }, - getByInvestigationId: async (investigationId: string): Promise => { + getByInvestigationId: async (investigationId: string): Promise => { return fetchWithAuth(`/api/chats/investigation/${investigationId}`, { method: 'GET' }) }, - getById: async (chatId: string): Promise => { + getById: async (chatId: string): Promise => { return fetchWithAuth(`/api/chats/${chatId}`, { method: 'GET' }) }, - create: async (body: BodyInit): Promise => { + create: async (body: BodyInit): Promise => { return fetchWithAuth(`/api/chats/create`, { method: 'POST', body: body }) }, - delete: async (chatId: string): Promise => { + delete: async (chatId: string): Promise => { return fetchWithAuth(`/api/chats/${chatId}`, { method: 'DELETE' }) diff --git a/flowsint-app/src/components/chat/chat-history.tsx b/flowsint-app/src/components/chat/chat-history.tsx index c4a00841..a8186ac4 100644 --- a/flowsint-app/src/components/chat/chat-history.tsx +++ b/flowsint-app/src/components/chat/chat-history.tsx @@ -1,22 +1,24 @@ import { chatCRUDService } from '@/api/chat-service' -import { useQuery } from '@tanstack/react-query' +import { useQuery, type UseMutationResult } from '@tanstack/react-query' import { SkeletonList } from '../shared/skeleton-list' import { Button } from '../ui/button' import { ArrowLeft, Trash, Sparkles } from 'lucide-react' import { Chat } from '@/types' -import { useCallback } from 'react' +import { useCallback, type Dispatch, type SetStateAction } from 'react' import { formatDistanceToNow } from 'date-fns' -import { useConfirm } from '../use-confirm-dialog' +import { useConfirm, type ConfirmProps } from '../use-confirm-dialog' import { useChatState } from '@/stores/use-chat-store' +type DeleteChatMutation = UseMutationResult + const ChatHistory = ({ setView, deleteChatMutation, handleCreateNewChat }: { - setView: any - deleteChatMutation: any - handleCreateNewChat: any + setView: Dispatch> + deleteChatMutation: DeleteChatMutation + handleCreateNewChat: () => void }) => { const { confirm } = useConfirm() const setCurrentChatId = useChatState((s) => s.setCurrentChatId) @@ -98,9 +100,9 @@ const ChatItem = ({ switchToChat }: { chat: Chat - confirm: any - deleteChatMutation: any - switchToChat: any + confirm: (props: ConfirmProps) => Promise + deleteChatMutation: DeleteChatMutation + switchToChat: (chatId: string) => void }) => { const handleDeleteChat = useCallback( async (e: { stopPropagation: () => void }) => { diff --git a/flowsint-app/src/components/use-confirm-dialog.tsx b/flowsint-app/src/components/use-confirm-dialog.tsx index f257f2d1..b73243f0 100644 --- a/flowsint-app/src/components/use-confirm-dialog.tsx +++ b/flowsint-app/src/components/use-confirm-dialog.tsx @@ -23,7 +23,7 @@ import React, { const defaultFunction = (): Promise => Promise.resolve(true) // Define the props that the ConfirmDialog will use -interface ConfirmProps { +export interface ConfirmProps { title: string message: string } diff --git a/flowsint-app/src/types/chat.ts b/flowsint-app/src/types/chat.ts index 841c3a4f..8577191d 100644 --- a/flowsint-app/src/types/chat.ts +++ b/flowsint-app/src/types/chat.ts @@ -36,6 +36,11 @@ export interface Chat { last_updated_at: string } +// getById returns the chat's messages inline, unlike the list endpoints. +export interface ChatDetail extends Chat { + messages: ChatMessage[] +} + export function toUIMessage(msg: ChatMessage): UIMessage { return { id: msg.id,