From 0b7371263c7f020685444c785a1de910cee41e75 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Tue, 29 Sep 2026 18:42:24 +0700 Subject: [PATCH] feat(bell): dedicated Trades tab The bell had All/Social/News/Crews; trade steps were only inside All. Added a 5th tab (Handshake, orange accent) listing offers, counter-offers, outcomes and trade confirmations, with its own count. All still shows them first. --- AGENTS.md | 8 ++++++- src/components/NotificationBell.tsx | 33 +++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ecf6e0e..d108524 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,7 +89,13 @@ session with **no other memory of this project**. So: → "Marketplace Offers". Trade/offer steps also feed **`useTradeNotifications`** → the bell's **All** tab (`TradeNotificationCard`, counted in the badge against `seenAt`) and OS notifications (new **`trades`** category in `notificationPrefs`, - wired in `OsNotificationBridge`). + wired in `OsNotificationBridge`). The bell also has a dedicated **Trades tab** + (5th tab, `Handshake`) listing them, with its own count. **Barter is supported + by design**: trade attestations carry `method` (`cash|lightning|trade|other` — + `MarkSoldDialog` picks it), so a swap feeds reputation exactly like a sale; an + offer with **no `amount`** plus a note is how a swap is proposed (there is + deliberately **no** "For trade" listing type yet — `LISTING_TYPES` is + `selling|wtb`). - **Cashu escrow** (marketplace): time-locked **P2PK** (lock to seller + buyer refund key + locktime) — see **`ESCROW.md`** and `src/lib/cashuEscrow.ts` (unit-tested). Protocol: `cashu_token` on the `31872`; each user advertises a diff --git a/src/components/NotificationBell.tsx b/src/components/NotificationBell.tsx index f07df77..f08861a 100644 --- a/src/components/NotificationBell.tsx +++ b/src/components/NotificationBell.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; import { nip19 } from 'nostr-tools'; -import { Bell, Users, Check, Loader2, EyeOff, Globe, CheckCheck, Heart, Radio, ArrowRight } from 'lucide-react'; +import { Bell, Users, Check, Loader2, EyeOff, Globe, CheckCheck, Heart, Radio, ArrowRight, Handshake } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { ScrollArea } from '@/components/ui/scroll-area'; @@ -347,7 +347,7 @@ export function NotificationBell({ className }: { className?: string }) { - + 0 && {badgeTotal}} + + Trades + {tradeNotifs.length > 0 && {tradeNotifs.length}} + + {/* ─── TRADES (offers, counter-offers, confirmations) ──────── */} + + {tradeLoading && tradeNotifs.length === 0 && ( +
+ Checking offers and trades… +
+ )} + {!tradeLoading && tradeNotifs.length === 0 && ( + + )} +
+ {tradeNotifs.map((n) => ( + seenAt} + onNavigate={() => setOpen(false)} + /> + ))} +
+
+ {/* ─── SOCIAL ──────────────────────────────────────────────── */} {activityLoading && activity.length === 0 && (