turash/bugulma/frontend/components/map/MapHeader.tsx
2025-12-15 10:06:41 +01:00

100 lines
3.4 KiB
TypeScript

import React, { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useMapActions, useMapFilter, useMapUI } from '@/contexts/MapContexts.tsx';
import { useHeaderSearch } from '@/hooks/useHeaderSearch.ts';
import { useTranslation } from '@/hooks/useI18n.tsx';
import { ChevronDown } from 'lucide-react';
import BrandIdentity from '@/components/layout/BrandIdentity.tsx';
import { HeaderLayout, HeaderSection } from '@/components/layout/Header.tsx';
import HeaderActions from '@/components/layout/HeaderActions.tsx';
import Button from '@/components/ui/Button.tsx';
import IconButton from '@/components/ui/IconButton.tsx';
import SearchBar from '@/components/ui/SearchBar.tsx';
import SearchSuggestions from '@/components/map/SearchSuggestions.tsx';
const MapHeader = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const {
searchTerm,
searchSuggestions,
isSuggesting,
isBackendSearching,
searchError,
clearSearch,
} = useMapFilter();
const { isSidebarOpen, addOrgButtonRef } = useMapUI();
const { setSearchTerm } = useMapFilter();
const { setIsSidebarOpen } = useMapUI();
const { handleAddOrganization } = useMapActions();
const { handleSearchSubmit } = useHeaderSearch({
initialValue: searchTerm,
enableIRIHandling: true,
onSearchChange: setSearchTerm,
});
const handleSearchChange = useCallback(
(value: string) => {
setSearchTerm(value);
},
[setSearchTerm]
);
return (
<HeaderLayout>
<HeaderSection>
<IconButton
variant={isSidebarOpen ? 'secondary' : 'ghost'}
size="sm"
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
aria-label={isSidebarOpen ? 'Close sidebar' : 'Open sidebar'}
aria-expanded={isSidebarOpen}
aria-controls="map-sidebar"
className="transition-all duration-200 hover:bg-accent"
title={isSidebarOpen ? 'Close sidebar' : 'Open sidebar'}
>
<ChevronDown
className={`h-5 w-5 transition-transform duration-200 ${
isSidebarOpen ? 'rotate-90' : '-rotate-90'
}`}
/>
</IconButton>
<BrandIdentity onClick={() => navigate('/')} />
</HeaderSection>
<HeaderSection align="center" className="order-3 md:order-2">
<div className="w-full md:w-auto md:flex-1 max-w-md relative">
<SearchBar
value={searchTerm}
onChange={handleSearchChange}
onSubmit={handleSearchSubmit}
showClearButton={true}
onClear={clearSearch}
containerClassName="w-full"
/>
<SearchSuggestions
suggestions={searchSuggestions}
isLoading={isSuggesting || isBackendSearching}
error={searchError}
searchTerm={searchTerm}
onSelect={(suggestion) => {
setSearchTerm(suggestion);
handleSearchSubmit(suggestion);
}}
/>
</div>
</HeaderSection>
<HeaderSection align="right" className="order-2 md:order-3 gap-2">
<Button ref={addOrgButtonRef} onClick={handleAddOrganization} size="sm">
{t('mapHeader.addButton')}
</Button>
<HeaderActions showThemeToggle={false} showAuthButton={false} />
</HeaderSection>
</HeaderLayout>
);
};
export default React.memo(MapHeader);