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[]>([]);
|
let favorites = $state<SearchHit[]>([]);
|
||||||
|
|
||||||
const ALL_PAGE = 10;
|
const ALL_PAGE = 10;
|
||||||
type AllSort = 'name' | 'rating' | 'cooked' | 'created';
|
type AllSort = 'name' | 'rating' | 'cooked' | 'created' | 'viewed';
|
||||||
const ALL_SORTS: { value: AllSort; label: string }[] = [
|
const ALL_SORTS: { value: AllSort; label: string }[] = [
|
||||||
{ value: 'name', label: 'Name' },
|
{ value: 'name', label: 'Name' },
|
||||||
{ value: 'rating', label: 'Bewertung' },
|
{ value: 'rating', label: 'Bewertung' },
|
||||||
{ value: 'cooked', label: 'Zuletzt gekocht' },
|
{ 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 {
|
function buildAllUrl(sort: AllSort, limit: number, offset: number): string {
|
||||||
const profileId = profileStore.active?.id;
|
const profileId = profileStore.active?.id;
|
||||||
@@ -166,7 +167,7 @@
|
|||||||
void loadRecent();
|
void loadRecent();
|
||||||
void searchFilterStore.load();
|
void searchFilterStore.load();
|
||||||
const saved = localStorage.getItem('kochwas.allSort');
|
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;
|
allSort = saved as AllSort;
|
||||||
}
|
}
|
||||||
// Fresh-mount: kick off the initial 10. On back-nav, snapshot.restore
|
// Fresh-mount: kick off the initial 10. On back-nav, snapshot.restore
|
||||||
@@ -205,6 +206,33 @@
|
|||||||
store.reSearch();
|
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,
|
// Sync current query back into the URL as ?q=... via replaceState,
|
||||||
// without spamming the history stack. Pushing a new entry happens only
|
// without spamming the history stack. Pushing a new entry happens only
|
||||||
// when the user clicks a result or otherwise navigates away.
|
// when the user clicks a result or otherwise navigates away.
|
||||||
|
|||||||
Reference in New Issue
Block a user