aethex-forge/client/pages/Community.tsx
sirpiglr 4077fac4c9 Move the feed page to the community section and add redirects
Update client-side routing and vercel.json to redirect the /feed endpoint to /community/feed, and integrate the Feed component into the Community page.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: a87bc4c4-2f36-45ef-9537-d97890015ee4
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/duiWnI1
Replit-Helium-Checkpoint-Created: true
2025-12-03 03:11:57 +00:00

4787 lines
199 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Layout from "@/components/Layout";
import SEO from "@/components/SEO";
import Feed from "@/pages/Feed";
const API_BASE = import.meta.env.VITE_API_BASE || "";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import LoadingScreen from "@/components/LoadingScreen";
import { aethexToast } from "@/lib/aethex-toast";
import { cn } from "@/lib/utils";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { useAuth } from "@/contexts/AuthContext";
import FeaturedStudiosGrid from "@/components/community/FeaturedStudiosGrid";
import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
type FormEvent,
type ReactNode,
} from "react";
import {
AlertTriangle,
ArrowDown,
ArrowRight,
Award,
BarChart3,
BookOpen,
Briefcase,
Calendar,
CheckCircle,
ClipboardList,
Clock,
Coffee,
Code,
Flag,
FolderGit2,
Gamepad2,
Gavel,
Github,
Hash,
Headphones,
Heart,
Layers,
Loader2,
Mail,
MapPin,
Megaphone,
MessageCircle,
MessageSquare,
MessageSquarePlus,
MessageSquareText,
Mic,
MonitorSmartphone,
Palette,
Play,
Puzzle,
Search,
Shield,
Shirt,
Sparkles,
Star,
TrendingUp,
Trophy,
Twitter,
Users,
UserCircle,
Video,
Vote,
type LucideIcon,
} from "lucide-react";
type EventStatus = "Registration Open" | "Recurring" | "Upcoming" | "Waitlist";
type CommunityEvent = {
id: string;
title: string;
date: string;
location: string;
type: string;
participants: number;
prize?: string | null;
status: EventStatus;
description: string;
agenda: string[];
registrationEnabled: boolean;
registrationUrl?: string;
};
type EventRegistrationPayload = {
name: string;
email: string;
teamName?: string;
message?: string;
};
type ForumSpace = {
id: string;
name: string;
description: string;
threads: number;
activeToday: number;
latestThread: {
title: string;
author: string;
timeAgo: string;
};
icon: LucideIcon;
};
type FeedbackChannel = {
id: string;
title: string;
description: string;
submissionsThisWeek: number;
statuses: {
label: string;
count: number;
tone: "neutral" | "positive" | "warning";
}[];
owner: string;
icon: LucideIcon;
};
type PollTrend = "up" | "steady" | "down";
type PollOption = {
id: string;
label: string;
votes: number;
trend: PollTrend;
};
type CommunityPoll = {
id: string;
question: string;
closesIn: string;
options: PollOption[];
};
type ChatChannel = {
id: string;
name: string;
description: string;
participants: number;
activeNow: number;
icon: LucideIcon;
};
type ProfileHighlight = {
id: string;
title: string;
description: string;
metricLabel: string;
metricValue: string;
icon: LucideIcon;
};
type WorkshopItem = {
id: string;
title: string;
description: string;
downloads: number;
rating: number;
author: string;
icon: LucideIcon;
};
type MediaItem = {
id: string;
title: string;
type: "Screenshot" | "Artwork" | "Video";
thumbnail: string;
author: string;
likes: number;
};
type SpotlightCreator = {
id: string;
name: string;
role: string;
highlight: string;
link: string;
avatar: string;
metrics: {
label: string;
value: string;
}[];
};
type FeaturedContributor = {
name: string;
avatar: string;
title: string;
contributions: number;
badge: string;
speciality: string;
bio: string;
recentContribution: string;
reputation: string;
profileUrl: string;
};
type ModerationTool = {
id: string;
title: string;
description: string;
icon: LucideIcon;
};
type ReportReason = {
id: string;
label: string;
description: string;
};
interface EventCardProps {
event: CommunityEvent;
animationDelay: number;
isRegistered: boolean;
registrant?: EventRegistrationPayload;
onRegister: (payload: EventRegistrationPayload) => void;
}
function EventCard({
event,
animationDelay,
isRegistered,
registrant,
onRegister,
}: EventCardProps) {
const [open, setOpen] = useState(false);
const [form, setForm] = useState({
name: registrant?.name ?? "",
email: registrant?.email ?? "",
teamName: registrant?.teamName ?? "",
message: registrant?.message ?? "",
});
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (registrant) {
setForm({
name: registrant.name,
email: registrant.email,
teamName: registrant.teamName ?? "",
message: registrant.message ?? "",
});
}
}, [registrant]);
useEffect(() => {
if (!open) {
setError(null);
}
}, [open]);
const handleSubmit = (eventSubmit: FormEvent<HTMLFormElement>) => {
eventSubmit.preventDefault();
const trimmedName = form.name.trim();
const trimmedEmail = form.email.trim();
const trimmedTeam = form.teamName.trim();
const trimmedMessage = form.message.trim();
if (!trimmedName || !trimmedEmail) {
setError("Please provide both your name and email to register.");
return;
}
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(trimmedEmail)) {
setError("Please enter a valid email address.");
return;
}
setError(null);
setSubmitting(true);
setTimeout(() => {
onRegister({
name: trimmedName,
email: trimmedEmail,
teamName: trimmedTeam || undefined,
message: trimmedMessage || undefined,
});
setSubmitting(false);
setOpen(false);
}, 600);
};
const statusStyles: Record<EventStatus, string> = {
"Registration Open":
"bg-gradient-to-r from-emerald-500/20 to-aethex-500/30 text-emerald-200 border border-emerald-400/40",
Recurring: "bg-blue-500/10 text-blue-200 border border-blue-400/40",
Upcoming: "bg-orange-500/10 text-orange-200 border border-orange-400/40",
Waitlist: "bg-amber-500/10 text-amber-200 border border-amber-400/40",
};
const buttonLabel = isRegistered ? "Manage Registration" : "Register";
const submitLabel = isRegistered
? "Update Registration"
: "Confirm Registration";
return (
<Card
className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift animate-slide-right"
style={{ animationDelay: `${animationDelay}s` }}
>
<CardContent className="p-6 space-y-6">
<div className="flex flex-col md:flex-row md:items-start justify-between gap-6">
<div className="space-y-3">
<div className="flex flex-wrap items-center gap-2">
<h3 className="text-xl font-semibold text-gradient">
{event.title}
</h3>
<Badge
className={cn(
"uppercase tracking-wide",
statusStyles[event.status],
)}
>
{event.status}
</Badge>
{isRegistered && (
<Badge className="border border-emerald-400/40 bg-emerald-500/10 text-emerald-200">
<CheckCircle className="mr-1 h-3.5 w-3.5" /> Registered
</Badge>
)}
</div>
<p className="text-sm text-muted-foreground max-w-2xl">
{event.description}
</p>
<div className="flex flex-wrap gap-4 text-sm text-muted-foreground">
<div className="flex items-center space-x-1">
<Calendar className="h-4 w-4" />
<span>{event.date}</span>
</div>
<div className="flex items-center space-x-1">
<MapPin className="h-4 w-4" />
<span>{event.location}</span>
</div>
<div className="flex items-center space-x-1">
<Users className="h-4 w-4" />
<span>{event.participants} spots</span>
</div>
{event.prize && (
<div className="flex items-center space-x-1">
<Award className="h-4 w-4" />
<span>{event.prize}</span>
</div>
)}
</div>
</div>
<div className="flex flex-col items-start gap-3 min-w-[200px]">
<Badge variant="outline" className="w-fit">
{event.type}
</Badge>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button
size="sm"
variant={isRegistered ? "outline" : "default"}
disabled={
!event.registrationEnabled && !event.registrationUrl
}
>
{buttonLabel}
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>{event.title}</DialogTitle>
<DialogDescription>
Reserve your spot by sharing your details. We'll send a
confirmation to your inbox.
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="grid gap-2">
<Label htmlFor={`name-${event.id}`}>Full name</Label>
<Input
id={`name-${event.id}`}
value={form.name}
onChange={(eventChange) =>
setForm((prev) => ({
...prev,
name: eventChange.target.value,
}))
}
placeholder="Enter your name"
required
/>
</div>
<div className="grid gap-2">
<Label htmlFor={`email-${event.id}`}>Email</Label>
<Input
id={`email-${event.id}`}
type="email"
value={form.email}
onChange={(eventChange) =>
setForm((prev) => ({
...prev,
email: eventChange.target.value,
}))
}
placeholder="you@example.com"
required
/>
</div>
<div className="grid gap-2">
<Label htmlFor={`team-${event.id}`}>
Team or studio (optional)
</Label>
<Input
id={`team-${event.id}`}
value={form.teamName}
onChange={(eventChange) =>
setForm((prev) => ({
...prev,
teamName: eventChange.target.value,
}))
}
placeholder="Who are you building with?"
/>
</div>
<div className="grid gap-2">
<Label htmlFor={`notes-${event.id}`}>
Notes for the organizers
</Label>
<Textarea
id={`notes-${event.id}`}
value={form.message}
onChange={(eventChange) =>
setForm((prev) => ({
...prev,
message: eventChange.target.value,
}))
}
placeholder="Let us know about accessibility or collaboration needs"
rows={3}
/>
</div>
{error && <p className="text-sm text-red-400">{error}</p>}
<DialogFooter>
<Button
type="submit"
disabled={submitting}
className="w-full"
>
{submitting ? (
<span className="flex items-center justify-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
Submitting…
</span>
) : (
submitLabel
)}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
{event.registrationUrl && (
<Button
asChild
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-foreground"
>
<a
href={event.registrationUrl}
target="_blank"
rel="noreferrer"
>
Event details
</a>
</Button>
)}
</div>
</div>
<div className="grid gap-3">
<p className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
Session outline
</p>
<ul className="space-y-2">
{event.agenda.map((item) => (
<li
key={item}
className="flex items-start gap-3 text-sm text-muted-foreground"
>
<ArrowRight className="mt-1 h-3.5 w-3.5 text-aethex-400" />
<span>{item}</span>
</li>
))}
</ul>
</div>
</CardContent>
</Card>
);
}
interface SectionHeaderProps {
badge?: string;
title: string;
description: string;
align?: "center" | "left";
}
function SectionHeader({
badge,
title,
description,
align = "center",
}: SectionHeaderProps) {
const containerClass =
align === "center" ? "mx-auto text-center" : "text-left";
return (
<div
className={cn(
"space-y-4 mb-16 animate-slide-up max-w-3xl",
containerClass,
)}
>
{badge && (
<Badge
variant="outline"
className={cn(
"w-fit border-aethex-400/50 text-aethex-300 bg-aethex-500/10",
align === "center" ? "mx-auto" : "",
)}
>
{badge}
</Badge>
)}
<h2 className="text-3xl lg:text-4xl font-bold text-gradient">{title}</h2>
<p className="text-lg text-muted-foreground">{description}</p>
</div>
);
}
interface PollCardProps {
poll: CommunityPoll;
selectedOption?: string;
onSelect: (optionId: string) => void;
}
function PollCard({ poll, selectedOption, onSelect }: PollCardProps) {
const totalVotes = poll.options.reduce(
(sum, option) => sum + option.votes,
0,
);
return (
<Card className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift">
<CardHeader className="space-y-3">
<div className="flex items-center justify-between text-xs uppercase tracking-wide text-muted-foreground">
<span className="flex items-center gap-2">
<Vote className="h-4 w-4 text-aethex-400" />
Community Poll
</span>
<span className="flex items-center gap-1">
<Clock className="h-4 w-4" />
{poll.closesIn}
</span>
</div>
<CardTitle className="text-xl text-foreground">
{poll.question}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
{poll.options.map((option) => {
const percentage =
totalVotes === 0
? 0
: Math.round((option.votes / totalVotes) * 100);
const isSelected = selectedOption === option.id;
const TrendIcon =
option.trend === "up"
? TrendingUp
: option.trend === "down"
? ArrowDown
: ArrowRight;
return (
<Button
key={option.id}
type="button"
variant={isSelected ? "default" : "outline"}
className={cn(
"relative w-full justify-between overflow-hidden border border-border/50 bg-background/80 text-left",
isSelected
? "bg-gradient-to-r from-aethex-500/20 to-neon-blue/20 border-aethex-400/60"
: "hover:border-aethex-400/40",
)}
onClick={() => onSelect(option.id)}
>
{percentage > 0 && (
<span
aria-hidden
className="absolute inset-y-0 left-0 -z-10 bg-aethex-500/10"
style={{ width: `${percentage}%` }}
/>
)}
<span className="flex items-center gap-2 text-sm font-medium">
<TrendIcon className="h-4 w-4" />
{option.label}
</span>
<span className="text-sm font-semibold">{percentage}%</span>
</Button>
);
})}
</div>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>{totalVotes} votes recorded</span>
<Badge
variant="outline"
className="flex items-center gap-1 border-aethex-400/40 bg-aethex-500/10 text-aethex-300"
>
<Sparkles className="h-3 w-3" /> Live insight
</Badge>
</div>
</CardContent>
</Card>
);
}
export default function Community() {
const { profile, user } = useAuth();
const [isLoading, setIsLoading] = useState(true);
const toastShownRef = useRef(false);
const [knowledgeQuery, setKnowledgeQuery] = useState("");
const [newsletterEmail, setNewsletterEmail] = useState("");
const [registeredEvents, setRegisteredEvents] = useState<
Record<string, EventRegistrationPayload>
>({});
const [polls, setPolls] = useState<CommunityPoll[]>(() => [
{
id: "winter-cosmetic",
question:
"Which cosmetic drop should we fast-track for the winter update?",
closesIn: "Closes in 3 days",
options: [
{
id: "frostbyte-operative",
label: "Frostbyte Operative Skin",
votes: 342,
trend: "up",
},
{
id: "aurora-trails",
label: "Aurora Hover Trails",
votes: 287,
trend: "steady",
},
{
id: "synthwave-lobby",
label: "Synthwave Lobby Music Pack",
votes: 198,
trend: "down",
},
],
},
{
id: "platform-priority",
question: "What should the team prioritise next for the companion app?",
closesIn: "Closes in 6 days",
options: [
{
id: "build-tracker",
label: "Squad build tracking & loadouts",
votes: 264,
trend: "up",
},
{
id: "voice-integrations",
label: "Native voice channel integration",
votes: 192,
trend: "steady",
},
{
id: "marketplace",
label: "Creator marketplace beta",
votes: 148,
trend: "up",
},
],
},
]);
const [pollSelections, setPollSelections] = useState<Record<string, string>>(
{},
);
const [reportForm, setReportForm] = useState({ reason: "", details: "" });
const handleKnowledgeSearch = useCallback(
(event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const query = knowledgeQuery.trim();
if (!query) {
aethexToast.system(
"Add a topic or question to search the knowledge base.",
);
return;
}
aethexToast.system(`Searching guides for "${query}"...`);
setKnowledgeQuery("");
},
[knowledgeQuery],
);
const handleNewsletterSignup = useCallback(
(event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const address = newsletterEmail.trim();
if (!address) {
aethexToast.system("Enter your email to join the newsletter.");
return;
}
aethexToast.system(
`Subscribed ${address} to the AeThex community briefing.`,
);
setNewsletterEmail("");
},
[newsletterEmail],
);
useEffect(() => {
const timer = setTimeout(() => {
setIsLoading(false);
if (!toastShownRef.current) {
aethexToast.system("Community hub connected");
toastShownRef.current = true;
}
}, 1000);
return () => clearTimeout(timer);
}, []);
const platforms = [
{
name: "Discord Server",
description: "Real-time chat with developers and get instant help",
icon: MessageSquare,
members: "15K+ members",
activity: "500+ daily active",
link: "/discord",
color: "from-purple-500 to-indigo-600",
},
{
name: "GitHub Community",
description: "Contribute to open source projects and share code",
icon: Github,
members: "8K+ contributors",
activity: "200+ repositories",
link: "/github",
color: "from-gray-700 to-gray-900",
},
{
name: "Twitter Community",
description: "Follow the latest updates and join conversations",
icon: Twitter,
members: "25K+ followers",
activity: "Daily updates",
link: "/twitter",
color: "from-blue-400 to-blue-600",
},
];
const events: CommunityEvent[] = [
{
id: "aethex-game-jam-2025",
title: "AeThex Game Jam 2025",
date: "January 17-19, 2025",
location: "Online",
type: "Competition",
participants: 500,
prize: "$10,000 grand prize",
status: "Registration Open",
description:
"A 48-hour remote jam where cross-discipline teams ship a playable build and pitch their live-ops plan to AeThex Studios.",
agenda: [
"Day 1, 9:00 AM PST — Theme reveal, team sync, and tech check",
"Day 2, 12:00 PM PST — Mentor office hours and vertical slice review",
"Day 3, 3:00 PM PST — Final submissions, judging, and community showcase",
],
registrationEnabled: true,
registrationUrl: "https://devconnect.sbs/events/game-jam-2025",
},
{
id: "weekly-developer-meetup",
title: "Weekly Developer Meetup",
date: "Every Wednesday, 7:00 PM PST",
location: "DevConnect Studio Lounge",
type: "Meetup",
participants: 80,
prize: null,
status: "Recurring",
description:
"An ongoing roundtable for sharing progress, pairing on blockers, and highlighting new community tools across AeThex projects.",
agenda: [
"15 min — Lightning updates from active squads",
"30 min — Deep-dive breakout rooms hosted by AeThex mentors",
"15 min — Open Q&A and contributor shout-outs",
],
registrationEnabled: true,
registrationUrl: "https://devconnect.sbs/events/weekly-meetup",
},
{
id: "ai-in-games-workshop",
title: "AI in Games Workshop",
date: "December 20, 2024",
location: "San Francisco HQ + Live Stream",
type: "Workshop",
participants: 120,
prize: null,
status: "Upcoming",
description:
"Hands-on sessions covering inference optimization, procedural storytelling, and guardrailed AI systems for live games.",
agenda: [
"Session 1 — Deploying performant ML models on AeThex Edge",
"Session 2 — Narrative design with adaptive dialogue tooling",
"Session 3 — Compliance, telemetry, and post-launch monitoring",
],
registrationEnabled: true,
registrationUrl: "https://devconnect.sbs/events/ai-games",
},
];
const stats = [
{ label: "Community Members", value: "50K+", icon: Users },
{ label: "Daily Messages", value: "2K+", icon: MessageCircle },
{ label: "Open Source Projects", value: "200+", icon: Code },
{ label: "Games Created", value: "1K+", icon: Gamepad2 },
];
// Compute onboarding progress from profile
const newMemberSteps = useMemo(() => {
if (!user || !profile) {
return [
{
id: "user-type",
title: "Choose Your Path",
description: "Selected your role: Game Developer, Client, or Member.",
icon: Flag,
completed: false,
},
{
id: "personal-info",
title: "Personal Information",
description: "Set your name, email, and account details.",
icon: UserCircle,
completed: false,
},
{
id: "experience",
title: "Experience Level",
description: "Told us about your background and skills.",
icon: Trophy,
completed: false,
},
{
id: "interests",
title: "Interests & Goals",
description: "Defined your goals and preferred services.",
icon: Sparkles,
completed: false,
},
{
id: "email-verified",
title: "Email Verified",
description: "Confirmed your email address.",
icon: CheckCircle,
completed: false,
},
];
}
return [
{
id: "user-type",
title: "Choose Your Path",
description: "Selected your role: Game Developer, Client, or Member.",
icon: Flag,
completed: Boolean((profile as any)?.user_type),
},
{
id: "personal-info",
title: "Personal Information",
description: "Set your name, email, and account details.",
icon: UserCircle,
completed: Boolean(profile?.full_name),
},
{
id: "experience",
title: "Experience Level",
description: "Told us about your background and skills.",
icon: Trophy,
completed: Boolean((profile as any)?.experience_level),
},
{
id: "interests",
title: "Interests & Goals",
description: "Defined your goals and preferred services.",
icon: Sparkles,
completed: Boolean((profile as any)?.interests?.length > 0),
},
{
id: "email-verified",
title: "Email Verified",
description: "Confirmed your email address.",
icon: CheckCircle,
completed: Boolean(
user?.email_confirmed_at ||
(user?.user_metadata as any)?.email_verified,
),
},
];
}, [user, profile]);
const newMemberResources = [
{
id: "orientation",
title: "Orientation Checklist",
description:
"Track every onboarding milestone with an interactive guide.",
href: "/onboarding",
label: "Open checklist",
},
{
id: "community-tour",
title: "Community Tour",
description:
"Watch a quick walkthrough of forums, events, and support channels.",
href: "/docs/getting-started",
label: "View tour",
},
{
id: "directory",
title: "Browse Creators & Studios",
description: "Discover nonAeThex developers and independent studios.",
href: "/directory",
label: "Open directory",
},
{
id: "starter-kit",
title: "Starter Resource Kit",
description:
"Download templates, style guides, and best practices curated by mentors.",
href: "/docs/examples",
label: "Browse kit",
},
];
const knowledgeSuggestions = [
"Connect Supabase auth",
"Host a community event",
"Fix build pipeline errors",
"Publish a player guide",
];
const knowledgeBaseTopics = [
{
id: "faq",
title: "FAQ & Community Policies",
description:
"Find answers to the most common setup, support, and conduct questions.",
articles: 42,
icon: ClipboardList,
href: "/support",
},
{
id: "how-to",
title: "How-to Guides",
description:
"Step-by-step tutorials for publishing builds, tracking analytics, and launching events.",
articles: 58,
icon: Code,
href: "/docs/tutorials",
},
{
id: "troubleshooting",
title: "Troubleshooting Library",
description:
"Resolve build errors, auth issues, and integration blockers with proven fixes.",
articles: 34,
icon: AlertTriangle,
href: "/status",
},
];
const mentorshipTracks = [
{
id: "technical",
title: "Technical mentorship",
description:
"Pair with senior engineers for architecture reviews, performance tuning, and launch plans.",
mentors: 36,
icon: Code,
},
{
id: "creative",
title: "Creative direction",
description:
"Work with art directors and narrative leads to sharpen your storytelling and worldbuilding.",
mentors: 22,
icon: Sparkles,
},
{
id: "career",
title: "Career coaching",
description:
"Get guidance on portfolios, interviews, and collaborating inside cross-disciplinary teams.",
mentors: 18,
icon: Users,
},
];
const caseStudyHighlights = [
{
id: "aurora",
title: "Aurora Protocol",
summary:
"Scaled from prototype to 150K players after co-developing monetisation loops with AeThex mentors.",
metricLabel: "Retention uplift",
metricValue: "+28%",
icon: TrendingUp,
},
{
id: "zenith",
title: "Project Zenith",
summary:
"Community artists produced 240+ assets in three weeks using our collaborative review pipeline.",
metricLabel: "Assets delivered",
metricValue: "243",
icon: FolderGit2,
},
{
id: "ember",
title: "Ember Syndicate",
summary:
"A mentorship trio rallied devs worldwide to revive a dormant roguelite into a live service.",
metricLabel: "Mentor sessions",
metricValue: "64",
icon: Heart,
},
];
const leaderboardCategories = [
{
id: "contributors",
title: "Top contributors",
description:
"Members with the most merged pull requests and community answers this month.",
leaders: ["QuasarForge", "LunaDev", "SynthRider"],
icon: Award,
},
{
id: "mentors",
title: "Mentor impact",
description:
"Hours spent mentoring, code reviewing, and onboarding new squads.",
leaders: ["ByteSage", "AriaNova", "FluxPilot"],
icon: Heart,
},
{
id: "creators",
title: "Creator highlights",
description:
"Streamers and educators with the highest workshop enrollments and video watch time.",
leaders: ["NeonNarrator", "EchoArtist", "TechnoFable"],
icon: Star,
},
];
const opportunityHighlights = [
{
id: "jobs",
title: "Job & Bounty Board",
description:
"Browse curated studio roles, funded milestones, and one-off bounties refreshed every Monday.",
metrics: [
{ label: "Active opportunities", value: "47" },
{ label: "Average reward", value: "$1.8K" },
],
icon: Briefcase,
href: "/community/opportunities",
ctaLabel: "Browse roles",
},
{
id: "swag",
title: "AeThex Swag Store",
description:
"Rep the community with limited-run drops designed by resident artists and event champions.",
metrics: [
{ label: "Items in stock", value: "32" },
{ label: "Next drop", value: "Aug 18" },
],
icon: Shirt,
href: "/store",
ctaLabel: "Shop collection",
},
];
const creativeActivities = [
{
id: "lore",
title: "Lore & World-Building",
description:
"Co-create canon with writers and narrative designers through weekly prompts and live Q&As.",
icon: Layers,
highlights: [
"Story room every Thursday",
"Archive of approved lore entries",
"Direct feedback from narrative leads",
],
href: "/community/lore",
},
{
id: "fan-art",
title: "Fan Art & Creations",
description:
"Celebrate visual, audio, and written masterpieces with monthly showcases and juried contests.",
icon: Palette,
highlights: [
"Creator of the Month feature",
"Quarterly themed contests",
"Licensing-ready asset library",
],
href: "/community/creators",
},
{
id: "tournaments",
title: "Community Tournaments",
description:
"Host bracketed showdowns, co-op raids, or creative jams with built-in tools and prize support.",
icon: Trophy,
highlights: [
"DIY tournament toolkit",
"Signal-boost in newsletter",
"Staff moderation assistance",
],
href: "/community/events",
},
{
id: "guides",
title: "Player Guides & Walkthroughs",
description:
"Publish mastery guides, speedrun paths, and onboarding walkthroughs with editorial amplification.",
icon: BookOpen,
highlights: [
"Featured guide slot on dashboard",
"Template library for writers",
"Revenue share for premium guides",
],
href: "/community/guides",
},
];
const recognitionPrograms = [
{
id: "ambassadors",
title: "Community Ambassador Program",
description:
"Empower passionate members to welcome newcomers, answer questions, and model best practices.",
icon: Megaphone,
perks: [
"Private strategy briefings",
"Exclusive badge and profile flair",
"Invite-only leadership roundtables",
],
href: "/community/ambassadors",
ctaLabel: "Apply to lead",
},
{
id: "creators",
title: "Content Creator Program",
description:
"Provide media kits, early patch notes, and co-marketing boosts for streamers and educators.",
icon: Video,
perks: [
"Early access to updates",
"Sponsored segment opportunities",
"Dedicated support channel",
],
href: "/community/creators-program",
ctaLabel: "Join the roster",
},
{
id: "feedback",
title: "Feedback & Playtesting Groups",
description:
"Curate squads of experienced players to stress-test builds and share actionable insights.",
icon: MessageSquareText,
perks: [
"Structured feedback templates",
"Direct line to product teams",
"Recognition in patch credits",
],
href: "/community/playtesting",
ctaLabel: "Request access",
},
];
const socialFeatures = [
{
id: "teams",
title: "Team & Guild Finder",
description:
"Match by timezone, skill rating, and preferred game modes to form squads that last.",
icon: Users,
bullets: [
"Smart matching by role and availability",
"Verified guild applications",
"Integrated scrim scheduler",
],
href: "/community/teams",
},
{
id: "setups",
title: "Share Your Setup",
description:
"Show off battlestations, mobile rigs, and cosplays with seasonal themes and prizes.",
icon: MonitorSmartphone,
bullets: [
"Monthly showcase livestream",
"Hardware partner spotlights",
"Community voting for fan favorites",
],
href: "/community/setups",
},
];
const communityTabItems = useMemo(
() => [
{ id: "feed", label: "Feed" },
{ id: "new-members", label: "New Members" },
{ id: "knowledge", label: "Knowledge Base" },
{ id: "mentorship", label: "Mentorship" },
{ id: "case-studies", label: "Case Studies" },
{ id: "leaderboards", label: "Leaderboards" },
{ id: "newsletter", label: "Newsletter" },
{ id: "growth", label: "Growth & Fun" },
{ id: "activities", label: "Content & Activities" },
{ id: "recognition", label: "Recognition" },
{ id: "features", label: "Community Features" },
{ id: "stats", label: "Community Stats" },
{ id: "platforms", label: "Platforms" },
{ id: "devconnect", label: "DevConnect" },
{ id: "forums", label: "Forums" },
{ id: "feedback", label: "Feedback" },
{ id: "polls", label: "Polls" },
{ id: "collaboration", label: "Collaboration" },
{ id: "events", label: "Events" },
{ id: "profiles", label: "Profiles" },
{ id: "featured", label: "Featured Leaders" },
{ id: "workshop", label: "Workshop" },
{ id: "media", label: "Media Galleries" },
{ id: "spotlight", label: "Spotlight" },
{ id: "governance", label: "Governance" },
{ id: "cta", label: "Join Us" },
],
[],
);
const navigate = useNavigate();
const location = useLocation();
const pathSegments = location.pathname.split("/").filter(Boolean);
const candidateTab = pathSegments[1];
const defaultTab = communityTabItems[0]?.id ?? "new-members";
const isValidTab = (value: string | undefined): value is string =>
communityTabItems.some((tab) => tab.id === value);
const activeTab = isValidTab(candidateTab) ? candidateTab : defaultTab;
useEffect(() => {
if (!isValidTab(candidateTab)) {
navigate(`/community/${defaultTab}`, { replace: true });
}
}, [candidateTab, defaultTab]);
const handleTabChange = (value: string) => {
const nextTab = isValidTab(value) ? value : defaultTab;
if (nextTab !== candidateTab) {
navigate(`/community/${nextTab}`);
}
};
const devConnectHighlights = [
{
title: "Unified Developer Profiles",
description:
"Showcase your AeThex achievements, GitHub contributions, and live projects in one public developer hub.",
icon: Users,
},
{
title: "Real-time Collaboration Rooms",
description:
"Spin up focused channels with voice, video, and whiteboards tailored for each build sprint.",
icon: MessageCircle,
},
{
title: "Integrated Delivery Pipeline",
description:
"Track deployments, alerts, and community feedback with automated insights across your stack.",
icon: TrendingUp,
},
];
const forumSpaces: ForumSpace[] = [
{
id: "strategy-lab",
name: "Strategy Lab",
description:
"Break down balance changes and evolving metas with systems designers.",
threads: 182,
activeToday: 46,
latestThread: {
title: "Season 4 economy tuning notes",
author: "PixelPilot",
timeAgo: "1h ago",
},
icon: Hash,
},
{
id: "build-clinic",
name: "Build Clinic",
description:
"Share pipelines, CI setups, and performance wins with fellow builders.",
threads: 241,
activeToday: 63,
latestThread: {
title: "Optimising shader hot reloads in WebGPU",
author: "LunaDev",
timeAgo: "3h ago",
},
icon: MessageSquarePlus,
},
{
id: "playtest-reports",
name: "Playtest Reports",
description:
"Swap qualitative feedback, telemetry, and next-step experiments.",
threads: 96,
activeToday: 22,
latestThread: {
title: "Week 18 retention snapshot",
author: "DataForge",
timeAgo: "30m ago",
},
icon: ClipboardList,
},
];
const feedbackChannels: FeedbackChannel[] = [
{
id: "bug-reports",
title: "Bug Reports",
description:
"Track crashes, blockers, and gameplay issues spotted by players.",
submissionsThisWeek: 52,
statuses: [
{ label: "New", count: 7, tone: "warning" },
{ label: "Triaged", count: 28, tone: "neutral" },
{ label: "Resolved", count: 17, tone: "positive" },
],
owner: "QA Vanguard",
icon: AlertTriangle,
},
{
id: "balance-insights",
title: "Balance Insights",
description:
"Surface tuning feedback for weapons, archetypes, and encounters.",
submissionsThisWeek: 38,
statuses: [
{ label: "In Review", count: 15, tone: "neutral" },
{ label: "Next Patch", count: 9, tone: "positive" },
{ label: "Released", count: 14, tone: "positive" },
],
owner: "Combat Council",
icon: BarChart3,
},
{
id: "feature-ideas",
title: "Ideas & Features",
description:
"Prioritise new systems, cosmetics, and social tools suggested by the community.",
submissionsThisWeek: 61,
statuses: [
{ label: "Ideation", count: 24, tone: "neutral" },
{ label: "Planned", count: 10, tone: "positive" },
{ label: "Backlog", count: 27, tone: "warning" },
],
owner: "Product Guild",
icon: Sparkles,
},
];
const chatChannels: ChatChannel[] = [
{
id: "squad-voice",
name: "Squad Voice Lounge",
description:
"Hop into matchmaking-ready rooms with spatial audio support.",
participants: 640,
activeNow: 132,
icon: Headphones,
},
{
id: "build-help",
name: "Build Help Desk",
description: "Pair programming office hours and live debugging streams.",
participants: 420,
activeNow: 94,
icon: MessageSquareText,
},
{
id: "playtest-queue",
name: "Live Playtest Queue",
description: "Coordinate session times and share immediate reactions.",
participants: 310,
activeNow: 57,
icon: Mic,
},
];
const profileHighlights: ProfileHighlight[] = [
{
id: "portfolio",
title: "Unified Portfolio",
description:
"Link GitHub, AeThex achievements, and live builds in one developer profile.",
metricLabel: "Portfolio views",
metricValue: "3.2K / wk",
icon: Layers,
},
{
id: "streaks",
title: "Contribution Streaks",
description:
"Track commits, bug reports, and mentoring sessions automatically.",
metricLabel: "Longest streak",
metricValue: "48 days",
icon: Sparkles,
},
{
id: "reputation",
title: "Reputation Signals",
description:
"Surface kudos, endorsements, and verified roles in the community.",
metricLabel: "Reputation",
metricValue: "4.9 ★",
icon: UserCircle,
},
];
const contributors: FeaturedContributor[] = [
{
name: "Alex Developer",
avatar:
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=120&h=120&fit=crop&crop=face",
title: "Community Leader",
contributions: 156,
badge: "🏆 Top Contributor",
speciality: "Game Development",
bio: "Hosts the weekly build clinics and mentors new squads shipping co-op missions.",
recentContribution:
"Rolled out the Adaptive Matchmaking toolkit for Season 4.",
reputation: "4.9/5 player rating",
profileUrl: "/passport/alex-developer",
},
{
name: "Sarah Coder",
avatar:
"https://images.unsplash.com/photo-1494790108755-2616b612b029?w=120&h=120&fit=crop&crop=face",
title: "Documentation Expert",
contributions: 89,
badge: "<22><><EFBFBD><EFBFBD> Knowledge Hero",
speciality: "Technical Writing",
bio: "Maintains the AeThex SDK quickstarts and keeps localisation packs up to date.",
recentContribution:
"Launched the multiplayer onboarding walkthrough in seven languages.",
reputation: "4.8/5 creator rating",
profileUrl: "/passport/sarah-coder",
},
{
name: "Jordan AI",
avatar:
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=120&h=120&fit=crop&crop=face",
title: "AI Researcher",
contributions: 134,
badge: "<22><><EFBFBD> AI Pioneer",
speciality: "Machine Learning",
bio: "Builds guardrailed inference pipelines and shares evaluation playbooks weekly.",
recentContribution:
"Released the Procedural Dialogue orchestrator adopted by 40+ teams.",
reputation: "4.9/5 mentor rating",
profileUrl: "/passport/jordan-ai",
},
];
const workshopItems: WorkshopItem[] = [
{
id: "photon-ridge",
title: "Photon Ridge Raid",
description:
"Modded endgame encounter balancing puzzle mechanics with co-op combat.",
downloads: 12045,
rating: 4.8,
author: "NebulaFox",
icon: FolderGit2,
},
{
id: "neon-run",
title: "Neon Run Track Pack",
description:
"Five synthwave-inspired courses with dynamic weather scripting.",
downloads: 8742,
rating: 4.7,
author: "CircuitBreaker",
icon: Puzzle,
},
{
id: "dynamic-hubs",
title: "Dynamic Hub Templates",
description:
"Drop-in lobby layouts with reactive NPC chatter and map voting.",
downloads: 6403,
rating: 4.9,
author: "Astra",
icon: Layers,
},
];
const mediaGallery: MediaItem[] = [
{
id: "screenshot-1",
title: "Aurora Rift",
type: "Screenshot",
thumbnail:
"https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=600&h=400&fit=crop",
author: "Nova",
likes: 684,
},
{
id: "artwork-1",
title: "Character concept: Vox",
type: "Artwork",
thumbnail:
"https://images.unsplash.com/photo-1604079628040-94301bb21b11?w=600&h=400&fit=crop",
author: "Sketchbyte",
likes: 542,
},
{
id: "video-1",
title: "Speedrun showcase",
type: "Video",
thumbnail:
"https://images.unsplash.com/photo-1511512578047-dfb367046420?w=600&h=400&fit=crop",
author: "Dash",
likes: 452,
},
{
id: "screenshot-2",
title: "Photon Ridge sunset",
type: "Screenshot",
thumbnail:
"https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=600&h=400&fit=crop",
author: "NebulaFox",
likes: 398,
},
{
id: "artwork-2",
title: "Kairos armor set",
type: "Artwork",
thumbnail:
"https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=600&h=400&fit=crop",
author: "Synth",
likes: 356,
},
{
id: "video-2",
title: "Live jam timelapse",
type: "Video",
thumbnail:
"https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=600&h=400&fit=crop",
author: "BeatSync",
likes: 312,
},
];
const spotlightCreators: SpotlightCreator[] = [
{
id: "nebulafox",
name: "NebulaFox",
role: "Systems Designer",
highlight:
"Created the Photon Ridge raid encounter adopted by 54% of squads.",
link: "/community/spotlight/nebulafox",
avatar:
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?w=120&h=120&fit=crop&crop=face",
metrics: [
{ label: "Downloads", value: "12K" },
{ label: "Avg Rating", value: "4.8" },
{ label: "Featured Weeks", value: "6" },
],
},
{
id: "lunatech",
name: "LunaTech",
role: "Technical Artist",
highlight:
"Delivered the AeThex holographic shader pack powering six community events.",
link: "/community/spotlight/lunatech",
avatar:
"https://images.unsplash.com/photo-1527980965255-d3b416303d12?w=120&h=120&fit=crop&crop=face",
metrics: [
{ label: "Adopted Studios", value: "32" },
{ label: "Workshop Forks", value: "210" },
{ label: "Tutorial Views", value: "18K" },
],
},
];
const roadmapSnapshot = [
{
id: "roadmap-1",
title: "Patch 3.6 — Balance refresh",
status: "In QA",
statusTone: "positive" as const,
eta: "Shipping Nov 16",
},
{
id: "roadmap-2",
title: "Creator economy beta",
status: "Planning",
statusTone: "neutral" as const,
eta: "Sprint 47",
},
{
id: "roadmap-3",
title: "Voice presence improvements",
status: "Investigating",
statusTone: "warning" as const,
eta: "Discovery ongoing",
},
];
const chatFeatures = [
"Discord bridge keeps roles in sync across text, voice, and forums",
"Threaded replies are archived to knowledge bases automatically",
"Temporary strike teams spin up with stage, video, and whiteboard tools",
];
const moderationGuidelines = [
{
title: "Respect every player",
description:
"Harassment, hate speech, and discrimination are removed without debate.",
},
{
title: "Keep feedback actionable",
description: "Aim critiques at builds and behaviours, never at people.",
},
{
title: "Collaborate transparently",
description:
"Disclose monetisation, affiliations, or sensitive data sources when sharing work.",
},
];
const moderationTools: ModerationTool[] = [
{
id: "auto-shields",
title: "Automated Shields",
description:
"Realtime filters flag slurs, spam, and phishing before they hit the feed.",
icon: Shield,
},
{
id: "casebook",
title: "Casebook Workflows",
description:
"Escalate complex cases with evidence bundles and audit trails.",
icon: Gavel,
},
{
id: "report-routing",
title: "Report Routing",
description:
"Route player reports to dedicated channel owners for rapid follow-up.",
icon: Flag,
},
];
const reportReasons: ReportReason[] = [
{
id: "harassment",
label: "Harassment or hateful content",
description:
"Toxic language, slurs, or targeted harassment toward a player or group.",
},
{
id: "cheating",
label: "Cheating or exploit",
description:
"Sharing hacks, stolen assets, or instructions to bypass fair play.",
},
{
id: "inappropriate",
label: "Inappropriate media",
description:
"Adult content, personal data leaks, or otherwise unsafe material.",
},
];
const feedbackToneStyles: Record<"neutral" | "positive" | "warning", string> =
{
neutral: "bg-blue-500/10 text-blue-200 border border-blue-400/40",
positive:
"bg-emerald-500/10 text-emerald-200 border border-emerald-400/40",
warning: "bg-amber-500/10 text-amber-200 border border-amber-400/40",
};
const selectedReportReason = reportReasons.find(
(reason) => reason.id === reportForm.reason,
);
const handleEventRegistration = useCallback(
(eventData: CommunityEvent, payload: EventRegistrationPayload) => {
setRegisteredEvents((prev) => ({
...prev,
[eventData.id]: payload,
}));
const firstName = payload.name.split(" ")[0] || payload.name;
aethexToast.system(
`${firstName}, you're registered for ${eventData.title}. Confirmation sent to ${payload.email}.`,
);
},
[],
);
const handlePollVote = useCallback(
(pollId: string, optionId: string) => {
setPolls((prevPolls) =>
prevPolls.map((poll) => {
if (poll.id !== pollId) {
return poll;
}
const previousSelection = pollSelections[pollId];
if (previousSelection === optionId) {
return poll;
}
return {
...poll,
options: poll.options.map((option) => {
if (option.id === optionId) {
return { ...option, votes: option.votes + 1 };
}
if (previousSelection && option.id === previousSelection) {
return { ...option, votes: Math.max(0, option.votes - 1) };
}
return option;
}),
};
}),
);
setPollSelections((prev) => ({
...prev,
[pollId]: optionId,
}));
},
[pollSelections],
);
const handleReportSubmit = useCallback(
async (submitEvent: FormEvent<HTMLFormElement>) => {
submitEvent.preventDefault();
const trimmedDetails = reportForm.details.trim();
if (!reportForm.reason) {
aethexToast.system("Select a reason before submitting a report.");
return;
}
if (!trimmedDetails) {
aethexToast.system(
"Add a brief description so moderators can respond quickly.",
);
return;
}
try {
const resp = await fetch(`${API_BASE}/api/moderation/reports`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
reporter_id: (profile as any)?.id || null,
target_type: "other",
target_id: null,
reason: reportForm.reason,
details: trimmedDetails,
}),
});
if (!resp.ok) {
const msg = await resp.text();
throw new Error(msg || "Failed to submit report");
}
aethexToast.system(
"Report submitted. Our moderation team will review shortly.",
);
setReportForm({ reason: "", details: "" });
} catch (e: any) {
aethexToast.system(String(e?.message || e));
}
},
[reportForm, profile],
);
if (isLoading) {
return (
<LoadingScreen
message="Connecting to Community..."
showProgress={true}
duration={1000}
/>
);
}
return (
<>
<SEO
pageTitle="Community"
description="AeThex Community: share progress, discover collaborators, and stay updated."
canonical={
typeof window !== "undefined"
? window.location.href
: (undefined as any)
}
/>
<Layout>
<div className="min-h-screen bg-aethex-gradient">
{/* Hero Section */}
<section className="relative py-20 lg:py-32">
<div className="container mx-auto px-4 text-center relative z-10">
<div className="max-w-4xl mx-auto space-y-8">
<Badge
variant="outline"
className="border-aethex-400/50 text-aethex-400 animate-bounce-gentle"
>
<Users className="h-3 w-3 mr-1" />
AeThex Community
</Badge>
<h1 className="text-4xl lg:text-6xl font-bold leading-tight">
<span className="text-gradient-purple">
Join the Innovation Network
</span>
</h1>
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
Connect with developers, creators, and innovators from around
the world. Share knowledge, collaborate on projects, and grow
together.
</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<Button
asChild
size="lg"
className="bg-gradient-to-r from-aethex-500 to-neon-blue hover:from-aethex-600 hover:to-neon-blue/90 glow-blue hover-lift"
>
<Link to="/discord" className="flex items-center space-x-2">
<MessageSquare className="h-5 w-5" />
<span>Join Discord</span>
<ArrowRight className="h-5 w-5" />
</Link>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="border-border/50 hover-lift"
>
<Link to="/github">View Projects</Link>
</Button>
</div>
</div>
</div>
</section>
<Tabs
value={activeTab}
onValueChange={handleTabChange}
className="space-y-12"
>
<div className="container mx-auto px-4">
<div className="overflow-x-auto pb-2">
<TabsList className="flex w-max flex-nowrap gap-2 rounded-2xl border border-border/60 bg-background/60 p-2">
{communityTabItems.map((tab) => (
<TabsTrigger
key={tab.id}
value={tab.id}
className="rounded-xl px-4 py-2 text-sm font-semibold text-muted-foreground transition whitespace-nowrap data-[state=active]:bg-gradient-to-r data-[state=active]:from-aethex-500/20 data-[state=active]:to-neon-blue/20 data-[state=active]:text-foreground data-[state=active]:shadow"
>
{tab.label}
</TabsTrigger>
))}
</TabsList>
</div>
</div>
{activeTab === "feed" && (
<TabsContent value="feed" className="mt-0">
<Feed embedded />
</TabsContent>
)}
{activeTab === "new-members" && (
<TabsContent value="new-members" className="mt-0">
{/* New Member Hub */}
<section className="py-20 bg-background/40">
<div className="container mx-auto px-4">
<SectionHeader
badge="New Member Hub"
title="Start strong in your first 7 days"
description="Follow a guided path, watch the welcome tour, and unlock your first achievements fast."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr,3fr]">
<Card className="relative overflow-hidden border-border/60 bg-background/80 backdrop-blur-xl">
<CardContent className="p-0">
<div className="relative aspect-video bg-gradient-to-br from-aethex-500/30 via-background to-neon-blue/30 flex items-center justify-center">
<div className="flex flex-col items-center space-y-4">
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-background/80 border border-aethex-400/50 shadow-lg shadow-aethex-500/20">
<Play className="h-8 w-8 text-aethex-400" />
</div>
<div className="text-center space-y-2">
<h3 className="text-xl font-semibold text-gradient">
Welcome to AeThex
</h3>
<p className="text-sm text-muted-foreground max-w-sm">
Learn how to customise your profile, meet
mentors, and ship your first contribution.
</p>
</div>
<Button asChild>
<a
href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
target="_blank"
rel="noreferrer"
className="flex items-center space-x-2"
>
<span>Watch welcome briefing</span>
<ArrowRight className="h-4 w-4" />
</a>
</Button>
</div>
<div className="absolute inset-0 pointer-events-none bg-[radial-gradient(circle_at_center,_rgba(80,199,255,0.25),_transparent_70%)]" />
</div>
<div className="p-6 space-y-4">
<h3 className="text-lg font-semibold text-foreground">
Orientation snapshot
</h3>
<div className="grid gap-3">
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Average onboarding time</span>
<span className="font-semibold text-aethex-400">
22 mins
</span>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Mentors online right now</span>
<span className="font-semibold text-aethex-400">
18
</span>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Starter quests completed this week</span>
<span className="font-semibold text-aethex-400">
412
</span>
</div>
</div>
</div>
</CardContent>
</Card>
<div className="grid gap-6">
<Card className="border-border/60 bg-background/80">
<CardHeader className="space-y-2">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<CheckCircle className="h-4 w-4 text-aethex-400" />
First steps checklist
</div>
<CardTitle className="text-2xl">
Ship your first wins this week
</CardTitle>
<CardDescription>
Work through the essentials and unlock the New
Recruit badge.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<ul className="space-y-4">
{newMemberSteps.map((step) => {
const Icon = step.icon;
return (
<li
key={step.id}
className="flex gap-4 group"
>
<div
className={cn(
"flex h-10 w-10 items-center justify-center rounded-lg transition-all",
step.completed
? "bg-emerald-500/20 text-emerald-400"
: "bg-aethex-500/10 text-aethex-300",
)}
>
{step.completed ? (
<CheckCircle className="h-5 w-5" />
) : (
<Icon className="h-5 w-5" />
)}
</div>
<div className="space-y-1 flex-1">
<p
className={cn(
"font-semibold",
step.completed
? "text-emerald-400 line-through"
: "text-foreground",
)}
>
{step.title}
</p>
<p className="text-sm text-muted-foreground">
{step.description}
</p>
</div>
{!step.completed && (
<Button
asChild
variant="ghost"
size="sm"
className="opacity-0 group-hover:opacity-100 transition-opacity"
>
<Link to="/onboarding">Complete</Link>
</Button>
)}
{step.completed && (
<Badge
variant="outline"
className="border-emerald-500/30 bg-emerald-500/10 text-emerald-400"
>
Done
</Badge>
)}
</li>
);
})}
</ul>
</CardContent>
</Card>
<Card className="border-border/60 bg-background/80">
<CardHeader className="space-y-2">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Sparkles className="h-4 w-4 text-aethex-400" />
Quick wins
</div>
<CardTitle className="text-2xl">
Jump into the right resources
</CardTitle>
<CardDescription>
Explore guides and shortcuts tailored for
first-time members.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
{newMemberResources.map((resource) => (
<div
key={resource.id}
className="flex flex-col gap-2 rounded-lg border border-border/40 bg-background/60 p-4 hover:border-aethex-400/40 transition-colors"
>
<div className="flex items-center justify-between gap-3">
<div>
<p className="font-semibold text-foreground">
{resource.title}
</p>
<p className="text-sm text-muted-foreground">
{resource.description}
</p>
</div>
<ArrowRight className="h-4 w-4 text-aethex-400" />
</div>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link to={resource.href}>
{resource.label}
</Link>
</Button>
</div>
))}
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "knowledge" && (
<TabsContent value="knowledge" className="mt-0">
{/* Knowledge Base */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Knowledge Base"
title="Search answers and how-to guides"
description="Get instant access to FAQs, tutorials, and troubleshooting playbooks maintained by the community."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr,3fr]">
<Card className="border-border/60 bg-background/80">
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Search className="h-4 w-4 text-aethex-400" />
Search the library
</div>
<CardTitle className="text-2xl">
Find step-by-step help
</CardTitle>
<CardDescription>
Enter a topic, tool, or problem and we will surface
curated guides written by mentors and staff.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<form
onSubmit={handleKnowledgeSearch}
className="space-y-3"
>
<div className="relative">
<Input
value={knowledgeQuery}
onChange={(event) =>
setKnowledgeQuery(event.target.value)
}
placeholder="e.g. Deploying multiplayer servers"
className="pl-10 bg-background/60 border-border/60"
aria-label="Search knowledge base"
/>
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
</div>
<Button
type="submit"
className="w-full justify-center"
>
Search articles
</Button>
</form>
<div className="space-y-2">
<p className="text-xs uppercase tracking-wide text-muted-foreground">
Quick suggestions
</p>
<div className="flex flex-wrap gap-2">
{knowledgeSuggestions.map((suggestion) => (
<Button
key={suggestion}
type="button"
variant="outline"
size="sm"
className="border-border/60"
onClick={() => setKnowledgeQuery(suggestion)}
>
{suggestion}
</Button>
))}
</div>
</div>
</CardContent>
</Card>
<div className="grid gap-4 sm:grid-cols-2">
{knowledgeBaseTopics.map((topic) => {
const Icon = topic.icon;
return (
<Card
key={topic.id}
className="border-border/50 bg-background/70 transition-all duration-300 hover:-translate-y-1 hover:border-aethex-400/60"
>
<CardHeader className="space-y-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Icon className="h-5 w-5 text-aethex-300" />
{topic.articles} articles
</div>
<Badge
variant="outline"
className="border-border/60"
>
Updated weekly
</Badge>
</div>
<CardTitle className="text-lg text-foreground">
{topic.title}
</CardTitle>
<CardDescription>
{topic.description}
</CardDescription>
</CardHeader>
<CardContent>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link to={topic.href}>Explore resources</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "mentorship" && (
<TabsContent value="mentorship" className="mt-0">
{/* Mentorship Program */}
<section className="py-20 bg-background/20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Mentorship"
title="Level up with experienced guides"
description="Match with mentors for technical deep dives, creative direction, and career coaching."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[3fr,2fr]">
<Card className="border-border/60 bg-background/80">
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Sparkles className="h-4 w-4 text-aethex-400" />
Mentor spotlight
</div>
<CardTitle className="text-2xl">
Kick off a guided sprint
</CardTitle>
<CardDescription>
Submit your goals and interests, and well connect
you with mentors who ship in similar spaces.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<ul className="space-y-3 text-sm text-muted-foreground">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-aethex-400" />
1:1 sessions and group clinics each week
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-aethex-400" />
Direct feedback on builds, pitch decks, and
production plans
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-aethex-400" />
Priority invites to closed playtests and God Mode
rewards
</li>
</ul>
<div className="flex flex-col sm:flex-row gap-3">
<Button asChild className="flex-1">
<Link to="/community/mentorship">
Request mentorship
</Link>
</Button>
<Button
asChild
variant="outline"
className="flex-1"
>
<Link to="/community/mentorship/apply">
Become a mentor
</Link>
</Button>
</div>
</CardContent>
</Card>
<div className="grid gap-4">
{mentorshipTracks.map((track) => {
const Icon = track.icon;
return (
<div
key={track.id}
className="rounded-xl border border-border/50 bg-background/70 p-5 hover:border-aethex-400/50 transition"
>
<div className="flex items-start gap-3">
<div className="mt-1 flex h-10 w-10 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div className="space-y-1">
<p className="text-lg font-semibold text-foreground">
{track.title}
</p>
<p className="text-sm text-muted-foreground">
{track.description}
</p>
<p className="text-xs uppercase tracking-wide text-muted-foreground">
{track.mentors} mentors available
</p>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "case-studies" && (
<TabsContent value="case-studies" className="mt-0">
{/* Case Studies */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Case Studies"
title="See how teams scale with AeThex"
description="Deep dives into projects that leveraged the community for momentum, funding, and retention."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{caseStudyHighlights.map((study) => {
const Icon = study.icon;
return (
<Card
key={study.id}
className="relative overflow-hidden border-border/60 bg-background/80 backdrop-blur-xl"
>
<div className="absolute inset-0 bg-gradient-to-br from-aethex-500/10 via-transparent to-neon-blue/10" />
<CardHeader className="relative space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Icon className="h-5 w-5 text-aethex-300" />
{study.metricLabel}
</div>
<CardTitle className="text-2xl text-foreground">
{study.title}
</CardTitle>
<p className="text-sm font-semibold text-aethex-300">
{study.metricValue}
</p>
</CardHeader>
<CardContent className="relative space-y-4">
<p className="text-sm text-muted-foreground leading-relaxed">
{study.summary}
</p>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link
to={`/community/case-studies/${study.id}`}
>
Read full story
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "leaderboards" && (
<TabsContent value="leaderboards" className="mt-0">
{/* Leaderboards */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Gamification"
title="Celebrate contributions across the network"
description="Track streaks, highlight achievements, and fuel friendly competition among builders."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{leaderboardCategories.map((category) => {
const Icon = category.icon;
return (
<Card
key={category.id}
className="border border-border/50 bg-background/70 shadow-sm hover:border-aethex-400/50 transition"
>
<CardHeader className="space-y-3">
<div className="flex items-center justify-between text-sm uppercase tracking-wide text-muted-foreground">
<span className="flex items-center gap-2">
<Icon className="h-4 w-4 text-aethex-300" />
{category.title}
</span>
<Badge
variant="outline"
className="border-border/50"
>
Updated daily
</Badge>
</div>
<CardDescription>
{category.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-2">
<ol className="space-y-1 text-sm">
{category.leaders.map((leader, index) => (
<li
key={leader}
className="flex items-center gap-2"
>
<span className="text-muted-foreground">
#{index + 1}
</span>
<span className="font-medium text-foreground">
{leader}
</span>
</li>
))}
</ol>
</CardContent>
</Card>
);
})}
</div>
<div className="mt-8 text-left">
<Button
asChild
variant="outline"
className="border-border/60"
>
<Link to="/community/leaderboards">
View full leaderboards
</Link>
</Button>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "newsletter" && (
<TabsContent value="newsletter" className="mt-0">
{/* Community Newsletter */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Briefing"
title="Get the top discussions in your inbox"
description="Stay ahead with weekly highlights, upcoming events, and featured creators curated by the AeThex team."
align="left"
/>
<Card className="border-border/60 bg-background/80 max-w-3xl">
<CardContent className="space-y-4 p-6 lg:p-8">
<div className="flex flex-col gap-3 text-sm text-muted-foreground">
<div className="flex items-center gap-2 text-xs uppercase tracking-wide">
<Mail className="h-4 w-4 text-aethex-300" />
Weekly digest
</div>
<p>
Each Monday we share major updates, spotlight
champions, and surface new opportunities—no noise,
just impact.
</p>
</div>
<form
onSubmit={handleNewsletterSignup}
className="flex flex-col gap-3 sm:flex-row"
>
<Input
type="email"
required
value={newsletterEmail}
onChange={(event) =>
setNewsletterEmail(event.target.value)
}
placeholder="you@example.com"
className="bg-background/60 border-border/60"
aria-label="Email address"
/>
<Button type="submit" className="sm:w-auto">
Subscribe
</Button>
</form>
<p className="text-xs text-muted-foreground">
We respect your time—unsubscribe anytime with a single
click.
</p>
</CardContent>
</Card>
</div>
</section>
</TabsContent>
)}
{activeTab === "growth" && (
<TabsContent value="growth" className="mt-0">
{/* Professional Growth & Fun */}
<section className="py-20 bg-background/20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Professional Growth & Fun"
title="Discover new opportunities and show your AeThex pride"
description="Connect with studios, earn bounties, and rock exclusive merch designed by the community."
align="left"
/>
<div className="grid gap-6 md:grid-cols-2">
{opportunityHighlights.map((item) => {
const Icon = item.icon;
return (
<Card
key={item.id}
className="border-border/50 bg-background/75 transition hover:-translate-y-1 hover:border-aethex-400/50"
>
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Icon className="h-4 w-4 text-aethex-300" />
{item.title}
</div>
<CardDescription>
{item.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid gap-3 sm:grid-cols-2">
{item.metrics.map((metric) => (
<div
key={metric.label}
className="rounded-lg border border-border/40 bg-background/60 p-3 text-sm"
>
<p className="text-muted-foreground">
{metric.label}
</p>
<p className="text-xl font-semibold text-foreground">
{metric.value}
</p>
</div>
))}
</div>
<Button
asChild
variant="outline"
className="w-fit"
>
<Link to={item.href}>{item.ctaLabel}</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "activities" && (
<TabsContent value="activities" className="mt-0">
{/* Content & Activities */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Content & Activities"
title="Create, compete, and build the universe together"
description="From lore summits to fan-art showcases, the community drives the culture forward."
align="left"
/>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
{creativeActivities.map((activity) => {
const Icon = activity.icon;
return (
<Card
key={activity.id}
className="border-border/50 bg-background/75 hover:border-aethex-400/50 transition"
>
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Icon className="h-4 w-4 text-aethex-300" />
{activity.title}
</div>
<CardDescription>
{activity.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<ul className="space-y-2 text-xs text-muted-foreground">
{activity.highlights.map((highlight) => (
<li
key={highlight}
className="flex items-start gap-2"
>
<ArrowRight className="mt-0.5 h-3 w-3 text-aethex-400" />
<span>{highlight}</span>
</li>
))}
</ul>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link to={activity.href}>Join in</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "recognition" && (
<TabsContent value="recognition" className="mt-0">
{/* Recognition & Roles */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Recognition & Roles"
title="Support champions powering the community"
description="Formal programs that reward ambassadors, creators, and playtest squads for their impact."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{recognitionPrograms.map((program) => {
const Icon = program.icon;
return (
<Card
key={program.id}
className="border-border/50 bg-background/75 hover:border-aethex-400/60 transition"
>
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Icon className="h-4 w-4 text-aethex-300" />
{program.title}
</div>
<CardDescription>
{program.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<ul className="space-y-2 text-xs text-muted-foreground">
{program.perks.map((perk) => (
<li
key={perk}
className="flex items-start gap-2"
>
<ArrowRight className="mt-0.5 h-3 w-3 text-aethex-400" />
<span>{perk}</span>
</li>
))}
</ul>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link to={program.href}>
{program.ctaLabel}
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "features" && (
<TabsContent value="features" className="mt-0">
{/* Community Features */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Features"
title="Form squads and celebrate your setup"
description="Tools that make it easy to find teammates and showcase the spaces where you build."
align="left"
/>
<div className="grid gap-6 md:grid-cols-2">
{socialFeatures.map((feature) => {
const Icon = feature.icon;
return (
<Card
key={feature.id}
className="border-border/50 bg-background/80 hover:border-aethex-400/50 transition"
>
<CardHeader className="space-y-3">
<div className="flex items-center gap-2 text-sm uppercase tracking-wide text-muted-foreground">
<Icon className="h-4 w-4 text-aethex-300" />
{feature.title}
</div>
<CardDescription>
{feature.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<ul className="space-y-2 text-xs text-muted-foreground">
{feature.bullets.map((bullet) => (
<li
key={bullet}
className="flex items-start gap-2"
>
<ArrowRight className="mt-0.5 h-3 w-3 text-aethex-400" />
<span>{bullet}</span>
</li>
))}
</ul>
<Button
asChild
variant="outline"
size="sm"
className="w-fit"
>
<Link to={feature.href}>Explore</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "stats" && (
<TabsContent value="stats" className="mt-0">
{/* Community Stats */}
<section className="py-16 bg-background/30">
<div className="container mx-auto px-4">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 max-w-4xl mx-auto">
{stats.map((stat, index) => {
const Icon = stat.icon;
return (
<div
key={stat.label}
className="text-center space-y-3 animate-scale-in"
style={{ animationDelay: `${index * 0.1}s` }}
>
<div className="flex justify-center">
<div className="p-3 rounded-lg bg-gradient-to-r from-aethex-500/20 to-neon-blue/20 border border-aethex-400/20">
<Icon className="h-6 w-6 text-aethex-400" />
</div>
</div>
<div>
<div className="text-3xl font-bold text-gradient">
{stat.value}
</div>
<p className="text-sm text-muted-foreground uppercase tracking-wide">
{stat.label}
</p>
</div>
</div>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "platforms" && (
<TabsContent value="platforms" className="mt-0">
{/* Community Platforms */}
<section className="py-20">
<div className="container mx-auto px-4">
<div className="text-center mb-16 animate-slide-up">
<h2 className="text-3xl lg:text-4xl font-bold text-gradient mb-4">
Connect on Your Favorite Platform
</h2>
<p className="text-lg text-muted-foreground">
Multiple ways to engage with the AeThex community
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
{platforms.map((platform, index) => {
const Icon = platform.icon;
return (
<Card
key={platform.name}
className="text-center border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift animate-scale-in"
style={{ animationDelay: `${index * 0.2}s` }}
>
<CardHeader>
<div
className={`mx-auto w-16 h-16 rounded-lg bg-gradient-to-r ${platform.color} flex items-center justify-center mb-4`}
>
<Icon className="h-8 w-8 text-white" />
</div>
<CardTitle className="text-xl">
{platform.name}
</CardTitle>
<CardDescription>
{platform.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 gap-2 text-sm">
<div className="flex justify-between">
<span>Members:</span>
<span className="font-semibold text-aethex-400">
{platform.members}
</span>
</div>
<div className="flex justify-between">
<span>Activity:</span>
<span className="font-semibold text-aethex-400">
{platform.activity}
</span>
</div>
</div>
<Button asChild className="w-full">
<Link to={platform.link}>
Join Now
<ArrowRight className="h-4 w-4 ml-2" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "devconnect" && (
<TabsContent value="devconnect" className="mt-0">
{/* DevConnect Spotlight */}
<section className="relative py-20 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-aethex-900/40 via-transparent to-neon-blue/30" />
<div className="container mx-auto px-4 relative z-10">
<div className="max-w-5xl mx-auto grid lg:grid-cols-[2fr_3fr] gap-10 items-center">
<div className="space-y-6 animate-slide-left">
<Badge className="bg-gradient-to-r from-aethex-500 to-neon-blue w-fit">
New Platform
</Badge>
<h2 className="text-3xl lg:text-4xl font-bold text-gradient">
Introducing DevConnect
</h2>
<p className="text-lg text-muted-foreground">
DevConnect is our dedicated hub for platform teams
building the next wave of AeThex experiences. Launch
collabs, monitor live services, and activate the
Studio network — all from one command center.
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Button
asChild
size="lg"
className="bg-gradient-to-r from-neon-blue to-aethex-500 hover:from-neon-blue/90 hover:to-aethex-500/90 glow-blue hover-lift"
>
<a
href="https://devconnect.sbs"
target="_blank"
rel="noreferrer"
className="flex items-center space-x-2"
>
<span>Launch DevConnect</span>
<ArrowRight className="h-5 w-5" />
</a>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="border-border/60"
>
<Link to="/contact">Talk with AeThex Team</Link>
</Button>
</div>
</div>
<Card className="border-border/40 bg-background/80 backdrop-blur-xl shadow-lg shadow-aethex-500/10 animate-slide-right">
<CardContent className="p-8 space-y-6">
<div className="grid gap-4">
{devConnectHighlights.map((highlight, index) => {
const Icon = highlight.icon;
return (
<div
key={highlight.title}
className="flex items-start gap-4 p-4 rounded-xl border border-border/40 bg-background/60"
>
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-r from-aethex-500/20 to-neon-blue/20 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div className="space-y-1">
<h3 className="font-semibold text-foreground">
{highlight.title}
</h3>
<p className="text-sm text-muted-foreground">
{highlight.description}
</p>
</div>
</div>
);
})}
</div>
<div className="rounded-lg border border-aethex-400/40 bg-gradient-to-r from-aethex-500/10 to-neon-blue/10 p-4 text-sm text-muted-foreground">
DevConnect syncs directly with AeThex developer
profiles, so your activity, streaks, and
achievements follow you across every build.
</div>
</CardContent>
</Card>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "forums" && (
<TabsContent value="forums" className="mt-0">
{/* Forums & Discussion */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Forums & Discussions"
title="Deep-dive with peers in dedicated boards"
description="Launch structured conversations for strategy, support, and storytelling."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{forumSpaces.map((space, index) => {
const Icon = space.icon;
return (
<Card
key={space.id}
className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift"
style={{ animationDelay: `${index * 0.1}s` }}
>
<CardHeader className="space-y-4">
<div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<CardTitle className="text-lg">
{space.name}
</CardTitle>
<CardDescription>
{space.description}
</CardDescription>
</div>
</div>
<Badge
variant="outline"
className="border-border/50"
>
{space.threads} threads
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between text-xs text-muted-foreground uppercase tracking-wide">
<span>{space.activeToday} active today</span>
<span className="flex items-center gap-2">
<MessageCircle className="h-3.5 w-3.5" />{" "}
Latest
</span>
</div>
<div className="rounded-lg border border-border/40 bg-background/80 p-4">
<p className="text-sm font-medium text-foreground">
{space.latestThread.title}
</p>
<p className="text-xs text-muted-foreground">
by {space.latestThread.author} •{" "}
{space.latestThread.timeAgo}
</p>
</div>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to={`/forums/${space.id}`}>
Enter space
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "feedback" && (
<TabsContent value="feedback" className="mt-0">
{/* Feedback & Roadmap */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Feedback & Roadmap"
title="Collect insights and close the loop with players"
description="Organise bug reports, balance discussions, and feature ideas in a transparent queue."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr_3fr]">
<div className="space-y-6">
{feedbackChannels.map((channel) => {
const Icon = channel.icon;
return (
<Card
key={channel.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex items-start justify-between gap-4">
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<CardTitle className="text-lg">
{channel.title}
</CardTitle>
<CardDescription>
{channel.description}
</CardDescription>
</div>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
{channel.submissionsThisWeek} this week
</Badge>
</div>
<p className="text-xs text-muted-foreground uppercase tracking-wide">
Stewarded by {channel.owner}
</p>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex flex-wrap gap-2">
{channel.statuses.map((status) => (
<Badge
key={status.label}
className={cn(
"text-xs",
feedbackToneStyles[status.tone],
)}
>
{status.label}: {status.count}
</Badge>
))}
</div>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to="/feedback">
Submit feedback
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Live roadmap snapshot</CardTitle>
<CardDescription>
Track what the team is shipping next based on player
momentum.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{roadmapSnapshot.map((item) => (
<div
key={item.id}
className="flex flex-col gap-2 rounded-lg border border-border/40 bg-background/80 p-4 sm:flex-row sm:items-center sm:justify-between"
>
<div>
<p className="font-medium text-foreground">
{item.title}
</p>
<p className="text-xs text-muted-foreground">
{item.eta}
</p>
</div>
<Badge
className={feedbackToneStyles[item.statusTone]}
>
{item.status}
</Badge>
</div>
))}
<Button
asChild
variant="outline"
className="w-full border-aethex-400/40"
>
<Link to="/roadmap">Open public roadmap</Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "polls" && (
<TabsContent value="polls" className="mt-0">
{/* Community Polls */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Polls"
title="Let players steer the next big moves"
description="Run lightweight polls to validate cosmetics, roadmap priorities, and upcoming events."
align="center"
/>
<div className="grid gap-6 md:grid-cols-2 max-w-5xl mx-auto">
{polls.map((poll) => (
<PollCard
key={poll.id}
poll={poll}
selectedOption={pollSelections[poll.id]}
onSelect={(optionId) =>
handlePollVote(poll.id, optionId)
}
/>
))}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "collaboration" && (
<TabsContent value="collaboration" className="mt-0">
{/* Real-time Collaboration */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Real-time Collaboration"
title="Integrated chat with Discord-style presence"
description="Spin up voice, text, and co-working rooms that bridge seamlessly with our forums and developer hubs."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[3fr_2fr]">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Active channels</CardTitle>
<CardDescription>
See whos online and jump into the conversations
that matter right now.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{chatChannels.map((channel) => {
const Icon = channel.icon;
return (
<div
key={channel.id}
className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-3"
>
<div className="flex items-start justify-between gap-3">
<div className="flex items-start gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<p className="font-medium text-foreground">
{channel.name}
</p>
<p className="text-sm text-muted-foreground">
{channel.description}
</p>
</div>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
{channel.participants} members
</Badge>
</div>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>Synced with Discord</span>
<span className="flex items-center gap-1 text-emerald-200">
<Sparkles className="h-3 w-3" />{" "}
{channel.activeNow} live now
</span>
</div>
</div>
);
})}
</CardContent>
</Card>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>
Why players love integrated chat
</CardTitle>
<CardDescription>
Keep every squad aligned across devices with
presence, threads, and recordings.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<ul className="space-y-3 text-sm text-muted-foreground">
{chatFeatures.map((feature) => (
<li
key={feature}
className="flex items-start gap-3"
>
<CheckCircle className="mt-0.5 h-4 w-4 text-aethex-400" />
<span>{feature}</span>
</li>
))}
</ul>
<Button asChild className="w-full">
<Link to="/chat">Launch real-time hub</Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "events" && (
<TabsContent value="events" className="mt-0">
{/* Upcoming Events */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Events"
title="Upcoming events"
description="Join our community events and level up your skills."
align="center"
/>
<div className="max-w-4xl mx-auto space-y-6">
{events.map((event, index) => (
<EventCard
key={event.id}
event={event}
animationDelay={index * 0.12}
isRegistered={Boolean(registeredEvents[event.id])}
registrant={registeredEvents[event.id]}
onRegister={(payload) =>
handleEventRegistration(event, payload)
}
/>
))}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "profiles" && (
<TabsContent value="profiles" className="mt-0">
{/* Developer Profile Highlights */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Developer Profiles"
title="Showcase your journey across AeThex"
description="Developer profiles blend achievements, portfolio pieces, and social proof so collaborators can find you fast."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{profileHighlights.map((highlight) => {
const Icon = highlight.icon;
return (
<Card
key={highlight.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-6 w-6" />
</div>
<CardTitle className="text-lg">
{highlight.title}
</CardTitle>
<CardDescription>
{highlight.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="rounded-lg border border-border/40 bg-background/80 p-4">
<p className="text-xs uppercase tracking-wide text-muted-foreground">
{highlight.metricLabel}
</p>
<p className="text-2xl font-semibold text-gradient-purple">
{highlight.metricValue}
</p>
</div>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "featured" && (
<TabsContent value="featured" className="mt-0">
{/* Featured Developers */}
<section
id="featured-developers"
className="py-20 bg-background/30"
>
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Leaders"
title="Featured developers"
description="Highlighting builders who mentor others, ship mods, and level up the entire network."
align="center"
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
{contributors.map((contributor, index) => (
<Card
key={contributor.name}
className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift animate-scale-in"
style={{ animationDelay: `${index * 0.2}s` }}
>
<CardContent className="p-6 space-y-4 text-center">
<img
src={contributor.avatar}
alt={contributor.name}
className="w-20 h-20 rounded-full mx-auto ring-4 ring-aethex-400/20"
/>
<div className="space-y-1">
<h3 className="font-semibold text-lg text-gradient">
{contributor.name}
</h3>
<p className="text-sm text-muted-foreground">
{contributor.title}
</p>
</div>
<Badge variant="outline" className="mx-auto">
{contributor.speciality}
</Badge>
<p className="text-sm text-muted-foreground text-left">
{contributor.bio}
</p>
<div className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-2 text-left">
<p className="text-sm font-medium text-foreground">
{contributor.recentContribution}
</p>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>{contributor.reputation}</span>
<span>
{contributor.contributions} contributions
</span>
</div>
</div>
<Badge className="bg-aethex-500/10 text-aethex-200 border border-aethex-400/40">
{contributor.badge}
</Badge>
<Button
asChild
variant="outline"
className="w-full border-aethex-400/40"
>
<Link to={contributor.profileUrl}>
View passport
</Link>
</Button>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<section id="featured-studios" className="py-16">
<div className="container mx-auto px-4">
<SectionHeader
badge="Studios"
title="Featured studios"
description="Studios building with AeThex across games and real-time apps."
align="center"
/>
<FeaturedStudiosGrid />
</div>
</section>
</TabsContent>
)}
{activeTab === "workshop" && (
<TabsContent value="workshop" className="mt-0">
{/* Workshop & Mod Support */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Workshop & Mods"
title="Build, share, and iterate with the community workshop"
description="Mods, templates, and toolkits come with analytics so teams can iterate quickly."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{workshopItems.map((item) => {
const Icon = item.icon;
return (
<Card
key={item.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-6 w-6" />
</div>
<CardTitle className="text-lg">
{item.title}
</CardTitle>
<CardDescription>
{item.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Downloads</span>
<span className="font-semibold text-aethex-200">
{item.downloads.toLocaleString()}
</span>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Rating</span>
<span className="font-semibold text-aethex-200">
{item.rating.toFixed(1)}
</span>
</div>
<p className="text-xs text-muted-foreground">
Created by {item.author}
</p>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to={`/workshop/${item.id}`}>
View asset
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "media" && (
<TabsContent value="media" className="mt-0">
{/* Media Galleries */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Media Galleries"
title="Show off your best captures and recaps"
description="Screenshots, artwork, and videos are curated into themed galleries to inspire the community."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{mediaGallery.map((item) => (
<Card
key={item.id}
className="border-border/40 bg-background/80 backdrop-blur overflow-hidden"
>
<div className="relative">
<img
src={item.thumbnail}
alt={item.title}
className="h-48 w-full object-cover"
loading="lazy"
/>
<Badge className="absolute left-4 top-4 bg-background/80 backdrop-blur border-border/60">
{item.type}
</Badge>
</div>
<CardContent className="space-y-3 p-5">
<div className="space-y-1">
<h3 className="font-semibold text-foreground">
{item.title}
</h3>
<p className="text-sm text-muted-foreground">
by {item.author}
</p>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span className="flex items-center gap-2">
<Heart className="h-4 w-4 text-aethex-400" />
{item.likes}
</span>
<Button
asChild
variant="ghost"
className="px-0 text-sm"
>
<Link to={`/gallery/${item.id}`}>
Open gallery
</Link>
</Button>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "spotlight" && (
<TabsContent value="spotlight" className="mt-0">
{/* Creator Spotlight */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Creator Spotlight"
title="Recognising standout community creators"
description="Spotlight creators whose mods, art, and systems elevate the AeThex ecosystem."
align="center"
/>
<div className="grid gap-6 lg:grid-cols-2 max-w-6xl mx-auto">
{spotlightCreators.map((creator) => (
<Card
key={creator.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardContent className="p-6 space-y-5">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div className="flex items-center gap-3">
<img
src={creator.avatar}
alt={creator.name}
className="h-14 w-14 rounded-full ring-4 ring-aethex-400/20"
/>
<div>
<p className="text-lg font-semibold text-gradient">
{creator.name}
</p>
<p className="text-sm text-muted-foreground">
{creator.role}
</p>
</div>
</div>
<Badge className="bg-aethex-500/10 border-aethex-400/40 text-aethex-200">
Featured creator
</Badge>
</div>
<p className="text-sm text-muted-foreground leading-relaxed">
{creator.highlight}
</p>
<div className="grid grid-cols-3 gap-3">
{creator.metrics.map((metric) => (
<div
key={`${creator.id}-${metric.label}`}
className="rounded-lg border border-border/40 bg-background/80 p-3 text-center"
>
<p className="text-xs text-muted-foreground uppercase tracking-wide">
{metric.label}
</p>
<p className="text-lg font-semibold text-foreground">
{metric.value}
</p>
</div>
))}
</div>
<Button asChild className="w-full">
<Link to={creator.link}>
View creator profile
</Link>
</Button>
</CardContent>
</Card>
))}
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "governance" && (
<TabsContent value="governance" className="mt-0">
{/* Community Governance */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Governance"
title="Clear guidelines, empowered moderators"
description="We invest in tools and processes so every player feels safe, heard, and respected."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr_3fr]">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader className="flex items-start justify-between gap-4">
<div>
<CardTitle>Community guidelines</CardTitle>
<CardDescription>
Expectations for every player and contributor.
</CardDescription>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
Updated weekly
</Badge>
</CardHeader>
<CardContent>
<ul className="space-y-3">
{moderationGuidelines.map((guideline) => (
<li
key={guideline.title}
className="flex items-start gap-3"
>
<Shield className="mt-0.5 h-4 w-4 text-aethex-400" />
<div>
<p className="text-sm font-medium text-foreground">
{guideline.title}
</p>
<p className="text-sm text-muted-foreground">
{guideline.description}
</p>
</div>
</li>
))}
</ul>
</CardContent>
</Card>
<div className="grid gap-8">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Moderation toolkit</CardTitle>
<CardDescription>
Equip community managers with actionable,
auditable controls.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-3">
{moderationTools.map((tool) => {
const Icon = tool.icon;
return (
<div
key={tool.id}
className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-3"
>
<div className="flex h-10 w-10 items-center justify-center rounded-md bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<p className="text-sm font-medium text-foreground">
{tool.title}
</p>
<p className="text-sm text-muted-foreground">
{tool.description}
</p>
</div>
);
})}
</CardContent>
</Card>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Submit a report</CardTitle>
<CardDescription>
Reports are routed to the right channel owners for
fast follow-up.
</CardDescription>
</CardHeader>
<CardContent>
<form
onSubmit={handleReportSubmit}
className="space-y-4"
>
<div className="space-y-2">
<Label htmlFor="report-reason">Reason</Label>
<select
id="report-reason"
value={reportForm.reason}
onChange={(event) =>
setReportForm((prev) => ({
...prev,
reason: event.target.value,
}))
}
className="w-full rounded-lg border border-border/50 bg-background/80 px-3 py-2 text-sm focus:border-aethex-400 focus:outline-none focus:ring-2 focus:ring-aethex-400/40"
>
<option value="">Select a reason</option>
{reportReasons.map((reason) => (
<option key={reason.id} value={reason.id}>
{reason.label}
</option>
))}
</select>
{selectedReportReason && (
<p className="text-xs text-muted-foreground">
{selectedReportReason.description}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="report-details">Details</Label>
<Textarea
id="report-details"
value={reportForm.details}
onChange={(event) =>
setReportForm((prev) => ({
...prev,
details: event.target.value,
}))
}
placeholder="Share links, timestamps, or context so moderators can follow up quickly."
rows={4}
/>
</div>
<Button type="submit" className="w-full">
Submit report
</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
</TabsContent>
)}
{activeTab === "cta" && (
<TabsContent value="cta" className="mt-0">
{/* CTA Section */}
<section className="py-20">
<div className="container mx-auto px-4 text-center">
<div className="max-w-3xl mx-auto space-y-8 animate-scale-in">
<h2 className="text-3xl lg:text-4xl font-bold text-gradient-purple">
Ready to Join Our Community?
</h2>
<p className="text-xl text-muted-foreground">
Connect with thousands of developers, share your
projects, and grow your skills in our supportive and
innovative community.
</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<Button
asChild
size="lg"
className="bg-gradient-to-r from-aethex-500 to-neon-blue hover:from-aethex-600 hover:to-neon-blue/90 glow-blue hover-lift text-lg px-8 py-6"
>
<Link
to="/discord"
className="flex items-center space-x-2"
>
<Heart className="h-5 w-5" />
<span>Join Community</span>
<ArrowRight className="h-5 w-5" />
</Link>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="border-aethex-400/50 hover:border-aethex-400 hover-lift text-lg px-8 py-6"
>
<Link to="/events">View All Events</Link>
</Button>
</div>
<div className="grid grid-cols-3 gap-8 mt-12">
<div className="text-center">
<Coffee className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Weekly Meetups</h3>
<p className="text-sm text-muted-foreground">
Virtual coffee chats
</p>
</div>
<div className="text-center">
<Star className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Recognition</h3>
<p className="text-sm text-muted-foreground">
Contributor rewards
</p>
</div>
<div className="text-center">
<TrendingUp className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Growth</h3>
<p className="text-sm text-muted-foreground">
Learn & advance
</p>
</div>
</div>
</div>
</div>
</section>
</TabsContent>
)}
</Tabs>
{false && (
<>
{/* DevConnect Spotlight */}
<section className="relative py-20 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-aethex-900/40 via-transparent to-neon-blue/30" />
<div className="container mx-auto px-4 relative z-10">
<div className="max-w-5xl mx-auto grid lg:grid-cols-[2fr_3fr] gap-10 items-center">
<div className="space-y-6 animate-slide-left">
<Badge className="bg-gradient-to-r from-aethex-500 to-neon-blue w-fit">
New Platform
</Badge>
<h2 className="text-3xl lg:text-4xl font-bold text-gradient">
Introducing DevConnect
</h2>
<p className="text-lg text-muted-foreground">
DevConnect is our dedicated hub for platform teams
building the next wave of AeThex experiences. Launch
collabs, monitor live services, and activate the Studio
network — all from one command center.
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Button
asChild
size="lg"
className="bg-gradient-to-r from-neon-blue to-aethex-500 hover:from-neon-blue/90 hover:to-aethex-500/90 glow-blue hover-lift"
>
<a
href="https://devconnect.sbs"
target="_blank"
rel="noreferrer"
className="flex items-center space-x-2"
>
<span>Launch DevConnect</span>
<ArrowRight className="h-5 w-5" />
</a>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="border-border/60"
>
<Link to="/contact">Talk with AeThex Team</Link>
</Button>
</div>
</div>
<Card className="border-border/40 bg-background/80 backdrop-blur-xl shadow-lg shadow-aethex-500/10 animate-slide-right">
<CardContent className="p-8 space-y-6">
<div className="grid gap-4">
{devConnectHighlights.map((highlight, index) => {
const Icon = highlight.icon;
return (
<div
key={highlight.title}
className="flex items-start gap-4 p-4 rounded-xl border border-border/40 bg-background/60"
>
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-r from-aethex-500/20 to-neon-blue/20 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div className="space-y-1">
<h3 className="font-semibold text-foreground">
{highlight.title}
</h3>
<p className="text-sm text-muted-foreground">
{highlight.description}
</p>
</div>
</div>
);
})}
</div>
<div className="rounded-lg border border-aethex-400/40 bg-gradient-to-r from-aethex-500/10 to-neon-blue/10 p-4 text-sm text-muted-foreground">
DevConnect syncs directly with AeThex developer
profiles, so your activity, streaks, and achievements
follow you across every build.
</div>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Forums & Discussion */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Forums & Discussions"
title="Deep-dive with peers in dedicated boards"
description="Launch structured conversations for strategy, support, and storytelling."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{forumSpaces.map((space, index) => {
const Icon = space.icon;
return (
<Card
key={space.id}
className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift"
style={{ animationDelay: `${index * 0.1}s` }}
>
<CardHeader className="space-y-4">
<div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<CardTitle className="text-lg">
{space.name}
</CardTitle>
<CardDescription>
{space.description}
</CardDescription>
</div>
</div>
<Badge
variant="outline"
className="border-border/50"
>
{space.threads} threads
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between text-xs text-muted-foreground uppercase tracking-wide">
<span>{space.activeToday} active today</span>
<span className="flex items-center gap-2">
<MessageCircle className="h-3.5 w-3.5" /> Latest
</span>
</div>
<div className="rounded-lg border border-border/40 bg-background/80 p-4">
<p className="text-sm font-medium text-foreground">
{space.latestThread.title}
</p>
<p className="text-xs text-muted-foreground">
by {space.latestThread.author} •{" "}
{space.latestThread.timeAgo}
</p>
</div>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to={`/forums/${space.id}`}>
Enter space
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
{/* Feedback & Roadmap */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Feedback & Roadmap"
title="Collect insights and close the loop with players"
description="Organise bug reports, balance discussions, and feature ideas in a transparent queue."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr_3fr]">
<div className="space-y-6">
{feedbackChannels.map((channel) => {
const Icon = channel.icon;
return (
<Card
key={channel.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex items-start justify-between gap-4">
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<CardTitle className="text-lg">
{channel.title}
</CardTitle>
<CardDescription>
{channel.description}
</CardDescription>
</div>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
{channel.submissionsThisWeek} this week
</Badge>
</div>
<p className="text-xs text-muted-foreground uppercase tracking-wide">
Stewarded by {channel.owner}
</p>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex flex-wrap gap-2">
{channel.statuses.map((status) => (
<Badge
key={status.label}
className={cn(
"text-xs",
feedbackToneStyles[status.tone],
)}
>
{status.label}: {status.count}
</Badge>
))}
</div>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to="/feedback">
Submit feedback
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Live roadmap snapshot</CardTitle>
<CardDescription>
Track what the team is shipping next based on player
momentum.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{roadmapSnapshot.map((item) => (
<div
key={item.id}
className="flex flex-col gap-2 rounded-lg border border-border/40 bg-background/80 p-4 sm:flex-row sm:items-center sm:justify-between"
>
<div>
<p className="font-medium text-foreground">
{item.title}
</p>
<p className="text-xs text-muted-foreground">
{item.eta}
</p>
</div>
<Badge
className={feedbackToneStyles[item.statusTone]}
>
{item.status}
</Badge>
</div>
))}
<Button
asChild
variant="outline"
className="w-full border-aethex-400/40"
>
<Link to="/roadmap">Open public roadmap</Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Community Polls */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Polls"
title="Let players steer the next big moves"
description="Run lightweight polls to validate cosmetics, roadmap priorities, and upcoming events."
align="center"
/>
<div className="grid gap-6 md:grid-cols-2 max-w-5xl mx-auto">
{polls.map((poll) => (
<PollCard
key={poll.id}
poll={poll}
selectedOption={pollSelections[poll.id]}
onSelect={(optionId) =>
handlePollVote(poll.id, optionId)
}
/>
))}
</div>
</div>
</section>
{/* Real-time Collaboration */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Real-time Collaboration"
title="Integrated chat with Discord-style presence"
description="Spin up voice, text, and co-working rooms that bridge seamlessly with our forums and developer hubs."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[3fr_2fr]">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Active channels</CardTitle>
<CardDescription>
See whos online and jump into the conversations that
matter right now.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{chatChannels.map((channel) => {
const Icon = channel.icon;
return (
<div
key={channel.id}
className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-3"
>
<div className="flex items-start justify-between gap-3">
<div className="flex items-start gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<div>
<p className="font-medium text-foreground">
{channel.name}
</p>
<p className="text-sm text-muted-foreground">
{channel.description}
</p>
</div>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
{channel.participants} members
</Badge>
</div>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>Synced with Discord</span>
<span className="flex items-center gap-1 text-emerald-200">
<Sparkles className="h-3 w-3" />{" "}
{channel.activeNow} live now
</span>
</div>
</div>
);
})}
</CardContent>
</Card>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Why players love integrated chat</CardTitle>
<CardDescription>
Keep every squad aligned across devices with presence,
threads, and recordings.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<ul className="space-y-3 text-sm text-muted-foreground">
{chatFeatures.map((feature) => (
<li
key={feature}
className="flex items-start gap-3"
>
<CheckCircle className="mt-0.5 h-4 w-4 text-aethex-400" />
<span>{feature}</span>
</li>
))}
</ul>
<Button asChild className="w-full">
<Link to="/chat">Launch real-time hub</Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Upcoming Events */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Events"
title="Upcoming events"
description="Join our community events and level up your skills."
align="center"
/>
<div className="max-w-4xl mx-auto space-y-6">
{events.map((event, index) => (
<EventCard
key={event.id}
event={event}
animationDelay={index * 0.12}
isRegistered={Boolean(registeredEvents[event.id])}
registrant={registeredEvents[event.id]}
onRegister={(payload) =>
handleEventRegistration(event, payload)
}
/>
))}
</div>
</div>
</section>
{/* Developer Profile Highlights */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Developer Profiles"
title="Showcase your journey across AeThex"
description="Developer profiles blend achievements, portfolio pieces, and social proof so collaborators can find you fast."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{profileHighlights.map((highlight) => {
const Icon = highlight.icon;
return (
<Card
key={highlight.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-6 w-6" />
</div>
<CardTitle className="text-lg">
{highlight.title}
</CardTitle>
<CardDescription>
{highlight.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="rounded-lg border border-border/40 bg-background/80 p-4">
<p className="text-xs uppercase tracking-wide text-muted-foreground">
{highlight.metricLabel}
</p>
<p className="text-2xl font-semibold text-gradient-purple">
{highlight.metricValue}
</p>
</div>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
{/* Featured Developers */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Leaders"
title="Featured developers"
description="Highlighting builders who mentor others, ship mods, and level up the entire network."
align="center"
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
{contributors.map((contributor, index) => (
<Card
key={contributor.name}
className="border-border/50 hover:border-aethex-400/50 transition-all duration-300 hover-lift animate-scale-in"
style={{ animationDelay: `${index * 0.2}s` }}
>
<CardContent className="p-6 space-y-4 text-center">
<img
src={contributor.avatar}
alt={contributor.name}
className="w-20 h-20 rounded-full mx-auto ring-4 ring-aethex-400/20"
/>
<div className="space-y-1">
<h3 className="font-semibold text-lg text-gradient">
{contributor.name}
</h3>
<p className="text-sm text-muted-foreground">
{contributor.title}
</p>
</div>
<Badge variant="outline" className="mx-auto">
{contributor.speciality}
</Badge>
<p className="text-sm text-muted-foreground text-left">
{contributor.bio}
</p>
<div className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-2 text-left">
<p className="text-sm font-medium text-foreground">
{contributor.recentContribution}
</p>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>{contributor.reputation}</span>
<span>
{contributor.contributions} contributions
</span>
</div>
</div>
<Badge className="bg-aethex-500/10 text-aethex-200 border border-aethex-400/40">
{contributor.badge}
</Badge>
<Button
asChild
variant="outline"
className="w-full border-aethex-400/40"
>
<Link to={contributor.profileUrl}>
View passport
</Link>
</Button>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Workshop & Mod Support */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Workshop & Mods"
title="Build, share, and iterate with the community workshop"
description="Mods, templates, and toolkits come with analytics so teams can iterate quickly."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{workshopItems.map((item) => {
const Icon = item.icon;
return (
<Card
key={item.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardHeader className="space-y-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-aethex-500/10 text-aethex-300">
<Icon className="h-6 w-6" />
</div>
<CardTitle className="text-lg">
{item.title}
</CardTitle>
<CardDescription>
{item.description}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Downloads</span>
<span className="font-semibold text-aethex-200">
{item.downloads.toLocaleString()}
</span>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>Rating</span>
<span className="font-semibold text-aethex-200">
{item.rating.toFixed(1)}
</span>
</div>
<p className="text-xs text-muted-foreground">
Created by {item.author}
</p>
<Button
asChild
variant="ghost"
className="w-full justify-between text-sm"
>
<Link to={`/workshop/${item.id}`}>
View asset
<ArrowRight className="h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
{/* Media Galleries */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Media Galleries"
title="Show off your best captures and recaps"
description="Screenshots, artwork, and videos are curated into themed galleries to inspire the community."
align="left"
/>
<div className="grid gap-6 md:grid-cols-3">
{mediaGallery.map((item) => (
<Card
key={item.id}
className="border-border/40 bg-background/80 backdrop-blur overflow-hidden"
>
<div className="relative">
<img
src={item.thumbnail}
alt={item.title}
className="h-48 w-full object-cover"
loading="lazy"
/>
<Badge className="absolute left-4 top-4 bg-background/80 backdrop-blur border-border/60">
{item.type}
</Badge>
</div>
<CardContent className="space-y-3 p-5">
<div className="space-y-1">
<h3 className="font-semibold text-foreground">
{item.title}
</h3>
<p className="text-sm text-muted-foreground">
by {item.author}
</p>
</div>
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span className="flex items-center gap-2">
<Heart className="h-4 w-4 text-aethex-400" />
{item.likes}
</span>
<Button
asChild
variant="ghost"
className="px-0 text-sm"
>
<Link to={`/gallery/${item.id}`}>
Open gallery
</Link>
</Button>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Creator Spotlight */}
<section className="py-20">
<div className="container mx-auto px-4">
<SectionHeader
badge="Creator Spotlight"
title="Recognising standout community creators"
description="Spotlight creators whose mods, art, and systems elevate the AeThex ecosystem."
align="center"
/>
<div className="grid gap-6 lg:grid-cols-2 max-w-6xl mx-auto">
{spotlightCreators.map((creator) => (
<Card
key={creator.id}
className="border-border/50 bg-background/80 backdrop-blur"
>
<CardContent className="p-6 space-y-5">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div className="flex items-center gap-3">
<img
src={creator.avatar}
alt={creator.name}
className="h-14 w-14 rounded-full ring-4 ring-aethex-400/20"
/>
<div>
<p className="text-lg font-semibold text-gradient">
{creator.name}
</p>
<p className="text-sm text-muted-foreground">
{creator.role}
</p>
</div>
</div>
<Badge className="bg-aethex-500/10 border-aethex-400/40 text-aethex-200">
Featured creator
</Badge>
</div>
<p className="text-sm text-muted-foreground leading-relaxed">
{creator.highlight}
</p>
<div className="grid grid-cols-3 gap-3">
{creator.metrics.map((metric) => (
<div
key={`${creator.id}-${metric.label}`}
className="rounded-lg border border-border/40 bg-background/80 p-3 text-center"
>
<p className="text-xs text-muted-foreground uppercase tracking-wide">
{metric.label}
</p>
<p className="text-lg font-semibold text-foreground">
{metric.value}
</p>
</div>
))}
</div>
<Button asChild className="w-full">
<Link to={creator.link}>View creator profile</Link>
</Button>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Community Governance */}
<section className="py-20 bg-background/30">
<div className="container mx-auto px-4">
<SectionHeader
badge="Community Governance"
title="Clear guidelines, empowered moderators"
description="We invest in tools and processes so every player feels safe, heard, and respected."
align="left"
/>
<div className="grid gap-8 lg:grid-cols-[2fr_3fr]">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader className="flex items-start justify-between gap-4">
<div>
<CardTitle>Community guidelines</CardTitle>
<CardDescription>
Expectations for every player and contributor.
</CardDescription>
</div>
<Badge
variant="outline"
className="border-aethex-400/40 text-aethex-200"
>
Updated weekly
</Badge>
</CardHeader>
<CardContent>
<ul className="space-y-3">
{moderationGuidelines.map((guideline) => (
<li
key={guideline.title}
className="flex items-start gap-3"
>
<Shield className="mt-0.5 h-4 w-4 text-aethex-400" />
<div>
<p className="text-sm font-medium text-foreground">
{guideline.title}
</p>
<p className="text-sm text-muted-foreground">
{guideline.description}
</p>
</div>
</li>
))}
</ul>
</CardContent>
</Card>
<div className="grid gap-8">
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Moderation toolkit</CardTitle>
<CardDescription>
Equip community managers with actionable, auditable
controls.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-3">
{moderationTools.map((tool) => {
const Icon = tool.icon;
return (
<div
key={tool.id}
className="rounded-lg border border-border/40 bg-background/80 p-4 space-y-3"
>
<div className="flex h-10 w-10 items-center justify-center rounded-md bg-aethex-500/10 text-aethex-300">
<Icon className="h-5 w-5" />
</div>
<p className="text-sm font-medium text-foreground">
{tool.title}
</p>
<p className="text-sm text-muted-foreground">
{tool.description}
</p>
</div>
);
})}
</CardContent>
</Card>
<Card className="border-border/50 bg-background/80 backdrop-blur">
<CardHeader>
<CardTitle>Submit a report</CardTitle>
<CardDescription>
Reports are routed to the right channel owners for
fast follow-up.
</CardDescription>
</CardHeader>
<CardContent>
<form
onSubmit={handleReportSubmit}
className="space-y-4"
>
<div className="space-y-2">
<Label htmlFor="report-reason">Reason</Label>
<select
id="report-reason"
value={reportForm.reason}
onChange={(event) =>
setReportForm((prev) => ({
...prev,
reason: event.target.value,
}))
}
className="w-full rounded-lg border border-border/50 bg-background/80 px-3 py-2 text-sm focus:border-aethex-400 focus:outline-none focus:ring-2 focus:ring-aethex-400/40"
>
<option value="">Select a reason</option>
{reportReasons.map((reason) => (
<option key={reason.id} value={reason.id}>
{reason.label}
</option>
))}
</select>
{selectedReportReason && (
<p className="text-xs text-muted-foreground">
{selectedReportReason.description}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="report-details">Details</Label>
<Textarea
id="report-details"
value={reportForm.details}
onChange={(event) =>
setReportForm((prev) => ({
...prev,
details: event.target.value,
}))
}
placeholder="Share links, timestamps, or context so moderators can follow up quickly."
rows={4}
/>
</div>
<Button type="submit" className="w-full">
Submit report
</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-20">
<div className="container mx-auto px-4 text-center">
<div className="max-w-3xl mx-auto space-y-8 animate-scale-in">
<h2 className="text-3xl lg:text-4xl font-bold text-gradient-purple">
Ready to Join Our Community?
</h2>
<p className="text-xl text-muted-foreground">
Connect with thousands of developers, share your projects,
and grow your skills in our supportive and innovative
community.
</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<Button
asChild
size="lg"
className="bg-gradient-to-r from-aethex-500 to-neon-blue hover:from-aethex-600 hover:to-neon-blue/90 glow-blue hover-lift text-lg px-8 py-6"
>
<Link
to="/discord"
className="flex items-center space-x-2"
>
<Heart className="h-5 w-5" />
<span>Join Community</span>
<ArrowRight className="h-5 w-5" />
</Link>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="border-aethex-400/50 hover:border-aethex-400 hover-lift text-lg px-8 py-6"
>
<Link to="/events">View All Events</Link>
</Button>
</div>
<div className="grid grid-cols-3 gap-8 mt-12">
<div className="text-center">
<Coffee className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Weekly Meetups</h3>
<p className="text-sm text-muted-foreground">
Virtual coffee chats
</p>
</div>
<div className="text-center">
<Star className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Recognition</h3>
<p className="text-sm text-muted-foreground">
Contributor rewards
</p>
</div>
<div className="text-center">
<TrendingUp className="h-8 w-8 text-aethex-400 mx-auto mb-2" />
<h3 className="font-semibold">Growth</h3>
<p className="text-sm text-muted-foreground">
Learn & advance
</p>
</div>
</div>
</div>
</div>
</section>
</>
)}
</div>
</Layout>
</>
);
}