Create FeaturedStudiosGrid component
cgen-17c083ada248403b9505c2055352f820
This commit is contained in:
parent
2ec37b100a
commit
c820c61d6c
1 changed files with 64 additions and 0 deletions
64
client/components/community/FeaturedStudiosGrid.tsx
Normal file
64
client/components/community/FeaturedStudiosGrid.tsx
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
interface Studio {
|
||||
id?: string;
|
||||
name: string;
|
||||
tagline?: string | null;
|
||||
metrics?: string | null;
|
||||
specialties?: string[] | null;
|
||||
rank?: number | null;
|
||||
}
|
||||
|
||||
export default function FeaturedStudiosGrid() {
|
||||
const [studios, setStudios] = useState<Studio[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await fetch("/api/featured-studios");
|
||||
const data = res.ok ? await res.json() : [];
|
||||
setStudios(Array.isArray(data) ? data : []);
|
||||
} catch {
|
||||
setStudios([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
if (loading) return <p className="text-sm text-muted-foreground text-center">Loading studios…</p>;
|
||||
if (!studios.length) return <p className="text-sm text-muted-foreground text-center">No featured studios yet.</p>;
|
||||
|
||||
return (
|
||||
<div className="grid gap-6 md:grid-cols-3">
|
||||
{studios.map((s) => (
|
||||
<Card key={s.id || s.name} className="border-border/50 bg-background/80 backdrop-blur">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">{s.name}</CardTitle>
|
||||
{s.tagline ? <CardDescription>{s.tagline}</CardDescription> : null}
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{s.metrics ? (
|
||||
<div className="rounded border border-border/40 bg-background/40 p-3 text-sm text-muted-foreground">
|
||||
{s.metrics}
|
||||
</div>
|
||||
) : null}
|
||||
{Array.isArray(s.specialties) && s.specialties.length ? (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{s.specialties.map((sp) => (
|
||||
<Badge key={sp} variant="outline" className="text-xs">
|
||||
{sp}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue