Overview
The Locations API provides comprehensive location management for the UAE market, including cities and areas with Arabic translations. This system supports delivery zone configuration, store location setup, and customer address management.
Location: convex/shared/locations.ts
Get Cities
Retrieves all available cities in the UAE.
TypeScript
JavaScript
Python
const cities = await convex . query ( api . shared . locations . getCities );
[
{
"_id" : "ct123456789" ,
"name" : "Dubai" ,
"nameArabic" : "دبي" ,
"isActive" : true ,
"sortOrder" : 1 ,
"_creationTime" : 1640995200000
},
{
"_id" : "ct987654321" ,
"name" : "Abu Dhabi" ,
"nameArabic" : "أبو ظبي" ,
"isActive" : true ,
"sortOrder" : 2 ,
"_creationTime" : 1640995200000
},
{
"_id" : "ct555666777" ,
"name" : "Sharjah" ,
"nameArabic" : "الشارقة" ,
"isActive" : true ,
"sortOrder" : 3 ,
"_creationTime" : 1640995200000
}
]
Get Areas by City
Retrieves all areas within a specific city.
TypeScript
JavaScript
Python
const areas = await convex . query ( api . shared . locations . getAreasByCity , {
cityId: "ct123456789"
});
[
{
"_id" : "ar123456789" ,
"name" : "Marina" ,
"nameArabic" : "مارينا" ,
"city" : "ct123456789" ,
"type" : "district" ,
"isActive" : true ,
"_creationTime" : 1640995200000
},
{
"_id" : "ar987654321" ,
"name" : "Downtown Dubai" ,
"nameArabic" : "وسط مدينة دبي" ,
"city" : "ct123456789" ,
"type" : "district" ,
"isActive" : true ,
"_creationTime" : 1640995200000
},
{
"_id" : "ar555666777" ,
"name" : "Jumeirah" ,
"nameArabic" : "جميرا" ,
"city" : "ct123456789" ,
"type" : "neighborhood" ,
"isActive" : true ,
"_creationTime" : 1640995200000
}
]
Get Location Hierarchy
Retrieves the complete location hierarchy for the entire UAE.
const hierarchy = await convex . query ( api . shared . locations . getLocationHierarchy );
{
"cities" : [
{
"_id" : "ct123456789" ,
"name" : "Dubai" ,
"nameArabic" : "دبي" ,
"areas" : [
{
"_id" : "ar123456789" ,
"name" : "Marina" ,
"nameArabic" : "مارينا" ,
"type" : "district"
},
{
"_id" : "ar987654321" ,
"name" : "Downtown Dubai" ,
"nameArabic" : "وسط مدينة دبي" ,
"type" : "district"
}
]
},
{
"_id" : "ct987654321" ,
"name" : "Abu Dhabi" ,
"nameArabic" : "أبو ظبي" ,
"areas" : [
{
"_id" : "ar111222333" ,
"name" : "Corniche" ,
"nameArabic" : "الكورنيش" ,
"type" : "district"
}
]
}
]
}
Get Location Details
Retrieves detailed location information for a specific city or area.
// Get city details
const cityDetails = await convex . query ( api . shared . locations . getLocationDetails , {
cityId: "ct123456789"
});
// Get area details
const areaDetails = await convex . query ( api . shared . locations . getLocationDetails , {
areaId: "ar123456789"
});
City Details Response
Area Details Response
{
"type" : "city" ,
"city" : {
"_id" : "ct123456789" ,
"name" : "Dubai" ,
"nameArabic" : "دبي" ,
"isActive" : true ,
"sortOrder" : 1 ,
"areaCount" : 45 ,
"storeCount" : 125
}
}
Search Areas
Searches for areas by name (supports both English and Arabic).
Search term (supports partial matching)
// Search in English
const areas = await convex . query ( api . shared . locations . searchAreas , {
searchTerm: "marina"
});
// Search in Arabic
const areasArabic = await convex . query ( api . shared . locations . searchAreas , {
searchTerm: "مارينا"
});
[
{
"_id" : "ar123456789" ,
"name" : "Marina" ,
"nameArabic" : "مارينا" ,
"city" : "ct123456789" ,
"cityName" : "Dubai" ,
"type" : "district" ,
"isActive" : true
},
{
"_id" : "ar444555666" ,
"name" : "Marina Village" ,
"nameArabic" : "قرية مارينا" ,
"city" : "ct987654321" ,
"cityName" : "Abu Dhabi" ,
"type" : "community" ,
"isActive" : true
}
]
Add Area
Adds a new area to a city (admin function).
Area type: district, neighborhood, community, sector, or zone
const newArea = await convex . mutation ( api . shared . locations . addArea , {
cityId: "ct123456789" ,
name: "Business Bay" ,
nameArabic: "خليج الأعمال" ,
type: "district"
});
{
"_id" : "ar789012345" ,
"name" : "Business Bay" ,
"nameArabic" : "خليج الأعمال" ,
"city" : "ct123456789" ,
"type" : "district" ,
"isActive" : true ,
"_creationTime" : 1640995200000
}
Clear Location Data
Clears all location data from the system (admin function - use with caution).
await convex . mutation ( api . shared . locations . clearLocationData );
Location Picker Component
Here’s a complete location picker component for your frontend:
React Component
Vue Component
import { useState , useEffect } from 'react' ;
import { useQuery } from 'convex/react' ;
import { api } from './convex/_generated/api' ;
interface LocationPickerProps {
onLocationSelect : ( cityId : string , areaId : string ) => void ;
selectedCityId ?: string ;
selectedAreaId ?: string ;
}
function LocationPicker ({ onLocationSelect , selectedCityId , selectedAreaId } : LocationPickerProps ) {
const [ searchTerm , setSearchTerm ] = useState ( '' );
const cities = useQuery ( api . shared . locations . getCities );
const areas = useQuery (
api . shared . locations . getAreasByCity ,
selectedCityId ? { cityId: selectedCityId } : "skip"
);
const searchResults = useQuery (
api . shared . locations . searchAreas ,
searchTerm . length > 2 ? { searchTerm } : "skip"
);
const handleCitySelect = ( cityId : string ) => {
onLocationSelect ( cityId , '' );
};
const handleAreaSelect = ( areaId : string ) => {
if ( selectedCityId ) {
onLocationSelect ( selectedCityId , areaId );
}
};
return (
< div className = "location-picker" >
{ /* Search */ }
< div className = "mb-4" >
< input
type = "text"
placeholder = "Search areas..."
value = { searchTerm }
onChange = {(e) => setSearchTerm (e.target.value)}
className = "w-full p-2 border rounded"
/>
{ searchResults && searchResults . length > 0 && (
< div className = "mt-2 border rounded max-h-32 overflow-y-auto" >
{ searchResults . map (( area ) => (
< div
key = {area. _id }
onClick = {() => {
handleCitySelect ( area . city );
handleAreaSelect ( area . _id );
setSearchTerm ( '' );
}}
className = "p-2 hover:bg-gray-100 cursor-pointer"
>
< div className = "font-medium" > {area. name } </ div >
< div className = "text-sm text-gray-600" > {area. nameArabic } • { area . cityName } </ div >
</ div >
))}
</ div >
)}
</ div >
{ /* City Selection */ }
< div className = "mb-4" >
< label className = "block text-sm font-medium mb-2" > City </ label >
< select
value = {selectedCityId || '' }
onChange = {(e) => handleCitySelect (e.target.value)}
className = "w-full p-2 border rounded"
>
< option value = "" > Select a city </ option >
{ cities ?. map (( city ) => (
< option key = {city. _id } value = {city. _id } >
{ city . name } - { city . nameArabic }
</ option >
))}
</ select >
</ div >
{ /* Area Selection */ }
{ selectedCityId && (
< div className = "mb-4" >
< label className = "block text-sm font-medium mb-2" > Area </ label >
< select
value = {selectedAreaId || '' }
onChange = {(e) => handleAreaSelect (e.target.value)}
className = "w-full p-2 border rounded"
>
< option value = "" > Select an area </ option >
{ areas ?. map (( area ) => (
< option key = {area. _id } value = {area. _id } >
{ area . name } - { area . nameArabic } ({area. type })
</ option >
))}
</ select >
</ div >
)}
</ div >
);
}
export default LocationPicker ;
Area Types
The system supports different area types for better organization:
District Large administrative divisions within cities (e.g., Downtown Dubai, Marina)
Neighborhood Residential areas within districts (e.g., Jumeirah 1, Al Barsha)
Community Planned communities or compounds (e.g., Arabian Ranches, The Springs)
Sector Industrial or commercial sectors (e.g., DIFC, DMCC)
Error Handling
Status Code : 404{
"error" : "City not found" ,
"cityId" : "ct123456789"
}
Status Code : 404{
"error" : "Area not found" ,
"areaId" : "ar123456789"
}
Status Code : 400{
"error" : "Area with this name already exists in the city"
}
The location system is specifically designed for the UAE market with comprehensive coverage of major cities and areas, including Arabic translations for better user experience.
Use the search functionality to provide users with a fast way to find their location, especially useful for areas with similar names across different cities.