Friends tab shows who you follow and who follows you
The app's Friends tab was only a search box. It now lists Following and Followers (with Follow / Remove buttons) until you type a search. The website gets the same Friends page and tab; search moves there from the top of the feed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { FollowList } from '@/components/FollowList';
|
||||
import { UserSearch } from '@/components/UserSearch';
|
||||
import { useMe } from '@/lib/api';
|
||||
|
||||
/** Friends: who you follow and who follows you, plus search to find new people. */
|
||||
export default function FriendsPage() {
|
||||
const { me, loggedOut } = useMe();
|
||||
const [tab, setTab] = useState<'following' | 'followers'>('following');
|
||||
if (loggedOut) return <p className="muted"><Link href="/login">Log in</Link> to see your friends.</p>;
|
||||
if (!me) return null;
|
||||
return (
|
||||
<div className="stack">
|
||||
<h1>Friends</h1>
|
||||
<UserSearch />
|
||||
<div className="row">
|
||||
{(['following', 'followers'] as const).map((t) => (
|
||||
<button key={t} className={`btn btn-small ${tab === t ? 'btn-primary' : ''}`} aria-pressed={tab === t} onClick={() => setTab(t)}>
|
||||
{t === 'following' ? 'Following' : 'Followers'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<FollowList key={tab} username={me.username} direction={tab} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import { Avatar } from '@/components/Avatar';
|
||||
import { Equalizer } from '@/components/Equalizer';
|
||||
import { NowPlayingCard } from '@/components/NowPlayingCard';
|
||||
import { SharingControls } from '@/components/SharingControls';
|
||||
import { UserSearch } from '@/components/UserSearch';
|
||||
import { api, fetcher, useMe } from '@/lib/api';
|
||||
import { useRealtime } from '@/lib/useRealtime';
|
||||
|
||||
@@ -60,7 +59,6 @@ function Feed() {
|
||||
|
||||
return (
|
||||
<div className="stack">
|
||||
<UserSearch />
|
||||
<SharingControls compact />
|
||||
{mine?.nowPlaying && (
|
||||
<section className="stack">
|
||||
@@ -78,7 +76,7 @@ function Feed() {
|
||||
(following?.users.length ? (
|
||||
<p className="muted">Nobody you follow has played anything yet. Their music will show up here live.</p>
|
||||
) : (
|
||||
<p className="muted">Nothing yet. Find friends above, and their music will show up here live.</p>
|
||||
<p className="muted">Nothing yet. <Link href="/friends">Find friends</Link>, and their music will show up here live.</p>
|
||||
))}
|
||||
{/* Cards rise in on load and glide to new positions when someone pins or starts playing. */}
|
||||
<AnimatePresence initial={true}>
|
||||
|
||||
@@ -5,13 +5,14 @@ import { usePathname } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { client, useMe } from '@/lib/api';
|
||||
|
||||
/** Top bar: logo and the three main places. On phones those move to a bottom tab bar. */
|
||||
/** Top bar: logo and the four main places. On phones those move to a bottom tab bar. */
|
||||
export function Nav() {
|
||||
const { me } = useMe();
|
||||
const path = usePathname();
|
||||
const tabs = me
|
||||
? [
|
||||
{ href: '/', label: 'Feed', icon: <FeedIcon />, active: path === '/' },
|
||||
{ href: '/friends', label: 'Friends', icon: <FriendsIcon />, active: path.startsWith('/friends') },
|
||||
{ href: `/u/${me.username}`, label: 'Profile', icon: <ProfileIcon />, active: path.startsWith(`/u/${me.username}`) },
|
||||
{ href: '/settings', label: 'Settings', icon: <SettingsIcon />, active: path.startsWith('/settings') || path === '/admin' },
|
||||
]
|
||||
@@ -89,6 +90,14 @@ const FeedIcon = () => (
|
||||
<circle cx="18" cy="16" r="3" />
|
||||
</svg>
|
||||
);
|
||||
const FriendsIcon = () => (
|
||||
<svg {...icon} aria-hidden>
|
||||
<circle cx="9" cy="8" r="3.5" />
|
||||
<path d="M2 20c0-3.6 3.1-6 7-6s7 2.4 7 6" />
|
||||
<path d="M16 4.5a3.5 3.5 0 0 1 0 7" />
|
||||
<path d="M18 14c2.4.6 4 2.6 4 6" />
|
||||
</svg>
|
||||
);
|
||||
const ProfileIcon = () => (
|
||||
<svg {...icon} aria-hidden>
|
||||
<circle cx="12" cy="8" r="4" />
|
||||
|
||||
Reference in New Issue
Block a user