feat(user-directory): enhance user navigation and display logic

Add userLinkBoards prop to UserDirectory component to determine link availability
Modify user filtering logic to always include users unless explicitly hidden
Update navigation to open Bluesky profile when no links are available
Add visual indicator for users without links

ewancroft.uk ec09ffc9 4a8e6e22

verified
Changed files
+31 -11
src
lib
components
routes
+29 -9
src/lib/components/archive/UserDirectory.svelte
··· 5 5 6 6 export let users: User[]; 7 7 export let primaryUserDid: string | undefined; 8 + export let userLinkBoards: { [did: string]: LinkBoard | undefined }; 9 + import type { LinkBoard } from "$lib/components/shared/interfaces"; 8 10 9 11 let loading = true; 10 12 let userProfiles: any[] = []; 11 13 12 14 onMount(async () => { 13 15 if (users && users.length > 0) { 14 - // Fetch profile data for each user 15 16 const profiles = await Promise.all( 16 17 users.map(async (user) => { 18 + let enrichedUser = { 19 + ...user, 20 + hasLinks: !!userLinkBoards?.[user.did]?.cards?.length 21 + }; 22 + 17 23 try { 18 24 const response = await fetch( 19 25 `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${user.did}` ··· 21 27 if (response.ok) { 22 28 const profile = await response.json(); 23 29 return { 24 - did: user.did, 30 + ...enrichedUser, 25 31 handle: profile.handle || user.handle, 26 32 displayName: profile.displayName || user.displayName, 27 33 avatar: profile.avatar, ··· 32 38 } catch (error) { 33 39 console.error(`Error fetching profile for ${user.did}:`, error); 34 40 } 35 - return user; // Return original if fetch fails 41 + 42 + return enrichedUser; // fallback if fetch fails 36 43 }) 37 44 ); 38 45 userProfiles = profiles.filter(Boolean); ··· 40 47 loading = false; 41 48 }); 42 49 43 - function navigateToUser(did: string) { 44 - goto(`/user/${encodeURIComponent(did)}`); 50 + function navigateToUser(user: any) { 51 + const userBoard = userLinkBoards[user.did]; 52 + if (userBoard && userBoard.cards?.length > 0) { 53 + goto(`/user/${encodeURIComponent(user.did)}`); 54 + } else { 55 + // Construct Bluesky profile URL 56 + const blueskyHandle = user.did; 57 + window.open(`https://bsky.app/profile/${blueskyHandle}`, '_blank'); 58 + } 45 59 } 46 60 </script> 47 61 ··· 68 82 <button 69 83 class="user-card cursor-pointer rounded-lg p-6 transition-transform hover:scale-105 text-left w-full" 70 84 style="background: var(--card-bg); border: 1px solid var(--border-color);" 71 - onclick={() => navigateToUser(user.did)} 85 + on:click={() => navigateToUser(user)} 72 86 > 73 87 {#if user.banner} 74 88 <div ··· 108 122 </div> 109 123 110 124 <div class="mt-4 text-center"> 111 - <span class="text-sm text-link hover:text-link-hover"> 112 - View links → 113 - </span> 125 + {#if user.hasLinks} 126 + <span class="text-sm text-link hover:text-link-hover"> 127 + View links → 128 + </span> 129 + {:else} 130 + <span class="text-sm text-link hover:text-link-hover"> 131 + No links - View Bluesky profile → 132 + </span> 133 + {/if} 114 134 </div> 115 135 </button> 116 136 {/each}
+1 -1
src/routes/+layout.ts
··· 100 100 if (hideOwnerCard && did === primaryUserDid) { 101 101 return false; // Hide the owner's card if HIDE_OWNER_CARD is true 102 102 } 103 - return userLinkBoards[did] !== undefined; 103 + return true; // Always include the user if not hidden 104 104 }), 105 105 noUsersConfigured: false, 106 106 primaryUserDid,
+1 -1
src/routes/+page.svelte
··· 73 73 </div> 74 74 </div> 75 75 {:else} 76 - <UserDirectory users={data.linkatUsers.map(did => ({ did }))} primaryUserDid={data.primaryUserDid} /> 76 + <UserDirectory users={data.linkatUsers.map(did => ({ did }))} primaryUserDid={data.primaryUserDid} userLinkBoards={data.userLinkBoards} /> 77 77 {/if} 78 78 </div>