104 lines
3.9 KiB
TypeScript
104 lines
3.9 KiB
TypeScript
import { getVoucherStatus } from "./voucher-status";
|
|
import { isExpiringSoon } from "./vouchers";
|
|
|
|
export type ViewVoucher = {
|
|
id: number;
|
|
name: string;
|
|
anbieter: string;
|
|
ablaufdatum: Date | string | null;
|
|
createdAt: Date | string;
|
|
status: string;
|
|
wertTyp: string;
|
|
kategorie: string | null;
|
|
};
|
|
|
|
export type VoucherFilter = { q: string; status: string; kategorie: string; typ: string };
|
|
|
|
function statusMatch(v: ViewVoucher, status: string): boolean {
|
|
if (!status) return true;
|
|
const s = getVoucherStatus({ status: v.status, ablaufdatum: v.ablaufdatum ? new Date(v.ablaufdatum) : null });
|
|
if (status === "eingeloest") return s === "eingeloest";
|
|
if (status === "abgelaufen") return s === "abgelaufen";
|
|
if (status === "bald") return s === "aktiv" && isExpiringSoon(v.ablaufdatum);
|
|
if (status === "aktiv") return s === "aktiv";
|
|
return true;
|
|
}
|
|
|
|
export function filterVouchers<T extends ViewVoucher>(list: T[], f: VoucherFilter): T[] {
|
|
const q = f.q.trim().toLowerCase();
|
|
return list.filter((v) => {
|
|
if (!statusMatch(v, f.status)) return false;
|
|
if (f.kategorie === "ohne") {
|
|
if (v.kategorie) return false;
|
|
} else if (f.kategorie && v.kategorie !== f.kategorie) {
|
|
return false;
|
|
}
|
|
if ((f.typ === "euro" || f.typ === "prozent") && v.wertTyp !== f.typ) return false;
|
|
if (q && !(v.name.toLowerCase().includes(q) || v.anbieter.toLowerCase().includes(q))) return false;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
export type SortKey = "neu" | "ablauf" | "name" | "anbieter";
|
|
|
|
function timeOrInfinity(d: Date | string | null): number {
|
|
if (!d) return Number.POSITIVE_INFINITY;
|
|
return new Date(d).getTime();
|
|
}
|
|
|
|
export function sortVouchers<T extends ViewVoucher>(list: T[], sort: string): T[] {
|
|
const arr = [...list];
|
|
if (sort === "ablauf") return arr.sort((a, b) => timeOrInfinity(a.ablaufdatum) - timeOrInfinity(b.ablaufdatum));
|
|
if (sort === "name") return arr.sort((a, b) => a.name.localeCompare(b.name, "de"));
|
|
if (sort === "anbieter")
|
|
return arr.sort(
|
|
(a, b) => a.anbieter.localeCompare(b.anbieter, "de") || a.name.localeCompare(b.name, "de")
|
|
);
|
|
return arr.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
}
|
|
|
|
export type GroupKey = "keine" | "anbieter" | "kategorie" | "ablauf";
|
|
|
|
export function ablaufGruppe(v: ViewVoucher): string {
|
|
const s = getVoucherStatus({ status: v.status, ablaufdatum: v.ablaufdatum ? new Date(v.ablaufdatum) : null });
|
|
if (s === "eingeloest") return "Eingelöst";
|
|
if (!v.ablaufdatum) return "Ohne Ablaufdatum";
|
|
if (s === "abgelaufen") return "Abgelaufen";
|
|
if (isExpiringSoon(v.ablaufdatum)) return "Bald fällig";
|
|
return "Später fällig";
|
|
}
|
|
|
|
const ABLAUF_REIHENFOLGE = ["Bald fällig", "Später fällig", "Ohne Ablaufdatum", "Abgelaufen", "Eingelöst"];
|
|
|
|
export function groupVouchers<T extends ViewVoucher>(list: T[], gruppe: string): { title: string; items: T[] }[] {
|
|
if (gruppe === "anbieter" || gruppe === "kategorie") {
|
|
const map = new Map<string, T[]>();
|
|
for (const v of list) {
|
|
const key = gruppe === "anbieter" ? v.anbieter : v.kategorie?.trim() || "Ohne Kategorie";
|
|
const items = map.get(key) ?? [];
|
|
items.push(v);
|
|
map.set(key, items);
|
|
}
|
|
return [...map.entries()]
|
|
.sort(([a], [b]) => a.localeCompare(b, "de"))
|
|
.map(([title, items]) => ({ title, items }));
|
|
}
|
|
if (gruppe === "ablauf") {
|
|
const map = new Map<string, T[]>();
|
|
for (const v of list) {
|
|
const key = ablaufGruppe(v);
|
|
const items = map.get(key) ?? [];
|
|
items.push(v);
|
|
map.set(key, items);
|
|
}
|
|
return ABLAUF_REIHENFOLGE.filter((t) => map.has(t)).map((title) => ({ title, items: map.get(title) as T[] }));
|
|
}
|
|
return [{ title: "", items: list }];
|
|
}
|
|
|
|
export function listCategories(list: { kategorie: string | null }[]): string[] {
|
|
return [...new Set(list.map((v) => v.kategorie?.trim()).filter((k): k is string => !!k))].sort((a, b) =>
|
|
a.localeCompare(b, "de")
|
|
);
|
|
}
|