refactoring
This commit is contained in:
@@ -1,139 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { sortEntriesByLabel } from '../utils/configUtils';
|
||||
import { formatDateValue } from '../utils/dateUtils';
|
||||
|
||||
const API_URL = '/api/iobroker/pickup-config';
|
||||
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
const usePickupConfig = () => {
|
||||
const [config, setConfig] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [status, setStatus] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const fetchConfig = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const response = await fetch(API_URL);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
setConfig(sortEntriesByLabel(Array.isArray(data) ? data : []));
|
||||
} catch (err) {
|
||||
setError('Fehler beim Laden der Konfiguration: ' + err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const saveConfig = useCallback(async () => {
|
||||
setStatus('Speichere...');
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const response = await fetch(API_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(config)
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
setStatus('Konfiguration erfolgreich gespeichert!');
|
||||
setTimeout(() => setStatus(''), 3000);
|
||||
} catch (err) {
|
||||
setError('Fehler beim Speichern: ' + err.message);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const updateEntryByIndex = useCallback((index, updater) => {
|
||||
setConfig((prev) => {
|
||||
if (!prev[index]) {
|
||||
return prev;
|
||||
}
|
||||
const next = [...prev];
|
||||
next[index] = updater(next[index]);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const updateEntryById = useCallback((entryId, updater) => {
|
||||
setConfig((prev) =>
|
||||
prev.map((item) => {
|
||||
if (item.id !== entryId) {
|
||||
return item;
|
||||
}
|
||||
return updater(item);
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
const toggleActive = useCallback((index) => {
|
||||
updateEntryByIndex(index, (entry) => ({ ...entry, active: !entry.active }));
|
||||
}, [updateEntryByIndex]);
|
||||
|
||||
const toggleProfileCheck = useCallback((index) => {
|
||||
updateEntryByIndex(index, (entry) => ({ ...entry, checkProfileId: !entry.checkProfileId }));
|
||||
}, [updateEntryByIndex]);
|
||||
|
||||
const toggleOnlyNotify = useCallback((index) => {
|
||||
updateEntryByIndex(index, (entry) => ({ ...entry, onlyNotify: !entry.onlyNotify }));
|
||||
}, [updateEntryByIndex]);
|
||||
|
||||
const changeWeekday = useCallback((index, value) => {
|
||||
updateEntryByIndex(index, (entry) => {
|
||||
const next = { ...entry, desiredWeekday: value };
|
||||
if (next.desiredDateRange) {
|
||||
delete next.desiredDateRange;
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}, [updateEntryByIndex]);
|
||||
|
||||
const updateDateRange = useCallback((entryId, startDate, endDate) => {
|
||||
const startValue = formatDateValue(startDate);
|
||||
const endValue = formatDateValue(endDate);
|
||||
updateEntryById(entryId, (entry) => {
|
||||
const next = { ...entry };
|
||||
if (startValue || endValue) {
|
||||
next.desiredDateRange = {
|
||||
start: startValue || endValue,
|
||||
end: endValue || startValue
|
||||
};
|
||||
if (next.desiredWeekday) {
|
||||
delete next.desiredWeekday;
|
||||
}
|
||||
} else if (next.desiredDateRange) {
|
||||
delete next.desiredDateRange;
|
||||
}
|
||||
if (next.desiredDate) {
|
||||
delete next.desiredDate;
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}, [updateEntryById]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchConfig();
|
||||
}, [fetchConfig]);
|
||||
|
||||
return {
|
||||
API_URL,
|
||||
config,
|
||||
loading,
|
||||
status,
|
||||
error,
|
||||
fetchConfig,
|
||||
saveConfig,
|
||||
toggleActive,
|
||||
toggleProfileCheck,
|
||||
toggleOnlyNotify,
|
||||
changeWeekday,
|
||||
updateDateRange
|
||||
};
|
||||
};
|
||||
|
||||
export default usePickupConfig;
|
||||
@@ -1,84 +0,0 @@
|
||||
import React from 'react';
|
||||
import { act, render } from '@testing-library/react';
|
||||
import usePickupConfig from './usePickupConfig';
|
||||
|
||||
describe('usePickupConfig', () => {
|
||||
const mockConfig = [
|
||||
{ id: '2', label: 'Beta Store', active: false, checkProfileId: true, onlyNotify: false },
|
||||
{ id: '1', label: 'alpha Shop', active: false, checkProfileId: true, onlyNotify: false }
|
||||
];
|
||||
|
||||
const advanceTimers = async (ms = 0) => {
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(ms);
|
||||
await Promise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
const renderHook = () => {
|
||||
let latest;
|
||||
const TestHarness = () => {
|
||||
latest = usePickupConfig();
|
||||
return null;
|
||||
};
|
||||
render(<TestHarness />);
|
||||
return () => latest;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
global.fetch = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(mockConfig)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
global.fetch.mockRestore?.();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('fetchConfig loads sorted configuration', async () => {
|
||||
const getHook = renderHook();
|
||||
await advanceTimers(600);
|
||||
const hook = getHook();
|
||||
expect(hook.loading).toBe(false);
|
||||
expect(hook.config[0].label).toBe('alpha Shop');
|
||||
expect(hook.config[hook.config.length - 1].label).toBe('Beta Store');
|
||||
});
|
||||
|
||||
test('mutators update entries as expected', async () => {
|
||||
const getHook = renderHook();
|
||||
await advanceTimers(600);
|
||||
|
||||
await act(async () => {
|
||||
getHook().toggleActive(0);
|
||||
getHook().toggleProfileCheck(0);
|
||||
getHook().toggleOnlyNotify(0);
|
||||
});
|
||||
|
||||
let updated = getHook().config[0];
|
||||
expect(updated.active).toBe(true);
|
||||
expect(updated.checkProfileId).toBe(false);
|
||||
expect(updated.onlyNotify).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
getHook().changeWeekday(0, 'Montag');
|
||||
});
|
||||
updated = getHook().config[0];
|
||||
expect(updated.desiredWeekday).toBe('Montag');
|
||||
expect(updated.desiredDateRange).toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
getHook().updateDateRange(updated.id, new Date('2025-01-01'), new Date('2025-01-03'));
|
||||
});
|
||||
updated = getHook().config[0];
|
||||
expect(updated.desiredDateRange).toEqual({
|
||||
start: '2025-01-01',
|
||||
end: '2025-01-03'
|
||||
});
|
||||
expect(updated.desiredWeekday).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user