diff --git a/src/components/admin/DesignerForm.tsx b/src/components/admin/DesignerForm.tsx
index 9291f665..bc72b0e9 100644
--- a/src/components/admin/DesignerForm.tsx
+++ b/src/components/admin/DesignerForm.tsx
@@ -12,9 +12,8 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { SlugField } from '@/components/ui/slug-field';
import { Ruler, Save, X } from 'lucide-react';
-import { Combobox } from '@/components/ui/combobox';
-import { useCompanyHeadquarters } from '@/hooks/useAutocompleteData';
import { useUserRole } from '@/hooks/useUserRole';
+import { HeadquartersLocationInput } from './HeadquartersLocationInput';
import { EntityMultiImageUploader, ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input';
import { submitDesignerCreation, submitDesignerUpdate } from '@/lib/entitySubmissionHelpers';
@@ -58,7 +57,6 @@ interface DesignerFormProps {
export function DesignerForm({ onSubmit, onCancel, initialData }: DesignerFormProps) {
const { isModerator } = useUserRole();
- const { headquarters } = useCompanyHeadquarters();
const { user } = useAuth();
const navigate = useNavigate();
@@ -199,14 +197,13 @@ export function DesignerForm({ onSubmit, onCancel, initialData }: DesignerFormPr
-
setValue('headquarters_location', value)}
- placeholder="Select or type location"
- searchPlaceholder="Search locations..."
- emptyText="No locations found"
+ setValue('headquarters_location', value)}
/>
+
+ Search OpenStreetMap for accurate location data, or manually enter location name.
+
diff --git a/src/components/admin/HeadquartersLocationInput.tsx b/src/components/admin/HeadquartersLocationInput.tsx
new file mode 100644
index 00000000..4bf4193c
--- /dev/null
+++ b/src/components/admin/HeadquartersLocationInput.tsx
@@ -0,0 +1,188 @@
+import { useState, useEffect } from 'react';
+import { Input } from '@/components/ui/input';
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
+import { Search, Edit, MapPin, Loader2, X } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+
+interface LocationResult {
+ place_id: number;
+ display_name: string;
+ address?: {
+ city?: string;
+ town?: string;
+ village?: string;
+ state?: string;
+ country?: string;
+ };
+}
+
+interface HeadquartersLocationInputProps {
+ value: string;
+ onChange: (value: string) => void;
+ disabled?: boolean;
+ className?: string;
+}
+
+export function HeadquartersLocationInput({
+ value,
+ onChange,
+ disabled = false,
+ className
+}: HeadquartersLocationInputProps) {
+ const [mode, setMode] = useState<'search' | 'manual'>('search');
+ const [searchQuery, setSearchQuery] = useState('');
+ const [results, setResults] = useState([]);
+ const [isSearching, setIsSearching] = useState(false);
+ const [showResults, setShowResults] = useState(false);
+
+ // Debounced search effect
+ useEffect(() => {
+ if (!searchQuery || searchQuery.length < 2) {
+ setResults([]);
+ setShowResults(false);
+ return;
+ }
+
+ const timeoutId = setTimeout(async () => {
+ setIsSearching(true);
+ try {
+ const response = await fetch(
+ `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
+ searchQuery
+ )}&limit=5&addressdetails=1`,
+ {
+ headers: {
+ 'User-Agent': 'ThemeParkArchive/1.0'
+ }
+ }
+ );
+
+ if (response.ok) {
+ const data = await response.json();
+ setResults(data);
+ setShowResults(true);
+ }
+ } catch (error) {
+ console.error('Error searching locations:', error);
+ } finally {
+ setIsSearching(false);
+ }
+ }, 500);
+
+ return () => clearTimeout(timeoutId);
+ }, [searchQuery]);
+
+ const formatLocation = (result: LocationResult): string => {
+ const { city, town, village, state, country } = result.address || {};
+ const cityName = city || town || village;
+
+ if (cityName && state && country) {
+ return `${cityName}, ${state}, ${country}`;
+ } else if (cityName && country) {
+ return `${cityName}, ${country}`;
+ } else if (country) {
+ return country;
+ }
+ return result.display_name;
+ };
+
+ const handleSelectLocation = (result: LocationResult) => {
+ const formatted = formatLocation(result);
+ onChange(formatted);
+ setSearchQuery('');
+ setShowResults(false);
+ setResults([]);
+ };
+
+ const handleClear = () => {
+ onChange('');
+ setSearchQuery('');
+ setResults([]);
+ setShowResults(false);
+ };
+
+ return (
+
+
setMode(val as 'search' | 'manual')}>
+
+
+
+ Search Location
+
+
+
+ Manual Entry
+
+
+
+
+
+ setSearchQuery(e.target.value)}
+ placeholder="Search for location (e.g., Munich, Germany)..."
+ disabled={disabled}
+ className="pr-10"
+ />
+ {isSearching && (
+
+ )}
+
+
+ {showResults && results.length > 0 && (
+
+ {results.map((result) => (
+
+ ))}
+
+ )}
+
+ {showResults && results.length === 0 && !isSearching && (
+
+ No locations found. Try a different search term.
+
+ )}
+
+ {value && (
+
+
+ {value}
+
+
+ )}
+
+
+
+ onChange(e.target.value)}
+ placeholder="Enter location manually..."
+ disabled={disabled}
+ />
+
+ Enter any location text. For better data quality, use Search mode.
+
+
+
+
+ );
+}
diff --git a/src/components/admin/ManufacturerForm.tsx b/src/components/admin/ManufacturerForm.tsx
index 48e8a8c5..37dd07b7 100644
--- a/src/components/admin/ManufacturerForm.tsx
+++ b/src/components/admin/ManufacturerForm.tsx
@@ -12,9 +12,8 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { SlugField } from '@/components/ui/slug-field';
import { Building2, Save, X } from 'lucide-react';
-import { Combobox } from '@/components/ui/combobox';
-import { useCompanyHeadquarters } from '@/hooks/useAutocompleteData';
import { useUserRole } from '@/hooks/useUserRole';
+import { HeadquartersLocationInput } from './HeadquartersLocationInput';
import { EntityMultiImageUploader, ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input';
import { submitManufacturerCreation, submitManufacturerUpdate } from '@/lib/entitySubmissionHelpers';
@@ -59,7 +58,6 @@ interface ManufacturerFormProps {
export function ManufacturerForm({ onSubmit, onCancel, initialData }: ManufacturerFormProps) {
const { isModerator } = useUserRole();
- const { headquarters } = useCompanyHeadquarters();
const { user } = useAuth();
const navigate = useNavigate();
@@ -200,14 +198,13 @@ export function ManufacturerForm({ onSubmit, onCancel, initialData }: Manufactur
-
setValue('headquarters_location', value)}
- placeholder="Select or type location"
- searchPlaceholder="Search locations..."
- emptyText="No locations found"
+ setValue('headquarters_location', value)}
/>
+
+ Search OpenStreetMap for accurate location data, or manually enter location name.
+
diff --git a/src/components/admin/OperatorForm.tsx b/src/components/admin/OperatorForm.tsx
index d90a20f0..1a0dd24f 100644
--- a/src/components/admin/OperatorForm.tsx
+++ b/src/components/admin/OperatorForm.tsx
@@ -12,9 +12,8 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { SlugField } from '@/components/ui/slug-field';
import { FerrisWheel, Save, X } from 'lucide-react';
-import { Combobox } from '@/components/ui/combobox';
-import { useCompanyHeadquarters } from '@/hooks/useAutocompleteData';
import { useUserRole } from '@/hooks/useUserRole';
+import { HeadquartersLocationInput } from './HeadquartersLocationInput';
import { EntityMultiImageUploader, ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input';
import { submitOperatorCreation, submitOperatorUpdate } from '@/lib/entitySubmissionHelpers';
@@ -58,7 +57,6 @@ interface OperatorFormProps {
export function OperatorForm({ onSubmit, onCancel, initialData }: OperatorFormProps) {
const { isModerator } = useUserRole();
- const { headquarters } = useCompanyHeadquarters();
const { user } = useAuth();
const navigate = useNavigate();
@@ -199,14 +197,13 @@ export function OperatorForm({ onSubmit, onCancel, initialData }: OperatorFormPr
-
setValue('headquarters_location', value)}
- placeholder="Select or type location"
- searchPlaceholder="Search locations..."
- emptyText="No locations found"
+ setValue('headquarters_location', value)}
/>
+
+ Search OpenStreetMap for accurate location data, or manually enter location name.
+
diff --git a/src/components/admin/PropertyOwnerForm.tsx b/src/components/admin/PropertyOwnerForm.tsx
index afd2207c..b2edebca 100644
--- a/src/components/admin/PropertyOwnerForm.tsx
+++ b/src/components/admin/PropertyOwnerForm.tsx
@@ -12,9 +12,8 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { SlugField } from '@/components/ui/slug-field';
import { Building2, Save, X } from 'lucide-react';
-import { Combobox } from '@/components/ui/combobox';
-import { useCompanyHeadquarters } from '@/hooks/useAutocompleteData';
import { useUserRole } from '@/hooks/useUserRole';
+import { HeadquartersLocationInput } from './HeadquartersLocationInput';
import { EntityMultiImageUploader, ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input';
import { submitPropertyOwnerCreation, submitPropertyOwnerUpdate } from '@/lib/entitySubmissionHelpers';
@@ -58,7 +57,6 @@ interface PropertyOwnerFormProps {
export function PropertyOwnerForm({ onSubmit, onCancel, initialData }: PropertyOwnerFormProps) {
const { isModerator } = useUserRole();
- const { headquarters } = useCompanyHeadquarters();
const { user } = useAuth();
const navigate = useNavigate();
@@ -199,14 +197,13 @@ export function PropertyOwnerForm({ onSubmit, onCancel, initialData }: PropertyO
-
setValue('headquarters_location', value)}
- placeholder="Select or type location"
- searchPlaceholder="Search locations..."
- emptyText="No locations found"
+ setValue('headquarters_location', value)}
/>
+
+ Search OpenStreetMap for accurate location data, or manually enter location name.
+
diff --git a/src/components/admin/index.ts b/src/components/admin/index.ts
index 429fae97..c9642531 100644
--- a/src/components/admin/index.ts
+++ b/src/components/admin/index.ts
@@ -1,6 +1,7 @@
// Admin components barrel exports
export { AdminPageLayout } from './AdminPageLayout';
export { DesignerForm } from './DesignerForm';
+export { HeadquartersLocationInput } from './HeadquartersLocationInput';
export { LocationSearch } from './LocationSearch';
export { ManufacturerForm } from './ManufacturerForm';
export { MarkdownEditor } from './MarkdownEditor';