Dashboard Design continue
This commit is contained in:
56
apps/hub/app/(app)/_components/Events.tsx
Normal file
56
apps/hub/app/(app)/_components/Events.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { getServerSession } from "../../api/auth/[...nextauth]/auth";
|
||||||
|
import { PrismaClient } from "@repo/db";
|
||||||
|
import { KursItem } from "../events/_components/item";
|
||||||
|
|
||||||
|
export default async () => {
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
const session = await getServerSession();
|
||||||
|
if (!session) return null;
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: session.user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!user) return null;
|
||||||
|
|
||||||
|
const events = await prisma.event.findMany({
|
||||||
|
include: {
|
||||||
|
appointments: {
|
||||||
|
where: {
|
||||||
|
appointmentDate: {
|
||||||
|
gte: new Date(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
participants: {
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const userAppointments = await prisma.eventAppointment.findMany({
|
||||||
|
where: {
|
||||||
|
Participants: {
|
||||||
|
some: {
|
||||||
|
userId: user.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-6 gap-4">
|
||||||
|
{events.map((event) => {
|
||||||
|
return (
|
||||||
|
<KursItem
|
||||||
|
selectedAppointments={userAppointments}
|
||||||
|
user={user}
|
||||||
|
event={event}
|
||||||
|
key={event.id}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -6,7 +6,7 @@ interface HeaderProps {
|
|||||||
handleCheckboxChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
handleCheckboxChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Header = ({ isChecked, handleCheckboxChange }: HeaderProps) => {
|
export default ({ isChecked, handleCheckboxChange }: HeaderProps) => {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
return (
|
return (
|
||||||
<header className="flex justify-between items-center p-4">
|
<header className="flex justify-between items-center p-4">
|
||||||
|
|||||||
66
apps/hub/app/(app)/_components/Logbook.tsx
Normal file
66
apps/hub/app/(app)/_components/Logbook.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import SortableTable from "../../_components/Table";
|
||||||
|
|
||||||
|
export default async () => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
header: "Station",
|
||||||
|
accessorKey: "publicId",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Einsatz Start",
|
||||||
|
accessorKey: "firstname",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Einsatz Ende",
|
||||||
|
accessorKey: "lastname",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Flugzeit",
|
||||||
|
accessorKey: "email",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const data: any[] = [
|
||||||
|
{
|
||||||
|
publicId: "Station 1",
|
||||||
|
firstname: "01.01.2021 12:00",
|
||||||
|
lastname: "01.01.2021 13:04",
|
||||||
|
email: "01h 04m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
publicId: "Station 1",
|
||||||
|
firstname: "01.01.2021 12:00",
|
||||||
|
lastname: "01.01.2021 13:04",
|
||||||
|
email: "01h 04m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
publicId: "Station 1",
|
||||||
|
firstname: "01.01.2021 12:00",
|
||||||
|
lastname: "01.01.2021 13:04",
|
||||||
|
email: "01h 04m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
publicId: "Station 1",
|
||||||
|
firstname: "01.01.2021 12:00",
|
||||||
|
lastname: "01.01.2021 13:04",
|
||||||
|
email: "01h 04m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
publicId: "Station 1",
|
||||||
|
firstname: "01.01.2021 12:00",
|
||||||
|
lastname: "01.01.2021 13:04",
|
||||||
|
email: "01h 04m",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SortableTable
|
||||||
|
data={data}
|
||||||
|
columns={columns}
|
||||||
|
showEditButton={false} // Set to true if you want to show edit buttons
|
||||||
|
prismaModel="user" // Pass the prisma model if needed
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
25
apps/hub/app/(app)/_components/StatsClientWrapper.tsx
Normal file
25
apps/hub/app/(app)/_components/StatsClientWrapper.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import Header from "./Header";
|
||||||
|
import Stats from "./stats";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [isChecked, setIsChecked] = useState(true);
|
||||||
|
|
||||||
|
const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setIsChecked(event.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header
|
||||||
|
isChecked={isChecked}
|
||||||
|
handleCheckboxChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-4 col-span-6 xl:col-span-3">
|
||||||
|
<Stats isChecked={isChecked} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -4,8 +4,8 @@ interface StatsProps {
|
|||||||
isChecked: boolean;
|
isChecked: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Stats = ({ isChecked }: StatsProps) => {
|
export default ({ isChecked }: StatsProps) => {
|
||||||
return isChecked ? PilotStats() : DispoStats();
|
return isChecked ? <PilotStats /> : <DispoStats />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PilotStats = (): JSX.Element => {
|
export const PilotStats = (): JSX.Element => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
import Logbook from "./_components/Logbook";
|
||||||
|
import { ArrowRight, NotebookText, Award, RocketIcon } from "lucide-react";
|
||||||
import { useState } from "react";
|
import Link from "next/link";
|
||||||
import { Header } from "./_components/Header";
|
import Events from "./_components/Events";
|
||||||
import { Stats } from "./_components/stats";
|
import StatsClientWrapper from "./_components/StatsClientWrapper";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
✔️ Einlog-Zeit
|
✔️ Einlog-Zeit
|
||||||
@@ -15,21 +15,45 @@ Aktive Events / Mandatory Events
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [isChecked, setIsChecked] = useState(true);
|
|
||||||
|
|
||||||
const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setIsChecked(event.target.checked);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Header
|
<StatsClientWrapper />
|
||||||
isChecked={isChecked}
|
|
||||||
handleCheckboxChange={handleCheckboxChange}
|
<div className="grid grid-cols-6 gap-4">
|
||||||
/>
|
|
||||||
<div className="card bg-base-200 shadow-xl mb-4 col-span-6 xl:col-span-3">
|
<div className="card bg-base-200 shadow-xl mb-4 col-span-6 xl:col-span-3">
|
||||||
<Stats isChecked={isChecked} />
|
<div className="card-body">
|
||||||
|
<h2 className="card-title justify-between">
|
||||||
|
<span className="card-title">
|
||||||
|
<NotebookText className="w-4 h-4" /> Logbook
|
||||||
|
</span>
|
||||||
|
<Link
|
||||||
|
className="badge badge-sm badge-info badge-outline"
|
||||||
|
href="/settings"
|
||||||
|
>
|
||||||
|
Zum vollständigen Logbook <ArrowRight className="w-4 h-4" />
|
||||||
|
</Link>
|
||||||
|
</h2>
|
||||||
|
<Logbook />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-4 col-span-6 xl:col-span-3">
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title justify-between">
|
||||||
|
<span className="card-title">
|
||||||
|
<Award className="w-4 h-4" /> Verdiente Abzeichen
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
Badges
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-span-full">
|
||||||
|
<p className="text-xl font-semibold text-left flex items-center gap-2 mb-2 mt-5">
|
||||||
|
<RocketIcon className="w-4 h-4" /> Laufende Events & Kurse
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Events />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
PersonIcon,
|
|
||||||
GearIcon,
|
GearIcon,
|
||||||
ExitIcon,
|
ExitIcon,
|
||||||
LockClosedIcon,
|
LockClosedIcon,
|
||||||
RocketIcon,
|
RocketIcon,
|
||||||
|
ReaderIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} from "@radix-ui/react-icons";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
@@ -22,6 +22,18 @@ export const VerticalNav = () => {
|
|||||||
Events & Kurse
|
Events & Kurse
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="/events">
|
||||||
|
<ReaderIcon />
|
||||||
|
Logbook
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="/settings">
|
||||||
|
<GearIcon />
|
||||||
|
Einstellungen
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<details open>
|
<details open>
|
||||||
<summary>
|
<summary>
|
||||||
@@ -41,12 +53,6 @@ export const VerticalNav = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<Link href="/settings">
|
|
||||||
<GearIcon />
|
|
||||||
Einstellungen
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user