mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 20:51:18 +00:00
Revert "added subtil glassmorphism"
This commit is contained in:
parent
5354a90a8d
commit
779585e6e2
11 changed files with 184 additions and 207 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import SettingsPersonalPageView from "@/src/modules/settings/ui/views/settings-personal-page-view";
|
import SettignsPersonalPageView from "@/src/modules/settings/ui/views/settings-personal-page-view";
|
||||||
|
|
||||||
export default async function SettingsPersonalPage() {
|
export default async function SettingsPersonalPage() {
|
||||||
return <SettingsPersonalPageView />;
|
return <SettignsPersonalPageView />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import AbstractTooltip from "@/src/components/layout/AbstractTooltip";
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/src/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from "@/src/components/ui/avatar";
|
||||||
import { Pen, Trash2, Link } from "lucide-react";
|
import { Pen, Trash2, Link } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Props für die CourseListItem Komponente
|
* Props für die CourseListItem Komponente
|
||||||
|
|
@ -32,7 +31,6 @@ interface CourseListItemProps {
|
||||||
status?: string; // Status des Kurses ("draft" oder "published")
|
status?: string; // Status des Kurses ("draft" oder "published")
|
||||||
isPast?: boolean; // Ob der Kurs in der Vergangenheit liegt
|
isPast?: boolean; // Ob der Kurs in der Vergangenheit liegt
|
||||||
showDeleteIcon?: boolean; // Ob das Löschen-Icon angezeigt werden soll
|
showDeleteIcon?: boolean; // Ob das Löschen-Icon angezeigt werden soll
|
||||||
coverImage?: string; // Optionales Cover-Bild
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -56,7 +54,6 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
||||||
status,
|
status,
|
||||||
isPast,
|
isPast,
|
||||||
showDeleteIcon,
|
showDeleteIcon,
|
||||||
coverImage,
|
|
||||||
}) => {
|
}) => {
|
||||||
// Prüfen, ob der Kurs voll belegt ist (für visuelle Hervorhebung)
|
// Prüfen, ob der Kurs voll belegt ist (für visuelle Hervorhebung)
|
||||||
const isFull = currentParticipants >= maxParticipants;
|
const isFull = currentParticipants >= maxParticipants;
|
||||||
|
|
@ -90,117 +87,109 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl shadow-sm hover:shadow-md hover:bg-white/70 transition flex flex-col relative overflow-hidden ${
|
className={`bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4 relative ${
|
||||||
isPast ? "opacity-60" : ""
|
isPast ? "opacity-60 bg-gray-50" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{coverImage && (
|
<div className="flex items-center w-full">
|
||||||
<div className="relative w-full h-36 shrink-0">
|
{trainers.map((trainerId, index) => {
|
||||||
<Image src={coverImage} alt={courseName} fill className="object-cover" />
|
const trainerInfo = trainersMap[trainerId];
|
||||||
</div>
|
const displayName = trainerInfo?.label ?? "Ehemaliger Trainer";
|
||||||
)}
|
const avatarSrc = trainerInfo?.pbSrc;
|
||||||
|
return (
|
||||||
<div className="flex flex-col gap-4 p-5">
|
<AbstractTooltip key={`${trainerId}-${index}`} tooltipText={displayName}>
|
||||||
<div className="flex items-center w-full">
|
<div
|
||||||
{trainers.map((trainerId, index) => {
|
className={`relative ${index !== 0 ? "-ml-3" : ""}`}
|
||||||
const trainerInfo = trainersMap[trainerId];
|
style={{ zIndex: trainers.length - index }}
|
||||||
const displayName = trainerInfo?.label ?? "Ehemaliger Trainer";
|
|
||||||
const avatarSrc = trainerInfo?.pbSrc;
|
|
||||||
return (
|
|
||||||
<AbstractTooltip key={`${trainerId}-${index}`} tooltipText={displayName}>
|
|
||||||
<div
|
|
||||||
className={`relative ${index !== 0 ? "-ml-3" : ""}`}
|
|
||||||
style={{ zIndex: trainers.length - index }}
|
|
||||||
>
|
|
||||||
<Avatar className="rounded-full border-2 border-white">
|
|
||||||
{avatarSrc && <AvatarImage src={avatarSrc} alt={displayName} />}
|
|
||||||
<AvatarFallback>{getInitials(displayName)}</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
</div>
|
|
||||||
</AbstractTooltip>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{/* Time */}
|
|
||||||
<div className="w-full flex justify-end">
|
|
||||||
<p className="text-gray-500 text-lg">
|
|
||||||
{timeFrom} - {timeTo}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Course Name */}
|
|
||||||
<h2 className="text-xl font-semibold text-gray-900">{courseName}</h2>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between w-full">
|
|
||||||
{/* Participant Number */}
|
|
||||||
<span className={isFull ? "text-red-600 font-semibold" : "text-gray-800"}>
|
|
||||||
{currentParticipants}/{maxParticipants} Teilnehmer
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{/* Price */}
|
|
||||||
<h2 className="text-lg font-semibold">
|
|
||||||
{price.toLocaleString("de-DE", {
|
|
||||||
style: "currency",
|
|
||||||
currency: "EUR",
|
|
||||||
})}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Participant Bar */}
|
|
||||||
<div className="w-full h-2 bg-white/40 rounded-full overflow-hidden">
|
|
||||||
<div
|
|
||||||
className={`h-full ${isFull ? "bg-red-500" : "bg-blue"}`}
|
|
||||||
style={{
|
|
||||||
width: `${maxParticipants > 0 ? (currentParticipants / maxParticipants) * 100 : 0}%`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between w-full">
|
|
||||||
<span
|
|
||||||
className={`w-fit text-xs font-semibold px-2 py-1 rounded-lg ${currentLevel.bg} ${currentLevel.text}`}
|
|
||||||
>
|
|
||||||
{currentLevel.label}
|
|
||||||
</span>
|
|
||||||
{/* Room */}
|
|
||||||
<p className="text-gray-500">{room}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between w-full">
|
|
||||||
{/* Status */}
|
|
||||||
{status && (
|
|
||||||
<span
|
|
||||||
className={`w-fit top-3 left-3 text-xs font-semibold px-2 py-1 rounded ${
|
|
||||||
status === "draft" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{status === "draft" ? "Entwurf" : "Veröffentlicht"}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{/* Actions */}
|
|
||||||
<div className="flex gap-2">
|
|
||||||
{courseId && status === "published" && (
|
|
||||||
<button
|
|
||||||
onClick={handleCopyLink}
|
|
||||||
className="p-2 rounded-md hover:bg-blue-100 transition"
|
|
||||||
title="Buchungslink kopieren"
|
|
||||||
>
|
>
|
||||||
<Link size={20} className="text-blue-600" />
|
<Avatar className="rounded-full border-2 border-white">
|
||||||
</button>
|
{avatarSrc && <AvatarImage src={avatarSrc} alt={displayName} />}
|
||||||
)}
|
<AvatarFallback>{getInitials(displayName)}</AvatarFallback>
|
||||||
{showDeleteIcon && onDelete && (
|
</Avatar>
|
||||||
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-500/10 transition">
|
</div>
|
||||||
<Trash2 size={20} className="text-red-600" />
|
</AbstractTooltip>
|
||||||
</button>
|
);
|
||||||
)}
|
})}
|
||||||
{onEdit && (
|
{/* Time */}
|
||||||
<button onClick={onEdit} className="p-2 rounded-md hover:bg-white/50 transition">
|
<div className="w-full flex justify-end">
|
||||||
<Pen size={20} className="text-gray-700" />
|
<p className="text-gray-500 text-lg">
|
||||||
</button>
|
{timeFrom} - {timeTo}
|
||||||
)}
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Course Name */}
|
||||||
|
<h2 className="text-xl font-semibold text-gray-900">{courseName}</h2>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
{/* Participant Number */}
|
||||||
|
<span className={isFull ? "text-red-600 font-semibold" : "text-gray-800"}>
|
||||||
|
{currentParticipants}/{maxParticipants} Teilnehmer
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* Price */}
|
||||||
|
<h2 className="text-lg font-semibold">
|
||||||
|
{price.toLocaleString("de-DE", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "EUR",
|
||||||
|
})}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Participant Bar */}
|
||||||
|
<div className="w-full h-2 bg-gray-200 rounded-full overflow-hidden">
|
||||||
|
<div
|
||||||
|
className={`h-full ${isFull ? "bg-red-500" : "bg-blue"}`}
|
||||||
|
style={{
|
||||||
|
width: `${maxParticipants > 0 ? (currentParticipants / maxParticipants) * 100 : 0}%`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
<span
|
||||||
|
className={`w-fit text-xs font-semibold px-2 py-1 rounded-lg ${currentLevel.bg} ${currentLevel.text}`}
|
||||||
|
>
|
||||||
|
{currentLevel.label}
|
||||||
|
</span>
|
||||||
|
{/* Room */}
|
||||||
|
<p className="text-gray-500">{room}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
{/* Status */}
|
||||||
|
{status && (
|
||||||
|
<span
|
||||||
|
className={`w-fit top-3 left-3 text-xs font-semibold px-2 py-1 rounded ${
|
||||||
|
status === "draft" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{status === "draft" ? "Entwurf" : "Veröffentlicht"}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{/* Actions */}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{courseId && status === "published" && (
|
||||||
|
<button
|
||||||
|
onClick={handleCopyLink}
|
||||||
|
className="p-2 rounded-md hover:bg-blue-100 transition"
|
||||||
|
title="Buchungslink kopieren"
|
||||||
|
>
|
||||||
|
<Link size={20} className="text-blue-600" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{showDeleteIcon && onDelete && (
|
||||||
|
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-100 transition">
|
||||||
|
<Trash2 size={20} className="text-red-600" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{onEdit && (
|
||||||
|
<button onClick={onEdit} className="p-2 rounded-md hover:bg-gray-100 transition">
|
||||||
|
<Pen size={20} className="text-gray-700" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -414,77 +414,67 @@ const PublicCourseCard = ({ course, business, defaultOpen = false }: PublicCours
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
onClick={() => setDialogOpen(true)}
|
onClick={() => setDialogOpen(true)}
|
||||||
className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl shadow-sm hover:shadow-md hover:bg-white/70 transition flex flex-col cursor-pointer overflow-hidden"
|
className="bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4"
|
||||||
>
|
>
|
||||||
{course.coverImage && (
|
<div className="flex items-center justify-between">
|
||||||
<div className="relative w-full h-36 shrink-0">
|
<p className="text-gray-500 text-sm">{formattedDate}</p>
|
||||||
<Image src={course.coverImage} alt={course.name} fill className="object-cover" />
|
<p className="text-gray-500 text-sm">
|
||||||
|
{course.timeFrom} – {course.timeTo}
|
||||||
|
</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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 p-5">
|
<h2 className="text-xl font-semibold text-gray-900">{course.name}</h2>
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<p className="text-gray-500 text-sm">{formattedDate}</p>
|
|
||||||
<p className="text-gray-500 text-sm">
|
|
||||||
{course.timeFrom} – {course.timeTo}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{course.trainerProfiles && course.trainerProfiles.length > 0 && (
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-1.5">
|
<span
|
||||||
{course.trainerProfiles.map((trainer) => {
|
className={`text-xs font-semibold px-2 py-1 rounded-lg ${currentLevel.bg} ${currentLevel.text}`}
|
||||||
const fullName =
|
>
|
||||||
[trainer.firstName, trainer.lastName].filter(Boolean).join(" ") || "Trainer";
|
{currentLevel.label}
|
||||||
return (
|
</span>
|
||||||
<Tooltip key={trainer.id}>
|
<span className="text-lg font-semibold">{formattedPrice}</span>
|
||||||
<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">
|
|
||||||
<span
|
|
||||||
className={`text-xs font-semibold px-2 py-1 rounded-lg ${currentLevel.bg} ${currentLevel.text}`}
|
|
||||||
>
|
|
||||||
{currentLevel.label}
|
|
||||||
</span>
|
|
||||||
<span className="text-lg font-semibold">{formattedPrice}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span
|
|
||||||
className={isFull ? "text-red-600 font-semibold text-sm" : "text-gray-700 text-sm"}
|
|
||||||
>
|
|
||||||
{course.currentParticipants}/{course.maxParticipants} Teilnehmer
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-full h-2 bg-white/40 rounded-full overflow-hidden">
|
|
||||||
<div
|
|
||||||
className={`h-full ${isFull ? "bg-red-500" : "bg-blue-500"}`}
|
|
||||||
style={{ width: `${fillPercent}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{isFull ? (
|
|
||||||
<Button disabled variant="outline" className="w-full">
|
|
||||||
Ausgebucht
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button className="w-full" onClick={() => setDialogOpen(true)}>
|
|
||||||
Jetzt anmelden
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className={isFull ? "text-red-600 font-semibold text-sm" : "text-gray-700 text-sm"}>
|
||||||
|
{course.currentParticipants}/{course.maxParticipants} Teilnehmer
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full h-2 bg-gray-200 rounded-full overflow-hidden">
|
||||||
|
<div
|
||||||
|
className={`h-full ${isFull ? "bg-red-500" : "bg-blue-500"}`}
|
||||||
|
style={{ width: `${fillPercent}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isFull ? (
|
||||||
|
<Button disabled variant="outline" className="w-full">
|
||||||
|
Ausgebucht
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button className="w-full" onClick={() => setDialogOpen(true)}>
|
||||||
|
Jetzt anmelden
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BookingDialog
|
<BookingDialog
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ const BusinessPublicView = ({
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50">
|
<div className="min-h-screen bg-gray-50">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="border-b border-white/60 bg-white/55 backdrop-blur-xl">
|
<div className="bg-white border-b border-gray-200">
|
||||||
<div className="max-w-6xl mx-auto px-6 py-10">
|
<div className="max-w-6xl mx-auto px-6 py-10">
|
||||||
<h1 className="text-4xl font-bold text-gray-900">{business.name}</h1>
|
<h1 className="text-4xl font-bold text-gray-900">{business.name}</h1>
|
||||||
{business.title && <p className="text-xl text-gray-500 mt-1">{business.title}</p>}
|
{business.title && <p className="text-xl text-gray-500 mt-1">{business.title}</p>}
|
||||||
|
|
@ -169,7 +169,7 @@ const BusinessPublicView = ({
|
||||||
{/* Left: sticky calendar */}
|
{/* Left: sticky calendar */}
|
||||||
<div className="lg:sticky lg:top-6 shrink-0 w-full lg:w-auto">
|
<div className="lg:sticky lg:top-6 shrink-0 w-full lg:w-auto">
|
||||||
<h2 className="text-2xl font-semibold text-gray-900 mb-3">{formattedSelectedDate}</h2>
|
<h2 className="text-2xl font-semibold text-gray-900 mb-3">{formattedSelectedDate}</h2>
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl shadow-sm p-4 flex justify-center">
|
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-4 flex justify-center">
|
||||||
<Calendar
|
<Calendar
|
||||||
mode="single"
|
mode="single"
|
||||||
selected={selectedDate}
|
selected={selectedDate}
|
||||||
|
|
@ -194,7 +194,7 @@ const BusinessPublicView = ({
|
||||||
className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors ${
|
className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors ${
|
||||||
resolvedSport === sport
|
resolvedSport === sport
|
||||||
? "bg-gray-900 text-white"
|
? "bg-gray-900 text-white"
|
||||||
: "border border-white/60 bg-white/55 backdrop-blur-sm text-gray-600 hover:bg-white/70"
|
: "bg-white border border-gray-200 text-gray-600 hover:border-gray-400"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{sport === "Alle" ? "Alle" : capitalize(sport)}
|
{sport === "Alle" ? "Alle" : capitalize(sport)}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ type Course = {
|
||||||
createdBy: string;
|
createdBy: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
coverImage: string | null;
|
|
||||||
_count?: {
|
_count?: {
|
||||||
bookings: number;
|
bookings: number;
|
||||||
};
|
};
|
||||||
|
|
@ -564,7 +563,7 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{filteredCourses.length === 0 ? (
|
{filteredCourses.length === 0 ? (
|
||||||
<div className="text-center py-12 border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl">
|
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
||||||
<p className="text-xl text-gray-600">
|
<p className="text-xl text-gray-600">
|
||||||
{courses.length === 0
|
{courses.length === 0
|
||||||
? "Sie haben noch keine Kurse erstellt"
|
? "Sie haben noch keine Kurse erstellt"
|
||||||
|
|
@ -610,7 +609,6 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
||||||
status={course.status}
|
status={course.status}
|
||||||
isPast={isPastCourse(course.date)}
|
isPast={isPastCourse(course.date)}
|
||||||
showDeleteIcon={deleteMode && canDelete}
|
showDeleteIcon={deleteMode && canDelete}
|
||||||
coverImage={course.coverImage ?? undefined}
|
|
||||||
onDelete={
|
onDelete={
|
||||||
canDelete ? () => handleDeleteClick(course.id, course.name) : undefined
|
canDelete ? () => handleDeleteClick(course.id, course.name) : undefined
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const DashboardView = async () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h1 className="text-3xl font-bold text-gray-900 mb-4">Willkommen zurück!</h1>
|
<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>
|
<p className="text-gray-600">Schön, dich wiederzusehen, {displayName}</p>
|
||||||
{isManager(userData) && (
|
{isManager(userData) && (
|
||||||
|
|
@ -28,13 +28,13 @@ const DashboardView = async () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<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">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-lg font-semibold mb-2">Profil</h2>
|
<h2 className="text-lg font-semibold mb-2">Profil</h2>
|
||||||
<p className="text-gray-600 text-sm">Verwalte deine persönlichen Daten</p>
|
<p className="text-gray-600 text-sm">Verwalte deine persönlichen Daten</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isManager(userData) ? (
|
{isManager(userData) ? (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-lg font-semibold mb-2">Meine Businesses</h2>
|
<h2 className="text-lg font-semibold mb-2">Meine Businesses</h2>
|
||||||
<p className="text-gray-600 text-sm">
|
<p className="text-gray-600 text-sm">
|
||||||
{userData.businesses.length}{" "}
|
{userData.businesses.length}{" "}
|
||||||
|
|
@ -42,7 +42,7 @@ const DashboardView = async () => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : isEmployee(userData) ? (
|
) : isEmployee(userData) ? (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-lg font-semibold mb-2">Meine Berechtigungen</h2>
|
<h2 className="text-lg font-semibold mb-2">Meine Berechtigungen</h2>
|
||||||
{(() => {
|
{(() => {
|
||||||
const p = userData.permissions;
|
const p = userData.permissions;
|
||||||
|
|
@ -79,20 +79,20 @@ const DashboardView = async () => {
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-lg font-semibold mb-2">Trainings</h2>
|
<h2 className="text-lg font-semibold mb-2">Trainings</h2>
|
||||||
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
|
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-lg font-semibold mb-2">Einstellungen</h2>
|
<h2 className="text-lg font-semibold mb-2">Einstellungen</h2>
|
||||||
<p className="text-gray-600 text-sm">Passe deine Einstellungen an</p>
|
<p className="text-gray-600 text-sm">Passe deine Einstellungen an</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isUser(userData) && (
|
{isUser(userData) && (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-xl font-semibold mb-4">Benutzerdaten</h2>
|
<h2 className="text-xl font-semibold mb-4">Benutzerdaten</h2>
|
||||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -132,7 +132,7 @@ const DashboardView = async () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isManager(userData) && (
|
{isManager(userData) && (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-xl font-semibold mb-4">Manager-Daten</h2>
|
<h2 className="text-xl font-semibold mb-4">Manager-Daten</h2>
|
||||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -164,7 +164,7 @@ const DashboardView = async () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isManager(userData) && userData.businesses.length > 0 && (
|
{isManager(userData) && userData.businesses.length > 0 && (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-xl font-semibold mb-4">Meine Businesses</h2>
|
<h2 className="text-xl font-semibold mb-4">Meine Businesses</h2>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{userData.businesses.map((business) => (
|
{userData.businesses.map((business) => (
|
||||||
|
|
@ -179,7 +179,7 @@ const DashboardView = async () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isEmployee(userData) && (
|
{isEmployee(userData) && (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl shadow-sm p-6">
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
<h2 className="text-xl font-semibold mb-4">Mitarbeiter-Daten</h2>
|
<h2 className="text-xl font-semibold mb-4">Mitarbeiter-Daten</h2>
|
||||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ const EmployeeListItem: React.FC<EmployeeListItemProps> = ({
|
||||||
showDeleteIcon,
|
showDeleteIcon,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-5 shadow-sm hover:shadow-md hover:bg-white/70 transition flex flex-col gap-4 relative">
|
<div className="bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4 relative">
|
||||||
{/* Status Badge */}
|
{/* Status Badge */}
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
|
@ -159,15 +159,15 @@ const EmployeeListItem: React.FC<EmployeeListItemProps> = ({
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{/* Action Buttons */}
|
{/* Action Buttons */}
|
||||||
<div className="flex justify-end items-center pt-3 border-t border-white/40">
|
<div className="flex justify-end items-center pt-3 border-t border-gray-200">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
{showDeleteIcon && onDelete && (
|
{showDeleteIcon && onDelete && (
|
||||||
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-500/10 transition">
|
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-100 transition">
|
||||||
<Trash2 size={20} className="text-red-600" />
|
<Trash2 size={20} className="text-red-600" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{onEdit && (
|
{onEdit && (
|
||||||
<button onClick={onEdit} className="p-2 rounded-md hover:bg-white/50 transition">
|
<button onClick={onEdit} className="p-2 rounded-md hover:bg-gray-100 transition">
|
||||||
<Pen size={20} className="text-gray-700" />
|
<Pen size={20} className="text-gray-700" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ const EmployeeListView = ({ canCreate, canEdit, canDelete }: EmployeeListViewPro
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{employees.length === 0 ? (
|
{employees.length === 0 ? (
|
||||||
<div className="text-center py-12 border border-white/60 bg-white/55 backdrop-blur-xl rounded-2xl">
|
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
||||||
<p className="text-xl text-gray-600">Keine Mitarbeiter vorhanden</p>
|
<p className="text-xl text-gray-600">Keine Mitarbeiter vorhanden</p>
|
||||||
{canCreate && (
|
{canCreate && (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
||||||
showDeleteIcon,
|
showDeleteIcon,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-5 shadow-sm hover:shadow-md hover:bg-white/70 transition flex flex-col gap-4 w-full max-w-xs justify-self-center">
|
<div className="bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4 w-full max-w-xs justify-self-center">
|
||||||
<div className="w-full flex items-center justify-between">
|
<div className="w-full flex items-center justify-between">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h2 className="text-xl text-gray-900">{roomName}</h2>
|
<h2 className="text-xl text-gray-900">{roomName}</h2>
|
||||||
|
|
@ -27,7 +27,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
||||||
<button
|
<button
|
||||||
aria-label={`Raum ${roomName} löschen`}
|
aria-label={`Raum ${roomName} löschen`}
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
className="p-2 rounded-md hover:bg-red-500/10 transition"
|
className="p-2 rounded-md hover:bg-red-100 transition"
|
||||||
>
|
>
|
||||||
<Trash2 size={20} className="text-red-600" />
|
<Trash2 size={20} className="text-red-600" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -36,7 +36,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
||||||
<button
|
<button
|
||||||
aria-label={`Raum ${roomName} bearbeiten`}
|
aria-label={`Raum ${roomName} bearbeiten`}
|
||||||
onClick={onEdit}
|
onClick={onEdit}
|
||||||
className="p-2 rounded-md hover:bg-white/50 transition"
|
className="p-2 rounded-md hover:bg-gray-100 transition"
|
||||||
>
|
>
|
||||||
<Pen size={20} className="text-gray-700" />
|
<Pen size={20} className="text-gray-700" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ const SettingsPaymentsView = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{businesses.length === 0 ? (
|
{businesses.length === 0 ? (
|
||||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-6 text-center">
|
<div className="border border-gray-200 rounded-xl p-6 bg-white text-center">
|
||||||
<p className="text-sm text-gray-500">Du hast noch keine Businesses angelegt.</p>
|
<p className="text-sm text-gray-500">Du hast noch keine Businesses angelegt.</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -139,7 +139,7 @@ const SettingsPaymentsView = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={business.id}
|
key={business.id}
|
||||||
className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-5 space-y-3"
|
className="border border-gray-200 rounded-xl p-5 bg-white space-y-3"
|
||||||
>
|
>
|
||||||
<div className="flex items-start justify-between gap-3">
|
<div className="flex items-start justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -190,7 +190,7 @@ const SettingsPaymentsView = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="border border-white/60 bg-white/40 backdrop-blur-xl rounded-xl p-4 text-xs text-gray-600">
|
<div className="border border-blue-100 bg-blue-50/50 rounded-xl p-4 text-xs text-gray-600">
|
||||||
<p className="font-medium text-gray-900 mb-1">So funktioniert es:</p>
|
<p className="font-medium text-gray-900 mb-1">So funktioniert es:</p>
|
||||||
<ul className="list-disc list-inside space-y-1">
|
<ul className="list-disc list-inside space-y-1">
|
||||||
<li>Klicke auf "Stripe-Konto verbinden" - du wirst zu Stripe weitergeleitet</li>
|
<li>Klicke auf "Stripe-Konto verbinden" - du wirst zu Stripe weitergeleitet</li>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const SettingsPersonalPageView = () => {
|
const SettignsPersonalPageView = () => {
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsPersonalPageView;
|
export default SettignsPersonalPageView;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue