Sprint 3.1 — Default colors → semantic (~15 files, ~99 replacements): - lime-500 → success, red-500 → destructive, cyan-500 → primary Sprint 3.2 — Hardcoded colors → semantic (~13 files, ~99 replacements): - text-white → text-foreground, bg-black → bg-background, bg-white → bg-card Sprint 3.3 — Legacy kodo-* → semantic (~27 files, ~122 replacements): - bg-kodo-ink → bg-card, bg-kodo-void → bg-background, text-kodo-steel → text-muted-foreground - Preserved kodo-cyan/magenta/lime/gold palette accents and gradients Sprint 3.4 — Arbitrary values → Tailwind scale (5 replacements): - min-h-[600px] → min-h-layout-page, min-h-[400px] → min-h-layout-page-sm - left-[50%] → left-1/2, min-h-[80px] → min-h-20, min-h-[40px] → min-h-10 Sprint 3.5 — Border-radius standardization (4 replacements): - Modal/dialog skeletons: rounded-lg → rounded-xl (convention) Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import React from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card } from '@/components/ui/card';
|
|
import { Check, Heart, UserPlus, MessageSquare } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
import type { Notification } from '@/types';
|
|
|
|
interface NotificationsViewItemProps {
|
|
notification: Notification;
|
|
onRead: (id: string) => void;
|
|
}
|
|
|
|
export function NotificationsViewItem({
|
|
notification,
|
|
onRead,
|
|
}: NotificationsViewItemProps) {
|
|
const icon =
|
|
notification.type === 'like' ? (
|
|
<Heart className="w-4 h-4" />
|
|
) : notification.type === 'follow' ? (
|
|
<UserPlus className="w-4 h-4" />
|
|
) : (
|
|
<MessageSquare className="w-4 h-4" />
|
|
);
|
|
const iconCn =
|
|
notification.type === 'like'
|
|
? 'bg-destructive/10 text-destructive'
|
|
: notification.type === 'follow'
|
|
? 'bg-success/10 text-success'
|
|
: 'bg-primary/10 text-primary';
|
|
|
|
return (
|
|
<Card
|
|
variant="glass"
|
|
className={cn(
|
|
'p-4 flex gap-4 transition-all hover:bg-white/5',
|
|
!notification.read &&
|
|
'border-l-2 border-l-primary bg-primary/5',
|
|
)}
|
|
>
|
|
<div className={cn('p-2 rounded-full h-fit', iconCn)}>{icon}</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm text-white mb-1">{notification.message}</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
{new Date(notification.timestamp).toLocaleString()}
|
|
</p>
|
|
</div>
|
|
{!notification.read && (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-8 w-8 p-0 rounded-full hover:bg-primary/20 text-primary"
|
|
onClick={() => onRead(notification.id)}
|
|
>
|
|
<Check className="w-4 h-4" />
|
|
</Button>
|
|
)}
|
|
</Card>
|
|
);
|
|
}
|