diff --git a/api/user/arm-follows.ts b/api/user/arm-follows.ts index 13bc500c..b8b05644 100644 --- a/api/user/arm-follows.ts +++ b/api/user/arm-follows.ts @@ -59,9 +59,7 @@ export default async function handler(req: any, res: any) { const { arm_affiliation } = req.body; if (!arm_affiliation) { - return res - .status(400) - .json({ error: "Missing arm_affiliation" }); + return res.status(400).json({ error: "Missing arm_affiliation" }); } if (!VALID_ARMS.includes(arm_affiliation)) { @@ -115,9 +113,7 @@ export default async function handler(req: any, res: any) { const { arm_affiliation } = req.body; if (!arm_affiliation) { - return res - .status(400) - .json({ error: "Missing arm_affiliation" }); + return res.status(400).json({ error: "Missing arm_affiliation" }); } // Unfollow the arm diff --git a/client/App.tsx b/client/App.tsx index 78f3c3c6..6b4373aa 100644 --- a/client/App.tsx +++ b/client/App.tsx @@ -181,633 +181,688 @@ const App = () => ( - - - {/* Subdomain Passport (aethex.me and aethex.space) handles its own redirect if not a subdomain */} - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } - /> - } /> - } /> - } - /> - } - /> + + + {/* Subdomain Passport (aethex.me and aethex.space) handles its own redirect if not a subdomain */} + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } + /> + } + /> - {/* Foundation Community Hub - Consolidated from /developers and /community */} - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> + {/* Foundation Community Hub - Consolidated from /developers and /community */} + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> - {/* Legacy redirects for backwards compatibility */} - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> + {/* Legacy redirects for backwards compatibility */} + + } + /> + + } + /> + + } + /> + } + /> + } + /> + } + /> - } - /> - } /> - } - /> - } /> - } /> - } /> - } - /> - } /> - } /> - } /> - } /> - } - /> + } + /> + } + /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + } /> + } + /> - {/* Creator Network routes */} - } /> - } - /> - } - /> - } - /> - } - /> + {/* Creator Network routes */} + } + /> + } + /> + } + /> + } + /> + } + /> - {/* Service routes */} - } - /> - {/* Legacy redirects - consolidated into /corp */} - } - /> - } /> + {/* Service routes */} + } + /> + {/* Legacy redirects - consolidated into /corp */} + } + /> + } + /> - } - /> - } /> - } - /> - } /> + } + /> + } /> + } + /> + } /> - {/* New Arm Landing Pages */} - } /> - } - /> - } /> - } - /> + {/* New Arm Landing Pages */} + } /> + } + /> + } + /> + } + /> - } /> - } - /> - } - /> - } - /> + } /> + } + /> + } + /> + } + /> - } /> - } - /> - } - /> - } - /> + } /> + } + /> + } + /> + } + /> - } /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> + } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> - {/* Staff Arm Routes */} - } /> - } /> + {/* Staff Arm Routes */} + } /> + } /> - {/* Staff Dashboard Routes */} - - - - } - /> + {/* Staff Dashboard Routes */} + + + + } + /> - {/* Staff Management Routes */} - - - - } - /> - - - - } - /> + {/* Staff Management Routes */} + + + + } + /> + + + + } + /> - {/* Staff Tools & Resources */} - - - - } - /> - - - - } - /> - - - - } - /> + {/* Staff Tools & Resources */} + + + + } + /> + + + + } + /> + + + + } + /> - {/* Staff Admin Pages */} - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> + {/* Staff Admin Pages */} + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> - {/* Dev-Link routes */} - } /> - } - /> + {/* Dev-Link routes */} + } /> + } + /> - {/* Client Hub routes */} - } /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> + {/* Client Hub routes */} + } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> - {/* Nexus routes */} - } /> + {/* Nexus routes */} + } /> - {/* Resource routes */} - - - - } - > - } /> - } /> - } /> - } - /> - } /> - } /> - } /> - } /> - } - /> - - } /> - } /> - } /> + {/* Resource routes */} + + + + } + > + } /> + } /> + } + /> + } + /> + } /> + } /> + } /> + } /> + } + /> + + } /> + } /> + } /> - {/* Legacy /community redirect to /foundation/community */} - } - /> - } - /> + {/* Legacy /community redirect to /foundation/community */} + + } + /> + + } + /> - {/* Ethos Guild Routes */} - } /> - } - /> - } - /> - } - /> + {/* Ethos Guild Routes */} + } + /> + } + /> + } + /> + } + /> - } /> - } /> - } /> + } /> + } /> + } /> - {/* Informational routes */} - } /> - } - /> - } /> - } /> - } /> - } /> - } /> - {/* Legacy /services redirect to /corp */} - } /> - } /> + {/* Informational routes */} + } /> + } + /> + } /> + } /> + } /> + } /> + } /> + {/* Legacy /services redirect to /corp */} + } + /> + } /> - {/* Legal routes */} - } /> - } /> + {/* Legal routes */} + } /> + } /> - {/* Discord Activity route */} - } /> + {/* Discord Activity route */} + } /> - {/* Docs routes */} - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> + {/* Docs routes */} + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> - {/* Internal Docs Hub Routes */} - } /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> + {/* Internal Docs Hub Routes */} + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> - {/* Explicit 404 route for static hosting fallbacks */} - } /> - {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} - } /> - - + {/* Explicit 404 route for static hosting fallbacks */} + } /> + {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} + } /> + + diff --git a/client/components/feed/ArmFeed.tsx b/client/components/feed/ArmFeed.tsx index 7f8489b5..8b27db8c 100644 --- a/client/components/feed/ArmFeed.tsx +++ b/client/components/feed/ArmFeed.tsx @@ -18,18 +18,85 @@ import { aethexSocialService } from "@/lib/aethex-social-service"; import { cn } from "@/lib/utils"; import { normalizeErrorMessage } from "@/lib/error-utils"; import { communityService, realtimeService } from "@/lib/supabase-service"; -import { ArrowUpRight, RotateCcw, TrendingUp, Users, Zap, Gamepad2, Briefcase, BookOpen, Network, Shield, Sparkles } from "lucide-react"; +import { + ArrowUpRight, + RotateCcw, + TrendingUp, + Users, + Zap, + Gamepad2, + Briefcase, + BookOpen, + Network, + Shield, + Sparkles, +} from "lucide-react"; -export type ArmType = "labs" | "gameforge" | "corp" | "foundation" | "devlink" | "nexus" | "staff"; +export type ArmType = + | "labs" + | "gameforge" + | "corp" + | "foundation" + | "devlink" + | "nexus" + | "staff"; -const ARMS: { id: ArmType; label: string; icon: any; color: string; description: string }[] = [ - { id: "labs", label: "Labs", icon: Zap, color: "text-yellow-400", description: "Innovation and experimentation" }, - { id: "gameforge", label: "GameForge", icon: Gamepad2, color: "text-green-400", description: "Game development excellence" }, - { id: "corp", label: "Corp", icon: Briefcase, color: "text-blue-400", description: "Commercial partnerships" }, - { id: "foundation", label: "Foundation", icon: BookOpen, color: "text-red-400", description: "Education and mentorship" }, - { id: "devlink", label: "Dev-Link", icon: Network, color: "text-cyan-400", description: "Developer networking" }, - { id: "nexus", label: "Nexus", icon: Sparkles, color: "text-purple-400", description: "Talent marketplace" }, - { id: "staff", label: "Staff", icon: Shield, color: "text-indigo-400", description: "Internal operations" }, +const ARMS: { + id: ArmType; + label: string; + icon: any; + color: string; + description: string; +}[] = [ + { + id: "labs", + label: "Labs", + icon: Zap, + color: "text-yellow-400", + description: "Innovation and experimentation", + }, + { + id: "gameforge", + label: "GameForge", + icon: Gamepad2, + color: "text-green-400", + description: "Game development excellence", + }, + { + id: "corp", + label: "Corp", + icon: Briefcase, + color: "text-blue-400", + description: "Commercial partnerships", + }, + { + id: "foundation", + label: "Foundation", + icon: BookOpen, + color: "text-red-400", + description: "Education and mentorship", + }, + { + id: "devlink", + label: "Dev-Link", + icon: Network, + color: "text-cyan-400", + description: "Developer networking", + }, + { + id: "nexus", + label: "Nexus", + icon: Sparkles, + color: "text-purple-400", + description: "Talent marketplace", + }, + { + id: "staff", + label: "Staff", + icon: Shield, + color: "text-indigo-400", + description: "Internal operations", + }, ]; interface FeedItem { @@ -179,20 +246,23 @@ export default function ArmFeed({ arm }: ArmFeedProps) { [isFollowingAuthor, user, toast], ); - const handleShare = useCallback(async (id: string) => { - const url = `${location.origin}/${arm}#post-${id}`; - try { - if ((navigator as any).share) { - await (navigator as any).share({ - title: "AeThex", - text: `Check out this ${ARMS.find((a) => a.id === arm)?.label} post`, - url, - }); + const handleShare = useCallback( + async (id: string) => { + const url = `${location.origin}/${arm}#post-${id}`; + try { + if ((navigator as any).share) { + await (navigator as any).share({ + title: "AeThex", + text: `Check out this ${ARMS.find((a) => a.id === arm)?.label} post`, + url, + }); + } + } catch (error) { + console.warn("Share cancelled", error); } - } catch (error) { - console.warn("Share cancelled", error); - } - }, [arm]); + }, + [arm], + ); const handleLike = useCallback( async (postId: string) => { diff --git a/client/components/passport/ProjectPassport.tsx b/client/components/passport/ProjectPassport.tsx index 13c9c026..013a1bc0 100644 --- a/client/components/passport/ProjectPassport.tsx +++ b/client/components/passport/ProjectPassport.tsx @@ -59,8 +59,7 @@ const ProjectPassport = ({ }; const statusLabel = project.status || "active"; - const statusClass = - statusColors[statusLabel] || statusColors["active"]; + const statusClass = statusColors[statusLabel] || statusColors["active"]; return ( diff --git a/client/components/settings/WalletVerification.tsx b/client/components/settings/WalletVerification.tsx index b4a777f1..0a0adb8d 100644 --- a/client/components/settings/WalletVerification.tsx +++ b/client/components/settings/WalletVerification.tsx @@ -54,7 +54,7 @@ export const WalletVerification = ({ const normalized = walletInput.trim().toLowerCase(); if (!isValidEthereumAddress(normalized)) { aethexToast.warning( - "Invalid Ethereum address. Must be 0x followed by 40 hexadecimal characters." + "Invalid Ethereum address. Must be 0x followed by 40 hexadecimal characters.", ); return; } @@ -78,7 +78,8 @@ export const WalletVerification = ({ if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( - errorData.error || `HTTP ${response.status}: Failed to connect wallet` + errorData.error || + `HTTP ${response.status}: Failed to connect wallet`, ); } @@ -93,7 +94,7 @@ export const WalletVerification = ({ } catch (error: any) { console.error("[Wallet Verification] Error:", error?.message); aethexToast.error( - error?.message || "Failed to connect wallet. Please try again." + error?.message || "Failed to connect wallet. Please try again.", ); } finally { setIsLoading(false); @@ -116,7 +117,8 @@ export const WalletVerification = ({ if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( - errorData.error || `HTTP ${response.status}: Failed to disconnect wallet` + errorData.error || + `HTTP ${response.status}: Failed to disconnect wallet`, ); } @@ -129,7 +131,7 @@ export const WalletVerification = ({ } catch (error: any) { console.error("[Wallet Verification] Error:", error?.message); aethexToast.error( - error?.message || "Failed to disconnect wallet. Please try again." + error?.message || "Failed to disconnect wallet. Please try again.", ); } finally { setIsLoading(false); @@ -150,7 +152,10 @@ export const WalletVerification = ({ 🔐 Wallet Verification {connectedWallet && ( - + Connected @@ -199,11 +204,14 @@ export const WalletVerification = ({ ✓ Proves you're the owner of this wallet (Web3 identity)
  • - ✓ Will unlock your .aethex TLD + ✓ Will unlock your{" "} + .aethex TLD verification when the Protocol launches
  • ✓ No smart contracts or gas fees required right now
  • -
  • ✓ Your wallet address is private and only visible to you
  • +
  • + ✓ Your wallet address is private and only visible to you +
  • diff --git a/client/components/social/FeedItemCard.tsx b/client/components/social/FeedItemCard.tsx index bca5c87a..e26fb574 100644 --- a/client/components/social/FeedItemCard.tsx +++ b/client/components/social/FeedItemCard.tsx @@ -18,14 +18,52 @@ import { communityService } from "@/lib/supabase-service"; import { Heart, MessageCircle, Share2, Volume2, VolumeX } from "lucide-react"; import type { FeedItem } from "@/pages/Feed"; -const ARM_COLORS: Record = { - labs: { bg: "bg-yellow-500/10", border: "border-l-4 border-l-yellow-400", badge: "bg-yellow-500/20 text-yellow-200", text: "text-yellow-400" }, - gameforge: { bg: "bg-green-500/10", border: "border-l-4 border-l-green-400", badge: "bg-green-500/20 text-green-200", text: "text-green-400" }, - corp: { bg: "bg-blue-500/10", border: "border-l-4 border-l-blue-400", badge: "bg-blue-500/20 text-blue-200", text: "text-blue-400" }, - foundation: { bg: "bg-red-500/10", border: "border-l-4 border-l-red-400", badge: "bg-red-500/20 text-red-200", text: "text-red-400" }, - devlink: { bg: "bg-cyan-500/10", border: "border-l-4 border-l-cyan-400", badge: "bg-cyan-500/20 text-cyan-200", text: "text-cyan-400" }, - nexus: { bg: "bg-purple-500/10", border: "border-l-4 border-l-purple-400", badge: "bg-purple-500/20 text-purple-200", text: "text-purple-400" }, - staff: { bg: "bg-indigo-500/10", border: "border-l-4 border-l-indigo-400", badge: "bg-indigo-500/20 text-indigo-200", text: "text-indigo-400" }, +const ARM_COLORS: Record< + string, + { bg: string; border: string; badge: string; text: string } +> = { + labs: { + bg: "bg-yellow-500/10", + border: "border-l-4 border-l-yellow-400", + badge: "bg-yellow-500/20 text-yellow-200", + text: "text-yellow-400", + }, + gameforge: { + bg: "bg-green-500/10", + border: "border-l-4 border-l-green-400", + badge: "bg-green-500/20 text-green-200", + text: "text-green-400", + }, + corp: { + bg: "bg-blue-500/10", + border: "border-l-4 border-l-blue-400", + badge: "bg-blue-500/20 text-blue-200", + text: "text-blue-400", + }, + foundation: { + bg: "bg-red-500/10", + border: "border-l-4 border-l-red-400", + badge: "bg-red-500/20 text-red-200", + text: "text-red-400", + }, + devlink: { + bg: "bg-cyan-500/10", + border: "border-l-4 border-l-cyan-400", + badge: "bg-cyan-500/20 text-cyan-200", + text: "text-cyan-400", + }, + nexus: { + bg: "bg-purple-500/10", + border: "border-l-4 border-l-purple-400", + badge: "bg-purple-500/20 text-purple-200", + text: "text-purple-400", + }, + staff: { + bg: "bg-indigo-500/10", + border: "border-l-4 border-l-indigo-400", + badge: "bg-indigo-500/20 text-indigo-200", + text: "text-indigo-400", + }, }; const ARM_LABELS: Record = { @@ -112,46 +150,50 @@ export function FeedItemCard({ const armLabel = ARM_LABELS[item.arm || "labs"] || "LABS"; return ( - +
    - - - - {item.authorName?.[0]?.toUpperCase() || "U"} - - -
    -
    - - {item.authorName} - - - {armLabel} - -
    + + + + {item.authorName?.[0]?.toUpperCase() || "U"} + + +
    +
    + + {item.authorName} + + + {armLabel} +
    +
    diff --git a/client/contexts/SubdomainPassportContext.tsx b/client/contexts/SubdomainPassportContext.tsx index d914842a..609c91dd 100644 --- a/client/contexts/SubdomainPassportContext.tsx +++ b/client/contexts/SubdomainPassportContext.tsx @@ -13,19 +13,17 @@ interface SubdomainPassportContextType { error: string | null; } -const SubdomainPassportContext = createContext( - { - subdomainInfo: null, - isLoading: true, - error: null, - } -); +const SubdomainPassportContext = createContext({ + subdomainInfo: null, + isLoading: true, + error: null, +}); export const useSubdomainPassport = () => { const context = useContext(SubdomainPassportContext); if (!context) { throw new Error( - "useSubdomainPassport must be used within SubdomainPassportProvider" + "useSubdomainPassport must be used within SubdomainPassportProvider", ); } return context; @@ -37,7 +35,7 @@ export const SubdomainPassportProvider = ({ children: React.ReactNode; }) => { const [subdomainInfo, setSubdomainInfo] = useState( - null + null, ); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); diff --git a/client/lib/aethex-social-service.ts b/client/lib/aethex-social-service.ts index 636129cb..b4537ffd 100644 --- a/client/lib/aethex-social-service.ts +++ b/client/lib/aethex-social-service.ts @@ -34,7 +34,7 @@ export const aethexSocialService = { async getFollowing(userId: string): Promise { try { const resp = await fetch( - `${API_BASE}/api/social/following?userId=${encodeURIComponent(userId)}` + `${API_BASE}/api/social/following?userId=${encodeURIComponent(userId)}`, ); if (!resp.ok) { @@ -60,7 +60,7 @@ export const aethexSocialService = { async getFollowers(userId: string): Promise { try { const resp = await fetch( - `${API_BASE}/api/social/followers?userId=${encodeURIComponent(userId)}` + `${API_BASE}/api/social/followers?userId=${encodeURIComponent(userId)}`, ); if (!resp.ok) { diff --git a/client/pages/AdminFeed.tsx b/client/pages/AdminFeed.tsx index 6a67a1ae..bb3c3609 100644 --- a/client/pages/AdminFeed.tsx +++ b/client/pages/AdminFeed.tsx @@ -158,10 +158,15 @@ export default function AdminFeed() { {/* Main Form */} - Create a New Post + + Create a New Post + -
    + {/* Title */}