added chrom

This commit is contained in:
PxlLoewe
2025-06-05 10:18:52 -07:00
parent 59f3da5c84
commit 63166b602a
9 changed files with 65 additions and 43 deletions

View File

@@ -1,7 +1,7 @@
import { Client, GatewayIntentBits } from "discord.js"; import { Client, GatewayIntentBits } from "discord.js";
const client = new Client({ const client = new Client({
intents: [GatewayIntentBits.Guilds], intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
}); });
const token = process.env.DISCORD_BOT_TOKEN; const token = process.env.DISCORD_BOT_TOKEN;

View File

@@ -51,12 +51,15 @@ const handleRoleChange = (action: "add" | "remove") => async (req: Request, res:
? roleIds.filter((id: string) => !currentRoleIds.includes(id)) ? roleIds.filter((id: string) => !currentRoleIds.includes(id))
: roleIds.filter((id: string) => currentRoleIds.includes(id)); : roleIds.filter((id: string) => currentRoleIds.includes(id));
console.log(`Attempting to ${action} roles:`, filteredRoleIds, roleIds); console.log(
`Attempting to ${action} roles: ${filteredRoleIds.join(", ")} to member ${member.nickname || member.user.username}`,
);
// Option to skip if no roles to add/remove // Option to skip if no roles to add/remove
/* if (filteredRoleIds.length === 0) { if (filteredRoleIds.length === 0) {
console.log(`No roles to ${action}`);
res.status(200).json({ message: `No roles to ${action}` }); res.status(200).json({ message: `No roles to ${action}` });
return; return;
} */ }
await member.roles[action](roleIds); await member.roles[action](roleIds);
res.status(200).json({ message: `Roles ${action}ed successfully` }); res.status(200).json({ message: `Roles ${action}ed successfully` });

View File

@@ -1,10 +1,11 @@
import { getMoodleCourseCompletionStatus, getMoodleUserById } from "./moodle"; import { getMoodleCourseCompletionStatus, getMoodleUserById } from "./moodle";
import { CronJob } from "cron"; import { CronJob } from "cron";
import { DISCORD_ROLES, prisma } from "@repo/db"; import { DISCORD_ROLES, ParticipantLog, prisma } from "@repo/db";
import { sendCourseCompletedEmail } from "modules/mail"; import { sendCourseCompletedEmail } from "modules/mail";
import { handleParticipantFinished } from "modules/event"; import { handleParticipantFinished } from "modules/event";
import { eventCompleted } from "helper/events"; import { eventCompleted } from "helper/events";
import { addRolesToMember, removeRolesFromMember } from "modules/discord"; import { addRolesToMember, removeRolesFromMember } from "modules/discord";
import { JsonValueType } from "@repo/db/zod";
const syncMoodleIds = async () => { const syncMoodleIds = async () => {
try { try {
@@ -122,9 +123,23 @@ const checkUnfinishedParticipants = async () => {
if (completed) return; if (completed) return;
if (!p.Event.discordRoleId) {
await prisma.participant.update({
where: {
id: p.id,
},
data: {
inscriptionWorkflowCompleted: true,
},
});
return;
}
console.log(
`User ${p.User.firstname} ${p.User.lastname} - ${p.User.publicId} did not finish event ${p.Event.name}`,
);
if (p.User.discordAccounts[0] && p.Event.discordRoleId) { if (p.User.discordAccounts[0] && p.Event.discordRoleId) {
await addRolesToMember(p.User.discordAccounts[0].discordId, [p.Event.discordRoleId]); await addRolesToMember(p.User.discordAccounts[0].discordId, [p.Event.discordRoleId]);
prisma.participant.update({ await prisma.participant.update({
where: { where: {
id: p.id, id: p.id,
}, },
@@ -135,7 +150,7 @@ const checkUnfinishedParticipants = async () => {
event: "Discord-Rolle hinzugefügt", event: "Discord-Rolle hinzugefügt",
timestamp: new Date(), timestamp: new Date(),
user: "system", user: "system",
}, } as ParticipantLog as any,
}, },
}, },
}); });

View File

@@ -117,7 +117,7 @@ const Template = ({ event, user }: { user: User; event: Event }) => (
<tr> <tr>
<td style={{ textAlign: "center", padding: "20px" }}> <td style={{ textAlign: "center", padding: "20px" }}>
{event.finishedBadges.map((badge) => ( {event.finishedBadges.map((badge) => (
<Badge badge={badge} /> <Badge key={badge} badge={badge} />
))} ))}
</td> </td>
</tr> </tr>

View File

@@ -11,17 +11,12 @@ interface ParticipantModalProps {
ref: RefObject<HTMLDialogElement | null>; ref: RefObject<HTMLDialogElement | null>;
} }
export const ParticipantModal = ({ export const ParticipantModal = ({ participantForm, ref }: ParticipantModalProps) => {
participantForm,
ref,
}: ParticipantModalProps) => {
return ( return (
<dialog className="modal" ref={ref}> <dialog className="modal" ref={ref}>
<div className="modal-box"> <div className="modal-box">
<form method="dialog"> <form method="dialog">
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"> <button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
</button>
</form> </form>
<h1 className="text-2xl">Teilnehmer bearbeiten</h1> <h1 className="text-2xl">Teilnehmer bearbeiten</h1>
<form <form
@@ -35,21 +30,18 @@ export const ParticipantModal = ({
})} })}
className="space-y-1" className="space-y-1"
> >
<Switch <Switch form={participantForm} name="attended" label="Termin Teilgenommen" />
form={participantForm} <Switch form={participantForm} name="appointmentCancelled" label="Termin abgesagt" />
name="attended"
label="Termin Teilgenommen"
/>
<Switch
form={participantForm}
name="appointmentCancelled"
label="Termin abgesagt"
/>
<Switch <Switch
form={participantForm} form={participantForm}
name="finisherMoodleCurseCompleted" name="finisherMoodleCurseCompleted"
label="Abschluss-Moodle-Kurs abgeschlossen" label="Abschluss-Moodle-Kurs abgeschlossen"
/> />
<Switch
form={participantForm}
name="inscriptionWorkflowCompleted"
label="Anmeldeprozess abgeschlossen (Discord-rollen vergeben)"
/>
<Switch <Switch
form={participantForm} form={participantForm}
name="completetionWorkflowFinished" name="completetionWorkflowFinished"
@@ -60,18 +52,12 @@ export const ParticipantModal = ({
<p className="w-full flex justify-between"> <p className="w-full flex justify-between">
<span>Termin ausgewählt am</span> <span>Termin ausgewählt am</span>
<span> <span>{new Date(participantForm.watch("enscriptionDate")).toLocaleString()}</span>
{new Date(
participantForm.watch("enscriptionDate"),
).toLocaleString()}
</span>
</p> </p>
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<h3 className="text-xl">Verlauf</h3> <h3 className="text-xl">Verlauf</h3>
{( {(participantForm.watch("statusLog") as unknown as ParticipantLog[])?.map((s) => (
participantForm.watch("statusLog") as unknown as ParticipantLog[]
)?.map((s) => (
<div className="flex justify-between" key={(s as any).timestamp}> <div className="flex justify-between" key={(s as any).timestamp}>
<p>{s.event}</p> <p>{s.event}</p>
<p>{s.user}</p> <p>{s.user}</p>

View File

@@ -161,13 +161,6 @@ export const ConnectionHistory: React.FC<{ user: User }> = ({ user }: { user: Us
<div className="flex-1"> <div className="flex-1">
<h2 className="card-title"> <h2 className="card-title">
<MixerHorizontalIcon className="w-5 h-5" /> Dispo-Verbindungs Historie <MixerHorizontalIcon className="w-5 h-5" /> Dispo-Verbindungs Historie
<button
onClick={() => {
dispoTableRef.current?.refresh();
}}
>
refresh
</button>
</h2> </h2>
<PaginatedTable <PaginatedTable
ref={dispoTableRef} ref={dispoTableRef}

View File

@@ -90,6 +90,13 @@ export default function SortableTable<TData>({
))} ))}
</tr> </tr>
))} ))}
{table.getRowModel().rows.length === 0 && (
<tr>
<td colSpan={columns.length} className="text-center font-bold text-sm text-gray-500">
Keine Daten gefunden
</td>
</tr>
)}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@@ -1,7 +1,8 @@
import axios, { AxiosError } from "axios"; import axios, { AxiosError } from "axios";
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import { DiscordAccount, prisma, PrismaClient } from "@repo/db"; import { DISCORD_ROLES, DiscordAccount, getPublicUser, prisma, PrismaClient } from "@repo/db";
import { getServerSession } from "../auth/[...nextauth]/auth"; import { getServerSession } from "../auth/[...nextauth]/auth";
import { addRolesToMember, removeRolesFromMember, renameMember } from "../../../helper/discord";
export const GET = async (req: NextRequest) => { export const GET = async (req: NextRequest) => {
const session = await getServerSession(); const session = await getServerSession();
@@ -67,8 +68,25 @@ export const GET = async (req: NextRequest) => {
update: discordObject, // Updates if found update: discordObject, // Updates if found
create: discordObject, // Creates if not found create: discordObject, // Creates if not found
}); });
const user = await prisma.user.findUnique({
where: { id: session.user.id },
});
if (user) {
await renameMember(discordUser.id, `${getPublicUser(user).fullName} - ${user?.publicId}`);
}
if (user?.permissions.includes("PILOT")) {
await addRolesToMember(discordUser.id, [DISCORD_ROLES.PILOT]);
} else {
await removeRolesFromMember(discordUser.id, [DISCORD_ROLES.PILOT]);
}
if (user?.permissions.includes("DISPO")) {
await addRolesToMember(discordUser.id, [DISCORD_ROLES.ONLINE_DISPATCHER]);
} else {
await removeRolesFromMember(discordUser.id, [DISCORD_ROLES.PILOT]);
}
return NextResponse.redirect(`${process.env.NEXT_PUBLIC_HUB_URL}/settings`); return NextResponse.redirect(`${process.env.NEXT_PUBLIC_HUB_URL}/settings`);
} catch (error: any) { } catch (error) {
console.error(error); console.error(error);
return NextResponse.json( return NextResponse.json(
{ {

View File

@@ -2,7 +2,7 @@
import axios from "axios"; import axios from "axios";
const discordAxiosClient = axios.create({ const discordAxiosClient = axios.create({
baseURL: process.env.DISCORD_SERVER_URL || "https://discord.com/api/v10", baseURL: process.env.DISCORD_SERVER_URL || "http://localhost:3005",
}); });
export const renameMember = async (memberId: string, newName: string) => { export const renameMember = async (memberId: string, newName: string) => {