Intranet LocationPicker düzeltmesi

This commit is contained in:
Sedat ÖZTÜRK 2026-05-08 17:17:11 +03:00
parent cbd96fd8f2
commit 0554717bc6
4 changed files with 114 additions and 24 deletions

View file

@ -12306,6 +12306,36 @@
"en": "Google Maps could not be loaded. Please check your internet connection.",
"tr": "Google Maps yüklenemedi. Lütfen internet bağlantınızı kontrol edin."
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.NoResults",
"en": "No results found",
"tr": "Sonuç bulunamadı"
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.OverQueryLimit",
"en": "Google Places query limit exceeded. Please try again later.",
"tr": "Google Places sorgu limiti aşıldı. Lütfen daha sonra tekrar deneyiniz."
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.RequestDenied",
"en": "Google Places request denied. Please check your API key, billing, or permissions settings.",
"tr": "Google Places isteği reddedildi. API key, billing veya yetki ayarlarını kontrol ediniz."
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.InvalidRequest",
"en": "Invalid location search request. Please check your input and try again.",
"tr": "Geçersiz konum arama isteği."
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.UnknownError",
"en": "Google Places returned a temporary error. Please try again.",
"tr": "Google Places geçici bir hata döndürdü. Lütfen tekrar deneyiniz."
},
{
"resourceName": "Platform",
"key": "App.Platform.Intranet.SocialWall.LocationPicker.SearchFailed",

17
ui/.env
View file

@ -3,3 +3,20 @@ VITE_CDN_URL='http://localhost:4005'
VITE_REACT_APP_VERSION=$npm_package_version
VITE_AI_URL='https://ai.sozsoft.com/webhook/'
VITE_GOOGLE_MAPS_API_KEY='AIzaSyAefS2rvF-xwq7OHpZ27UYxXPbMo6OwACc'
# Google Cloud Consoleda:
# APIs & Services > Enabled APIs & services bölümüne gir.
# Şunların aktif olduğundan emin ol:
# Maps JavaScript API
# Places API
# Eğer ileride koordinat/adres çözümleme yapıyorsan ayrıca:
# Geocoding API
# APIs & Services > Credentials > API Key içine gir.
# API restrictions bölümünde:
# Eğer Restrict key seçiliyse, izinli API listesine şunları ekle:
# Maps JavaScript API
# Places API

View file

@ -1001,7 +1001,7 @@ const FileManager = () => {
size="sm"
icon={<FaTh />}
className={classNames(
'rounded-r-none border-r px-2 sm:px-3',
'rounded-r-none border-r ',
viewMode === 'grid' && 'bg-blue-50 dark:bg-blue-900/20 text-blue-600',
)}
onClick={() => setViewMode('grid')}
@ -1012,7 +1012,7 @@ const FileManager = () => {
size="sm"
icon={<FaList />}
className={classNames(
'rounded-l-none px-2 sm:px-3',
'rounded-l-none ',
viewMode === 'list' && 'bg-blue-50 dark:bg-blue-900/20 text-blue-600',
)}
onClick={() => setViewMode('list')}

View file

@ -29,7 +29,7 @@ declare global {
}
const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) => {
const { translate } = useLocalization();
const { translate } = useLocalization()
const [searchQuery, setSearchQuery] = useState('')
const [locations, setLocations] = useState<LocationData[]>([])
const [selectedLocation, setSelectedLocation] = useState<LocationData | null>(null)
@ -108,6 +108,28 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
searchInputRef.current?.focus()
}, [])
const getGooglePlacesErrorMessage = (status: any) => {
switch (status) {
case window.google.maps.places.PlacesServiceStatus.ZERO_RESULTS:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.NoResults')
case window.google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.OverQueryLimit')
case window.google.maps.places.PlacesServiceStatus.REQUEST_DENIED:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.RequestDenied')
case window.google.maps.places.PlacesServiceStatus.INVALID_REQUEST:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.InvalidRequest')
case window.google.maps.places.PlacesServiceStatus.UNKNOWN_ERROR:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.UnknownError')
default:
return translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchFailed')
}
}
// Google Places Autocomplete ile konum arama
useEffect(() => {
if (debounceTimerRef.current) {
@ -134,28 +156,32 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
{
input: searchQuery,
componentRestrictions: { country: 'tr' },
language: 'tr'
language: 'tr',
},
async (predictions: any, status: any) => {
if (status === window.google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
setLocations([])
setError(getGooglePlacesErrorMessage(status))
setIsLoading(false)
return
}
if (status !== window.google.maps.places.PlacesServiceStatus.OK) {
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchFailed'))
setLocations([])
setError(getGooglePlacesErrorMessage(status))
setIsLoading(false)
return
}
if (!predictions || predictions.length === 0) {
setLocations([])
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.NoResults'))
setIsLoading(false)
return
}
// Her bir prediction için detaylı bilgi al
setError(null)
const detailedLocations: LocationData[] = []
let completed = 0
@ -163,7 +189,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
placesServiceRef.current.getDetails(
{
placeId: prediction.place_id,
fields: ['name', 'formatted_address', 'geometry', 'place_id']
fields: ['name', 'formatted_address', 'geometry', 'place_id'],
},
(place: any, placeStatus: any) => {
completed++
@ -175,19 +201,24 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
address: place.formatted_address,
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
placeId: place.place_id
placeId: place.place_id,
})
}
// Tüm istekler tamamlandıysa state'i güncelle
if (completed === predictions.length) {
if (detailedLocations.length === 0) {
setError('Konum detayları alınamadı. API yetkilerini kontrol ediniz.')
} else {
setError(null)
}
setLocations(detailedLocations)
setIsLoading(false)
}
}
},
)
})
}
},
)
} catch (err) {
console.error('Location search error:', err)
@ -224,7 +255,9 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
<h2 className="text-xl font-bold text-gray-900 dark:text-white">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.AddLocation')}</h2>
<h2 className="text-xl font-bold text-gray-900 dark:text-white">
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.AddLocation')}
</h2>
<button
onClick={onClose}
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full transition-colors"
@ -242,7 +275,9 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder={translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchPlaceholder')}
placeholder={translate(
'::App.Platform.Intranet.SocialWall.LocationPicker.SearchPlaceholder',
)}
disabled={!isGoogleLoaded}
className="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-gray-100 dark:disabled:bg-gray-600 disabled:cursor-not-allowed"
/>
@ -259,12 +294,16 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
{!isGoogleLoaded ? (
<div className="text-center py-12">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.LoadingGoogleMaps')}</p>
<p className="text-gray-500 dark:text-gray-400">
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.LoadingGoogleMaps')}
</p>
</div>
) : isLoading ? (
<div className="text-center py-12">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchingLocations')}</p>
<p className="text-gray-500 dark:text-gray-400">
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchingLocations')}
</p>
</div>
) : error ? (
<div className="text-center py-12">
@ -298,7 +337,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
'w-full text-left p-3 rounded-lg transition-all hover:bg-gray-50 dark:hover:bg-gray-700',
selectedLocation?.id === location.id
? 'bg-blue-50 dark:bg-blue-900/30 border-2 border-blue-500'
: 'border-2 border-transparent'
: 'border-2 border-transparent',
)}
>
<div className="flex items-start gap-3">
@ -306,9 +345,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
<FaMapMarkerAlt
className={classNames(
'w-5 h-5',
selectedLocation?.id === location.id
? 'text-blue-600'
: 'text-gray-400'
selectedLocation?.id === location.id ? 'text-blue-600' : 'text-gray-400',
)}
/>
</div>
@ -318,7 +355,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
'font-semibold mb-1',
selectedLocation?.id === location.id
? 'text-blue-600 dark:text-blue-400'
: 'text-gray-900 dark:text-gray-100'
: 'text-gray-900 dark:text-gray-100',
)}
>
{location.name}
@ -333,7 +370,11 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
{selectedLocation?.id === location.id && (
<div className="mt-1">
<div className="w-5 h-5 bg-blue-600 rounded-full flex items-center justify-center">
<svg className="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20">
<svg
className="w-3 h-3 text-white"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
@ -361,7 +402,9 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
</span>
</span>
) : (
<span>{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SelectLocation')}</span>
<span>
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SelectLocation')}
</span>
)}
</div>
<div className="flex gap-2">