Spaces:
Paused
Paused
| import { useEffect, useState } from "react"; | |
| import { getQueryHistory } from "../api/client"; | |
| import type { QueryHistoryItem } from "../types"; | |
| interface Props { | |
| onSelect: (item: QueryHistoryItem) => void; | |
| } | |
| function relativeTime(dateStr: string): string { | |
| const diff = Date.now() - new Date(dateStr).getTime(); | |
| const mins = Math.floor(diff / 60_000); | |
| if (mins < 1) return "just now"; | |
| if (mins < 60) return `${mins}m ago`; | |
| const hours = Math.floor(mins / 60); | |
| if (hours < 24) return `${hours}h ago`; | |
| return `${Math.floor(hours / 24)}d ago`; | |
| } | |
| export default function QueryHistory({ onSelect }: Props) { | |
| const [history, setHistory] = useState<QueryHistoryItem[]>([]); | |
| const [loading, setLoading] = useState(true); | |
| useEffect(() => { | |
| getQueryHistory(10) | |
| .then(setHistory) | |
| .catch(console.error) | |
| .finally(() => setLoading(false)); | |
| }, []); | |
| if (loading) { | |
| return ( | |
| <div className="space-y-1.5 px-1" aria-busy="true" aria-label="Loading history"> | |
| {Array.from({ length: 4 }).map((_, i) => ( | |
| <div key={i} className="h-8 shimmer-dark rounded-md" style={{ opacity: 1 - i * 0.15 }} /> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| if (!history.length) { | |
| return ( | |
| <div className="px-2 py-4 text-center"> | |
| <svg className="w-5 h-5 text-slate-600 mx-auto mb-1.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}> | |
| <path strokeLinecap="round" strokeLinejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| <p className="text-xs text-slate-500">No queries yet</p> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="space-y-0.5"> | |
| {history.map((item) => ( | |
| <button | |
| key={item.id} | |
| onClick={() => onSelect(item)} | |
| title={item.query_text} | |
| className="w-full text-left px-2 py-2 rounded-md transition-colors group hover:bg-slate-800" | |
| > | |
| <p className="text-xs text-slate-400 group-hover:text-slate-200 truncate leading-snug transition-colors"> | |
| {item.query_text} | |
| </p> | |
| <p className="text-[10px] text-slate-600 group-hover:text-slate-500 mt-0.5 transition-colors"> | |
| {relativeTime(item.created_at)} | |
| </p> | |
| </button> | |
| ))} | |
| </div> | |
| ); | |
| } | |