added suer to p-log, HUB_URL in hub-server, dynamic badges in email

This commit is contained in:
PxlLoewe
2025-03-12 17:44:53 -07:00
parent b1992f64d3
commit b573d7cd5a
11 changed files with 79 additions and 41 deletions

View File

@@ -4,3 +4,4 @@ MAIL_SERVER=
MAIL_USER= MAIL_USER=
MAIL_PASSWORD= MAIL_PASSWORD=
MAIL_PORT= MAIL_PORT=
HUB_URL=http://localhost:3000

View File

@@ -0,0 +1,21 @@
import { BADGES } from "@repo/db";
import React from "react";
const badgeImageMapping = {
[BADGES.P1]: "p-1.png",
[BADGES.P2]: "p-2.png",
[BADGES.P3]: "p-3.png",
[BADGES.D1]: "d-1.png",
[BADGES.D2]: "d-2.png",
[BADGES.D3]: "d-3.png",
[BADGES.DAY1]: "day-1-member.png",
};
export const Badge = ({ badge }: { badge: BADGES }) => (
<img
src={`${process.env.HUB_URL}/badges/${badgeImageMapping[badge]}`}
alt="Badge"
width="80"
style={{ display: "block", margin: "0 auto" }}
/>
);

View File

@@ -1,6 +1,7 @@
import * as React from "react"; import * as React from "react";
import { Event, User } from "@repo/db"; import { Event, User } from "@repo/db";
import { Html, Button, render } from "@react-email/components"; import { Html, Button, render } from "@react-email/components";
import { Badge } from "./Badge";
const styles = ` const styles = `
* { * {
@@ -87,7 +88,7 @@ const Template = ({ event, user }: { user: User; event: Event }) => (
<tr> <tr>
<td style={{ textAlign: "center", paddingTop: "30px" }}> <td style={{ textAlign: "center", paddingTop: "30px" }}>
<img <img
src="http://localhost:3000/mail/var_logo.png" src={`${process.env.HUB_URL}/mail/var_logo.png`}
alt="Logo" alt="Logo"
width="80" width="80"
style={{ display: "block", margin: "0 auto" }} style={{ display: "block", margin: "0 auto" }}
@@ -119,12 +120,9 @@ const Template = ({ event, user }: { user: User; event: Event }) => (
</tr> </tr>
<tr> <tr>
<td style={{ textAlign: "center", padding: "20px" }}> <td style={{ textAlign: "center", padding: "20px" }}>
<img {event.finishedBadges.map((badge) => (
src="http://localhost:3000/badges/p-1.png" <Badge badge={badge} />
alt="Badge" ))}
width="80"
style={{ display: "block", margin: "0 auto" }}
/>
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@@ -123,7 +123,7 @@ export const AppointmentModal = ({
</span> </span>
); );
} else { } else {
return <span>Abwarten</span>; return <span>?</span>;
} }
}, },
}, },
@@ -149,7 +149,7 @@ export const AppointmentModal = ({
onClick={async () => { onClick={async () => {
await upsertParticipant({ await upsertParticipant({
eventId: event!.id, eventId: event!.id,
userId: participantForm.watch("userId"), userId: row.original.userId,
attended: true, attended: true,
appointmentCancelled: false, appointmentCancelled: false,
}); });
@@ -160,22 +160,23 @@ export const AppointmentModal = ({
Anwesend Anwesend
</button> </button>
)} )}
{!row.original.attended && event?.hasPresenceEvents && ( {!row.original.appointmentCancelled &&
event?.hasPresenceEvents && (
<button <button
type="button" type="button"
onSubmit={() => {}} onSubmit={() => {}}
onClick={async () => { onClick={async () => {
await upsertParticipant({ await upsertParticipant({
eventId: event!.id, eventId: event!.id,
userId: participantForm.watch("userId"), userId: row.original.userId,
attended: false, attended: false,
appointmentCancelled: true, appointmentCancelled: true,
statusLog: [ statusLog: [
...(row.original.statusLog as any), ...(row.original.statusLog as any),
{ {
event: "Gefehlt", event: "Gefehlt an Event",
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
user: `${session?.user?.firstname} (${session?.user?.lastname} - ${session?.user?.publicId})`, user: `${session?.user?.firstname} ${session?.user?.lastname} - ${session?.user?.publicId}`,
}, },
], ],
}); });
@@ -183,7 +184,7 @@ export const AppointmentModal = ({
}} }}
className="btn btn-outline btn-error btn-sm" className="btn btn-outline btn-error btn-sm"
> >
nicht da abwesend
</button> </button>
)} )}
</div> </div>

View File

@@ -1,6 +1,6 @@
import { Switch } from "../../../../_components/ui/Switch"; import { Switch } from "../../../../_components/ui/Switch";
import { Button } from "../../../../_components/ui/Button"; import { Button } from "../../../../_components/ui/Button";
import { Participant, Prisma } from "@repo/db"; import { Participant, ParticipantLog, Prisma } from "@repo/db";
import { UseFormReturn } from "react-hook-form"; import { UseFormReturn } from "react-hook-form";
import { upsertParticipant } from "../../../events/actions"; import { upsertParticipant } from "../../../events/actions";
import { RefObject } from "react"; import { RefObject } from "react";
@@ -59,7 +59,7 @@ export const ParticipantModal = ({
<h3 className="text-xl">Termine</h3> <h3 className="text-xl">Termine</h3>
<p className="w-full flex justify-between"> <p className="w-full flex justify-between">
<span>Termin ausgewählt</span> <span>Termin ausgewählt am</span>
<span> <span>
{new Date( {new Date(
participantForm.watch("enscriptionDate"), participantForm.watch("enscriptionDate"),
@@ -69,9 +69,12 @@ export const ParticipantModal = ({
</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")?.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 as any).event}</p> <p>{s.event}</p>
<p>{s.user}</p>
<p>{new Date((s as any).timestamp).toLocaleString()}</p> <p>{new Date((s as any).timestamp).toLocaleString()}</p>
</div> </div>
))} ))}

View File

@@ -214,6 +214,7 @@ const ModalBtn = ({
appointmentDate: appointmentDate:
selectedAppointment.appointmentDate, selectedAppointment.appointmentDate,
}, },
user: `${user?.firstname} ${user?.lastname} - ${user?.publicId}`,
event: "Termin abgesagt", event: "Termin abgesagt",
timestamp: new Date(), timestamp: new Date(),
}, },

View File

@@ -12,7 +12,8 @@
"**/*.tsx", "**/*.tsx",
"next-env.d.ts", "next-env.d.ts",
"next.config.js", "next.config.js",
".next/types/**/*.ts" ".next/types/**/*.ts",
"types/.d.ts"
], ],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

View File

@@ -1,4 +1,5 @@
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
import { JsonArray, JsonObject } from "@prisma/client/runtime/library";
declare module "@prisma/client" { declare module "@prisma/client" {
export type InputJsonValue = export type InputJsonValue =
@@ -8,4 +9,6 @@ declare module "@prisma/client" {
| null | null
| JsonObject | JsonObject
| JsonArray; | JsonArray;
export type JsonValue = any; // Erzwingt Flexibilität
} }

View File

@@ -4,3 +4,4 @@ export * from "./generated/client"; // exports generated types from prisma
import * as zodTypes from "./generated/zod"; import * as zodTypes from "./generated/zod";
export const zod = zodTypes; export const zod = zodTypes;
export * from "./prisma/json";

View File

@@ -0,0 +1,7 @@
import { JsonValue } from "@prisma/client/runtime/library";
export interface ParticipantLog {
event: string;
timestamp: Date;
user: string;
}

View File

@@ -0,0 +1 @@
export type { ParticipantLog } from "./ParticipantLog";