87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
// app/components/ui/Cards.tsx
|
|
|
|
import { Archive, CheckCircle, Download, ExternalLink } from 'lucide-react';
|
|
import { ReactNode } from 'react';
|
|
|
|
// --- Types ---
|
|
export interface DocumentItem {
|
|
title: string;
|
|
file: string;
|
|
icon: ReactNode;
|
|
size: string;
|
|
}
|
|
|
|
export interface LinkItem {
|
|
title: string;
|
|
url: string;
|
|
}
|
|
|
|
// --- Document Card Component ---
|
|
interface DocumentCardProps {
|
|
doc: DocumentItem;
|
|
isOffline: boolean;
|
|
isCached: boolean;
|
|
}
|
|
|
|
export function DocumentCard({ doc, isOffline, isCached }: DocumentCardProps) {
|
|
return (
|
|
<a
|
|
href={doc.file}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className={`group flex items-center justify-between p-4 rounded-2xl border transition-colors ${isOffline && !isCached
|
|
? 'opacity-50 grayscale cursor-not-allowed pointer-events-none border-transparent bg-eggshell/50'
|
|
: 'bg-white/50 hover:bg-white border-slate-teal/10'
|
|
}`}
|
|
>
|
|
<div className="flex items-center text-slate-teal">
|
|
<div className={`p-2.5 rounded-xl mr-3 text-eggshell shrink-0 transition-colors ${isCached ? 'bg-moss' : 'bg-slate-teal'}`}>
|
|
{doc.icon}
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<span className="font-bold text-sm leading-tight text-ebony">{doc.title}</span>
|
|
<div className="flex flex-wrap items-center gap-2 mt-1">
|
|
<span className="text-[10px] font-bold text-moss bg-moss/10 px-2 py-0.5 rounded uppercase tracking-wider">
|
|
{doc.size}
|
|
</span>
|
|
{isCached && (
|
|
<span className="flex items-center gap-1 text-[10px] font-bold text-moss bg-moss/10 px-2 py-0.5 rounded uppercase tracking-wider">
|
|
<Archive size={10} /> Nedladdad
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{isCached ? (
|
|
<CheckCircle size={18} className="text-moss shrink-0 ml-2" />
|
|
) : (
|
|
<Download size={18} className="text-slate-teal/50 group-hover:text-slate-teal transition-colors shrink-0 ml-2" />
|
|
)}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
// --- External Link Card Component ---
|
|
interface ExternalLinkCardProps {
|
|
link: LinkItem;
|
|
isOffline: boolean;
|
|
}
|
|
|
|
export function ExternalLinkCard({ link, isOffline }: ExternalLinkCardProps) {
|
|
return (
|
|
<a
|
|
href={isOffline ? '#' : link.url}
|
|
target={isOffline ? '_self' : '_blank'}
|
|
rel="noopener noreferrer"
|
|
className={`group flex items-center justify-between p-4 rounded-2xl border transition-colors ${isOffline
|
|
? 'opacity-40 grayscale cursor-not-allowed pointer-events-none bg-eggshell/50 border-transparent'
|
|
: 'bg-white/50 hover:bg-white border-slate-teal/10'
|
|
}`}
|
|
>
|
|
<span className="font-bold text-slate-teal text-sm leading-tight pr-4">{link.title}</span>
|
|
<div className={`rounded-full p-2 transition-colors shrink-0 ${isOffline ? 'bg-transparent' : 'bg-white group-hover:bg-seafoam'}`}>
|
|
<ExternalLink size={16} className={isOffline ? 'text-ebony/40' : 'text-slate-teal group-hover:text-eggshell'} />
|
|
</div>
|
|
</a>
|
|
);
|
|
} |