feat(home): Sort-Chip 'Zuletzt angesehen' + Profile-Switch-Refetch
Neuer Wert 'viewed' im AllSort-Enum + ALL_SORTS-Array. localStorage- Whitelist ergaenzt. Reactive $effect lauscht auf profileStore.active und refetcht offset=0 nur wenn aktueller Sort 'viewed' ist — andere Sortierungen sind profilunabhaengig. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,12 +27,13 @@
|
||||
let favorites = $state<SearchHit[]>([]);
|
||||
|
||||
const ALL_PAGE = 10;
|
||||
type AllSort = 'name' | 'rating' | 'cooked' | 'created';
|
||||
type AllSort = 'name' | 'rating' | 'cooked' | 'created' | 'viewed';
|
||||
const ALL_SORTS: { value: AllSort; label: string }[] = [
|
||||
{ value: 'name', label: 'Name' },
|
||||
{ value: 'rating', label: 'Bewertung' },
|
||||
{ value: 'cooked', label: 'Zuletzt gekocht' },
|
||||
{ value: 'created', label: 'Hinzugefügt' }
|
||||
{ value: 'created', label: 'Hinzugefügt' },
|
||||
{ value: 'viewed', label: 'Zuletzt angesehen' }
|
||||
];
|
||||
function buildAllUrl(sort: AllSort, limit: number, offset: number): string {
|
||||
const profileId = profileStore.active?.id;
|
||||
@@ -166,7 +167,7 @@
|
||||
void loadRecent();
|
||||
void searchFilterStore.load();
|
||||
const saved = localStorage.getItem('kochwas.allSort');
|
||||
if (saved && ['name', 'rating', 'cooked', 'created'].includes(saved)) {
|
||||
if (saved && ['name', 'rating', 'cooked', 'created', 'viewed'].includes(saved)) {
|
||||
allSort = saved as AllSort;
|
||||
}
|
||||
// Fresh-mount: kick off the initial 10. On back-nav, snapshot.restore
|
||||
@@ -205,6 +206,33 @@
|
||||
store.reSearch();
|
||||
});
|
||||
|
||||
// 'viewed' sort depends on the active profile. When the user switches
|
||||
// profiles, refetch with the new profile_id so the list reflects what
|
||||
// the *current* profile has viewed. Other sorts are profile-agnostic
|
||||
// and don't need this.
|
||||
$effect(() => {
|
||||
const active = profileStore.active;
|
||||
if (allSort !== 'viewed') return;
|
||||
if (allLoading) return;
|
||||
// Re-fetch the first page; rehydrate would re-load the previous
|
||||
// depth, but a sort-context change should reset to page 1 anyway.
|
||||
void (async () => {
|
||||
allLoading = true;
|
||||
try {
|
||||
const res = await fetch(buildAllUrl('viewed', ALL_PAGE, 0));
|
||||
if (!res.ok) return;
|
||||
const body = await res.json();
|
||||
const hits = body.hits as SearchHit[];
|
||||
allRecipes = hits;
|
||||
allExhausted = hits.length < ALL_PAGE;
|
||||
} finally {
|
||||
allLoading = false;
|
||||
}
|
||||
// 'active' is referenced so $effect tracks it as a dep:
|
||||
void active;
|
||||
})();
|
||||
});
|
||||
|
||||
// Sync current query back into the URL as ?q=... via replaceState,
|
||||
// without spamming the history stack. Pushing a new entry happens only
|
||||
// when the user clicks a result or otherwise navigates away.
|
||||
|
||||
Reference in New Issue
Block a user