diff --git a/client/components/showcase/ShowcaseCard.tsx b/client/components/showcase/ShowcaseCard.tsx index a0d47ccb..3e677c20 100644 --- a/client/components/showcase/ShowcaseCard.tsx +++ b/client/components/showcase/ShowcaseCard.tsx @@ -1,4 +1,10 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; @@ -15,17 +21,26 @@ export default function ShowcaseCard({ p }: { p: ShowcaseProject }) { {p.image && (
- {p.title} + {p.title}
)}
{p.orgUnit && ( - {p.orgUnit} + + {p.orgUnit} + )} {p.timeframe && ( - {p.timeframe} + + {p.timeframe} + )}
@@ -36,7 +51,9 @@ export default function ShowcaseCard({ p }: { p: ShowcaseProject }) { {p.tags && p.tags.length > 0 && (
{p.tags.map((t) => ( - {t} + + {t} + ))}
)} @@ -61,7 +78,9 @@ export default function ShowcaseCard({ p }: { p: ShowcaseProject }) {
{p.links.map((l) => ( ))}
diff --git a/client/data/showcase.ts b/client/data/showcase.ts index c7737141..b6ddfca5 100644 --- a/client/data/showcase.ts +++ b/client/data/showcase.ts @@ -45,9 +45,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "Marketplace for buying, selling, and trading digital goods and services across the AeThex ecosystem.", tags: ["Platform", "Marketplace", "Commerce"], - contributors: [ - { name: "AeThex Commerce", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "AeThex Commerce", avatar: "/placeholder.svg" }], }, { id: "rodeo-roundup", @@ -58,9 +56,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "App for discovering and tracking rodeos nearby with structured event data, maps, and alerts.", tags: ["Studio", "Mobile", "Events", "Maps"], - contributors: [ - { name: "Studio Build Team", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Studio Build Team", avatar: "/placeholder.svg" }], }, { id: "hells-highway", @@ -85,9 +81,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "Internal game development toolkit and build pipeline utilities for rapid prototyping and shipping.", tags: ["Labs", "Toolkit", "DevTools"], - contributors: [ - { name: "Labs Automation", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Labs Automation", avatar: "/placeholder.svg" }], }, { id: "lone-star-bar", @@ -98,9 +92,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "17+ social game on Roblox focusing on immersive spaces and social mechanics.", tags: ["Studio", "Roblox", "Social", "Game"], - contributors: [ - { name: "Social Experiences", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Social Experiences", avatar: "/placeholder.svg" }], links: [ { label: "Roblox", @@ -116,9 +108,7 @@ export const SHOWCASE: ShowcaseProject[] = [ timeframe: "Nov 2022 – Present", description: "Narrative‑driven initiative produced by AeThex Studio.", tags: ["Studio", "Narrative", "Production"], - contributors: [ - { name: "Story Group", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Story Group", avatar: "/placeholder.svg" }], links: [ { label: "Show project", href: "https://aethex.co/crooked-are-we" }, ], @@ -132,9 +122,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "Studio directed and shipped a polished prototype game in 86 hours for INSPIRE 2025.", tags: ["Studio", "Game Jam", "Leadership", "Prototype"], - contributors: [ - { name: "Strike Team", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Strike Team", avatar: "/placeholder.svg" }], }, { id: "the-prototypes-control", @@ -145,9 +133,7 @@ export const SHOWCASE: ShowcaseProject[] = [ description: "Roblox DevRel Challenge 2025 entry focused on rapid prototyping and control schemes.", tags: ["Studio", "Roblox", "Prototype", "Challenge"], - contributors: [ - { name: "Prototype Unit", avatar: "/placeholder.svg" }, - ], + contributors: [{ name: "Prototype Unit", avatar: "/placeholder.svg" }], links: [ { label: "Roblox", diff --git a/client/pages/Projects.tsx b/client/pages/Projects.tsx index 7f6639e6..255c3ba8 100644 --- a/client/pages/Projects.tsx +++ b/client/pages/Projects.tsx @@ -1,6 +1,12 @@ import Layout from "@/components/Layout"; import { Badge } from "@/components/ui/badge"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import ShowcaseCard from "@/components/showcase/ShowcaseCard"; import { SHOWCASE, type ShowcaseProject } from "@/data/showcase"; @@ -22,7 +28,7 @@ export default function Projects() { supabase .from("showcase_projects" as any) .select( - "id,title,org_unit,role,timeframe,description,tags,image, links:showcase_project_links(label,href), contributors:showcase_contributors(name,title,avatar)" + "id,title,org_unit,role,timeframe,description,tags,image, links:showcase_project_links(label,href), contributors:showcase_contributors(name,title,avatar)", ) .order("created_at", { ascending: false }) .then(({ data, error }) => { @@ -70,7 +76,15 @@ export default function Projects() { .finally(() => setLoading(false)); }, [dbItems]); - const items = useMemo(() => (dbItems && dbItems.length ? dbItems : cmsItems && cmsItems.length ? cmsItems : SHOWCASE), [dbItems, cmsItems]); + const items = useMemo( + () => + dbItems && dbItems.length + ? dbItems + : cmsItems && cmsItems.length + ? cmsItems + : SHOWCASE, + [dbItems, cmsItems], + ); const hasProjects = Array.isArray(items) && items.length > 0; return ( @@ -79,13 +93,33 @@ export default function Projects() {
- Showcase -

Projects & Testimonials

-

Studio initiatives across AeThex Platform, Labs, and Studio.

+ + Showcase + +

+ Projects & Testimonials +

+

+ Studio initiatives across AeThex Platform, Labs, and Studio. +

{isOwner && ( - )}
@@ -103,7 +137,8 @@ export default function Projects() { No projects yet - Add entries in code/client/data/showcase.ts or manage them via CMS. + Add entries in code/client/data/showcase.ts or + manage them via CMS. diff --git a/client/pages/ProjectsAdmin.tsx b/client/pages/ProjectsAdmin.tsx index ac192e37..bd8595f0 100644 --- a/client/pages/ProjectsAdmin.tsx +++ b/client/pages/ProjectsAdmin.tsx @@ -1,22 +1,41 @@ import Layout from "@/components/Layout"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { supabase } from "@/lib/supabase"; import { useAuth } from "@/contexts/AuthContext"; import { useEffect, useState } from "react"; -interface Link { label: string; href: string } -interface Contributor { name: string; title?: string; avatar?: string } +interface Link { + label: string; + href: string; +} +interface Contributor { + name: string; + title?: string; + avatar?: string; +} export default function ProjectsAdmin() { const { user } = useAuth(); const isOwner = user?.email?.toLowerCase() === "mrpiglr@gmail.com"; const [list, setList] = useState([]); const [loading, setLoading] = useState(false); - const [draft, setDraft] = useState({ title: "", org_unit: "Studio", timeframe: "", description: "", tags: "" }); + const [draft, setDraft] = useState({ + title: "", + org_unit: "Studio", + timeframe: "", + description: "", + tags: "", + }); useEffect(() => { if (!isOwner) return; @@ -30,18 +49,32 @@ export default function ProjectsAdmin() { }, [isOwner]); const create = async () => { - const tags = (draft.tags || "").split(",").map((s: string) => s.trim()).filter(Boolean); - const { error } = await supabase.from("showcase_projects" as any).insert({ - title: draft.title, - org_unit: draft.org_unit, - role: "AeThex", - timeframe: draft.timeframe || null, - description: draft.description || null, - tags, - }); + const tags = (draft.tags || "") + .split(",") + .map((s: string) => s.trim()) + .filter(Boolean); + const { error } = await supabase + .from("showcase_projects" as any) + .insert({ + title: draft.title, + org_unit: draft.org_unit, + role: "AeThex", + timeframe: draft.timeframe || null, + description: draft.description || null, + tags, + }); if (!error) { - setDraft({ title: "", org_unit: "Studio", timeframe: "", description: "", tags: "" }); - const { data } = await supabase.from("showcase_projects" as any).select("id,title,org_unit,role,timeframe,description,tags").order("created_at", { ascending: false }); + setDraft({ + title: "", + org_unit: "Studio", + timeframe: "", + description: "", + tags: "", + }); + const { data } = await supabase + .from("showcase_projects" as any) + .select("id,title,org_unit,role,timeframe,description,tags") + .order("created_at", { ascending: false }); setList(data || []); } }; @@ -69,11 +102,22 @@ export default function ProjectsAdmin() {
- Admin -

Projects Admin

-

Create and manage showcase entries (Supabase)

+ + Admin + +

+ Projects Admin +

+

+ Create and manage showcase entries (Supabase) +

- +
@@ -84,20 +128,48 @@ export default function ProjectsAdmin() { Title and basics - setDraft({ ...draft, title: e.target.value })} /> + setDraft({ ...draft, title: e.target.value })} + />
- + setDraft({ ...draft, org_unit: e.target.value }) + } + > - setDraft({ ...draft, timeframe: e.target.value })} /> + + setDraft({ ...draft, timeframe: e.target.value }) + } + />
-