Merge pull request #112 from Since-3/feature/added-customer-data-to-customer-page

added real customer data to the customer page in the admin dashbaord
This commit is contained in:
Rajpreet0 2026-05-26 19:29:59 +02:00 • committed by GitHub
commit 9231d9651c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 86 additions and 80 deletions

View file

@ -1,9 +1,15 @@
import { requireManager } from "@/src/lib/auth/getUser";
import { getKunden } from "@/src/modules/kunden/actions/kunden-actions";
import KundenView from "@/src/modules/kunden/ui/views/kunden-view";
const KundenPage = async () => {
await requireManager();
return <KundenView />;
const result = await getKunden();
if (!result.success) {
throw new Error(result.error);
}
return <KundenView initialKunden={result.kunden} />;
};
export default KundenPage;

View file

@ -256,7 +256,7 @@ export async function requireGuest() {
* Redirects to /dashboard if user is not a manager.
* Redirects to /login if not authenticated.
*/
export async function requireManager() {
export async function requireManager(): Promise<ManagerData> {
const userData = await requireAuthWithData();
if (!isManager(userData)) {
@ -264,7 +264,7 @@ export async function requireManager() {
redirect("/dashboard");
}
return userData;
return userData as ManagerData;
}
// Helper function to check if user is a manager

View file

@ -0,0 +1,68 @@
"use server";
import { prisma } from "@/src/lib/prisma";
import { requireManager } from "@/src/lib/auth/getUser";
export type KundeRow = {
id: string;
name: string;
email: string;
telefon: string;
status: "Bezahlt" | "Storniert" | "Ausstehend";
};
function mapPaymentStatus(paymentStatus: string): KundeRow["status"] {
if (paymentStatus === "paid") return "Bezahlt";
if (paymentStatus === "refunded") return "Storniert";
return "Ausstehend";
}
export async function getKunden(): Promise<
{ success: true; kunden: KundeRow[] } | { success: false; error: string }
> {
const manager = await requireManager();
const businessIds = manager.businesses.map((b) => b.id);
try {
if (businessIds.length === 0) {
return { success: true, kunden: [] };
}
// Alle Bookings für Kurse die zu diesem Manager gehören, gruppiert nach User
const bookings = await prisma.courseBooking.findMany({
where: {
course: { businessId: { in: businessIds } },
},
select: {
paymentStatus: true,
user: {
select: {
id: true,
name: true,
email: true,
tel: true,
},
},
},
orderBy: { createdAt: "desc" },
});
// Pro User nur den letzten (relevantesten) Status behalten
const seen = new Map<string, KundeRow>();
for (const booking of bookings) {
if (!seen.has(booking.user.id)) {
seen.set(booking.user.id, {
id: booking.user.id,
name: booking.user.name ?? booking.user.email,
email: booking.user.email,
telefon: booking.user.tel ?? "–",
status: mapPaymentStatus(booking.paymentStatus),
});
}
}
return { success: true, kunden: Array.from(seen.values()) };
} catch {
return { success: false, error: "Kunden konnten nicht geladen werden." };
}
}

View file

@ -14,9 +14,9 @@ import { useRouter } from "next/navigation";
import type { Kunde } from "../views/kunden-view";
const STATUS_STYLES: Record<Kunde["status"], string> = {
Teilgenommen: "bg-green-100 text-green-700",
Bezahlt: "bg-green-100 text-green-700",
Storniert: "bg-red-100 text-red-600",
Bezahlt: "bg-blue-100 text-blue-700",
Ausstehend: "bg-yellow-100 text-yellow-700",
};
interface KundenTableProps {

View file

@ -4,86 +4,18 @@ import { useState } from "react";
import { Input } from "@/src/components/ui/input";
import { Search } from "lucide-react";
import KundenTable from "../components/kunden-table";
import type { KundeRow } from "../../actions/kunden-actions";
const DUMMY_KUNDEN = [
{
id: "1",
name: "Stern Thireau",
email: "sthireau0@prilog.org",
telefon: "+49 160 14256244",
status: "Teilgenommen" as const,
},
{
id: "2",
name: "Ford Mckibbin",
email: "fmckibbin1@slate.com",
telefon: "+49 160 84256328",
status: "Storniert" as const,
},
{
id: "3",
name: "Foss Roglieri",
email: "froglieri2@xing.com",
telefon: "+49 160 78745913",
status: "Teilgenommen" as const,
},
{
id: "4",
name: "Maurits Elgey",
email: "melgey3@blogger.com",
telefon: "+49 160 55834625",
status: "Teilgenommen" as const,
},
{
id: "5",
name: "Gun Kaasmann",
email: "gkaasmann4@economist.com",
telefon: "+49 160 32679584",
status: "Teilgenommen" as const,
},
{
id: "6",
name: "Edmund McCrae",
email: "emccrae5@woothemes.com",
telefon: "+49 160 69321457",
status: "Bezahlt" as const,
},
{
id: "7",
name: "Samuel Totman",
email: "stotman6@wisc.edu",
telefon: "+49 160 96851428",
status: "Teilgenommen" as const,
},
{
id: "8",
name: "Patsy Cuardall",
email: "pcuardall70@barnesandnoble.com",
telefon: "+49 160 38591426",
status: "Bezahlt" as const,
},
{
id: "9",
name: "Barnaby Carl",
email: "bcarl8@alexa.com",
telefon: "+49 160 77958426",
status: "Storniert" as const,
},
{
id: "10",
name: "Lena Bergmann",
email: "lbergmann9@spiegel.de",
telefon: "+49 160 12345678",
status: "Bezahlt" as const,
},
];
export type Kunde = KundeRow;
export type Kunde = (typeof DUMMY_KUNDEN)[number];
interface KundenViewProps {
initialKunden: KundeRow[];
}
const KundenView = () => {
const KundenView = ({ initialKunden }: KundenViewProps) => {
const [search, setSearch] = useState("");
const filtered = DUMMY_KUNDEN.filter(
const filtered = initialKunden.filter(
(k) =>
k.name.toLowerCase().includes(search.toLowerCase()) ||
k.email.toLowerCase().includes(search.toLowerCase()) ||