mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 19:51:17 +00:00
fix more design things
This commit is contained in:
parent
02b28a570b
commit
2f93618eb3
7 changed files with 78 additions and 62 deletions
|
|
@ -9,8 +9,14 @@ interface Props {
|
|||
const Layout = ({ children }: Props) => {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
{/* Mesh-Gradient Background */}
|
||||
<div className="fixed inset-0 -z-10 bg-[oklch(0.97_0_0)]">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_60%_at_-10%_-10%,oklch(0.82_0.06_240/_0.5)_0%,transparent_60%)]" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_60%_50%_at_110%_110%,oklch(0.88_0.09_85/_0.45)_0%,transparent_55%)]" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_50%_40%_at_50%_120%,oklch(0.84_0.05_260/_0.3)_0%,transparent_60%)]" />
|
||||
</div>
|
||||
<DashboardSidebarWrapper />
|
||||
<main className="flex flex-col h-screen w-full bg-muted px-4">
|
||||
<main className="flex flex-col h-screen w-full px-4">
|
||||
<DashboardNavbar />
|
||||
{children}
|
||||
</main>
|
||||
|
|
|
|||
|
|
@ -129,27 +129,29 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
|||
</div>
|
||||
|
||||
{/* Course Name */}
|
||||
<h2 className="text-xl font-semibold text-gray-900">{courseName}</h2>
|
||||
<h2 className="text-xl font-black text-gray-900 leading-tight">{courseName}</h2>
|
||||
|
||||
<div className="flex items-center justify-between w-full">
|
||||
{/* Participant Number */}
|
||||
<span className={isFull ? "text-red-600 font-semibold" : "text-gray-800"}>
|
||||
<span
|
||||
className={`text-sm ${isFull ? "text-red-500 font-semibold" : "text-gray-400 font-light"}`}
|
||||
>
|
||||
{currentParticipants}/{maxParticipants} Teilnehmer
|
||||
</span>
|
||||
|
||||
{/* Price */}
|
||||
<h2 className="text-lg font-semibold">
|
||||
<span className="text-lg font-black text-gray-900">
|
||||
{price.toLocaleString("de-DE", {
|
||||
style: "currency",
|
||||
currency: "EUR",
|
||||
})}
|
||||
</h2>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Participant Bar */}
|
||||
<div className="w-full h-2 bg-white/40 rounded-full overflow-hidden">
|
||||
<div className="w-full h-1.5 bg-white/40 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`h-full ${isFull ? "bg-red-500" : "bg-blue"}`}
|
||||
className={`h-full rounded-full ${isFull ? "bg-red-400" : "bg-blue"}`}
|
||||
style={{
|
||||
width: `${maxParticipants > 0 ? (currentParticipants / maxParticipants) * 100 : 0}%`,
|
||||
}}
|
||||
|
|
@ -163,10 +165,10 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
|||
{currentLevel.label}
|
||||
</span>
|
||||
{/* Room */}
|
||||
<p className="text-gray-500">{room}</p>
|
||||
<p className="text-xs text-gray-400 font-light">{room}</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div className="h-px bg-white/50" />
|
||||
|
||||
<div className="flex items-center justify-between w-full">
|
||||
{/* Status */}
|
||||
|
|
|
|||
|
|
@ -564,19 +564,17 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
|||
)}
|
||||
|
||||
{filteredCourses.length === 0 ? (
|
||||
<div className="text-center py-12 border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl">
|
||||
<p className="text-xl text-gray-600">
|
||||
{courses.length === 0
|
||||
? "Sie haben noch keine Kurse erstellt"
|
||||
: "Keine Kurse gefunden mit den ausgewählten Filtern"}
|
||||
<div className="text-center py-16 border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl">
|
||||
<p className="text-3xl font-black text-gray-800 mb-2">
|
||||
{courses.length === 0 ? "Noch keine Kurse" : "Keine Treffer"}
|
||||
</p>
|
||||
<p className="text-gray-500 mt-2">
|
||||
<p className="text-gray-400 font-light text-sm">
|
||||
{courses.length === 0
|
||||
? "Erstellen Sie Ihren ersten Kurs!"
|
||||
: "Ändern Sie die Filter oder setzen Sie sie zurück"}
|
||||
? "Erstelle deinen ersten Kurs und starte durch."
|
||||
: "Andere Filter ausprobieren oder zurücksetzen."}
|
||||
</p>
|
||||
{courses.length === 0 && canCreate && (
|
||||
<Button onClick={() => router.push("/courses/create")} className="mt-4">
|
||||
<Button onClick={() => router.push("/courses/create")} className="mt-6">
|
||||
Kurs anlegen
|
||||
</Button>
|
||||
)}
|
||||
|
|
@ -589,9 +587,12 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
|||
|
||||
return (
|
||||
<div key={dateKey}>
|
||||
<h2 className="text-2xl font-bold text-gray-800 mb-4">
|
||||
{formatDate(firstCourse.date)}
|
||||
</h2>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<h2 className="text-xs font-semibold tracking-widest text-gray-400 uppercase">
|
||||
{formatDate(firstCourse.date)}
|
||||
</h2>
|
||||
<div className="flex-1 h-px bg-white/50" />
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{coursesForDate.map((course) => (
|
||||
<CourseListItem
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ const DashboardNavbar = () => {
|
|||
const pageTitle = getPageTitle(pathname);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-x-4 items-center py-4 bg-muted">
|
||||
<div className="sticky top-0 z-10 -mx-4 px-4 mb-8 bg-white/55 backdrop-blur-xl supports-backdrop-filter:bg-white/45 border-b border-white/30 shadow-sm">
|
||||
<div className="flex gap-x-4 items-center py-4">
|
||||
<Button className="size-9 cursor-pointer" variant="outline" onClick={toggleSidebar}>
|
||||
{state === "collapsed" || isMobile ? (
|
||||
<PanelLeftIcon className="size-4" />
|
||||
|
|
@ -70,7 +70,6 @@ const DashboardNavbar = () => {
|
|||
|
||||
<h1 className="text-xl font-semibold mt-1">{pageTitle}</h1>
|
||||
</div>
|
||||
<hr className="mb-8" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,38 +12,44 @@ const DashboardView = async () => {
|
|||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-4">Willkommen zurück!</h1>
|
||||
<p className="text-gray-600">Schön, dich wiederzusehen, {displayName}</p>
|
||||
{isManager(userData) && (
|
||||
<span className="inline-block mt-2 px-3 py-1 bg-blue-100 text-blue-800 text-sm font-medium rounded-full">
|
||||
Manager
|
||||
</span>
|
||||
)}
|
||||
{isEmployee(userData) && (
|
||||
<span className="inline-block mt-2 px-3 py-1 bg-green-100 text-green-800 text-sm font-medium rounded-full">
|
||||
Mitarbeiter
|
||||
</span>
|
||||
)}
|
||||
<div className="border border-white/60 bg-white/60 backdrop-blur-xl rounded-2xl shadow-sm p-8 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_80%_at_100%_0%,oklch(0.88_0.09_85/_0.25)_0%,transparent_70%)] pointer-events-none" />
|
||||
<p className="text-xs font-semibold tracking-widest text-gray-400 uppercase mb-2">
|
||||
Dashboard
|
||||
</p>
|
||||
<h1 className="text-4xl font-black text-gray-900 mb-1">Willkommen zurück!</h1>
|
||||
<p className="text-gray-500 font-light">{displayName}</p>
|
||||
<div className="mt-4 flex gap-2">
|
||||
{isManager(userData) && (
|
||||
<span className="inline-flex items-center px-3 py-1 bg-blue/10 text-blue text-xs font-semibold rounded-full border border-blue/10">
|
||||
Manager
|
||||
</span>
|
||||
)}
|
||||
{isEmployee(userData) && (
|
||||
<span className="inline-flex items-center px-3 py-1 bg-green-500/10 text-green-700 text-xs font-semibold rounded-full border border-green-500/10">
|
||||
Mitarbeiter
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-lg font-semibold mb-2">Profil</h2>
|
||||
<p className="text-gray-600 text-sm">Verwalte deine persönlichen Daten</p>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-1">Profil</h2>
|
||||
<p className="text-gray-400 text-sm font-light">Verwalte deine persönlichen Daten</p>
|
||||
</div>
|
||||
|
||||
{isManager(userData) ? (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-lg font-semibold mb-2">Meine Businesses</h2>
|
||||
<p className="text-gray-600 text-sm">
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-1">Meine Businesses</h2>
|
||||
<p className="text-gray-400 text-sm font-light">
|
||||
{userData.businesses.length}{" "}
|
||||
{userData.businesses.length === 1 ? "Business" : "Businesses"}
|
||||
</p>
|
||||
</div>
|
||||
) : isEmployee(userData) ? (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-lg font-semibold mb-2">Meine Berechtigungen</h2>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-1">Meine Berechtigungen</h2>
|
||||
{(() => {
|
||||
const p = userData.permissions;
|
||||
const RESOURCE_LABELS: Record<string, string> = {
|
||||
|
|
@ -80,20 +86,20 @@ const DashboardView = async () => {
|
|||
</div>
|
||||
) : (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-lg font-semibold mb-2">Trainings</h2>
|
||||
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-1">Trainings</h2>
|
||||
<p className="text-gray-400 text-sm font-light">Deine gebuchten Trainingseinheiten</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-lg font-semibold mb-2">Einstellungen</h2>
|
||||
<p className="text-gray-600 text-sm">Passe deine Einstellungen an</p>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-1">Einstellungen</h2>
|
||||
<p className="text-gray-400 text-sm font-light">Passe deine Einstellungen an</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isUser(userData) && (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Benutzerdaten</h2>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-4">Benutzerdaten</h2>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<dt className="text-sm font-medium text-gray-500">Name</dt>
|
||||
|
|
@ -133,7 +139,7 @@ const DashboardView = async () => {
|
|||
|
||||
{isManager(userData) && (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Manager-Daten</h2>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-4">Manager-Daten</h2>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<dt className="text-sm font-medium text-gray-500">Vorname</dt>
|
||||
|
|
@ -165,10 +171,10 @@ const DashboardView = async () => {
|
|||
|
||||
{isManager(userData) && userData.businesses.length > 0 && (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Meine Businesses</h2>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-4">Meine Businesses</h2>
|
||||
<div className="space-y-4">
|
||||
{userData.businesses.map((business) => (
|
||||
<div key={business.id} className="border-l-4 border-blue-500 pl-4 py-2">
|
||||
<div key={business.id} className="border-l-2 border-white/60 pl-4 py-1">
|
||||
<h3 className="text-lg font-semibold text-gray-900">{business.name}</h3>
|
||||
<p className="text-sm text-gray-600 mt-1">{business.address}</p>
|
||||
<p className="text-sm text-gray-600">{business.email}</p>
|
||||
|
|
@ -180,7 +186,7 @@ const DashboardView = async () => {
|
|||
|
||||
{isEmployee(userData) && (
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Mitarbeiter-Daten</h2>
|
||||
<h2 className="text-base font-semibold text-gray-900 mb-4">Mitarbeiter-Daten</h2>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<dt className="text-sm font-medium text-gray-500">Vorname</dt>
|
||||
|
|
|
|||
|
|
@ -18,18 +18,20 @@ const SettingsMenuItem: React.FC<SettingsMenuItemProps> = ({
|
|||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="border border-gray-200 rounded-xl p-5 bg-white flex items-center gap-4 hover:border-gray-300 hover:shadow-sm transition-all group"
|
||||
className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-5 flex items-center gap-4 hover:bg-white/75 hover:shadow-sm transition-all group"
|
||||
>
|
||||
<div className="bg-gray-100 rounded-lg p-2.5 group-hover:bg-gray-200 transition-colors">
|
||||
<Icon size={18} className="text-gray-700" />
|
||||
<div className="bg-white/60 rounded-xl p-2.5 group-hover:bg-white/80 transition-colors border border-white/50">
|
||||
<Icon size={18} className="text-blue" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="font-medium text-gray-900 text-sm">{name}</p>
|
||||
{description && <p className="text-xs text-gray-500 mt-0.5 truncate">{description}</p>}
|
||||
<p className="font-semibold text-gray-900 text-sm">{name}</p>
|
||||
{description && (
|
||||
<p className="text-xs text-gray-400 font-light mt-0.5 truncate">{description}</p>
|
||||
)}
|
||||
</div>
|
||||
<ChevronRight
|
||||
size={16}
|
||||
className="text-gray-400 group-hover:text-gray-600 transition-colors shrink-0"
|
||||
className="text-gray-300 group-hover:text-gray-500 group-hover:translate-x-0.5 transition-all shrink-0"
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
LucideIcon,
|
||||
Megaphone,
|
||||
PanelTop,
|
||||
Settings,
|
||||
TicketPercent,
|
||||
TicketX,
|
||||
User,
|
||||
|
|
@ -86,10 +85,11 @@ const SettingsOverviewView = async () => {
|
|||
return (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h1 className="text-2xl flex gap-2 font-bold">
|
||||
<Settings /> Allgemeine Einstellungen
|
||||
</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">Verwalte deine App-Einstellungen</p>
|
||||
<p className="text-xs font-semibold tracking-widest text-gray-400 uppercase mb-1">
|
||||
Konfiguration
|
||||
</p>
|
||||
<h1 className="text-3xl font-black text-gray-900">Einstellungen</h1>
|
||||
<p className="text-sm text-gray-400 font-light mt-1">Verwalte deine App-Einstellungen</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
{settingsMenuTitles.map((item) => (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue