Merge pull request #93 from Since-3/refactor/settings-ui-redsign

redsigned the settings page
This commit is contained in:
Rajpreet0 2026-05-05 23:29:29 +02:00 • committed by GitHub
commit 1b8277050e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 148 additions and 32 deletions

View file

@ -1,5 +1,5 @@
import SettingsView from "@/src/modules/settings/ui/views/settings-view";
import SettingsOverviewView from "@/src/modules/settings/ui/views/settings-overview-view";
export default function SettingsPage() {
return <SettingsView />;
return <SettingsOverviewView />;
}

View file

@ -0,0 +1,5 @@
import SettingsPublicPageView from "@/src/modules/settings/ui/views/settings-public-page-view";
export default function SettingsPublicPage() {
return <SettingsPublicPageView />;
}

View file

@ -309,6 +309,25 @@ const PublicCourseCard = ({ course, business }: PublicCourseCardProps) => {
</p>
</div>
{course.trainerProfiles && course.trainerProfiles.length > 0 && (
<div className="flex items-center gap-1.5">
{course.trainerProfiles.map((trainer) => {
const fullName =
[trainer.firstName, trainer.lastName].filter(Boolean).join(" ") || "Trainer";
return (
<Tooltip key={trainer.id}>
<TooltipTrigger asChild>
<div>
<TrainerAvatar trainer={trainer} size="sm" />
</div>
</TooltipTrigger>
<TooltipContent side="top">{fullName}</TooltipContent>
</Tooltip>
);
})}
</div>
)}
<h2 className="text-xl font-semibold text-gray-900">{course.name}</h2>
<div className="flex items-center justify-between">
@ -333,25 +352,6 @@ const PublicCourseCard = ({ course, business }: PublicCourseCardProps) => {
/>
</div>
{course.trainerProfiles && course.trainerProfiles.length > 0 && (
<div className="flex items-center gap-1.5">
{course.trainerProfiles.map((trainer) => {
const fullName =
[trainer.firstName, trainer.lastName].filter(Boolean).join(" ") || "Trainer";
return (
<Tooltip key={trainer.id}>
<TooltipTrigger asChild>
<div>
<TrainerAvatar trainer={trainer} size="sm" />
</div>
</TooltipTrigger>
<TooltipContent side="top">{fullName}</TooltipContent>
</Tooltip>
);
})}
</div>
)}
{isFull ? (
<Button disabled variant="outline" className="w-full">
Ausgebucht

View file

@ -16,6 +16,7 @@ const menuTitles: Record<string, string> = {
"/employee": "Mitarbeiter Übersicht",
"/employee/create": "Mitarbeiter erstellen",
"/settings": "Einstellungen",
"/settings/public-page": "Einstellungen",
};
const dynamicRoutes: Array<{

View file

@ -0,0 +1,38 @@
import Link from "next/link";
import { LucideIcon } from "lucide-react";
import { ChevronRight } from "lucide-react";
interface SettingsMenuItemProps {
name: string;
description?: string;
icon: LucideIcon;
href: string;
}
const SettingsMenuItem: React.FC<SettingsMenuItemProps> = ({
name,
description,
icon: Icon,
href,
}) => {
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"
>
<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>
<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>}
</div>
<ChevronRight
size={16}
className="text-gray-400 group-hover:text-gray-600 transition-colors shrink-0"
/>
</Link>
);
};
export default SettingsMenuItem;

View file

@ -0,0 +1,62 @@
import { requireAuthWithData, isManager } from "@/src/lib/auth/getUser";
import SettingsMenuItem from "../components/SettingsMenuItem";
import { LucideIcon, PanelTop, Settings, User } from "lucide-react";
type SettingsMenuItem = {
icon: LucideIcon;
name: string;
href: string;
description?: string;
};
const settingsMenuTitles: SettingsMenuItem[] = [
{
icon: User,
name: "Persöhnliche Einstellungen",
href: "/settings/personal",
description: "Verwalte deine persöhnlichen Daten",
},
{
icon: PanelTop,
name: "Öffentliche Seite",
href: "/settings/public-page",
description: "Verwalte deine öffentliche Kursseite",
},
];
const SettingsOverviewView = async () => {
const userData = await requireAuthWithData();
if (!isManager(userData)) {
return (
<div>
<h1 className="text-2xl font-bold mb-1">Einstellungen</h1>
<p className="text-gray-500 text-sm">Keine weiteren Einstellungen verfügbar.</p>
</div>
);
}
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>
</div>
<div className="flex flex-col gap-4">
{settingsMenuTitles.map((item) => (
<SettingsMenuItem
key={item.href}
name={item.name}
description={item.description}
icon={item.icon}
href={item.href}
/>
))}
</div>
</div>
);
};
export default SettingsOverviewView;

View file

@ -1,15 +1,17 @@
import Link from "next/link";
import { ChevronLeft } from "lucide-react";
import { requireAuthWithData, isManager } from "@/src/lib/auth/getUser";
import { prisma } from "@/src/lib/prisma";
import BusinessPublicToggle from "../components/BusinessPublicToggle";
const SettingsView = async () => {
const SettingsPublicPageView = async () => {
const userData = await requireAuthWithData();
if (!isManager(userData)) {
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-2">Einstellungen</h1>
<p className="text-gray-500">Keine weiteren Einstellungen verfügbar.</p>
<div>
<h1 className="text-2xl font-bold mb-1">Öffentliche Seite</h1>
<p className="text-gray-500 text-sm">Keine Berechtigung.</p>
</div>
);
}
@ -21,17 +23,25 @@ const SettingsView = async () => {
});
return (
<div className="space-y-6">
<div className="space-y-4">
<div>
<h1 className="text-3xl font-bold">Einstellungen</h1>
<p className="text-gray-500 mt-1">Verwalte die öffentlichen Seiten deiner Businesses</p>
<Link
href="/settings"
className="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-gray-900 transition-colors mb-3"
>
<ChevronLeft size={15} className="mb-1" />
Einstellungen
</Link>
<h1 className="text-2xl font-bold">Öffentliche Seite</h1>
<p className="text-sm text-gray-500 mt-1">
Steuere welche Kursseiten öffentlich sichtbar sind
</p>
</div>
{businesses.length === 0 ? (
<p className="text-gray-400">Noch kein Business angelegt.</p>
<p className="text-gray-400 text-sm">Noch kein Business angelegt.</p>
) : (
<div className="space-y-4">
<h2 className="text-xl font-semibold">Öffentliche Seiten</h2>
<div className="space-y-3">
{businesses.map((business) => (
<BusinessPublicToggle
key={business.id}
@ -47,4 +57,4 @@ const SettingsView = async () => {
);
};
export default SettingsView;
export default SettingsPublicPageView;