feat(favorites-system): User kann Customer/Project favoritisieren (localStorage) [tsc:fail]
This commit is contained in:
parent
eb65bea128
commit
29646c8015
@ -1,5 +1,8 @@
|
||||
{
|
||||
"completed_features": [],
|
||||
"current_feature": "recently-viewed-widget",
|
||||
"started_at": "2026-05-23T09:18:37.298269"
|
||||
"current_feature": "favorites-system",
|
||||
"started_at": "2026-05-23T09:18:37.298269",
|
||||
"attempted_features": [
|
||||
"recently-viewed-widget"
|
||||
]
|
||||
}
|
||||
@ -3300,3 +3300,21 @@ src/index.ts(27,25): error TS2769: No overload matches this call.
|
||||
Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
|
||||
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
|
||||
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>,
|
||||
- `09:19:02` **INFO** Committed feature recently-viewed-widget
|
||||
- `09:19:02` **INFO** Pushed: rc=0
|
||||
|
||||
## Phase-3 Feature: favorites-system (2026-05-23 09:19:02)
|
||||
|
||||
- `09:19:02` **INFO** Description: User kann Customer/Project favoritisieren (localStorage)
|
||||
- `09:19:02` **INFO** Generating apps/web/src/lib/favorites.ts (useFavorites() hook + util. Manages localStorage 'favorites' Set per e…)
|
||||
- `09:19:22` **INFO** wrote 2276 chars in 19.9s (attempt 1)
|
||||
- `09:19:22` **INFO** Running tsc --noEmit on api…
|
||||
- `09:19:24` **WARN** tsc errors:
|
||||
src/db/schema.ts(37,14): error TS7022: 'customers' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
|
||||
src/db/schema.ts(45,59): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
src/db/schema.ts(49,14): error TS7022: 'projects' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
|
||||
src/db/schema.ts(53,56): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
src/index.ts(27,25): error TS2769: No overload matches this call.
|
||||
Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
|
||||
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
|
||||
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>,
|
||||
|
||||
87
apps/web/src/lib/favorites.ts
Normal file
87
apps/web/src/lib/favorites.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
const STORAGE_KEY = 'emberclone_favorites';
|
||||
const FAVORITES_EVENT = 'emberclone_favorites_updated';
|
||||
|
||||
export const favoritesUtils = {
|
||||
getFavorites: (): Record<string, Set<string>> => {
|
||||
const data = localStorage.getItem(STORAGE_KEY);
|
||||
if (!data) return {};
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
const result: Record<string, Set<string>> = {};
|
||||
for (const [type, ids] of Object.entries(parsed)) {
|
||||
result[type] = new Set(ids as string[]);
|
||||
}
|
||||
return result;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
saveFavorites: (favorites: Record<string, Set<string>>) => {
|
||||
const data: Record<string, string[]> = {};
|
||||
for (const [type, ids] of Object.entries(favorites)) {
|
||||
data[type] = Array.from(ids);
|
||||
}
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
||||
window.dispatchEvent(new CustomEvent(FAVORITES_EVENT));
|
||||
},
|
||||
|
||||
isFavorite: (type: string, id: string): boolean => {
|
||||
const favs = favoritesUtils.getFavorites();
|
||||
return favs[type]?.has(id) ?? false;
|
||||
},
|
||||
|
||||
toggleFavorite: (type: string, id: string) => {
|
||||
const favs = favoritesUtils.getFavorites();
|
||||
if (!favs[type]) {
|
||||
favs[type] = new Set();
|
||||
}
|
||||
|
||||
if (favs[type].has(id)) {
|
||||
favs[type].delete(id);
|
||||
} else {
|
||||
favs[type].add(id);
|
||||
}
|
||||
|
||||
favoritesUtils.saveFavorites(favs);
|
||||
},
|
||||
|
||||
getAllFavorites: (type: string): string[] => {
|
||||
const favs = favoritesUtils.getFavorites();
|
||||
return Array.from(favs[type] || []);
|
||||
}
|
||||
};
|
||||
|
||||
export function useFavorites() {
|
||||
const [favorites, setFavorites] = useState(() => favoritesUtils.getFavorites());
|
||||
|
||||
useEffect(() => {
|
||||
const handleUpdate = () => {
|
||||
setFavorites(favoritesUtils.getFavorites());
|
||||
};
|
||||
|
||||
window.addEventListener(FAVORITES_EVENT, handleUpdate);
|
||||
return () => window.removeEventListener(FAVORITES_EVENT, handleUpdate);
|
||||
}, []);
|
||||
|
||||
const isFavorite = (type: string, id: string) => {
|
||||
return favorites[type]?.has(id) ?? false;
|
||||
};
|
||||
|
||||
const toggle = (type: string, id: string) => {
|
||||
favoritesUtils.toggleFavorite(type, id);
|
||||
};
|
||||
|
||||
const getAll = (type: string) => {
|
||||
return Array.from(favorites[type] || []);
|
||||
};
|
||||
|
||||
return {
|
||||
isFavorite,
|
||||
toggle,
|
||||
getAll,
|
||||
favorites
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user