mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-06-27 18:50:41 +00:00
# What does this PR do? * Add responses list and detail views * Refactored components to be shared as much as possible between chat completions and responses ## Test Plan <img width="2014" alt="image" src="https://github.com/user-attachments/assets/6dee12ea-8876-4351-a6eb-2338058466ef" /> <img width="2021" alt="image" src="https://github.com/user-attachments/assets/6c7c71b8-25b7-4199-9c57-6960be5580c8" /> added tests
141 lines
3.4 KiB
TypeScript
141 lines
3.4 KiB
TypeScript
import React from "react";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
|
|
export function DetailLoadingView({ title }: { title: string }) {
|
|
return (
|
|
<>
|
|
<Skeleton className="h-8 w-3/4 mb-6" /> {/* Title Skeleton */}
|
|
<div className="flex flex-col md:flex-row gap-6">
|
|
<div className="flex-grow md:w-2/3 space-y-6">
|
|
{[...Array(2)].map((_, i) => (
|
|
<Card key={`main-skeleton-card-${i}`}>
|
|
<CardHeader>
|
|
<CardTitle>
|
|
<Skeleton className="h-6 w-1/2" />
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-2">
|
|
<Skeleton className="h-4 w-full" />
|
|
<Skeleton className="h-4 w-full" />
|
|
<Skeleton className="h-4 w-3/4" />
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
<div className="md:w-1/3">
|
|
<div className="p-4 border rounded-lg shadow-sm bg-white space-y-3">
|
|
<Skeleton className="h-6 w-1/3 mb-3" />{" "}
|
|
{/* Properties Title Skeleton */}
|
|
{[...Array(5)].map((_, i) => (
|
|
<div key={`prop-skeleton-${i}`} className="space-y-1">
|
|
<Skeleton className="h-4 w-1/4" />
|
|
<Skeleton className="h-4 w-1/2" />
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function DetailErrorView({
|
|
title,
|
|
id,
|
|
error,
|
|
}: {
|
|
title: string;
|
|
id: string;
|
|
error: Error;
|
|
}) {
|
|
return (
|
|
<>
|
|
<h1 className="text-2xl font-bold mb-6">{title}</h1>
|
|
<p>
|
|
Error loading details for ID {id}: {error.message}
|
|
</p>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function DetailNotFoundView({
|
|
title,
|
|
id,
|
|
}: {
|
|
title: string;
|
|
id: string;
|
|
}) {
|
|
return (
|
|
<>
|
|
<h1 className="text-2xl font-bold mb-6">{title}</h1>
|
|
<p>No details found for ID: {id}.</p>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export interface PropertyItemProps {
|
|
label: string;
|
|
value: React.ReactNode;
|
|
className?: string;
|
|
hasBorder?: boolean;
|
|
}
|
|
|
|
export function PropertyItem({
|
|
label,
|
|
value,
|
|
className = "",
|
|
hasBorder = false,
|
|
}: PropertyItemProps) {
|
|
return (
|
|
<li
|
|
className={`${hasBorder ? "pt-1 mt-1 border-t border-gray-200" : ""} ${className}`}
|
|
>
|
|
<strong>{label}:</strong>{" "}
|
|
{typeof value === "string" || typeof value === "number" ? (
|
|
<span className="text-gray-900 font-medium">{value}</span>
|
|
) : (
|
|
value
|
|
)}
|
|
</li>
|
|
);
|
|
}
|
|
|
|
export interface PropertiesCardProps {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function PropertiesCard({ children }: PropertiesCardProps) {
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Properties</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ul className="space-y-2 text-sm text-gray-600">{children}</ul>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
export interface DetailLayoutProps {
|
|
title: string;
|
|
mainContent: React.ReactNode;
|
|
sidebar: React.ReactNode;
|
|
}
|
|
|
|
export function DetailLayout({
|
|
title,
|
|
mainContent,
|
|
sidebar,
|
|
}: DetailLayoutProps) {
|
|
return (
|
|
<>
|
|
<h1 className="text-2xl font-bold mb-6">{title}</h1>
|
|
<div className="flex flex-col md:flex-row gap-6">
|
|
<div className="flex-grow md:w-2/3 space-y-6">{mainContent}</div>
|
|
<div className="md:w-1/3">{sidebar}</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|