first commit
This commit is contained in:
commit
6e354ba041
109 changed files with 12110 additions and 0 deletions
129
frontend/src/components/dashboard/RecentActivities.tsx
Normal file
129
frontend/src/components/dashboard/RecentActivities.tsx
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import { Link } from 'react-router-dom'
|
||||
import { FileText, Zap, PenTool, LayoutGrid, ChevronRight } from 'lucide-react'
|
||||
import type { CreateType } from '../../data/createData'
|
||||
import type { DocumentRecord } from '../../lib/documents'
|
||||
import {
|
||||
formatRelativeTime,
|
||||
getActivityDate,
|
||||
getProjectColor,
|
||||
getProjectIcon,
|
||||
typeColors,
|
||||
typeLabels,
|
||||
} from '../../lib/documentUtils'
|
||||
|
||||
const typeIcons: Record<CreateType, typeof FileText> = {
|
||||
silo: FileText,
|
||||
shed: Zap,
|
||||
sketch: PenTool,
|
||||
stead: LayoutGrid,
|
||||
}
|
||||
|
||||
function getActionLabel(doc: DocumentRecord): string {
|
||||
const created = new Date(doc.createdAt).getTime()
|
||||
const updated = new Date(doc.updatedAt).getTime()
|
||||
if (Math.abs(updated - created) < 5000) {
|
||||
return `Created by ${doc.createdBy}`
|
||||
}
|
||||
return `Updated by ${doc.createdBy}`
|
||||
}
|
||||
|
||||
interface RecentActivitiesProps {
|
||||
documents: DocumentRecord[]
|
||||
loading?: boolean
|
||||
onViewAll?: () => void
|
||||
}
|
||||
|
||||
export default function RecentActivities({
|
||||
documents,
|
||||
loading,
|
||||
onViewAll,
|
||||
}: RecentActivitiesProps) {
|
||||
const items = documents.slice(0, 8)
|
||||
|
||||
return (
|
||||
<div className="rounded-2xl border border-silos-cream-dark bg-white">
|
||||
<div className="flex items-center justify-between border-b border-silos-cream-dark px-5 py-4">
|
||||
<h3 className="font-semibold text-silos-text">Recent Activities</h3>
|
||||
{items.length > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onViewAll}
|
||||
className="text-sm font-medium text-silos-tan hover:text-silos-brown"
|
||||
>
|
||||
View all
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<ul className="divide-y divide-silos-cream-dark">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<li key={i} className="px-5 py-4">
|
||||
<div className="h-10 animate-pulse rounded-lg bg-silos-cream" />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : items.length === 0 ? (
|
||||
<div className="px-5 py-12 text-center text-sm text-silos-muted">
|
||||
No activity yet. Create a Silo, Sketch, Shed, or Stead to get started.
|
||||
</div>
|
||||
) : (
|
||||
<ul className="divide-y divide-silos-cream-dark">
|
||||
{items.map((doc) => {
|
||||
const Icon = typeIcons[doc.type]
|
||||
const color = doc.type === 'stead' ? getProjectColor(doc) : typeColors[doc.type]
|
||||
const initial = doc.createdBy[0]?.toUpperCase() ?? '?'
|
||||
|
||||
return (
|
||||
<li key={doc.id}>
|
||||
<Link
|
||||
to={`/workspace/${doc.type}/${doc.id}`}
|
||||
className="flex w-full items-center gap-4 px-5 py-4 text-left transition-colors hover:bg-silos-cream/40"
|
||||
>
|
||||
<div
|
||||
className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg"
|
||||
style={{ backgroundColor: `${color}22` }}
|
||||
>
|
||||
{doc.type === 'stead' ? (
|
||||
<span className="text-lg">{getProjectIcon(doc)}</span>
|
||||
) : (
|
||||
<Icon className="h-5 w-5" style={{ color }} />
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate font-medium text-silos-text">{doc.title}</p>
|
||||
<p className="mt-0.5 truncate text-sm text-silos-muted">
|
||||
{getActionLabel(doc)} · {typeLabels[doc.type]}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-3">
|
||||
<span className="hidden text-xs text-silos-muted sm:inline">
|
||||
{formatRelativeTime(getActivityDate(doc))}
|
||||
</span>
|
||||
<div
|
||||
className="flex h-7 w-7 items-center justify-center rounded-full text-xs font-semibold text-white"
|
||||
style={{ backgroundColor: color }}
|
||||
>
|
||||
{initial}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{items.length > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onViewAll}
|
||||
className="flex w-full items-center justify-center gap-1 border-t border-silos-cream-dark py-3.5 text-sm font-medium text-silos-brown transition-colors hover:bg-silos-cream/40"
|
||||
>
|
||||
View all recent activities
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue