fix: resolve TagSelector build error and improve component type safety

- Fixed undefined setTags in TagSelector.tsx
- Updated TagSelector to use Dexie cache for immediate UI updates
- Refined TastingList mapping to satisfy TypeScript interface
- Verified fix with a successful production build
This commit is contained in:
2025-12-19 14:17:40 +01:00
parent f52cfb80fc
commit cbb28b389c
2 changed files with 14 additions and 10 deletions

View File

@@ -34,7 +34,7 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
const tagList = tags || [];
if (!search) return tagList;
const s = search.toLowerCase();
return tagList.filter((tag: any) => {
return tagList.filter((tag) => {
const rawMatch = tag.name.toLowerCase().includes(s);
const translatedMatch = tag.is_system_default && t(`aroma.${tag.name}`).toLowerCase().includes(s);
return rawMatch || translatedMatch;
@@ -47,14 +47,14 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
setIsCreating(true);
const result = await createCustomTag(search, category);
if (result.success && result.tag) {
setTags(prev => [...prev, result.tag!]);
await db.cache_tags.put(result.tag!);
onToggleTag(result.tag!.id);
setSearch('');
}
setIsCreating(false);
};
const selectedTags = tags.filter(t => selectedTagIds.includes(t.id));
const selectedTags = (tags || []).filter(t => selectedTagIds.includes(t.id));
return (
<div className="space-y-3">
@@ -137,7 +137,7 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
<Sparkles size={10} /> {t('camera.wbMatchFound') ? 'KI Vorschläge' : 'AI Suggestions'}
</div>
<div className="flex flex-wrap gap-1.5">
{tags
{(tags || [])
.filter(t => !selectedTagIds.includes(t.id) && suggestedTagNames.some((s: string) => s.toLowerCase() === t.name.toLowerCase()))
.map(tag => (
<button
@@ -162,7 +162,7 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
</div>
<div className="flex flex-wrap gap-1.5">
{suggestedCustomTagNames
.filter(name => !tags.some(t => t.name.toLowerCase() === name.toLowerCase()))
.filter(name => !(tags || []).some(t => t.name.toLowerCase() === name.toLowerCase()))
.map(name => (
<button
key={name}
@@ -172,7 +172,7 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
setCreatingSuggestion(name);
const result = await createCustomTag(name, category);
if (result.success && result.tag) {
setTags(prev => [...prev, result.tag!]);
await db.cache_tags.put(result.tag!);
onToggleTag(result.tag!.id);
}
setCreatingSuggestion(null);
@@ -190,7 +190,7 @@ export default function TagSelector({ category, selectedTagIds, onToggleTag, lab
{/* Suggestions Chips (limit to 6 random or most common) */}
{!search && tags.length > 0 && (
<div className="flex flex-wrap gap-1.5 pt-1">
{tags
{(tags || [])
.filter(t => !selectedTagIds.includes(t.id) && (!suggestedTagNames || !suggestedTagNames.some((s: string) => s.toLowerCase() === t.name.toLowerCase())))
.slice(0, 8)
.map(tag => (

View File

@@ -37,6 +37,7 @@ interface Tasting {
}
}[];
user_id: string;
isPending?: boolean;
}
interface TastingListProps {
@@ -88,7 +89,10 @@ export default function TastingList({ initialTastings, currentUserId, bottleId }
bottle_id: p.bottle_id,
created_at: p.tasted_at,
user_id: currentUserId || '',
isPending: true
isPending: true,
tasting_buddies: [],
tasting_sessions: undefined,
tasting_tags: []
}))
];
@@ -149,7 +153,7 @@ export default function TastingList({ initialTastings, currentUserId, bottleId }
}`}>
{note.is_sample ? 'Sample' : 'Bottle'}
</span>
{(note as any).isPending && (
{note.isPending && (
<div className="bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400 px-2 py-0.5 rounded-lg text-[10px] font-black uppercase tracking-tighter flex items-center gap-1.5 animate-pulse">
<Clock size={10} />
Wartet auf Sync...
@@ -174,7 +178,7 @@ export default function TastingList({ initialTastings, currentUserId, bottleId }
<Calendar size={12} />
{new Date(note.created_at).toLocaleDateString('de-DE')}
</div>
{(!currentUserId || note.user_id === currentUserId) && !(note as any).isPending && (
{(!currentUserId || note.user_id === currentUserId) && !note.isPending && (
<button
onClick={() => handleDelete(note.id, note.bottle_id)}
disabled={!!isDeleting}