Enhance Service Messages by Config & activeUntil #9
This commit is contained in:
@@ -2,25 +2,24 @@
|
|||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Notam } from "@repo/db";
|
import { Notam } from "@repo/db";
|
||||||
import {
|
import { NotamOptionalDefaults, NotamOptionalDefaultsSchema } from "@repo/db/zod";
|
||||||
NotamOptionalDefaults,
|
|
||||||
NotamOptionalDefaultsSchema,
|
|
||||||
} from "@repo/db/zod";
|
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { addMessage, disableMessage } from "../action";
|
import { addMessage, disableMessage } from "../action";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { DateInput } from "_components/ui/DateInput";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css"; // <-- Add this line at the top if using react-datepicker
|
||||||
|
|
||||||
export const MessageForm = ({ message }: { message?: Notam }) => {
|
export const MessageForm = ({ message }: { message?: Notam }) => {
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
|
||||||
const getDefaultShowUntilDate = () => {
|
const getDefaultShowUntilDate = () => {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
date.setDate(date.getDate() + 5);
|
|
||||||
return date;
|
return date;
|
||||||
};
|
};
|
||||||
|
|
||||||
const disableMessageClient = async () => {
|
const disableMessageClient = async () => {
|
||||||
disableMessage();
|
await disableMessage();
|
||||||
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const form = useForm<NotamOptionalDefaults>({
|
const form = useForm<NotamOptionalDefaults>({
|
||||||
@@ -28,8 +27,9 @@ export const MessageForm = ({ message }: { message?: Notam }) => {
|
|||||||
defaultValues: {
|
defaultValues: {
|
||||||
message: message?.message,
|
message: message?.message,
|
||||||
color: message?.color,
|
color: message?.color,
|
||||||
isMainMsg: true,
|
|
||||||
active: true,
|
active: true,
|
||||||
|
wartungsmodus: message?.wartungsmodus,
|
||||||
|
disableHPG: message?.disableHPG,
|
||||||
showUntil: getDefaultShowUntilDate(),
|
showUntil: getDefaultShowUntilDate(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -39,7 +39,8 @@ export const MessageForm = ({ message }: { message?: Notam }) => {
|
|||||||
onSubmit={form.handleSubmit(async (values) => {
|
onSubmit={form.handleSubmit(async (values) => {
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
try {
|
try {
|
||||||
const msg = await addMessage(values);
|
await addMessage(values);
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
console.error("Failed to add message", error);
|
console.error("Failed to add message", error);
|
||||||
@@ -57,51 +58,76 @@ export const MessageForm = ({ message }: { message?: Notam }) => {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div className="gap-2 flex justify-between col-span-6">
|
<div className="gap-2 flex justify-between col-span-6">
|
||||||
<div className="content-center">
|
<div className="flex flex-col gap-4">
|
||||||
<input
|
<div className="content-center">
|
||||||
type="radio"
|
<input
|
||||||
value="INFO"
|
type="radio"
|
||||||
{...form.register("color")}
|
value="INFO"
|
||||||
className="radio radio-info ml-2 mr-2"
|
{...form.register("color")}
|
||||||
/>
|
className="radio radio-info ml-2 mr-2"
|
||||||
<span>Info</span>
|
/>
|
||||||
<input
|
<span>Info</span>
|
||||||
type="radio"
|
<input
|
||||||
value="SUCCESS"
|
type="radio"
|
||||||
{...form.register("color")}
|
value="SUCCESS"
|
||||||
className="radio radio-success ml-2 mr-2"
|
{...form.register("color")}
|
||||||
/>
|
className="radio radio-success ml-2 mr-2"
|
||||||
<span>Success</span>
|
/>
|
||||||
<input
|
<span>Success</span>
|
||||||
type="radio"
|
<input
|
||||||
value="WARNING"
|
type="radio"
|
||||||
{...form.register("color")}
|
value="WARNING"
|
||||||
className="radio radio-warning ml-2 mr-2"
|
{...form.register("color")}
|
||||||
/>
|
className="radio radio-warning ml-2 mr-2"
|
||||||
<span>Warning</span>
|
/>
|
||||||
<input
|
<span>Warning</span>
|
||||||
type="radio"
|
<input
|
||||||
value="ERROR"
|
type="radio"
|
||||||
{...form.register("color")}
|
value="ERROR"
|
||||||
className="radio radio-error ml-2 mr-2"
|
{...form.register("color")}
|
||||||
/>
|
className="radio radio-error ml-2 mr-2"
|
||||||
<span>Error</span>
|
/>
|
||||||
|
<span>Error</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 ml-2">
|
||||||
|
<label className="label">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox checkbox-primary"
|
||||||
|
{...form.register("wartungsmodus")}
|
||||||
|
/>
|
||||||
|
Wartungsmodus einschalten
|
||||||
|
</label>
|
||||||
|
<label className="label">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox checkbox-primary"
|
||||||
|
{...form.register("disableHPG")}
|
||||||
|
/>
|
||||||
|
HPG Alarmierung deaktivieren
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 ml-2">
|
||||||
|
<label className="label">Nachricht & Effekte bis (optional)</label>
|
||||||
|
<DateInput
|
||||||
|
control={form.control}
|
||||||
|
name="showUntil"
|
||||||
|
showTimeInput
|
||||||
|
timeCaption="Uhrzeit"
|
||||||
|
showTimeCaption
|
||||||
|
className="input input-md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex flex-col justify-end">
|
||||||
<button
|
<div className="flex justify-center gap-2">
|
||||||
type="submit"
|
<button type="submit" className="btn btn-soft" onClick={disableMessageClient}>
|
||||||
className="btn btn-soft mr-2"
|
Aktuelle Nachricht deaktivieren
|
||||||
onClick={disableMessageClient}
|
</button>
|
||||||
>
|
<button type="submit" className="btn btn-primary" disabled={isSubmitting}>
|
||||||
Aktuelle Nachricht deaktivieren
|
Speichern
|
||||||
</button>
|
</button>
|
||||||
<button
|
</div>
|
||||||
type="submit"
|
|
||||||
className="btn btn-primary"
|
|
||||||
disabled={isSubmitting}
|
|
||||||
>
|
|
||||||
Speichern
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -3,19 +3,23 @@ import { prisma, Prisma } from "@repo/db";
|
|||||||
|
|
||||||
export const addMessage = async (message: Prisma.NotamCreateInput) => {
|
export const addMessage = async (message: Prisma.NotamCreateInput) => {
|
||||||
try {
|
try {
|
||||||
// Set all current messages with isMainMsg=true to active=false
|
|
||||||
await prisma.notam.updateMany({
|
await prisma.notam.updateMany({
|
||||||
where: { isMainMsg: true },
|
where: { active: true },
|
||||||
data: { active: false },
|
data: { active: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showUntil = new Date(message.showUntil);
|
||||||
|
const showUntilActive = showUntil > new Date();
|
||||||
|
|
||||||
await prisma.notam.create({
|
await prisma.notam.create({
|
||||||
data: {
|
data: {
|
||||||
message: message.message,
|
message: message.message,
|
||||||
color: message.color,
|
color: message.color,
|
||||||
isMainMsg: true,
|
|
||||||
active: true,
|
active: true,
|
||||||
showUntil: new Date().toISOString(),
|
wartungsmodus: message.wartungsmodus,
|
||||||
|
disableHPG: message.disableHPG,
|
||||||
|
showUntilActive,
|
||||||
|
showUntil,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -25,9 +29,8 @@ export const addMessage = async (message: Prisma.NotamCreateInput) => {
|
|||||||
|
|
||||||
export const disableMessage = async () => {
|
export const disableMessage = async () => {
|
||||||
try {
|
try {
|
||||||
// Set all current messages with isMainMsg=true to active=false
|
|
||||||
await prisma.notam.updateMany({
|
await prisma.notam.updateMany({
|
||||||
where: { isMainMsg: true },
|
where: { active: true },
|
||||||
data: { active: false },
|
data: { active: false },
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { MessageSquareWarning } from "lucide-react";
|
import { Check, MessageSquareWarning } from "lucide-react";
|
||||||
import { MessageForm } from "./_components/messageForm";
|
import { MessageForm } from "./_components/messageForm";
|
||||||
import { PaginatedTable } from "_components/PaginatedTable";
|
import { PaginatedTable } from "_components/PaginatedTable";
|
||||||
import { ColumnDef } from "@tanstack/react-table";
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
@@ -23,6 +23,7 @@ export default function MessagePage() {
|
|||||||
</div>
|
</div>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
prismaModel="notam"
|
prismaModel="notam"
|
||||||
|
initialOrderBy={[{ id: "createdAt", desc: true }]}
|
||||||
columns={
|
columns={
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -31,19 +32,58 @@ export default function MessagePage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "color",
|
accessorKey: "color",
|
||||||
header: "Status",
|
header: "Typ",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const color = row.getValue("color");
|
const color = row.getValue("color");
|
||||||
return color;
|
return color;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "wartungsmodus",
|
||||||
|
header: "Wartungsmodus",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const wartungsmodus = row.getValue("wartungsmodus");
|
||||||
|
return wartungsmodus ? <Check /> : "";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "disableHPG",
|
||||||
|
header: "HPG deaktiviert",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const disableHPG = row.getValue("disableHPG");
|
||||||
|
return disableHPG ? <Check /> : "";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "showUntil",
|
||||||
|
header: "Zeitlimit",
|
||||||
|
cell: ({ row, cell }) => {
|
||||||
|
const showUntil = new Date(cell.getValue() as string);
|
||||||
|
const createdAt = new Date(row.getValue("createdAt") as string);
|
||||||
|
if (showUntil > createdAt) {
|
||||||
|
return showUntil.toLocaleDateString("de-DE", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
header: "Erstellt am",
|
header: "Erstellt am",
|
||||||
sortDescFirst: false,
|
|
||||||
cell: ({ cell }) => {
|
cell: ({ cell }) => {
|
||||||
const date = new Date(cell.getValue() as string);
|
const date = new Date(cell.getValue() as string);
|
||||||
return date.toLocaleDateString();
|
return date.toLocaleDateString("de-DE", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
] as ColumnDef<Notam>[]
|
] as ColumnDef<Notam>[]
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { handleParticipantEnrolled } from "../../../../helper/events";
|
import { handleParticipantEnrolled } from "../../../../helper/events";
|
||||||
import { eventCompleted } from "@repo/shared-components";
|
import { eventCompleted } from "@repo/shared-components";
|
||||||
import MDEditor from "@uiw/react-md-editor";
|
import MDEditor from "@uiw/react-md-editor";
|
||||||
import { DayPicker } from "react-day-picker";
|
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { se } from "date-fns/locale";
|
|
||||||
|
|
||||||
interface ModalBtnProps {
|
interface ModalBtnProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const fetchMainMessage = async () => {
|
|||||||
return await prisma.notam.findFirst({
|
return await prisma.notam.findFirst({
|
||||||
where: {
|
where: {
|
||||||
active: true,
|
active: true,
|
||||||
isMainMsg: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -15,19 +14,19 @@ export const WarningAlert = async () => {
|
|||||||
let msgColor;
|
let msgColor;
|
||||||
switch (mainMessage?.color) {
|
switch (mainMessage?.color) {
|
||||||
case "WARNING":
|
case "WARNING":
|
||||||
msgColor = "alert alert-soft alert-warning ml-3 py-2";
|
msgColor = "alert alert-soft alert-warning ml-3 py-2 flex items-center gap-2";
|
||||||
break;
|
break;
|
||||||
case "INFO":
|
case "INFO":
|
||||||
msgColor = "alert alert-soft alert-info ml-3 py-2";
|
msgColor = "alert alert-soft alert-info ml-3 py-2 flex items-center gap-2";
|
||||||
break;
|
break;
|
||||||
case "SUCCESS":
|
case "SUCCESS":
|
||||||
msgColor = "alert alert-soft alert-success ml-3 py-2";
|
msgColor = "alert alert-soft alert-success ml-3 py-2 flex items-center gap-2";
|
||||||
break;
|
break;
|
||||||
case "ERROR":
|
case "ERROR":
|
||||||
msgColor = "alert alert-error ml-3 py-2";
|
msgColor = "alert alert-error ml-3 py-2 flex items-center gap-2";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msgColor = "alert alert-soft ml-3 py-2";
|
msgColor = "alert alert-soft ml-3 py-2 flex items-center gap-2";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mainMessage?.message == "" || !mainMessage) {
|
if (mainMessage?.message == "" || !mainMessage) {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `isMainMsg` on the `Notam` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notam" DROP COLUMN "isMainMsg";
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notam" ADD COLUMN "disableHPG" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
ADD COLUMN "wartungsmodus" BOOLEAN NOT NULL DEFAULT false;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notam" ADD COLUMN "showUntilActive" BOOLEAN NOT NULL DEFAULT false;
|
||||||
@@ -8,12 +8,14 @@ enum GlobalColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Notam {
|
model Notam {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
color GlobalColor
|
color GlobalColor
|
||||||
message String
|
message String
|
||||||
showUntil DateTime
|
showUntil DateTime
|
||||||
isMainMsg Boolean
|
showUntilActive Boolean @default(false)
|
||||||
active Boolean
|
wartungsmodus Boolean @default(false)
|
||||||
createdAt DateTime @default(now())
|
disableHPG Boolean @default(false)
|
||||||
updatedAt DateTime @updatedAt
|
active Boolean
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user