mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 20:51:18 +00:00
Merge pull request #116 from Since-3/feature/added-glassmorphism
added subtil glassmorphism
This commit is contained in:
commit
5354a90a8d
11 changed files with 200 additions and 177 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import SettignsPersonalPageView from "@/src/modules/settings/ui/views/settings-personal-page-view";
|
||||
import SettingsPersonalPageView from "@/src/modules/settings/ui/views/settings-personal-page-view";
|
||||
|
||||
export default async function SettingsPersonalPage() {
|
||||
return <SettignsPersonalPageView />;
|
||||
return <SettingsPersonalPageView />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import AbstractTooltip from "@/src/components/layout/AbstractTooltip";
|
|||
import { Avatar, AvatarFallback, AvatarImage } from "@/src/components/ui/avatar";
|
||||
import { Pen, Trash2, Link } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import Image from "next/image";
|
||||
|
||||
/**
|
||||
* Props für die CourseListItem Komponente
|
||||
|
|
@ -31,6 +32,7 @@ interface CourseListItemProps {
|
|||
status?: string; // Status des Kurses ("draft" oder "published")
|
||||
isPast?: boolean; // Ob der Kurs in der Vergangenheit liegt
|
||||
showDeleteIcon?: boolean; // Ob das Löschen-Icon angezeigt werden soll
|
||||
coverImage?: string; // Optionales Cover-Bild
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -54,6 +56,7 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
|||
status,
|
||||
isPast,
|
||||
showDeleteIcon,
|
||||
coverImage,
|
||||
}) => {
|
||||
// Prüfen, ob der Kurs voll belegt ist (für visuelle Hervorhebung)
|
||||
const isFull = currentParticipants >= maxParticipants;
|
||||
|
|
@ -87,109 +90,117 @@ const CourseListItem: React.FC<CourseListItemProps> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
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 bg-gray-50" : ""
|
||||
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 ${
|
||||
isPast ? "opacity-60" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center w-full">
|
||||
{trainers.map((trainerId, index) => {
|
||||
const trainerInfo = trainersMap[trainerId];
|
||||
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>
|
||||
{coverImage && (
|
||||
<div className="relative w-full h-36 shrink-0">
|
||||
<Image src={coverImage} alt={courseName} fill className="object-cover" />
|
||||
</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",
|
||||
<div className="flex flex-col gap-4 p-5">
|
||||
<div className="flex items-center w-full">
|
||||
{trainers.map((trainerId, index) => {
|
||||
const trainerInfo = trainersMap[trainerId];
|
||||
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>
|
||||
);
|
||||
})}
|
||||
</h2>
|
||||
</div>
|
||||
{/* Time */}
|
||||
<div className="w-full flex justify-end">
|
||||
<p className="text-gray-500 text-lg">
|
||||
{timeFrom} - {timeTo}
|
||||
</p>
|
||||
</div>
|
||||
</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>
|
||||
{/* Course Name */}
|
||||
<h2 className="text-xl font-semibold text-gray-900">{courseName}</h2>
|
||||
|
||||
<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"}
|
||||
<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>
|
||||
)}
|
||||
{/* 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"
|
||||
|
||||
{/* 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"
|
||||
}`}
|
||||
>
|
||||
<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>
|
||||
{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-500/10 transition">
|
||||
<Trash2 size={20} className="text-red-600" />
|
||||
</button>
|
||||
)}
|
||||
{onEdit && (
|
||||
<button onClick={onEdit} className="p-2 rounded-md hover:bg-white/50 transition">
|
||||
<Pen size={20} className="text-gray-700" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -414,67 +414,77 @@ const PublicCourseCard = ({ course, business, defaultOpen = false }: PublicCours
|
|||
<>
|
||||
<div
|
||||
onClick={() => setDialogOpen(true)}
|
||||
className="bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4"
|
||||
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"
|
||||
>
|
||||
<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 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>
|
||||
);
|
||||
})}
|
||||
{course.coverImage && (
|
||||
<div className="relative w-full h-36 shrink-0">
|
||||
<Image src={course.coverImage} alt={course.name} fill className="object-cover" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<h2 className="text-xl font-semibold text-gray-900">{course.name}</h2>
|
||||
<div className="flex flex-col gap-4 p-5">
|
||||
<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>
|
||||
|
||||
<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>
|
||||
{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">
|
||||
<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 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>
|
||||
|
||||
<BookingDialog
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ const BusinessPublicView = ({
|
|||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* Header */}
|
||||
<div className="bg-white border-b border-gray-200">
|
||||
<div className="border-b border-white/60 bg-white/55 backdrop-blur-xl">
|
||||
<div className="max-w-6xl mx-auto px-6 py-10">
|
||||
<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>}
|
||||
|
|
@ -169,7 +169,7 @@ const BusinessPublicView = ({
|
|||
{/* Left: sticky calendar */}
|
||||
<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>
|
||||
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-4 flex justify-center">
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl shadow-sm p-4 flex justify-center">
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={selectedDate}
|
||||
|
|
@ -194,7 +194,7 @@ const BusinessPublicView = ({
|
|||
className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors ${
|
||||
resolvedSport === sport
|
||||
? "bg-gray-900 text-white"
|
||||
: "bg-white border border-gray-200 text-gray-600 hover:border-gray-400"
|
||||
: "border border-white/60 bg-white/55 backdrop-blur-sm text-gray-600 hover:bg-white/70"
|
||||
}`}
|
||||
>
|
||||
{sport === "Alle" ? "Alle" : capitalize(sport)}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ type Course = {
|
|||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
coverImage: string | null;
|
||||
_count?: {
|
||||
bookings: number;
|
||||
};
|
||||
|
|
@ -563,7 +564,7 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
|||
)}
|
||||
|
||||
{filteredCourses.length === 0 ? (
|
||||
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
||||
<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"
|
||||
|
|
@ -609,6 +610,7 @@ const CourseListView = ({ canCreate, canEdit, canDelete }: CourseListViewProps)
|
|||
status={course.status}
|
||||
isPast={isPastCourse(course.date)}
|
||||
showDeleteIcon={deleteMode && canDelete}
|
||||
coverImage={course.coverImage ?? undefined}
|
||||
onDelete={
|
||||
canDelete ? () => handleDeleteClick(course.id, course.name) : undefined
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const DashboardView = async () => {
|
|||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="bg-white rounded-lg shadow p-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) && (
|
||||
|
|
@ -28,13 +28,13 @@ const DashboardView = async () => {
|
|||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="bg-white rounded-lg shadow p-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>
|
||||
</div>
|
||||
|
||||
{isManager(userData) ? (
|
||||
<div className="bg-white rounded-lg shadow p-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">Meine Businesses</h2>
|
||||
<p className="text-gray-600 text-sm">
|
||||
{userData.businesses.length}{" "}
|
||||
|
|
@ -42,7 +42,7 @@ const DashboardView = async () => {
|
|||
</p>
|
||||
</div>
|
||||
) : isEmployee(userData) ? (
|
||||
<div className="bg-white rounded-lg shadow p-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">Meine Berechtigungen</h2>
|
||||
{(() => {
|
||||
const p = userData.permissions;
|
||||
|
|
@ -79,20 +79,20 @@ const DashboardView = async () => {
|
|||
})()}
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white rounded-lg shadow p-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">Trainings</h2>
|
||||
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="bg-white rounded-lg shadow p-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">Einstellungen</h2>
|
||||
<p className="text-gray-600 text-sm">Passe deine Einstellungen an</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isUser(userData) && (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<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>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
|
|
@ -132,7 +132,7 @@ const DashboardView = async () => {
|
|||
)}
|
||||
|
||||
{isManager(userData) && (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<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>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
|
|
@ -164,7 +164,7 @@ const DashboardView = async () => {
|
|||
)}
|
||||
|
||||
{isManager(userData) && userData.businesses.length > 0 && (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<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>
|
||||
<div className="space-y-4">
|
||||
{userData.businesses.map((business) => (
|
||||
|
|
@ -179,7 +179,7 @@ const DashboardView = async () => {
|
|||
)}
|
||||
|
||||
{isEmployee(userData) && (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<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>
|
||||
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const EmployeeListItem: React.FC<EmployeeListItemProps> = ({
|
|||
showDeleteIcon,
|
||||
}) => {
|
||||
return (
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-5 shadow-sm hover:shadow-md transition flex flex-col gap-4 relative">
|
||||
<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">
|
||||
{/* Status Badge */}
|
||||
<div className="flex justify-between items-start">
|
||||
<div className="flex gap-2">
|
||||
|
|
@ -159,15 +159,15 @@ const EmployeeListItem: React.FC<EmployeeListItemProps> = ({
|
|||
})()}
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex justify-end items-center pt-3 border-t border-gray-200">
|
||||
<div className="flex justify-end items-center pt-3 border-t border-white/40">
|
||||
<div className="flex gap-2">
|
||||
{showDeleteIcon && onDelete && (
|
||||
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-100 transition">
|
||||
<button onClick={onDelete} className="p-2 rounded-md hover:bg-red-500/10 transition">
|
||||
<Trash2 size={20} className="text-red-600" />
|
||||
</button>
|
||||
)}
|
||||
{onEdit && (
|
||||
<button onClick={onEdit} className="p-2 rounded-md hover:bg-gray-100 transition">
|
||||
<button onClick={onEdit} className="p-2 rounded-md hover:bg-white/50 transition">
|
||||
<Pen size={20} className="text-gray-700" />
|
||||
</button>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ const EmployeeListView = ({ canCreate, canEdit, canDelete }: EmployeeListViewPro
|
|||
</div>
|
||||
|
||||
{employees.length === 0 ? (
|
||||
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
||||
<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">Keine Mitarbeiter vorhanden</p>
|
||||
{canCreate && (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
|||
showDeleteIcon,
|
||||
}) => {
|
||||
return (
|
||||
<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="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="w-full flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<h2 className="text-xl text-gray-900">{roomName}</h2>
|
||||
|
|
@ -27,7 +27,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
|||
<button
|
||||
aria-label={`Raum ${roomName} löschen`}
|
||||
onClick={onDelete}
|
||||
className="p-2 rounded-md hover:bg-red-100 transition"
|
||||
className="p-2 rounded-md hover:bg-red-500/10 transition"
|
||||
>
|
||||
<Trash2 size={20} className="text-red-600" />
|
||||
</button>
|
||||
|
|
@ -36,7 +36,7 @@ const RoomsListItem: React.FC<RoomsListItemProps> = ({
|
|||
<button
|
||||
aria-label={`Raum ${roomName} bearbeiten`}
|
||||
onClick={onEdit}
|
||||
className="p-2 rounded-md hover:bg-gray-100 transition"
|
||||
className="p-2 rounded-md hover:bg-white/50 transition"
|
||||
>
|
||||
<Pen size={20} className="text-gray-700" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ const SettingsPaymentsView = () => {
|
|||
</div>
|
||||
|
||||
{businesses.length === 0 ? (
|
||||
<div className="border border-gray-200 rounded-xl p-6 bg-white text-center">
|
||||
<div className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-6 text-center">
|
||||
<p className="text-sm text-gray-500">Du hast noch keine Businesses angelegt.</p>
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -139,7 +139,7 @@ const SettingsPaymentsView = () => {
|
|||
return (
|
||||
<div
|
||||
key={business.id}
|
||||
className="border border-gray-200 rounded-xl p-5 bg-white space-y-3"
|
||||
className="border border-white/60 bg-white/55 backdrop-blur-xl rounded-xl p-5 space-y-3"
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
|
|
@ -190,7 +190,7 @@ const SettingsPaymentsView = () => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="border border-blue-100 bg-blue-50/50 rounded-xl p-4 text-xs text-gray-600">
|
||||
<div className="border border-white/60 bg-white/40 backdrop-blur-xl rounded-xl p-4 text-xs text-gray-600">
|
||||
<p className="font-medium text-gray-900 mb-1">So funktioniert es:</p>
|
||||
<ul className="list-disc list-inside space-y-1">
|
||||
<li>Klicke auf "Stripe-Konto verbinden" - du wirst zu Stripe weitergeleitet</li>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const SettignsPersonalPageView = () => {
|
||||
const SettingsPersonalPageView = () => {
|
||||
return <div></div>;
|
||||
};
|
||||
|
||||
export default SettignsPersonalPageView;
|
||||
export default SettingsPersonalPageView;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue