feat: implement business detail client view with interactive features including rating, favoriting, messaging, and analytics tracking

This commit is contained in:
2026-05-09 21:12:01 +02:00
parent 6a42c52b58
commit 6acd5ebe2e
14 changed files with 516 additions and 40 deletions

View File

@@ -9,9 +9,10 @@ interface Props {
label?: string;
placeholder?: string;
suggestions?: string[];
onlySuggestions?: boolean;
}
export default function TagInput({ value, onChange, label, placeholder, suggestions = [] }: Props) {
export default function TagInput({ value, onChange, label, placeholder, suggestions = [], onlySuggestions = false }: Props) {
const [inputValue, setInputValue] = useState('');
const [filteredSuggestions, setFilteredSuggestions] = useState<string[]>([]);
const [showSuggestions, setShowSuggestions] = useState(false);
@@ -52,7 +53,15 @@ export default function TagInput({ value, onChange, label, placeholder, suggesti
}, []);
const addTag = (tagToAdd?: string) => {
if (onlySuggestions && !tagToAdd) return;
const tag = (tagToAdd || inputValue).trim().toLowerCase();
// If restricted, check if tag exists in suggestions
if (onlySuggestions && tagToAdd && !suggestions.some(s => s.toLowerCase() === tag)) {
return;
}
if (tag && !value.includes(tag)) {
onChange([...value, tag]);
}
@@ -69,10 +78,10 @@ export default function TagInput({ value, onChange, label, placeholder, suggesti
e.preventDefault();
if (selectedIndex >= 0 && filteredSuggestions[selectedIndex]) {
addTag(filteredSuggestions[selectedIndex]);
} else {
} else if (!onlySuggestions) {
addTag();
}
} else if (e.key === ',' || e.key === ';') {
} else if ((e.key === ',' || e.key === ';') && !onlySuggestions) {
e.preventDefault();
addTag();
} else if (e.key === 'ArrowDown') {