108 lines
4.0 KiB
TypeScript
108 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { useSelector, useDispatch } from "react-redux";
|
|
import { getMessagesThunk } from "@/redux/thunks/getMessagesThunk";
|
|
import type { AppDispatch } from "@/redux/store";
|
|
|
|
type Meldung = {
|
|
t: string;
|
|
s: number;
|
|
c: string;
|
|
m: string;
|
|
i: string;
|
|
v: string;
|
|
};
|
|
|
|
type Props = {
|
|
className?: string;
|
|
};
|
|
|
|
export default function Last20MessagesTable({ className }: Props) {
|
|
const dispatch = useDispatch<AppDispatch>();
|
|
type RootState = {
|
|
messages: {
|
|
data: Meldung[];
|
|
};
|
|
};
|
|
const { data: messages } = useSelector((state: RootState) => state.messages);
|
|
|
|
const [sourceFilter] = useState<string>("Alle");
|
|
|
|
const today = new Date();
|
|
const prior30 = new Date();
|
|
prior30.setDate(today.getDate() - 30);
|
|
const formatDate = (d: Date) => d.toISOString().split("T")[0];
|
|
const [fromDate] = useState<string>(formatDate(prior30));
|
|
const [toDate] = useState<string>(formatDate(today));
|
|
|
|
useEffect(() => {
|
|
dispatch(getMessagesThunk({ fromDate, toDate }));
|
|
}, [dispatch, fromDate, toDate]);
|
|
|
|
const filteredMessages =
|
|
sourceFilter === "Alle"
|
|
? messages
|
|
: messages.filter((m: Meldung) => m.i === sourceFilter);
|
|
|
|
return (
|
|
<div className={`flex flex-col gap-3 p-4 ${className}`}>
|
|
<div className="overflow-auto max-h-[80vh]">
|
|
<table className="min-w-full border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
<thead className="text-left sticky top-0 z-10 bg-[var(--color-surface-alt)]/70 dark:bg-[var(--color-surface-alt)]/25 text-[var(--color-fg)]">
|
|
<tr>
|
|
<th className="p-2 border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
Prio
|
|
</th>
|
|
<th className="p-2 border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
Zeitstempel
|
|
</th>
|
|
<th className="p-2 border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
Quelle
|
|
</th>
|
|
<th className="p-2 border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
Meldung
|
|
</th>
|
|
<th className="p-2 border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-fg)]">
|
|
Status
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{filteredMessages.slice(0, 20).map((msg, index) => (
|
|
<tr
|
|
key={index}
|
|
className="hover:bg-[var(--color-surface-alt)]/70 dark:hover:bg-[var(--color-surface-alt)]/30 transition"
|
|
>
|
|
<td className="border p-2 bg-[var(--color-surface)] text-[var(--color-fg)] border-[var(--color-border)]">
|
|
<div
|
|
className="w-4 h-4 rounded"
|
|
style={{ backgroundColor: msg.c }}
|
|
></div>
|
|
</td>
|
|
<td className="border p-2 bg-[var(--color-surface)] text-[var(--color-fg)] border-[var(--color-border)]">
|
|
{msg.t}
|
|
</td>
|
|
<td className="border p-2 bg-[var(--color-surface)] text-[var(--color-fg)] border-[var(--color-border)]">
|
|
{msg.i}
|
|
</td>
|
|
<td className="border p-2 bg-[var(--color-surface)] text-[var(--color-fg)] border-[var(--color-border)]">
|
|
{msg.m}
|
|
</td>
|
|
<td className="border p-2 bg-[var(--color-surface)] text-[var(--color-fg)] border-[var(--color-border)]">
|
|
{msg.v}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
{messages.length === 0 && (
|
|
<div className="mt-4 text-center italic text-[var(--color-fg-muted)]">
|
|
Keine Meldungen im gewählten Zeitraum vorhanden.
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|