Journal für abholungen
This commit is contained in:
@@ -95,6 +95,60 @@ const JournalPage = ({ authorizedFetch, stores }) => {
|
|||||||
return parsed.getTime();
|
return parsed.getTime();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const getIntervalMonths = useCallback((interval) => {
|
||||||
|
if (interval === 'monthly') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (interval === 'quarterly') {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 12;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const addMonths = useCallback((date, months) => {
|
||||||
|
const copy = new Date(date.getTime());
|
||||||
|
copy.setMonth(copy.getMonth() + months);
|
||||||
|
return copy;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const startOfDay = useCallback((date) => {
|
||||||
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getNextReminderTimestamp = useCallback(
|
||||||
|
(entry) => {
|
||||||
|
if (!entry?.reminder?.enabled || !entry.pickupDate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const baseDate = new Date(`${entry.pickupDate}T00:00:00`);
|
||||||
|
if (Number.isNaN(baseDate.getTime())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const intervalMonths = getIntervalMonths(entry.reminder.interval);
|
||||||
|
const daysBefore = Number.isFinite(entry.reminder.daysBefore)
|
||||||
|
? Math.max(0, entry.reminder.daysBefore)
|
||||||
|
: 42;
|
||||||
|
const todayStart = startOfDay(new Date());
|
||||||
|
let occurrence = startOfDay(baseDate);
|
||||||
|
const guardYear = todayStart.getFullYear() + 200;
|
||||||
|
while (occurrence < todayStart && occurrence.getFullYear() < guardYear) {
|
||||||
|
occurrence = startOfDay(addMonths(occurrence, intervalMonths));
|
||||||
|
}
|
||||||
|
if (occurrence.getFullYear() >= guardYear) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let reminderDate = new Date(occurrence.getTime());
|
||||||
|
reminderDate.setDate(reminderDate.getDate() - daysBefore);
|
||||||
|
if (reminderDate < todayStart) {
|
||||||
|
occurrence = startOfDay(addMonths(occurrence, intervalMonths));
|
||||||
|
reminderDate = new Date(occurrence.getTime());
|
||||||
|
reminderDate.setDate(reminderDate.getDate() - daysBefore);
|
||||||
|
}
|
||||||
|
return reminderDate.getTime();
|
||||||
|
},
|
||||||
|
[addMonths, getIntervalMonths, startOfDay]
|
||||||
|
);
|
||||||
|
|
||||||
const filteredEntries = useMemo(() => {
|
const filteredEntries = useMemo(() => {
|
||||||
const query = filters.query.trim().toLowerCase();
|
const query = filters.query.trim().toLowerCase();
|
||||||
const fromValue = parseDateValue(filters.dateFrom);
|
const fromValue = parseDateValue(filters.dateFrom);
|
||||||
@@ -142,11 +196,25 @@ const JournalPage = ({ authorizedFetch, stores }) => {
|
|||||||
const aLabel = a.storeName || storeLabelMap.get(String(a.storeId)) || '';
|
const aLabel = a.storeName || storeLabelMap.get(String(a.storeId)) || '';
|
||||||
const bLabel = b.storeName || storeLabelMap.get(String(b.storeId)) || '';
|
const bLabel = b.storeName || storeLabelMap.get(String(b.storeId)) || '';
|
||||||
return bLabel.localeCompare(aLabel);
|
return bLabel.localeCompare(aLabel);
|
||||||
|
},
|
||||||
|
nextReminderAsc: (a, b) => {
|
||||||
|
const aNext = getNextReminderTimestamp(a);
|
||||||
|
const bNext = getNextReminderTimestamp(b);
|
||||||
|
if (aNext === null && bNext === null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (aNext === null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (bNext === null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return aNext - bNext;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const sorter = sorters[sortBy] || sorters.pickupDateDesc;
|
const sorter = sorters[sortBy] || sorters.pickupDateDesc;
|
||||||
return [...results].sort(sorter);
|
return [...results].sort(sorter);
|
||||||
}, [entries, filters, parseDateValue, sortBy, storeLabelMap]);
|
}, [entries, filters, getNextReminderTimestamp, parseDateValue, sortBy, storeLabelMap]);
|
||||||
|
|
||||||
const releaseEntryImageUrls = useCallback((entryList) => {
|
const releaseEntryImageUrls = useCallback((entryList) => {
|
||||||
if (!Array.isArray(entryList)) {
|
if (!Array.isArray(entryList)) {
|
||||||
@@ -538,6 +606,7 @@ const JournalPage = ({ authorizedFetch, stores }) => {
|
|||||||
<option value="createdAtAsc">Erstellt ↑</option>
|
<option value="createdAtAsc">Erstellt ↑</option>
|
||||||
<option value="storeNameAsc">Betrieb A–Z</option>
|
<option value="storeNameAsc">Betrieb A–Z</option>
|
||||||
<option value="storeNameDesc">Betrieb Z–A</option>
|
<option value="storeNameDesc">Betrieb Z–A</option>
|
||||||
|
<option value="nextReminderAsc">Nächste Erinnerung</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user