feat: KitchenStock light UI, Gemma 31B AI, supermarket store filters & 130+ vegan products

This commit is contained in:
KitchenStock
2026-07-26 20:08:16 +02:00
commit 83fcf6909c
81 changed files with 17001 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
import { format, parseISO, differenceInCalendarDays, isValid } from 'date-fns';
import { de } from 'date-fns/locale';
import type { ExpirationWarningStatus } from '@/types/domain';
export function formatDateGerman(dateStr: string | Date | null | undefined): string {
if (!dateStr) return '-';
const date = typeof dateStr === 'string' ? parseISO(dateStr) : dateStr;
if (!isValid(date)) return '-';
return format(date, 'dd.MM.yyyy', { locale: de });
}
export function formatDateTimeGerman(dateStr: string | Date | null | undefined): string {
if (!dateStr) return '-';
const date = typeof dateStr === 'string' ? parseISO(dateStr) : dateStr;
if (!isValid(date)) return '-';
return format(date, 'dd.MM.yyyy HH:mm', { locale: de });
}
export function getExpirationStatus(expirationDateStr: string | null | undefined): ExpirationWarningStatus {
if (!expirationDateStr) {
return { status: 'OK', label: 'Kein Ablaufdatum', daysRemaining: null };
}
const expDate = parseISO(expirationDateStr);
if (!isValid(expDate)) {
return { status: 'OK', label: 'Kein Ablaufdatum', daysRemaining: null };
}
const today = new Date();
const daysDiff = differenceInCalendarDays(expDate, today);
if (daysDiff < 0) {
return {
status: 'EXPIRED',
label: `Abgelaufen (${Math.abs(daysDiff)} Tag${Math.abs(daysDiff) === 1 ? '' : 'e'})`,
daysRemaining: daysDiff,
};
}
if (daysDiff === 0) {
return { status: 'TODAY', label: 'Läuft heute ab', daysRemaining: 0 };
}
if (daysDiff <= 3) {
return { status: 'IN_3_DAYS', label: `Läuft in ${daysDiff} Tagen ab`, daysRemaining: daysDiff };
}
if (daysDiff <= 7) {
return { status: 'IN_7_DAYS', label: `Läuft in ${daysDiff} Tagen ab`, daysRemaining: daysDiff };
}
if (daysDiff <= 14) {
return { status: 'IN_14_DAYS', label: `Läuft in ${daysDiff} Tagen ab`, daysRemaining: daysDiff };
}
return { status: 'OK', label: `Haltbar bis ${formatDateGerman(expDate)}`, daysRemaining: daysDiff };
}