aktueller stand
This commit is contained in:
@@ -347,6 +347,13 @@ const AdminSettingsPanel = ({
|
||||
className="border rounded p-2 w-full focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
|
||||
placeholder="Bot-Token"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={adminSettings.notifications?.telegram?.chatId || ''}
|
||||
onChange={(event) => onNotificationChange('telegram', 'chatId', event.target.value)}
|
||||
className="border rounded p-2 w-full focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
|
||||
placeholder="Admin-Chat-ID"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { formatDistanceToNowStrict } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import {
|
||||
createColumnHelper,
|
||||
flexRender,
|
||||
@@ -47,6 +49,57 @@ const ColumnSelectFilter = ({ column, options, placeholder = 'Alle' }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const formatLastPickupLabel = (value) => {
|
||||
if (!value) {
|
||||
return 'Unbekannt';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return 'Unbekannt';
|
||||
}
|
||||
return date.toLocaleDateString('de-DE');
|
||||
};
|
||||
|
||||
const formatLastPickupRelative = (value) => {
|
||||
if (!value) {
|
||||
return 'Unbekannt';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return 'Unbekannt';
|
||||
}
|
||||
return formatDistanceToNowStrict(date, { addSuffix: true, locale: de });
|
||||
};
|
||||
|
||||
const getLastPickupTimestamp = (value) => {
|
||||
if (!value) {
|
||||
return -1;
|
||||
}
|
||||
const date = new Date(value);
|
||||
const time = date.getTime();
|
||||
return Number.isNaN(time) ? -1 : time;
|
||||
};
|
||||
|
||||
const getLastPickupStyle = (value) => {
|
||||
const time = getLastPickupTimestamp(value);
|
||||
if (time <= 0) {
|
||||
return {};
|
||||
}
|
||||
const ageDays = (Date.now() - time) / (1000 * 60 * 60 * 24);
|
||||
if (ageDays < 90) {
|
||||
return {};
|
||||
}
|
||||
const minDays = 90;
|
||||
const maxDays = 180;
|
||||
const ratio = Math.min(Math.max((ageDays - minDays) / (maxDays - minDays), 0), 1);
|
||||
const start = { r: 220, g: 38, b: 38 };
|
||||
const end = { r: 127, g: 29, b: 29 };
|
||||
const r = Math.round(start.r + (end.r - start.r) * ratio);
|
||||
const g = Math.round(start.g + (end.g - start.g) * ratio);
|
||||
const b = Math.round(start.b + (end.b - start.b) * ratio);
|
||||
return { color: `rgb(${r}, ${g}, ${b})` };
|
||||
};
|
||||
|
||||
function readConfigTableState() {
|
||||
if (typeof window === 'undefined') {
|
||||
return { sorting: [], columnFilters: [] };
|
||||
@@ -222,11 +275,53 @@ const DashboardView = ({
|
||||
sortingFn: 'alphanumeric',
|
||||
filterFn: 'includesString'
|
||||
}),
|
||||
columnHelper.accessor('lastPickupAt', {
|
||||
header: ({ column }) => (
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full items-center justify-between text-left font-semibold"
|
||||
onClick={column.getToggleSortingHandler()}
|
||||
>
|
||||
<span>Letzte Abholung</span>
|
||||
{column.getIsSorted() ? (
|
||||
<span className="text-xs text-gray-500">{column.getIsSorted() === 'asc' ? '▲' : '▼'}</span>
|
||||
) : (
|
||||
<span className="text-xs text-gray-400">⇅</span>
|
||||
)}
|
||||
</button>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const lastPickupAt = row.original.lastPickupAt;
|
||||
const style = getLastPickupStyle(lastPickupAt);
|
||||
return (
|
||||
<span
|
||||
className="text-sm text-gray-700"
|
||||
style={style}
|
||||
title={formatLastPickupLabel(lastPickupAt)}
|
||||
>
|
||||
{formatLastPickupRelative(lastPickupAt)}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
sortingFn: (rowA, rowB, columnId) => {
|
||||
const a = getLastPickupTimestamp(rowA.getValue(columnId));
|
||||
const b = getLastPickupTimestamp(rowB.getValue(columnId));
|
||||
return a - b;
|
||||
},
|
||||
enableColumnFilter: false
|
||||
}),
|
||||
columnHelper.display({
|
||||
id: 'checkProfileId',
|
||||
header: () => <span>Profil prüfen</span>,
|
||||
cell: ({ row }) => (
|
||||
<div className="text-center" title={row.original.lastFetchDate ? `Letzte Abholung: ${row.original.lastFetchDate}` : 'Keine Info zur letzten Abholung'}>
|
||||
<div
|
||||
className="text-center"
|
||||
title={
|
||||
row.original.lastPickupAt
|
||||
? `Letzte Abholung: ${formatLastPickupLabel(row.original.lastPickupAt)}`
|
||||
: 'Keine Info zur letzten Abholung'
|
||||
}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-5 w-5"
|
||||
@@ -242,7 +337,14 @@ const DashboardView = ({
|
||||
id: 'skipDormantCheck',
|
||||
header: () => <span>Ruhe-Prüfung</span>,
|
||||
cell: ({ row }) => (
|
||||
<div className="text-center" title={row.original.lastFetchDate ? `Letzte Abholung: ${row.original.lastFetchDate}` : 'Keine Info zur letzten Abholung'}>
|
||||
<div
|
||||
className="text-center"
|
||||
title={
|
||||
row.original.lastPickupAt
|
||||
? `Letzte Abholung: ${formatLastPickupLabel(row.original.lastPickupAt)}`
|
||||
: 'Keine Info zur letzten Abholung'
|
||||
}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-5 w-5"
|
||||
|
||||
@@ -29,7 +29,8 @@ export const normalizeAdminSettings = (raw) => {
|
||||
},
|
||||
telegram: {
|
||||
enabled: !!raw.notifications?.telegram?.enabled,
|
||||
botToken: raw.notifications?.telegram?.botToken || ''
|
||||
botToken: raw.notifications?.telegram?.botToken || '',
|
||||
chatId: raw.notifications?.telegram?.chatId || ''
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -72,7 +73,8 @@ export const serializeAdminSettings = (adminSettings) => {
|
||||
},
|
||||
telegram: {
|
||||
enabled: !!adminSettings.notifications?.telegram?.enabled,
|
||||
botToken: adminSettings.notifications?.telegram?.botToken || ''
|
||||
botToken: adminSettings.notifications?.telegram?.botToken || '',
|
||||
chatId: adminSettings.notifications?.telegram?.chatId || ''
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user