added suer to p-log, HUB_URL in hub-server, dynamic badges in email
This commit is contained in:
@@ -4,3 +4,4 @@ MAIL_SERVER=
|
|||||||
MAIL_USER=
|
MAIL_USER=
|
||||||
MAIL_PASSWORD=
|
MAIL_PASSWORD=
|
||||||
MAIL_PORT=
|
MAIL_PORT=
|
||||||
|
HUB_URL=http://localhost:3000
|
||||||
21
apps/hub-server/modules/mail-templates/Badge.tsx
Normal file
21
apps/hub-server/modules/mail-templates/Badge.tsx
Normal 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" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -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(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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"]
|
||||||
}
|
}
|
||||||
|
|||||||
3
apps/hub/types/prisma.d.ts
vendored
3
apps/hub/types/prisma.d.ts
vendored
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
7
packages/database/prisma/json/ParticipantLog.ts
Normal file
7
packages/database/prisma/json/ParticipantLog.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { JsonValue } from "@prisma/client/runtime/library";
|
||||||
|
|
||||||
|
export interface ParticipantLog {
|
||||||
|
event: string;
|
||||||
|
timestamp: Date;
|
||||||
|
user: string;
|
||||||
|
}
|
||||||
1
packages/database/prisma/json/index.ts
Normal file
1
packages/database/prisma/json/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type { ParticipantLog } from "./ParticipantLog";
|
||||||
Reference in New Issue
Block a user