trretretret's picture
Initial commit: Add research assistant application
b708f13
"use client";
import * as React from "react";
import { SearchX, FileStack } from "lucide-react";
import { PaperCard, PaperCardProps } from "@/components/molecules/PaperCard";
import { Icon } from "@/components/atoms/Icon";
import { Spinner } from "@/components/atoms/Spinner";
import { cn } from "@/lib/utils";
interface PaperGridProps {
papers: PaperCardProps[];
isLoading?: boolean;
onAddPaper?: (paper: PaperCardProps) => void;
className?: string;
}
/**
* PaperGrid Organism
* Responsively displays a collection of research papers.
* Handles loading, empty, and populated states for the RM Research Assistant.
*/
export function PaperGrid({
papers,
isLoading,
onAddPaper,
className
}: PaperGridProps) {
// 1. Loading State (Skeleton Placeholder logic)
if (isLoading) {
return (
<div className={cn("grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", className)}>
{[...Array(6)].map((_, i) => (
<div
key={i}
className="h-[220px] animate-pulse rounded-lg border bg-muted/20"
/>
))}
<div className="col-span-full flex justify-center py-12">
<Spinner size={32} className="text-primary/40" />
</div>
</div>
);
}
// 2. Empty State (No Results)
if (papers.length === 0) {
return (
<div className={cn(
"flex flex-col items-center justify-center rounded-xl border-2 border-dashed bg-muted/5 py-24 text-center",
className
)}>
<div className="rounded-full bg-muted p-4 mb-4">
<Icon icon={SearchX} size={32} className="text-muted-foreground" />
</div>
<h3 className="text-lg font-semibold text-foreground">No papers found</h3>
<p className="max-w-[300px] text-sm text-muted-foreground mt-1">
Try adjusting your search query or filters to find what you're looking for.
</p>
</div>
);
}
// 3. Populated Grid State
return (
<div className={cn(
"grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3",
className
)}>
{papers.map((paper, index) => (
<PaperCard
key={paper.doi || `${paper.title}-${index}`}
{...paper}
onAdd={() => onAddPaper?.(paper)}
className="h-full" // Ensures cards in the same row have equal height
/>
))}
</div>
);
}