Discord account Linkage, penalty update
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
ConnectedAircraft,
|
||||
ConnectedDispatcher,
|
||||
DiscordAccount,
|
||||
FormerDiscordAccount,
|
||||
Penalty,
|
||||
PERMISSION,
|
||||
Prisma,
|
||||
@@ -60,6 +61,7 @@ import { penaltyColumns } from "(app)/admin/penalty/columns";
|
||||
import { addPenalty, editPenaltys } from "(app)/admin/penalty/actions";
|
||||
import { reportColumns } from "(app)/admin/report/columns";
|
||||
import { sendMailByTemplate } from "../../../../../../helper/mail";
|
||||
import Image from "next/image";
|
||||
|
||||
interface ProfileFormProps {
|
||||
user: User;
|
||||
@@ -566,6 +568,7 @@ interface AdminFormProps {
|
||||
minutes: number;
|
||||
lastLogin?: Date;
|
||||
};
|
||||
formerDiscordAccounts: (FormerDiscordAccount & { DiscordAccount: DiscordAccount | null })[];
|
||||
reports: {
|
||||
total: number;
|
||||
open: number;
|
||||
@@ -585,6 +588,7 @@ export const AdminForm = ({
|
||||
pilotTime,
|
||||
reports,
|
||||
discordAccount,
|
||||
formerDiscordAccounts,
|
||||
openBans,
|
||||
openTimebans,
|
||||
}: AdminFormProps) => {
|
||||
@@ -755,6 +759,64 @@ export const AdminForm = ({
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<h2 className="card-title mt-2">
|
||||
<DiscordLogoIcon className="h-5 w-5" /> Frühere Discord Accounts
|
||||
</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="table-sm table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Avatar</th>
|
||||
<th>Benutzername</th>
|
||||
<th>Discord ID</th>
|
||||
<th>getrennt am</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{discordAccount && (
|
||||
<tr>
|
||||
<td>
|
||||
<Image
|
||||
src={`https://cdn.discordapp.com/avatars/${discordAccount.discordId}/${discordAccount.avatar}.png`}
|
||||
alt="Discord Avatar"
|
||||
width={40}
|
||||
height={40}
|
||||
className="h-10 w-10 rounded-full"
|
||||
/>
|
||||
</td>
|
||||
<td>{discordAccount.username}</td>
|
||||
<td>{discordAccount.discordId}</td>
|
||||
<td>N/A (Aktuell verbunden)</td>
|
||||
</tr>
|
||||
)}
|
||||
{formerDiscordAccounts.map((account) => (
|
||||
<tr key={account.discordId}>
|
||||
<td>
|
||||
{account.DiscordAccount && (
|
||||
<Image
|
||||
src={`https://cdn.discordapp.com/avatars/${account.DiscordAccount.discordId}/${account.DiscordAccount.avatar}.png`}
|
||||
alt="Discord Avatar"
|
||||
width={40}
|
||||
height={40}
|
||||
className="h-10 w-10 rounded-full"
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>{account.DiscordAccount?.username || "Unbekannt"}</td>
|
||||
<td>{account.DiscordAccount?.discordId || "Unbekannt"}</td>
|
||||
<td>{new Date(account.removedAt).toLocaleDateString()}</td>
|
||||
</tr>
|
||||
))}
|
||||
{!discordAccount && formerDiscordAccounts.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={3} className="text-center text-gray-400">
|
||||
Keine Discord Accounts verknüpft
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2 className="card-title">
|
||||
<ChartBarBigIcon className="h-5 w-5" /> Aktivität
|
||||
|
||||
@@ -12,16 +12,37 @@ import { getUserPenaltys } from "@repo/shared-components";
|
||||
|
||||
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
const user = await prisma.user.findUnique({
|
||||
let user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
include: {
|
||||
discordAccounts: true,
|
||||
DiscordAccount: true,
|
||||
CanonicalUser: true,
|
||||
Duplicates: true,
|
||||
},
|
||||
});
|
||||
if (!user) {
|
||||
user = await prisma.user.findFirst({
|
||||
where: {
|
||||
publicId: id,
|
||||
},
|
||||
include: {
|
||||
DiscordAccount: true,
|
||||
CanonicalUser: true,
|
||||
Duplicates: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const formerDiscordAccounts = await prisma.formerDiscordAccount.findMany({
|
||||
where: {
|
||||
userId: user?.id,
|
||||
},
|
||||
include: {
|
||||
DiscordAccount: true,
|
||||
},
|
||||
});
|
||||
if (!user) return <Error statusCode={404} title="User not found" />;
|
||||
|
||||
const dispoSessions = await prisma.connectedDispatcher.findMany({
|
||||
@@ -121,11 +142,12 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
|
||||
</div>
|
||||
<div className="card bg-base-200 col-span-6 mb-4 shadow-xl xl:col-span-3">
|
||||
<AdminForm
|
||||
formerDiscordAccounts={formerDiscordAccounts}
|
||||
user={user}
|
||||
dispoTime={dispoTime}
|
||||
pilotTime={pilotTime}
|
||||
reports={reports}
|
||||
discordAccount={user.discordAccounts[0]}
|
||||
discordAccount={user.DiscordAccount ?? undefined}
|
||||
openBans={openBans}
|
||||
openTimebans={openTimeban}
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { User2 } from "lucide-react";
|
||||
import { PaginatedTable } from "../../../_components/PaginatedTable";
|
||||
import Link from "next/link";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { DiscordAccount, Prisma, User } from "@repo/db";
|
||||
import { DiscordAccount, Penalty, Prisma, User } from "@repo/db";
|
||||
import { useSession } from "next-auth/react";
|
||||
|
||||
const AdminUserPage = () => {
|
||||
@@ -21,16 +21,15 @@ const AdminUserPage = () => {
|
||||
{ firstname: { contains: searchTerm, mode: "insensitive" } },
|
||||
{ lastname: { contains: searchTerm, mode: "insensitive" } },
|
||||
{ email: { contains: searchTerm, mode: "insensitive" } },
|
||||
{
|
||||
discordAccounts: {
|
||||
some: { username: { contains: searchTerm, mode: "insensitive" } },
|
||||
},
|
||||
},
|
||||
{ publicId: { contains: searchTerm, mode: "insensitive" } },
|
||||
{ DiscordAccount: { username: { contains: searchTerm, mode: "insensitive" } } },
|
||||
],
|
||||
} as Prisma.UserWhereInput;
|
||||
}}
|
||||
include={{
|
||||
discordAccounts: true,
|
||||
DiscordAccount: true,
|
||||
ReceivedReports: true,
|
||||
Penaltys: true,
|
||||
}}
|
||||
initialOrderBy={[
|
||||
{
|
||||
@@ -55,6 +54,15 @@ const AdminUserPage = () => {
|
||||
{
|
||||
header: "Berechtigungen",
|
||||
cell(props) {
|
||||
const activePenaltys = props.row.original.Penaltys.filter(
|
||||
(penalty) =>
|
||||
!penalty.suspended &&
|
||||
(penalty.type === "BAN" ||
|
||||
(penalty.type === "TIME_BAN" && penalty!.until! > new Date())),
|
||||
);
|
||||
if (activePenaltys.length > 0) {
|
||||
return <span className="font-bold text-red-600">AKTIVE STRAFE</span>;
|
||||
}
|
||||
if (props.row.original.permissions.length === 0) {
|
||||
return <span className="text-gray-700">Keine</span>;
|
||||
} else if (props.row.original.permissions.includes("ADMIN_USER_ADVANCED")) {
|
||||
@@ -69,14 +77,26 @@ const AdminUserPage = () => {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Strafen / Reports",
|
||||
cell(props) {
|
||||
const penaltyCount = props.row.original.Penaltys.length;
|
||||
const reportCount = props.row.original.ReceivedReports.length;
|
||||
return (
|
||||
<span className="w-full text-center">
|
||||
{penaltyCount} / {reportCount}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Discord",
|
||||
cell(props) {
|
||||
const discord = props.row.original.discordAccounts;
|
||||
if (discord.length === 0) {
|
||||
const discord = props.row.original.DiscordAccount;
|
||||
if (!discord) {
|
||||
return <span className="text-gray-700">Nicht verbunden</span>;
|
||||
}
|
||||
return <span>{discord.map((d) => d.username).join(", ")}</span>;
|
||||
return <span>{discord.username}</span>;
|
||||
},
|
||||
},
|
||||
...(session?.user.permissions.includes("ADMIN_USER_ADVANCED")
|
||||
@@ -97,7 +117,13 @@ const AdminUserPage = () => {
|
||||
</div>
|
||||
),
|
||||
},
|
||||
] as ColumnDef<User & { discordAccounts: DiscordAccount[] }>[]
|
||||
] as ColumnDef<
|
||||
User & {
|
||||
DiscordAccount: DiscordAccount;
|
||||
ReceivedReports: Report[];
|
||||
Penaltys: Penalty[];
|
||||
}
|
||||
>[]
|
||||
} // Define the columns for the user table
|
||||
leftOfSearch={
|
||||
<p className="flex items-center gap-2 text-left text-2xl font-semibold">
|
||||
|
||||
Reference in New Issue
Block a user