feat(platform): checkpoint current implementation state

This commit is contained in:
2026-04-01 07:42:03 +02:00
parent 3e53471f05
commit 8c5be51251
125 changed files with 10269 additions and 17808 deletions
@@ -32,6 +32,28 @@ type CountryRow = {
metroCities: { id: string; name: string }[];
};
type HolidayPreviewDetail = {
count: number;
locationContext: {
countryCode: string | null;
stateCode: string | null;
metroCity: string | null;
year: number;
};
summary: {
byScope: Array<{ scope: string; count: number }>;
bySourceType: Array<{ sourceType: string; count: number }>;
byCalendar: Array<{ calendarName: string; count: number }>;
};
holidays: Array<{
date: string;
name: string;
scope: string;
calendarName: string;
sourceType: string;
}>;
};
const SCOPE_LABELS: Record<ScopeType, string> = {
COUNTRY: "Land",
STATE: "Bundesland/Region",
@@ -87,7 +109,15 @@ export function HolidayCalendarEditor() {
return rows.find((country) => country.id === selectedCalendar?.country.id) ?? null;
}, [countries, selectedCalendar]);
const previewQuery = trpc.holidayCalendar.previewResolvedHolidays.useQuery(
const previewQuery = (trpc.holidayCalendar.previewResolvedHolidaysDetail.useQuery as unknown as (
input: {
countryId: string;
year: number;
stateCode?: string;
metroCityId?: string;
},
options: { enabled: boolean; staleTime: number },
) => { data: HolidayPreviewDetail | undefined; isLoading: boolean })(
{
countryId: selectedCalendar?.country.id ?? countryId,
year: previewYear,
@@ -105,6 +135,7 @@ export function HolidayCalendarEditor() {
utils.holidayCalendar.listCalendars.invalidate(),
utils.holidayCalendar.getCalendarById.invalidate(),
utils.holidayCalendar.previewResolvedHolidays.invalidate(),
utils.holidayCalendar.previewResolvedHolidaysDetail.invalidate(),
]);
};
@@ -829,26 +860,45 @@ export function HolidayCalendarEditor() {
</div>
<div className="max-h-80 overflow-auto rounded-lg border border-gray-200 dark:border-gray-700">
{previewQuery.data && (
<div className="border-b border-gray-200 bg-gray-50 px-3 py-2 text-xs text-gray-600 dark:border-gray-700 dark:bg-gray-900/60 dark:text-gray-300">
<div className="font-medium text-gray-700 dark:text-gray-200">
Basis: {[
previewQuery.data.locationContext.countryCode,
previewQuery.data.locationContext.stateCode,
previewQuery.data.locationContext.metroCity,
].filter(Boolean).join(" / ") || "n/a"}
</div>
<div className="mt-1">
Scope: {previewQuery.data.summary.byScope.map((item) => `${item.scope} ${item.count}`).join(" · ") || "none"}
</div>
<div className="mt-1">
Sources: {previewQuery.data.summary.bySourceType.map((item) => `${item.sourceType} ${item.count}`).join(" · ") || "none"}
</div>
</div>
)}
<table data-testid="holiday-preview-table" className="w-full text-sm">
<thead className="bg-gray-50 dark:bg-gray-900/60">
<tr>
<th className="px-3 py-2 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Datum</th>
<th className="px-3 py-2 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Name</th>
<th className="px-3 py-2 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Scope</th>
<th className="px-3 py-2 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Quelle</th>
</tr>
</thead>
<tbody>
{(previewQuery.data ?? []).length === 0 && (
{(!previewQuery.data || previewQuery.data.holidays.length === 0) && (
<tr>
<td colSpan={3} className="px-3 py-6 text-center text-sm text-gray-400">
<td colSpan={4} className="px-3 py-6 text-center text-sm text-gray-400">
{previewQuery.isLoading ? "Laedt Vorschau..." : "Keine Feiertage fuer diese Auswahl vorhanden."}
</td>
</tr>
)}
{(previewQuery.data ?? []).map((entry) => (
{(previewQuery.data?.holidays ?? []).map((entry) => (
<tr key={`${entry.date}-${entry.name}`} className="border-t border-gray-200 dark:border-gray-700">
<td className="px-3 py-2 text-gray-700 dark:text-gray-300">{entry.date}</td>
<td className="px-3 py-2 text-gray-900 dark:text-gray-100">{entry.name}</td>
<td className="px-3 py-2 text-gray-600 dark:text-gray-400">{entry.scope}</td>
<td className="px-3 py-2 text-gray-600 dark:text-gray-400">{entry.calendarName}</td>
</tr>
))}