"use client"; import { useState, useEffect } from "react"; import { X, Plus } from "lucide-react"; import type { Tag } from "@/lib/db/schema"; interface TagInputProps { selectedTags: string[]; onAddTag: (name: string) => void; onRemoveTag: (name: string) => void; } export function TagInput({ selectedTags, onAddTag, onRemoveTag }: TagInputProps) { const [recentTags, setRecentTags] = useState([]); const [inputValue, setInputValue] = useState(""); const [showInput, setShowInput] = useState(false); useEffect(() => { async function loadRecentTags() { try { const res = await fetch("/api/tags?limit=10"); if (res.ok) { const tags = await res.json(); setRecentTags(tags); } } catch { // Ignore } } loadRecentTags(); }, []); const availableTags = recentTags.filter((t) => !selectedTags.includes(t.name)); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const trimmed = inputValue.trim(); if (trimmed) { onAddTag(trimmed); setInputValue(""); setShowInput(false); } }; return (
{/* Selected tags */} {selectedTags.length > 0 && (
{selectedTags.map((tag) => ( {tag} ))}
)} {/* Recent tags to tap */} {availableTags.length > 0 && (
{availableTags.slice(0, 6).map((tag) => ( ))}
)} {/* Add custom tag */} {showInput ? (
setInputValue(e.target.value)} placeholder="Type a tag..." className="flex-1 px-3 py-2 bg-surface border border-border rounded-lg text-sm focus:outline-none focus:border-muted" autoFocus onBlur={() => { if (!inputValue.trim()) setShowInput(false); }} />
) : ( )}
); } interface TagChipsProps { tags: { id: string; name: string }[]; maxDisplay?: number; } export function TagChips({ tags, maxDisplay = 2 }: TagChipsProps) { if (tags.length === 0) return null; const displayed = tags.slice(0, maxDisplay); const remaining = tags.length - maxDisplay; return (
{displayed.map((tag) => ( {tag.name} ))} {remaining > 0 && ( +{remaining} )}
); }