import type { HttpResponse } from "@yaakapp-internal/models"; import { deleteModel } from "@yaakapp-internal/models"; import { HStack, Icon } from "@yaakapp-internal/ui"; import { differenceInHours, differenceInMinutes, format, isToday, isYesterday, } from "date-fns"; import { useDeleteHttpResponses } from "../hooks/useDeleteHttpResponses"; import { useKeyValue } from "../hooks/useKeyValue"; import { DismissibleBanner } from "./core/DismissibleBanner"; import { Dropdown, type DropdownItem } from "./core/Dropdown"; import { formatMillis } from "./core/HttpResponseDurationTag"; import { HttpStatusTag } from "./core/HttpStatusTag"; import { IconButton } from "./core/IconButton"; import { SizeTag } from "./core/SizeTag"; interface Props { responses: HttpResponse[]; activeResponse: HttpResponse; onPinnedResponseId: (id: string) => void; className?: string; } export const RecentHttpResponsesDropdown = function ResponsePane({ activeResponse, responses, onPinnedResponseId, }: Props) { const deleteAllResponses = useDeleteHttpResponses(activeResponse?.requestId); const movedActionsBannerId = "response-actions-moved-to-response-menu-2026-07-02-v2"; const { value: dismissedMovedActions } = useKeyValue({ namespace: "global", key: ["dismiss-banner", movedActionsBannerId], fallback: false, }); const latestResponseId = responses[0]?.id ?? "n/a"; const responseHistoryItems: DropdownItem[] = []; let lastHistoryGroup: string | null = null; let hasRecentResponses = false; let hasShownRecentEmptyState = false; const now = new Date(); for (const r of responses) { const createdAt = `${r.createdAt}Z`; const createdAtDate = new Date(createdAt); const minutesAgo = differenceInMinutes(now, createdAtDate); const hoursAgo = differenceInHours(now, createdAtDate); let historyGroup = format(createdAtDate, "MMM d, yyyy"); if (minutesAgo < 5) historyGroup = "Just now"; else if (minutesAgo < 15) historyGroup = "5 minutes ago"; else if (minutesAgo < 60) historyGroup = "15 minutes ago"; else if (hoursAgo < 3) historyGroup = "1 hour ago"; else if (hoursAgo < 6) historyGroup = "3 hours ago"; else if (isToday(createdAtDate)) historyGroup = "Today"; else if (isYesterday(createdAtDate)) historyGroup = "Yesterday"; else if (createdAtDate.getFullYear() === now.getFullYear()) historyGroup = format(createdAtDate, "MMM d"); const absoluteTime = format(createdAt, "MMM d, yyyy, h:mm:ss a O"); if (historyGroup === "Just now") { hasRecentResponses = true; } else if (!hasRecentResponses && !hasShownRecentEmptyState) { responseHistoryItems.push({ type: "content", label: No recent requests, }); hasShownRecentEmptyState = true; } if (historyGroup !== "Just now" && historyGroup !== lastHistoryGroup) { responseHistoryItems.push({ type: "separator", label: {historyGroup}, }); lastHistoryGroup = historyGroup; } responseHistoryItems.push({ label: ( {r.elapsed >= 0 ? formatMillis(r.elapsed) : "n/a"} ), leftSlot: activeResponse?.id === r.id ? : , onSelect: () => onPinnedResponseId(r.id), }); } if (!hasRecentResponses && !hasShownRecentEmptyState) { responseHistoryItems.push({ type: "content", label: No recent requests, }); } return ( , onSelect: () => deleteModel(activeResponse), }, { label: "Delete all", leftSlot: , onSelect: deleteAllResponses.mutate, disabled: responses.length === 0, }, { label: "Unpin Response", onSelect: () => onPinnedResponseId(activeResponse.id), leftSlot: , hidden: latestResponseId === activeResponse.id, disabled: responses.length === 0, }, { type: "content", hidden: dismissedMovedActions === true, label: (

Copy and save actions moved to the Response tab menu.

), }, { type: "separator", label: "Recent", }, ...responseHistoryItems, ]} >
); };