Skip to content

Commit d7522fc

Browse files
fix: full web-modern frontend audit — 17 bugs fixed, AGPL headers, navbar cleanup
CRITICAL: groups/[id] broken JSX nesting preventing tab rendering HIGH: 3 wrong API endpoints (rsvps, wallet alerts/export), profile null crashes, feed tabs showing wrong data, home page double footer + hardcoded unread count MEDIUM: messages stale closure, search URL sync, preferences save feedback, wallet export/alerts UI, feed share button, members connection feedback + email privacy + division by zero, security modal shared error state, settings missing refreshUser, listings router.push Also: - Navbar self-fetches unreadCount (no longer needs prop from every page) - Removed unreadCount boilerplate from 60+ pages - Added AGPL v3 copyright headers to 27 files missing them - Created missing pages: /terms, /listings/[id]/edit, /events/[id]/edit, /groups/[id]/edit 71 files changed, 441 insertions(+), 496 deletions(-) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bb4a69f commit d7522fc

File tree

75 files changed

+1405
-496
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1405
-496
lines changed

apps/web-modern/src/app/activity/page.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ function ActivityContent() {
7878
const [currentPage, setCurrentPage] = useState(1);
7979
const [totalPages, setTotalPages] = useState(1);
8080
const [filter, setFilter] = useState<ActivityType>("all");
81-
const [unreadCount, setUnreadCount] = useState(0);
8281

8382
const fetchActivity = useCallback(async () => {
8483
setIsLoading(true);
@@ -108,14 +107,6 @@ function ActivityContent() {
108107
useEffect(() => {
109108
fetchActivity();
110109
}, [fetchActivity]);
111-
112-
useEffect(() => {
113-
api
114-
.getUnreadMessageCount()
115-
.then((res) => setUnreadCount(res?.count || 0))
116-
.catch(() => {});
117-
}, []);
118-
119110
const handleFilterChange = (newFilter: ActivityType) => {
120111
setFilter(newFilter);
121112
setCurrentPage(1);
@@ -137,7 +128,7 @@ function ActivityContent() {
137128

138129
return (
139130
<div className="min-h-screen">
140-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
131+
<Navbar user={user} onLogout={logout} />
141132
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
142133
<div className="mb-8">
143134
<h1 className="text-3xl font-bold text-white flex items-center gap-3">

apps/web-modern/src/app/assistant/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright © 2024–2026 Jasper Ford
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
// Author: Jasper Ford
4+
// See NOTICE file for attribution and acknowledgements.
5+
16
"use client";
27

38
import { useEffect, useState, useRef } from "react";

apps/web-modern/src/app/availability/page.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ function AvailabilityContent() {
6767
const [slots, setSlots] = useState<Slot[]>([]);
6868
const [exceptions, setExceptions] = useState<Exception[]>([]);
6969
const [isLoading, setIsLoading] = useState(true);
70-
const [unreadCount, setUnreadCount] = useState(0);
7170

7271
// New slot form
7372
const [newDay, setNewDay] = useState("1");
@@ -98,10 +97,6 @@ function AvailabilityContent() {
9897
useEffect(() => {
9998
fetchData();
10099
}, [fetchData]);
101-
useEffect(() => {
102-
api.getUnreadMessageCount().then((res) => setUnreadCount(res?.count || 0));
103-
}, []);
104-
105100
const handleAddSlot = async () => {
106101
try {
107102
await api.addAvailabilitySlot({
@@ -140,7 +135,7 @@ function AvailabilityContent() {
140135

141136
return (
142137
<div className="min-h-screen">
143-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
138+
<Navbar user={user} onLogout={logout} />
144139
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
145140
<div className="mb-8">
146141
<h1 className="text-3xl font-bold text-white flex items-center gap-3">

apps/web-modern/src/app/blog/[slug]/page.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ function BlogPostContent({ params }: { params: Promise<{ slug: string }> }) {
3737
const { user, logout } = useAuth();
3838
const [post, setPost] = useState<BlogPostDetail | null>(null);
3939
const [isLoading, setIsLoading] = useState(true);
40-
const [unreadCount, setUnreadCount] = useState(0);
4140

4241
const fetchPost = useCallback(async () => {
4342
setIsLoading(true);
@@ -52,13 +51,9 @@ function BlogPostContent({ params }: { params: Promise<{ slug: string }> }) {
5251
}, [slug]);
5352

5453
useEffect(() => { fetchPost(); }, [fetchPost]);
55-
useEffect(() => {
56-
api.getUnreadMessageCount().then((res) => setUnreadCount(res?.count || 0));
57-
}, []);
58-
5954
return (
6055
<div className="min-h-screen">
61-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
56+
<Navbar user={user} onLogout={logout} />
6257
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
6358
<Link href="/blog" className="inline-flex items-center gap-2 text-white/50 hover:text-white mb-6 transition-colors">
6459
<ArrowLeft className="w-4 h-4" /> Back to Blog

apps/web-modern/src/app/blog/page.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ function BlogContent() {
4343
const [isLoading, setIsLoading] = useState(true);
4444
const [currentPage, setCurrentPage] = useState(1);
4545
const [totalPages, setTotalPages] = useState(1);
46-
const [unreadCount, setUnreadCount] = useState(0);
4746

4847
const fetchPosts = useCallback(async () => {
4948
setIsLoading(true);
@@ -59,13 +58,9 @@ function BlogContent() {
5958
}, [currentPage]);
6059

6160
useEffect(() => { fetchPosts(); }, [fetchPosts]);
62-
useEffect(() => {
63-
api.getUnreadMessageCount().then((res) => setUnreadCount(res?.count || 0));
64-
}, []);
65-
6661
return (
6762
<div className="min-h-screen">
68-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
63+
<Navbar user={user} onLogout={logout} />
6964
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
7065
<div className="mb-8">
7166
<h1 className="text-3xl font-bold text-white flex items-center gap-3">

apps/web-modern/src/app/connections/page.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright © 2024–2026 Jasper Ford
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
// Author: Jasper Ford
4+
// See NOTICE file for attribution and acknowledgements.
5+
16
"use client";
27

38
import { useEffect, useState, useCallback } from "react";
@@ -43,7 +48,6 @@ function ConnectionsContent() {
4348
const [filter, setFilter] = useState<ConnectionFilter>("accepted");
4449
const [currentPage, setCurrentPage] = useState(1);
4550
const [totalPages, setTotalPages] = useState(1);
46-
const [unreadCount, setUnreadCount] = useState(0);
4751

4852
const fetchConnections = useCallback(async () => {
4953
setIsLoading(true);
@@ -66,11 +70,6 @@ function ConnectionsContent() {
6670
useEffect(() => {
6771
fetchConnections();
6872
}, [fetchConnections]);
69-
70-
useEffect(() => {
71-
api.getUnreadMessageCount().then((res) => setUnreadCount(res?.count || 0));
72-
}, []);
73-
7473
const handleAccept = async (connectionId: number) => {
7574
try {
7675
await api.respondToConnection(connectionId, "accepted");
@@ -116,7 +115,7 @@ function ConnectionsContent() {
116115

117116
return (
118117
<div className="min-h-screen">
119-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
118+
<Navbar user={user} onLogout={logout} />
120119

121120
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
122121
{/* Header */}

apps/web-modern/src/app/dashboard/page.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright © 2024–2026 Jasper Ford
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
// Author: Jasper Ford
4+
// See NOTICE file for attribution and acknowledgements.
5+
16
"use client";
27

38
import { useEffect, useState } from "react";
@@ -55,8 +60,8 @@ function DashboardContent() {
5560
const [balance, setBalance] = useState<WalletBalance | null>(null);
5661
const [transactions, setTransactions] = useState<Transaction[]>([]);
5762
const [listings, setListings] = useState<Listing[]>([]);
58-
const [unreadCount, setUnreadCount] = useState(0);
5963
const [gamification, setGamification] = useState<GamificationProfile | null>(null);
64+
const [messageCount, setMessageCount] = useState(0);
6065
const [isLoading, setIsLoading] = useState(true);
6166

6267
useEffect(() => {
@@ -66,14 +71,14 @@ function DashboardContent() {
6671
api.getBalance(),
6772
api.getTransactions({ limit: 5 }),
6873
api.getListings({ status: "active", limit: 4 }),
69-
api.getUnreadMessageCount(),
74+
api.getUnreadMessageCount().catch(() => ({ count: 0 })),
7075
api.getGamificationProfile().catch(() => null),
7176
]);
7277

7378
setBalance(balanceRes);
7479
setTransactions(txRes?.data || []);
7580
setListings(listingsRes?.data || []);
76-
setUnreadCount(msgRes?.count || 0);
81+
setMessageCount(msgRes?.count || 0);
7782
if (gamRes?.profile) {
7883
setGamification(gamRes.profile);
7984
}
@@ -89,7 +94,7 @@ function DashboardContent() {
8994

9095
return (
9196
<div className="min-h-screen">
92-
<Navbar user={user} unreadCount={unreadCount} onLogout={logout} />
97+
<Navbar user={user} onLogout={logout} />
9398

9499
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
95100
{/* Welcome Header */}
@@ -225,7 +230,7 @@ function DashboardContent() {
225230
<div className="w-10 h-10 rounded-xl bg-cyan-500/20 flex items-center justify-center mb-4">
226231
<MessageSquare className="w-5 h-5 text-cyan-400" />
227232
</div>
228-
<p className="text-2xl font-bold text-white">{unreadCount}</p>
233+
<p className="text-2xl font-bold text-white">{messageCount}</p>
229234
<p className="text-sm text-white/50 mb-4">Unread Messages</p>
230235
<Link href="/messages" className="mt-auto">
231236
<Button

apps/web-modern/src/app/error.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright © 2024–2026 Jasper Ford
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
// Author: Jasper Ford
4+
// See NOTICE file for attribution and acknowledgements.
5+
16
"use client";
27

38
import { useEffect } from "react";

0 commit comments

Comments
 (0)