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:
@@ -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 => (
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user