From ce0e0de4a034bfc26e2152a56822e023a89fcb77 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Tue, 4 Nov 2025 20:10:35 +0000 Subject: [PATCH] Todo list updated cgen-e064d62d2f404d14829a183607e571dd --- client/pages/Squads.tsx | 332 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 client/pages/Squads.tsx diff --git a/client/pages/Squads.tsx b/client/pages/Squads.tsx new file mode 100644 index 00000000..440e5896 --- /dev/null +++ b/client/pages/Squads.tsx @@ -0,0 +1,332 @@ +import Layout from "@/components/Layout"; +import { useAuth } from "@/contexts/AuthContext"; +import { useEffect, useMemo, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, +} from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { Badge } from "@/components/ui/badge"; +import { aethexCollabService } from "@/lib/aethex-collab-service"; +import LoadingScreen from "@/components/LoadingScreen"; +import { aethexToast } from "@/lib/aethex-toast"; +import { + Users, + Plus, + Zap, + Target, + Trophy, + MessageSquare, +} from "lucide-react"; + +export default function Squads() { + const { user, profile, loading } = useAuth(); + const navigate = useNavigate(); + const [isLoading, setIsLoading] = useState(true); + const [squads, setSquads] = useState([]); + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + const [creating, setCreating] = useState(false); + + useEffect(() => { + if (!loading && !user) navigate("/login", { replace: true }); + }, [loading, user, navigate]); + + useEffect(() => { + const load = async () => { + if (!user?.id) return; + setIsLoading(true); + try { + const mySquads = await aethexCollabService.listMyTeams(user.id); + setSquads(mySquads.filter((t) => t.squad_type === true) || []); + } finally { + setIsLoading(false); + } + }; + load(); + }, [user?.id]); + + const canCreate = useMemo( + () => name.trim().length > 2 && !creating, + [name, creating], + ); + + const handleCreate = async () => { + if (!canCreate || !user) return; + + setCreating(true); + try { + const newSquad = await aethexCollabService.createTeam(user.id, { + name: name.trim(), + description: description.trim(), + squad_type: true, + }); + + if (newSquad) { + setSquads([...squads, newSquad]); + setName(""); + setDescription(""); + aethexToast.success({ + title: "Squad created", + description: `${name} is ready to go!`, + }); + } + } catch (error) { + aethexToast.error({ + title: "Failed to create squad", + description: + error instanceof Error ? error.message : "Please try again", + }); + } finally { + setCreating(false); + } + }; + + if (loading || isLoading) return ; + + return ( + +
+
+ {/* Header */} +
+
+
+

+ Squads Hub +

+

+ Form squads and ship projects together. Match by skill, + timezone, and goals. +

+
+
+ +
+
+
+ + {/* Stats Overview */} +
+ + + + Total Squads + + + +
{squads.length}
+
+
+ + + + Active Members + + + +
+ {squads.reduce((acc, squad) => acc + (squad.members?.length || 1), 0)} +
+
+
+ + + + Projects Shipped + + + +
0
+
+
+ + + + Contributions + + + +
0
+
+
+
+ + {/* Create New Squad Form */} + + +
+ + Create a New Squad +
+ + Build your squad and start collaborating + +
+ +
+ + setName(e.target.value)} + className="mt-2 bg-background/60 border-border/40" + /> +
+
+ +