fix: HeroUI v3 compound API (Card.Content/Card.Header) + @heroui/styles CSS import
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled
This commit is contained in:
@@ -2,8 +2,6 @@ import {
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Chip,
|
||||
Input,
|
||||
Spinner,
|
||||
@@ -504,13 +502,13 @@ function App() {
|
||||
className="papo-card"
|
||||
onPress={() => setCurrentGuildId(guild.id)}
|
||||
>
|
||||
<CardContent className="flex flex-row items-center gap-4 p-5">
|
||||
<Card.Content className="flex flex-row items-center gap-4 p-5">
|
||||
<Avatar src={guildIconUrl(guild)} name={guild.name} radius="lg" />
|
||||
<div>
|
||||
<div className="text-lg font-semibold">{guild.name}</div>
|
||||
<div className="text-sm text-white/50">ID: {guild.id}</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
@@ -550,7 +548,7 @@ function App() {
|
||||
</div>
|
||||
|
||||
<Card className="papo-card mt-auto">
|
||||
<CardContent className="gap-3 p-4">
|
||||
<Card.Content className="gap-3 p-4">
|
||||
<div className="text-xs uppercase tracking-[0.18em] text-white/45">Angemeldet als</div>
|
||||
<div className="font-semibold">
|
||||
{user?.username}
|
||||
@@ -567,14 +565,14 @@ function App() {
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</aside>
|
||||
|
||||
<main className="px-4 py-6 md:px-8">
|
||||
<div className="mx-auto max-w-[1520px]">
|
||||
<Card className="papo-card mb-5">
|
||||
<CardContent className="flex flex-col gap-6 p-6 md:flex-row md:items-start md:justify-between">
|
||||
<Card.Content className="flex flex-col gap-6 p-6 md:flex-row md:items-start md:justify-between">
|
||||
<div>
|
||||
<h1 className="papo-section-title">Guild Dashboard</h1>
|
||||
<p className="papo-section-subtitle">Komplettes HeroUI-Rework fuer dein Bot-Dashboard</p>
|
||||
@@ -596,13 +594,13 @@ function App() {
|
||||
</label>
|
||||
{statusMessage ? <div className="mt-2 text-sm text-warning-300">{statusMessage}</div> : null}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
|
||||
{section === 'overview' && (
|
||||
<div className="space-y-5">
|
||||
<Card className="papo-card">
|
||||
<CardContent className="flex flex-col gap-5 p-5 xl:flex-row xl:items-center xl:justify-between">
|
||||
<Card.Content className="flex flex-col gap-5 p-5 xl:flex-row xl:items-center xl:justify-between">
|
||||
<div className="flex min-w-0 items-center gap-4">
|
||||
<Avatar className="h-20 w-20" radius="lg" src={guildIconUrl(selectedGuild)} />
|
||||
<div className="min-w-0">
|
||||
@@ -625,7 +623,7 @@ function App() {
|
||||
>
|
||||
Bot aktiv
|
||||
</Chip>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
|
||||
<div className="grid gap-5 xl:grid-cols-[1.05fr_1.05fr_1fr]">
|
||||
@@ -644,24 +642,24 @@ function App() {
|
||||
/>
|
||||
|
||||
<Card className="papo-card">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">Activity</h2>
|
||||
<p className="mt-1 text-sm text-white/50">Live-Statistiken aus deinem Bot</p>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="gap-3 p-5">
|
||||
</Card.Header>
|
||||
<Card.Content className="gap-3 p-5">
|
||||
<ActivityTile icon={<MessageSquare size={18} />} kind="messages" label="Messages (24h)" value={activity?.messages24h ?? 0} />
|
||||
<ActivityTile icon={<Command size={18} />} kind="commands" label="Commands (24h)" value={activity?.commands24h ?? 0} />
|
||||
<ActivityTile icon={<Shield size={18} />} kind="automod" label="Automod (24h)" value={activity?.automod24h ?? 0} />
|
||||
<Button className="mt-2 justify-between" endContent={<ChevronRight size={16} />} variant="bordered" onPress={() => setSection('settings')}>
|
||||
Alle Logs anzeigen
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
|
||||
<Card className="papo-card">
|
||||
<CardHeader className="flex items-center justify-between px-5 pt-5 pb-0">
|
||||
<Card.Header className="flex items-center justify-between px-5 pt-5 pb-0">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">Guild Logs</h2>
|
||||
<p className="mt-1 text-sm text-white/50">Neueste Ereignisse</p>
|
||||
@@ -669,13 +667,13 @@ function App() {
|
||||
<Button endContent={<ChevronRight size={16} />} size="sm" variant="light" onPress={() => setSection('settings')}>
|
||||
Alle anzeigen
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent className="p-5">
|
||||
</Card.Header>
|
||||
<Card.Content className="p-5">
|
||||
<div className="papo-scroll max-h-[360px] space-y-3 overflow-auto pr-2">
|
||||
{logs.length ? (
|
||||
logs.map((log, index) => (
|
||||
<Card key={`${log.timestamp}-${index}`} className="border border-white/5 bg-white/[0.03]">
|
||||
<CardContent className="gap-2 p-4">
|
||||
<Card.Content className="gap-2 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Chip color={log.level === 'warn' ? 'warning' : log.level === 'error' ? 'danger' : 'default'} size="sm" variant="bordered">
|
||||
{(log.level || 'info').toUpperCase()}
|
||||
@@ -683,38 +681,38 @@ function App() {
|
||||
<span className="text-xs text-white/45">{formatDate(log.timestamp)}</span>
|
||||
</div>
|
||||
<div className="text-sm text-white/80">{log.category ? `[${log.category}] ` : ''}{log.message || '-'}</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
<div className="text-sm text-white/45">Keine Logs</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Card className="papo-card">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">Schnellzugriff</h2>
|
||||
<p className="mt-1 text-sm text-white/50">Die wichtigsten Bereiche deines Dashboards</p>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-4 p-5 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-6">
|
||||
</Card.Header>
|
||||
<Card.Content className="grid gap-4 p-5 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-6">
|
||||
{navItems
|
||||
.filter((item) => !['overview', 'admin'].includes(item.key))
|
||||
.slice(0, 6)
|
||||
.map((item) => (
|
||||
<Card key={item.key} isPressable className="border border-white/6 bg-white/[0.03]" onPress={() => setSection(item.key)}>
|
||||
<CardContent className="gap-3 p-4">
|
||||
<Card.Content className="gap-3 p-4">
|
||||
<div className="papo-icon-badge">{item.icon}</div>
|
||||
<div className="font-semibold">{item.label}</div>
|
||||
<div className="text-sm text-white/45">HeroUI-Komponenten fuer den Bereich {item.label}</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
@@ -914,13 +912,13 @@ function App() {
|
||||
<div className="grid gap-3 xl:grid-cols-2">
|
||||
{modules.map((module) => (
|
||||
<Card key={module.key} className="border border-white/6 bg-white/[0.03]">
|
||||
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
||||
<Card.Content className="flex flex-row items-center justify-between gap-4 p-4">
|
||||
<div>
|
||||
<div className="font-semibold">{module.name}</div>
|
||||
<div className="text-sm text-white/45">{module.description || ''}</div>
|
||||
</div>
|
||||
<Switch isSelected={module.enabled} onValueChange={(value) => void toggleModule(module.key, value)} />
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
@@ -933,14 +931,14 @@ function App() {
|
||||
<div className="space-y-3">
|
||||
{(events || []).map((event) => (
|
||||
<Card key={event.id} className="border border-white/6 bg-white/[0.03]">
|
||||
<CardContent className="gap-2 p-4">
|
||||
<Card.Content className="gap-2 p-4">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="font-semibold">{event.title}</div>
|
||||
<Button color="danger" size="sm" variant="flat" onPress={() => deleteEvent(event.id)}>Löschen</Button>
|
||||
</div>
|
||||
<div className="text-sm text-white/45">{event.description || 'Keine Beschreibung'}</div>
|
||||
<div className="text-xs text-white/35">{formatDate(event.startsAt)}</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
@@ -973,13 +971,13 @@ function App() {
|
||||
function SectionCard(props: { title: string; subtitle: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<Card className="papo-card">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">{props.title}</h2>
|
||||
<p className="mt-1 text-sm text-white/50">{props.subtitle}</p>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-5">{props.children}</CardContent>
|
||||
</Card.Header>
|
||||
<Card.Content className="p-5">{props.children}</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -987,10 +985,10 @@ function SectionCard(props: { title: string; subtitle: string; children: React.R
|
||||
function FormCard(props: { title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<Card className="border border-white/6 bg-white/[0.03]">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div className="text-lg font-semibold">{props.title}</div>
|
||||
</CardHeader>
|
||||
<CardContent className="gap-4 p-5">{props.children}</CardContent>
|
||||
</Card.Header>
|
||||
<Card.Content className="gap-4 p-5">{props.children}</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -998,14 +996,14 @@ function FormCard(props: { title: string; children: React.ReactNode }) {
|
||||
function ListCard(props: { title: string; items: string[] }) {
|
||||
return (
|
||||
<Card className="border border-white/6 bg-white/[0.03]">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div className="text-lg font-semibold">{props.title}</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-5">
|
||||
</Card.Header>
|
||||
<Card.Content className="p-5">
|
||||
<div className="papo-scroll max-h-[460px] space-y-3 overflow-auto pr-1">
|
||||
{props.items.length ? props.items.map((item, index) => <div key={`${item}-${index}`} className="rounded-xl border border-white/6 bg-white/[0.02] px-4 py-3 text-sm text-white/75">{item}</div>) : <div className="text-sm text-white/45">Keine Daten</div>}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1013,30 +1011,30 @@ function ListCard(props: { title: string; items: string[] }) {
|
||||
function InfoPanel(props: { title: string; items: Array<{ icon: React.ReactNode; label: string; value: string }>; actionLabel: string; onAction: () => void }) {
|
||||
return (
|
||||
<Card className="papo-card">
|
||||
<CardHeader className="px-5 pt-5 pb-0">
|
||||
<Card.Header className="px-5 pt-5 pb-0">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">{props.title}</h2>
|
||||
<p className="mt-1 text-sm text-white/50">Wichtige Guild-Daten auf einen Blick</p>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="gap-4 p-5">
|
||||
</Card.Header>
|
||||
<Card.Content className="gap-4 p-5">
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
{props.items.map((item) => (
|
||||
<Card key={item.label} className="border border-white/6 bg-white/[0.03]">
|
||||
<CardContent className="gap-3 p-4">
|
||||
<Card.Content className="gap-3 p-4">
|
||||
<div className="flex items-center gap-2 text-sm uppercase tracking-[0.14em] text-white/45">
|
||||
<span className="text-warning-300">{item.icon}</span>
|
||||
{item.label}
|
||||
</div>
|
||||
<div className="text-xl font-bold">{item.value}</div>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<Button className="justify-between" endContent={<ChevronRight size={16} />} variant="bordered" onPress={props.onAction}>
|
||||
{props.actionLabel}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1044,7 +1042,7 @@ function InfoPanel(props: { title: string; items: Array<{ icon: React.ReactNode;
|
||||
function ActivityTile(props: { icon: React.ReactNode; label: string; value: number; kind: 'messages' | 'commands' | 'automod' }) {
|
||||
return (
|
||||
<Card className="border border-white/6 bg-white/[0.03]">
|
||||
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
||||
<Card.Content className="flex flex-row items-center justify-between gap-4 p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="papo-icon-badge">{props.icon}</div>
|
||||
<div>
|
||||
@@ -1055,7 +1053,7 @@ function ActivityTile(props: { icon: React.ReactNode; label: string; value: numb
|
||||
<svg className="papo-chart" viewBox="0 0 120 40">
|
||||
<path d={sparkPath(props.kind)} stroke={chartColor(props.kind)} />
|
||||
</svg>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1072,13 +1070,13 @@ function SettingsLayout(props: { title: string; subtitle: string; children: Reac
|
||||
</Button>
|
||||
</FormCard>
|
||||
<Card className="border border-white/6 bg-white/[0.03]">
|
||||
<CardContent className="items-start gap-4 p-5">
|
||||
<Card.Content className="items-start gap-4 p-5">
|
||||
<div className="text-lg font-semibold">Design-Richtung</div>
|
||||
<p className="text-sm text-white/55">
|
||||
Dieser Bereich nutzt jetzt dieselbe HeroUI-Oberfläche wie dein Overview-Dashboard.
|
||||
Die tieferen Spezial-Workflows aus dem alten Inline-Dashboard werden hier schrittweise in echte React-Komponenten überführt.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</div>
|
||||
</SectionCard>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
@import "tailwindcss";
|
||||
@import "@heroui/styles";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
Reference in New Issue
Block a user