From 9e178af3494e424654baf083cbe807d262dedab6 Mon Sep 17 00:00:00 2001 From: Carlos Gutierrez Date: Sat, 14 Feb 2026 20:37:34 -0500 Subject: [PATCH] Add endorsement badges and endorsement history Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/components/UserCard.tsx | 2 +- src/routes/Profile.tsx | 17 +++++++++++++++++ src/store/useAppStore.ts | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/components/UserCard.tsx b/src/components/UserCard.tsx index af4efe1..0d8958e 100644 --- a/src/components/UserCard.tsx +++ b/src/components/UserCard.tsx @@ -9,7 +9,7 @@ const UserCard: React.FC<{ user: User }> = ({ user }) => {
{user.bio}
{user.specialties.map((s) => ( - {s} + {s} ({user.endorsements[s] ?? 0}) ))}
diff --git a/src/routes/Profile.tsx b/src/routes/Profile.tsx index 5091b77..5e9d434 100644 --- a/src/routes/Profile.tsx +++ b/src/routes/Profile.tsx @@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom' import useAppStore from '../store/useAppStore' import EndorseButton from '../components/EndorseButton' import UserCard from '../components/UserCard' +import { formatTime } from '../utils/fileHelpers' const Profile: React.FC = () => { const { id } = useParams<{ id: string }>() @@ -10,6 +11,8 @@ const Profile: React.FC = () => { const posts = useAppStore((s) => s.posts.filter((p) => p.authorId === id)) const endorseUser = useAppStore((s) => s.endorseUser) const currentUserId = useAppStore((s) => s.currentUserId) + const endorsementHistory = useAppStore((s) => s.endorsementHistory) + const allUsers = useAppStore((s) => s.users) if (!user) return
User not found
@@ -31,6 +34,20 @@ const Profile: React.FC = () => { + {(() => { + const recent = endorsementHistory.filter((e) => e.type === 'user' && e.toUserId === id).slice(0,5) + if (recent.length === 0) return null + return ( +
+

Recent endorsements

+ {recent.map((r) => { + const byName = allUsers.find((u) => u.id === r.by)?.name ?? 'Someone' + return
{byName} endorsed {r.specialty} ยท {formatTime(r.createdAt)} ago
+ })} +
+ ) + })()} +

Posts

{posts.length === 0 &&
No posts yet.
} {posts.map((p) => ( diff --git a/src/store/useAppStore.ts b/src/store/useAppStore.ts index ca256d2..3bd4fb1 100644 --- a/src/store/useAppStore.ts +++ b/src/store/useAppStore.ts @@ -11,6 +11,7 @@ type AppState = { currentUserId: string | null selectedPostId: string | null ui: UIState + endorsementHistory: { id: string; type: 'user' | 'post'; by?: string | null; toUserId?: string; postId?: string; specialty?: string; createdAt: number }[] seedData: () => void createUser: (data: { name: string; email: string; bio: string; specialties: string[] }) => User setCurrentUser: (id: string | null) => void @@ -30,6 +31,7 @@ const useAppStore = create((set, get) => ({ currentUserId: null, selectedPostId: null, ui: { isCreatePostOpen: false }, + endorsementHistory: [], seedData: () => { const users = seedUsers() @@ -69,6 +71,7 @@ const useAppStore = create((set, get) => ({ }, endorseUser: (userId, specialty) => { + const by = get().currentUserId ?? null set((state) => ({ users: state.users.map((u) => { if (u.id !== userId) return u @@ -76,15 +79,20 @@ const useAppStore = create((set, get) => ({ current[specialty] = (current[specialty] || 0) + 1 return { ...u, endorsements: current } }), + endorsementHistory: [{ id: makeId(), type: 'user', by, toUserId: userId, specialty, createdAt: Date.now() }, ...(state.endorsementHistory || [])], })) }, + endorsePost: (postId) => { + const by = get().currentUserId ?? null set((state) => ({ posts: state.posts.map((p) => (p.id === postId ? { ...p, endorsements: p.endorsements + 1 } : p)), + endorsementHistory: [{ id: makeId(), type: 'post', by, postId, createdAt: Date.now() }, ...(state.endorsementHistory || [])], })) }, + attachPDFToPost: (postId, file) => { const url = URL.createObjectURL(file) set((state) => ({