cawncade-ai / frontend /src /components /SourceCard.jsx
Nawaz-khan-droid
build: finalize stratos refactor, textarea hardening, and payload limit alignment
acf82bb
Raw
History Blame Contribute Delete
3.13 kB
import React from 'react';
import { ExternalLink, Youtube } from 'lucide-react';
export default function SourceCard({ sources }) {
if (!sources || sources.length === 0) return null;
const getSourceUrl = (source) => {
if (source?.url) return source.url;
if (source?.video_id) return `https://www.youtube.com/watch?v=${source.video_id}`;
return '#';
};
return (
<div className="glass-card space-y-4 p-5">
<h4 className="text-sm font-medium text-slate-400">Sources ({sources.length})</h4>
<div className="max-h-80 space-y-2 overflow-y-auto pr-1">
{sources.map((source, i) => {
const isVideoSource = source?.source_type === 'video';
const sourceUrl = getSourceUrl(source);
const previewText = source?.snippet || source?.transcript || source?.video_transcript || '';
return (
<a
key={i}
href={sourceUrl}
target="_blank"
rel="noopener noreferrer"
className="group block rounded-2xl border border-white/10 bg-white/[0.04] p-4 transition-all duration-200 hover:border-sky-400/25 hover:bg-white/[0.07]"
>
<div className="flex items-start gap-3">
<div className="min-w-0 flex-1">
<p className="truncate text-sm text-slate-100 transition-colors group-hover:text-sky-300">
{source?.title || 'Untitled'}
</p>
<div className="mt-1 flex items-center gap-1.5 truncate text-xs text-slate-500">
{isVideoSource ? (
<span className="inline-flex items-center gap-1.5 rounded-full border border-sky-400/25 bg-sky-500/10 px-2 py-1 text-[11px] font-medium text-sky-300">
<Youtube className="h-3.5 w-3.5 shrink-0 text-sky-400" />
Video Transcript
</span>
) : (
<span>{source?.source_name || sourceUrl}</span>
)}
</div>
</div>
<div className="flex shrink-0 items-center gap-2">
{source?.is_trusted && (
<span className="rounded-full border border-emerald-400/20 bg-emerald-500/10 px-2 py-1 text-[10px] font-medium text-emerald-300">
TRUSTED
</span>
)}
<ExternalLink className="mt-0.5 h-3.5 w-3.5 text-slate-600 transition-colors group-hover:text-sky-300" />
</div>
</div>
{previewText && (
<p className="mt-3 line-clamp-3 text-xs leading-relaxed text-slate-400">{previewText}</p>
)}
{source?.retrieval_tier && (
<div className="mt-3 flex items-center gap-2 text-[10px] text-slate-600">
<span>{source.retrieval_tier}</span>
{source?.channel && <span>{source.channel}</span>}
</div>
)}
</a>
);
})}
</div>
</div>
);
}