(() => {
+ if (!events) return [];
+ const parsedGoals: GoalItem[] = [];
+ for (const event of events) {
+ const parsed = parseGoalEvent(event);
+ if (!parsed || isGoalExpired(parsed)) continue;
+ parsedGoals.push({
+ event,
+ title: parsed.title,
+ amountSats: parsed.amountSats,
+ communityATag: parsed.communityATag,
+ closedAt: parsed.closedAt,
+ });
+ }
+ return parsedGoals
+ .sort((a, b) => {
+ const aDeadline = a.closedAt ?? Number.MAX_SAFE_INTEGER;
+ const bDeadline = b.closedAt ?? Number.MAX_SAFE_INTEGER;
+ return aDeadline - bDeadline;
+ })
+ .slice(0, limit);
+ }, [events, limit]);
+
+ const isLoading = scopedATag ? goalsLoading : communitiesLoading || goalsLoading;
+
+ if (!scopedATag && aTags.length === 0 && !isLoading) {
+ return (
+
+ Join communities to follow fundraising goals.
+
+ );
+ }
+
+ if (isLoading) {
+ return (
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+
+
+
+ ))}
+
+ );
+ }
+
+ if (isError) {
+ return Failed to load community goals.
;
+ }
+
+ if (goals.length === 0) {
+ return No active fundraising goals.
;
+ }
+
+ return (
+
+ {goals.map((goal) => {
+ const encoded = nip19.neventEncode({ id: goal.event.id, author: goal.event.pubkey });
+ return (
+
+
{goal.title}
+
+
+ {formatSats(goal.amountSats)} sats
+
+ {!scopedATag && goal.communityATag && communityNameByATag.get(goal.communityATag) && (
+
+ {communityNameByATag.get(goal.communityATag)}
+
+ )}
+
+ );
+ })}
+
+ );
+}
diff --git a/src/components/widgets/MyCommunitiesWidget.tsx b/src/components/widgets/MyCommunitiesWidget.tsx
new file mode 100644
index 00000000..178838a4
--- /dev/null
+++ b/src/components/widgets/MyCommunitiesWidget.tsx
@@ -0,0 +1,83 @@
+import { useMemo } from 'react';
+import { Link } from 'react-router-dom';
+import { Crown } from 'lucide-react';
+import { nip19 } from 'nostr-tools';
+
+import { Skeleton } from '@/components/ui/skeleton';
+import { useMyCommunities } from '@/hooks/useMyCommunities';
+import { COMMUNITY_DEFINITION_KIND } from '@/lib/communityUtils';
+
+interface MyCommunitiesWidgetProps {
+ limit?: number;
+}
+
+/** Sidebar widget listing communities the current user founded or joined. */
+export function MyCommunitiesWidget({ limit = 6 }: MyCommunitiesWidgetProps) {
+ const { data: communities, isLoading } = useMyCommunities();
+
+ const items = useMemo(
+ () => (communities ?? []).slice(0, limit),
+ [communities, limit],
+ );
+
+ if (isLoading) {
+ return (
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+
+
+
+ ))}
+
+ );
+ }
+
+ if (!communities || communities.length === 0) {
+ return (
+
+ Join communities to build your Agora network.
+
+ );
+ }
+
+ return (
+
+ {items.map((entry) => {
+ const naddr = nip19.naddrEncode({
+ kind: COMMUNITY_DEFINITION_KIND,
+ pubkey: entry.event.pubkey,
+ identifier: entry.community.dTag,
+ });
+
+ return (
+
+
+
{entry.community.name}
+ {entry.isFounded && (
+
+
+ Founder
+
+ )}
+
+ {entry.community.description && (
+
+ {entry.community.description}
+
+ )}
+
+ );
+ })}
+
+
+ View all communities
+
+
+
+ );
+}