Prettier format pending files

This commit is contained in:
Builder.io 2025-09-27 21:48:02 +00:00
parent d28c0e3937
commit ef56ff44fd
8 changed files with 333 additions and 98 deletions

View file

@ -52,7 +52,10 @@ const App = () => (
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/admin" element={<Admin />} />
<Route path="/network" element={<Network />} />
<Route path="/profile" element={<Navigate to="/network" replace />} />
<Route
path="/profile"
element={<Navigate to="/network" replace />}
/>
<Route path="/login" element={<Login />} />
{/* Service routes */}

View file

@ -63,7 +63,9 @@ export default function Layout({ children }: LayoutProps) {
{(() => {
const isOwner = Array.isArray(roles) && roles.includes("owner");
const navItems = user
? (isOwner ? [{ name: "Admin", href: "/admin" }, ...userNavigation] : userNavigation)
? isOwner
? [{ name: "Admin", href: "/admin" }, ...userNavigation]
: userNavigation
: navigation;
return navItems.map((item, index) => (
<Link
@ -93,7 +95,12 @@ export default function Layout({ children }: LayoutProps) {
{user ? (
// Logged in - always show Dashboard button; show avatar menu if profile exists
<div className="flex items-center space-x-3">
<Button asChild variant="outline" size="sm" className="hover-lift">
<Button
asChild
variant="outline"
size="sm"
className="hover-lift"
>
<Link to="/dashboard">Dashboard</Link>
</Button>
<Button variant="ghost" size="sm" className="hover-lift">
@ -141,9 +148,9 @@ export default function Layout({ children }: LayoutProps) {
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to="/dashboard" className="cursor-pointer">
<Settings className="mr-2 h-4 w-4" />
Settings
</Link>
<Settings className="mr-2 h-4 w-4" />
Settings
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem

View file

@ -114,7 +114,9 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
// Auto-seed owner roles if logging in as site owner
const ownerEmail = userProfile?.email?.toLowerCase();
if (ownerEmail === "mrpiglr@gmail.com" && !r.includes("owner")) {
const seeded = Array.from(new Set(["owner", "admin", "founder", ...r]));
const seeded = Array.from(
new Set(["owner", "admin", "founder", ...r]),
);
await aethexRoleService.setUserRoles(userId, seeded);
r = seeded;
}

View file

@ -57,7 +57,7 @@ function isTableMissing(err: any): boolean {
const msg = String(err?.message || err?.hint || err?.details || "");
return (
err?.code === "42P01" || // undefined_table
msg.includes("relation \"") ||
msg.includes('relation "') ||
msg.includes("does not exist") ||
msg.includes("table")
);
@ -86,12 +86,15 @@ export const aethexUserService = {
email: user.email,
} as AethexUserProfile;
}
const created = await mockAuth.updateProfile(user.id as any, {
username: user.email?.split("@")[0] || "user",
email: user.email || "",
role: "member",
onboarded: true,
} as any);
const created = await mockAuth.updateProfile(
user.id as any,
{
username: user.email?.split("@")[0] || "user",
email: user.email || "",
role: "member",
onboarded: true,
} as any,
);
return {
...(created as any),
email: user.email,
@ -123,7 +126,10 @@ export const aethexUserService = {
if (error) {
console.warn("Error updating profile, attempting mock fallback:", error);
if (isTableMissing(error)) {
const mock = await mockAuth.updateProfile(userId as any, updates as any);
const mock = await mockAuth.updateProfile(
userId as any,
updates as any,
);
return mock as unknown as AethexUserProfile;
}
throw error;
@ -162,17 +168,20 @@ export const aethexUserService = {
if (error) {
console.warn("Error creating profile, attempting mock fallback:", error);
if (isTableMissing(error)) {
const mock = await mockAuth.updateProfile(userId as any, {
username: profileData.username || `user_${Date.now()}`,
full_name: profileData.full_name,
bio: profileData.bio,
location: profileData.location,
linkedin_url: profileData.linkedin_url as any,
github_url: profileData.github_url as any,
twitter_url: profileData.twitter_url as any,
level: 1,
total_xp: 0,
} as any);
const mock = await mockAuth.updateProfile(
userId as any,
{
username: profileData.username || `user_${Date.now()}`,
full_name: profileData.full_name,
bio: profileData.bio,
location: profileData.location,
linkedin_url: profileData.linkedin_url as any,
github_url: profileData.github_url as any,
twitter_url: profileData.twitter_url as any,
level: 1,
total_xp: 0,
} as any,
);
return {
...(mock as any),
@ -206,7 +215,9 @@ export const aethexUserService = {
interest,
}));
const { error } = await supabase.from("user_interests").insert(interestRows);
const { error } = await supabase
.from("user_interests")
.insert(interestRows);
if (error) {
if (isTableMissing(error)) return;
@ -283,7 +294,10 @@ export const aethexProjectService = {
},
async deleteProject(projectId: string): Promise<boolean> {
const { error } = await supabase.from("projects").delete().eq("id", projectId);
const { error } = await supabase
.from("projects")
.delete()
.eq("id", projectId);
if (error) {
console.warn("Error deleting project:", error);
@ -410,7 +424,8 @@ export const aethexAchievementService = {
const updates: any = {};
if ("total_xp" in (profile as any)) updates.total_xp = newTotalXP;
if ("level" in (profile as any)) updates.level = newLevel;
if ("loyalty_points" in (profile as any)) updates.loyalty_points = newLoyaltyPoints;
if ("loyalty_points" in (profile as any))
updates.loyalty_points = newLoyaltyPoints;
if (Object.keys(updates).length > 0) {
await supabase.from("user_profiles").update(updates).eq("id", userId);
@ -426,7 +441,10 @@ export const aethexAchievementService = {
.single();
if (levelUpAchievement.data) {
await this.awardAchievement(userId, (levelUpAchievement.data as any).id);
await this.awardAchievement(
userId,
(levelUpAchievement.data as any).id,
);
}
}
}
@ -588,9 +606,12 @@ export const aethexRoleService = {
async setUserRoles(userId: string, roles: string[]): Promise<void> {
try {
const rows = roles.map((role) => ({ user_id: userId, role }));
const { error } = await supabase.from("user_roles").upsert(rows as any, {
onConflict: "user_id,role",
} as any);
const { error } = await supabase.from("user_roles").upsert(
rows as any,
{
onConflict: "user_id,role",
} as any,
);
if (!error) return;
} catch {}

View file

@ -20,7 +20,8 @@ export const aethexSocialService = {
.from("user_follows")
.select("following_id")
.eq("follower_id", userId);
if (!error && data) return (data as any[]).map((r: any) => r.following_id);
if (!error && data)
return (data as any[]).map((r: any) => r.following_id);
} catch {}
try {
const raw = localStorage.getItem("mock_follows");
@ -40,7 +41,9 @@ export const aethexSocialService = {
} catch {}
const raw = localStorage.getItem("mock_follows");
const map = raw ? JSON.parse(raw) : {};
const set: string[] = Array.from(new Set([...(map[followerId] || []), followingId]));
const set: string[] = Array.from(
new Set([...(map[followerId] || []), followingId]),
);
map[followerId] = set;
localStorage.setItem("mock_follows", JSON.stringify(map));
},
@ -56,7 +59,9 @@ export const aethexSocialService = {
} catch {}
const raw = localStorage.getItem("mock_follows");
const map = raw ? JSON.parse(raw) : {};
const list: string[] = (map[followerId] || []).filter((id: string) => id !== followingId);
const list: string[] = (map[followerId] || []).filter(
(id: string) => id !== followingId,
);
map[followerId] = list;
localStorage.setItem("mock_follows", JSON.stringify(map));
},

View file

@ -3,10 +3,23 @@ import LoadingScreen from "@/components/LoadingScreen";
import { useAuth } from "@/contexts/AuthContext";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import {
Card,
CardContent,
CardHeader,
CardTitle,
CardDescription,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Shield, UserCog, Rocket, Settings, Users, Activity } from "lucide-react";
import {
Shield,
UserCog,
Rocket,
Settings,
Users,
Activity,
} from "lucide-react";
export default function Admin() {
const { user, loading, roles } = useAuth();
@ -23,7 +36,11 @@ export default function Admin() {
if (loading || !user) {
return (
<LoadingScreen message="Verifying admin access..." showProgress duration={1000} />
<LoadingScreen
message="Verifying admin access..."
showProgress
duration={1000}
/>
);
}
@ -35,10 +52,14 @@ export default function Admin() {
<Card className="bg-red-500/10 border-red-500/30">
<CardHeader>
<CardTitle className="text-red-400">Access Denied</CardTitle>
<CardDescription>You dont have permission to access the admin panel.</CardDescription>
<CardDescription>
You dont have permission to access the admin panel.
</CardDescription>
</CardHeader>
<CardContent>
<Button onClick={() => navigate("/dashboard")}>Go to Dashboard</Button>
<Button onClick={() => navigate("/dashboard")}>
Go to Dashboard
</Button>
</CardContent>
</Card>
</div>
@ -54,16 +75,37 @@ export default function Admin() {
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold text-gradient">Admin Panel</h1>
<p className="text-muted-foreground">Site Owner Admin Founder</p>
<p className="text-muted-foreground">
Site Owner Admin Founder
</p>
<div className="flex gap-2 mt-2">
<Badge variant="outline" className="border-green-500/50 text-green-400">Site Owner</Badge>
<Badge variant="outline" className="border-blue-500/50 text-blue-400">Admin</Badge>
<Badge variant="outline" className="border-purple-500/50 text-purple-400">Founder</Badge>
<Badge
variant="outline"
className="border-green-500/50 text-green-400"
>
Site Owner
</Badge>
<Badge
variant="outline"
className="border-blue-500/50 text-blue-400"
>
Admin
</Badge>
<Badge
variant="outline"
className="border-purple-500/50 text-purple-400"
>
Founder
</Badge>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline" onClick={() => navigate("/dashboard")}>Dashboard</Button>
<Button variant="outline" onClick={() => navigate("/profile")}>Profile</Button>
<Button variant="outline" onClick={() => navigate("/dashboard")}>
Dashboard
</Button>
<Button variant="outline" onClick={() => navigate("/profile")}>
Profile
</Button>
</div>
</div>
@ -74,12 +116,15 @@ export default function Admin() {
<Shield className="h-5 w-5 text-green-400" />
<CardTitle className="text-lg">Access Control</CardTitle>
</div>
<CardDescription>Owner-only access is enforced by email</CardDescription>
<CardDescription>
Owner-only access is enforced by email
</CardDescription>
</CardHeader>
<CardContent>
<ul className="text-sm space-y-1 text-muted-foreground">
<li>
Owner: <span className="text-foreground">mrpiglr@gmail.com</span>
Owner:{" "}
<span className="text-foreground">mrpiglr@gmail.com</span>
</li>
<li>All other users are denied access</li>
</ul>
@ -92,7 +137,9 @@ export default function Admin() {
<Users className="h-5 w-5 text-blue-400" />
<CardTitle className="text-lg">Users & Roles</CardTitle>
</div>
<CardDescription>Future: manage roles, invitations, and status</CardDescription>
<CardDescription>
Future: manage roles, invitations, and status
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">Coming soon</p>
@ -108,7 +155,12 @@ export default function Admin() {
<CardDescription>Branding, legal, integrations</CardDescription>
</CardHeader>
<CardContent>
<Button variant="outline" onClick={() => navigate("/get-started")}>Open Settings</Button>
<Button
variant="outline"
onClick={() => navigate("/get-started")}
>
Open Settings
</Button>
</CardContent>
</Card>
@ -138,8 +190,16 @@ export default function Admin() {
<CardDescription>Common admin operations</CardDescription>
</CardHeader>
<CardContent className="flex flex-wrap gap-2">
<Button size="sm" onClick={() => navigate("/dashboard")}>View Dashboard</Button>
<Button size="sm" variant="outline" onClick={() => navigate("/onboarding")}>Run Onboarding</Button>
<Button size="sm" onClick={() => navigate("/dashboard")}>
View Dashboard
</Button>
<Button
size="sm"
variant="outline"
onClick={() => navigate("/onboarding")}
>
Run Onboarding
</Button>
</CardContent>
</Card>

View file

@ -141,9 +141,9 @@ export default function Index() {
Crafting Digital Realities
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto animate-slide-up">
Where vision meets execution. We craft experiences through
design, development, and community.
</p>
Where vision meets execution. We craft experiences through
design, development, and community.
</p>
</div>
</div>
@ -247,8 +247,12 @@ export default function Index() {
<section className="py-20">
<div className="container mx-auto px-4">
<div className="text-center mb-12">
<h2 className="text-3xl lg:text-4xl font-bold text-gradient">Everything We Offer</h2>
<p className="text-muted-foreground mt-2">Explore services, programs, resources, and community</p>
<h2 className="text-3xl lg:text-4xl font-bold text-gradient">
Everything We Offer
</h2>
<p className="text-muted-foreground mt-2">
Explore services, programs, resources, and community
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
@ -258,7 +262,9 @@ export default function Index() {
<CardDescription>Studios and indie support</CardDescription>
</CardHeader>
<CardContent>
<Button asChild className="w-full"><Link to="/game-development">Learn More</Link></Button>
<Button asChild className="w-full">
<Link to="/game-development">Learn More</Link>
</Button>
</CardContent>
</Card>
@ -268,7 +274,9 @@ export default function Index() {
<CardDescription>Architecture & delivery</CardDescription>
</CardHeader>
<CardContent>
<Button asChild className="w-full"><Link to="/consulting">Learn More</Link></Button>
<Button asChild className="w-full">
<Link to="/consulting">Learn More</Link>
</Button>
</CardContent>
</Card>
@ -278,7 +286,9 @@ export default function Index() {
<CardDescription>Programs and guidance</CardDescription>
</CardHeader>
<CardContent>
<Button asChild className="w-full"><Link to="/mentorship">Learn More</Link></Button>
<Button asChild className="w-full">
<Link to="/mentorship">Learn More</Link>
</Button>
</CardContent>
</Card>
@ -288,7 +298,9 @@ export default function Index() {
<CardDescription>Innovation and R&D</CardDescription>
</CardHeader>
<CardContent>
<Button asChild className="w-full"><Link to="/research">Learn More</Link></Button>
<Button asChild className="w-full">
<Link to="/research">Learn More</Link>
</Button>
</CardContent>
</Card>
</div>
@ -301,8 +313,12 @@ export default function Index() {
</CardHeader>
<CardContent>
<div className="flex gap-2">
<Button asChild variant="outline"><Link to="/docs">Docs</Link></Button>
<Button asChild variant="outline"><Link to="/docs/tutorials">Tutorials</Link></Button>
<Button asChild variant="outline">
<Link to="/docs">Docs</Link>
</Button>
<Button asChild variant="outline">
<Link to="/docs/tutorials">Tutorials</Link>
</Button>
</div>
</CardContent>
</Card>
@ -314,8 +330,12 @@ export default function Index() {
</CardHeader>
<CardContent>
<div className="flex gap-2">
<Button asChild variant="outline"><Link to="/community">Community</Link></Button>
<Button asChild variant="outline"><Link to="/blog">Blog</Link></Button>
<Button asChild variant="outline">
<Link to="/community">Community</Link>
</Button>
<Button asChild variant="outline">
<Link to="/blog">Blog</Link>
</Button>
</div>
</CardContent>
</Card>
@ -327,8 +347,12 @@ export default function Index() {
</CardHeader>
<CardContent>
<div className="flex gap-2">
<Button asChild variant="outline"><Link to="/about">About</Link></Button>
<Button asChild variant="outline"><Link to="/contact">Contact</Link></Button>
<Button asChild variant="outline">
<Link to="/about">About</Link>
</Button>
<Button asChild variant="outline">
<Link to="/contact">Contact</Link>
</Button>
</div>
</CardContent>
</Card>
@ -355,12 +379,36 @@ export default function Index() {
{/* Interactive Technology Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 animate-fade-in">
{[
{ name: "Game Studios", status: "Active", color: "from-purple-500 to-blue-600" },
{ name: "Design Systems", status: "Evolving", color: "from-blue-500 to-green-600" },
{ name: "Creator Tools", status: "Live", color: "from-green-500 to-yellow-600" },
{ name: "Launch Ops", status: "Scaling", color: "from-yellow-500 to-red-600" },
{ name: "Content Pipeline", status: "In Progress", color: "from-red-500 to-purple-600" },
{ name: "Edge Experiences", status: "Deployed", color: "from-purple-500 to-pink-600" },
{
name: "Game Studios",
status: "Active",
color: "from-purple-500 to-blue-600",
},
{
name: "Design Systems",
status: "Evolving",
color: "from-blue-500 to-green-600",
},
{
name: "Creator Tools",
status: "Live",
color: "from-green-500 to-yellow-600",
},
{
name: "Launch Ops",
status: "Scaling",
color: "from-yellow-500 to-red-600",
},
{
name: "Content Pipeline",
status: "In Progress",
color: "from-red-500 to-purple-600",
},
{
name: "Edge Experiences",
status: "Deployed",
color: "from-purple-500 to-pink-600",
},
].map((tech, index) => (
<Card
key={index}

View file

@ -3,7 +3,13 @@ import { useAuth } from "@/contexts/AuthContext";
import { useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import LoadingScreen from "@/components/LoadingScreen";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
@ -52,7 +58,13 @@ export default function Network() {
};
if (loading || isLoading) {
return <LoadingScreen message="Loading your network..." showProgress duration={1000} />;
return (
<LoadingScreen
message="Loading your network..."
showProgress
duration={1000}
/>
);
}
if (!user) return null;
@ -68,14 +80,28 @@ export default function Network() {
<div className="flex items-center gap-4">
<Avatar className="h-16 w-16">
<AvatarImage src={profile?.avatar_url} />
<AvatarFallback>{profile?.full_name?.[0] || user.email?.[0]?.toUpperCase()}</AvatarFallback>
<AvatarFallback>
{profile?.full_name?.[0] ||
user.email?.[0]?.toUpperCase()}
</AvatarFallback>
</Avatar>
<div>
<h2 className="text-xl font-semibold">{profile?.full_name || user.email?.split("@")[0]}</h2>
<p className="text-sm text-muted-foreground">{profile?.role || "Member"}</p>
<h2 className="text-xl font-semibold">
{profile?.full_name || user.email?.split("@")[0]}
</h2>
<p className="text-sm text-muted-foreground">
{profile?.role || "Member"}
</p>
<div className="mt-2 flex gap-2">
<Badge variant="outline" className="border-aethex-400/50 text-aethex-400">Level {profile?.level || 1}</Badge>
<Badge variant="outline">{(profile as any)?.experience_level || "beginner"}</Badge>
<Badge
variant="outline"
className="border-aethex-400/50 text-aethex-400"
>
Level {profile?.level || 1}
</Badge>
<Badge variant="outline">
{(profile as any)?.experience_level || "beginner"}
</Badge>
</div>
</div>
</div>
@ -83,8 +109,18 @@ export default function Network() {
<p className="text-sm text-muted-foreground">{profile.bio}</p>
)}
<div className="flex gap-2">
<Button variant="outline" onClick={() => navigate("/dashboard")}>Edit Profile</Button>
<Button variant="outline" onClick={() => navigate("/onboarding")}>Improve Profile</Button>
<Button
variant="outline"
onClick={() => navigate("/dashboard")}
>
Edit Profile
</Button>
<Button
variant="outline"
onClick={() => navigate("/onboarding")}
>
Improve Profile
</Button>
</div>
</CardContent>
</Card>
@ -92,25 +128,50 @@ export default function Network() {
<Card className="bg-card/50 border-border/50">
<CardHeader>
<CardTitle>Recommendations</CardTitle>
<CardDescription>People who align with your interests</CardDescription>
<CardDescription>
People who align with your interests
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
{recommended.slice(0, 3).map((r) => (
<div key={r.id} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Avatar className="h-10 w-10"><AvatarImage src={r.avatar_url} /><AvatarFallback>{(r.full_name || r.username || "U")[0]}</AvatarFallback></Avatar>
<Avatar className="h-10 w-10">
<AvatarImage src={r.avatar_url} />
<AvatarFallback>
{(r.full_name || r.username || "U")[0]}
</AvatarFallback>
</Avatar>
<div>
<div className="font-medium">{r.full_name || r.username}</div>
<div className="text-xs text-muted-foreground">{r.bio?.slice(0, 40) || "Member"}</div>
<div className="font-medium">
{r.full_name || r.username}
</div>
<div className="text-xs text-muted-foreground">
{r.bio?.slice(0, 40) || "Member"}
</div>
</div>
</div>
<Button size="sm" variant={isFollowing(r.id) ? "outline" : "default"} onClick={() => toggleFollow(r.id)}>
{isFollowing(r.id) ? (<span className="flex items-center gap-1"><UserCheck className="h-4 w-4" /> Following</span>) : (<span className="flex items-center gap-1"><UserPlus className="h-4 w-4" /> Follow</span>)}
<Button
size="sm"
variant={isFollowing(r.id) ? "outline" : "default"}
onClick={() => toggleFollow(r.id)}
>
{isFollowing(r.id) ? (
<span className="flex items-center gap-1">
<UserCheck className="h-4 w-4" /> Following
</span>
) : (
<span className="flex items-center gap-1">
<UserPlus className="h-4 w-4" /> Follow
</span>
)}
</Button>
</div>
))}
{recommended.length === 0 && (
<div className="text-sm text-muted-foreground">No recommendations yet.</div>
<div className="text-sm text-muted-foreground">
No recommendations yet.
</div>
)}
</CardContent>
</Card>
@ -121,25 +182,53 @@ export default function Network() {
<Card className="bg-card/50 border-border/50">
<CardHeader>
<CardTitle>Discover People</CardTitle>
<CardDescription>Connect with creators, clients, and members</CardDescription>
<CardDescription>
Connect with creators, clients, and members
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{recommended.map((r) => (
<div key={r.id} className="flex items-center justify-between p-3 rounded-lg border border-border/50 hover:border-aethex-400/50 transition-all">
<div
key={r.id}
className="flex items-center justify-between p-3 rounded-lg border border-border/50 hover:border-aethex-400/50 transition-all"
>
<div className="flex items-center gap-3">
<Avatar className="h-12 w-12"><AvatarImage src={r.avatar_url} /><AvatarFallback>{(r.full_name || r.username || "U")[0]}</AvatarFallback></Avatar>
<Avatar className="h-12 w-12">
<AvatarImage src={r.avatar_url} />
<AvatarFallback>
{(r.full_name || r.username || "U")[0]}
</AvatarFallback>
</Avatar>
<div>
<div className="font-semibold">{r.full_name || r.username}</div>
<div className="text-xs text-muted-foreground">{r.bio?.slice(0, 80) || "Member"}</div>
<div className="font-semibold">
{r.full_name || r.username}
</div>
<div className="text-xs text-muted-foreground">
{r.bio?.slice(0, 80) || "Member"}
</div>
</div>
</div>
<Button size="sm" variant={isFollowing(r.id) ? "outline" : "default"} onClick={() => toggleFollow(r.id)}>
{isFollowing(r.id) ? (<span className="flex items-center gap-1"><UserCheck className="h-4 w-4" /> Following</span>) : (<span className="flex items-center gap-1"><UserPlus className="h-4 w-4" /> Follow</span>)}
<Button
size="sm"
variant={isFollowing(r.id) ? "outline" : "default"}
onClick={() => toggleFollow(r.id)}
>
{isFollowing(r.id) ? (
<span className="flex items-center gap-1">
<UserCheck className="h-4 w-4" /> Following
</span>
) : (
<span className="flex items-center gap-1">
<UserPlus className="h-4 w-4" /> Follow
</span>
)}
</Button>
</div>
))}
{recommended.length === 0 && (
<div className="text-sm text-muted-foreground">No people found yet.</div>
<div className="text-sm text-muted-foreground">
No people found yet.
</div>
)}
</CardContent>
</Card>