101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { ClubActivityItem } from './types';
|
|
import { EmptyState } from './empty-state';
|
|
|
|
interface ClubActivityListProps {
|
|
activities?: ClubActivityItem[];
|
|
}
|
|
|
|
export function ClubActivityList({ activities = [] }: ClubActivityListProps) {
|
|
const [filter, setFilter] = useState<'all' | 'membership' | 'ride' | 'wall' | 'admin'>('all');
|
|
|
|
const filtered = activities.filter((item) => {
|
|
if (filter === 'all') return true;
|
|
return item.type === filter;
|
|
});
|
|
|
|
return (
|
|
<section className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-5 shadow-lg">
|
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
|
|
<div>
|
|
<h2 className="font-headline text-lg sm:text-xl font-bold text-white tracking-tight">
|
|
Club Activity Stream
|
|
</h2>
|
|
<p className="font-body text-xs sm:text-sm text-slate-400 mt-0.5">
|
|
Recent events, memberships, and administrative actions.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Filter Pills */}
|
|
<div className="flex items-center gap-1 overflow-x-auto p-1 rounded-xl bg-surface-container border border-brand-border/60">
|
|
{(
|
|
[
|
|
{ key: 'all', label: 'All Activity' },
|
|
{ key: 'membership', label: 'Memberships' },
|
|
{ key: 'ride', label: 'Rides' },
|
|
{ key: 'wall', label: 'Wall' },
|
|
{ key: 'admin', label: 'Administrative' },
|
|
] as const
|
|
).map((tab) => (
|
|
<button
|
|
key={tab.key}
|
|
onClick={() => setFilter(tab.key)}
|
|
className={`px-3 py-1 rounded-lg font-mono text-xs transition-colors whitespace-nowrap cursor-pointer ${
|
|
filter === tab.key
|
|
? 'bg-brand-cyan text-obsidian-darkest font-bold shadow-sm'
|
|
: 'text-slate-400 hover:text-white'
|
|
}`}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{filtered.length === 0 ? (
|
|
<EmptyState
|
|
icon="event_note"
|
|
title="No Recent Activity"
|
|
description="No recent activity logged for this filter. Activity stream integration scheduled for future release."
|
|
className="py-6"
|
|
/>
|
|
) : (
|
|
<div className="space-y-2">
|
|
{filtered.map((item) => {
|
|
const iconMap = {
|
|
membership: 'how_to_reg',
|
|
ride: 'add_road',
|
|
wall: 'forum',
|
|
admin: 'tune',
|
|
};
|
|
|
|
return (
|
|
<div
|
|
key={item.id}
|
|
className="flex flex-col sm:flex-row sm:items-center justify-between p-3 rounded-xl bg-surface-container/60 border border-brand-border/60 hover:bg-surface-container-high/80 transition-colors gap-2"
|
|
>
|
|
<div className="flex items-center gap-2.5 min-w-0">
|
|
<div className="w-8 h-8 rounded-lg bg-surface-container-high border border-brand-border/60 flex items-center justify-center text-brand-cyan shrink-0">
|
|
<span className="material-symbols-outlined text-[17px]">
|
|
{iconMap[item.type] || 'circle'}
|
|
</span>
|
|
</div>
|
|
<div className="min-w-0 font-body text-xs text-slate-200">
|
|
<span className="font-semibold text-white">{item.actorName}</span>{' '}
|
|
<span>{item.actionText}</span>
|
|
</div>
|
|
</div>
|
|
<div className="font-mono text-[11px] text-slate-400 shrink-0 self-end sm:self-center">
|
|
{item.timestamp}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|