@@ -12,10 +12,10 @@ import type { Zone, Camera } from "./types/api"
1212import "./App.css"
1313
1414function App ( ) {
15- const [ mapState , setMapState ] = useState < MapState > ( {
16- center : [ 59.9343 , 30 .3351] ,
17- zoom : 12 ,
18- } )
15+ const [ mapState , setMapState ] = useState < MapState > ( {
16+ center : [ 60.8943 , 31 .3351] ,
17+ zoom : 7 ,
18+ } )
1919
2020 const [ freeSpotFilter , setFreeSpotFilter ] =
2121 useState < FreeSpotFilterValue > ( "all" )
@@ -140,111 +140,123 @@ function App() {
140140 return (
141141 < div className = "min-h-screen bg-gray-50" >
142142 < main className = "mx-auto" >
143+ < div
144+ className = "absolute top-2 right-2 sm:top-4 sm:right-4 z-[1000] bg-white/70 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 map-overlay" >
145+ < div className = "flex items-center justify-between p-1 sm:p-2 min-w-0" >
146+ < div className = "flex items-center space-x-2 sm:space-x-3 min-w-0 flex-1 flex-wrap gap-1" >
147+ < span className = "text-xs sm:text-sm text-gray-700" > < a
148+ href = "https://github.com/ParkTrack-Project" target = "_blank" rel = "noopener noreferrer" > GitHub</ a > </ span >
149+ < span className = "text-xs sm:text-sm text-gray-700" > < a href = "https://docs.parktrack.live" target = "_blank" rel = "noopener noreferrer" > Документация</ a > </ span >
150+ < span className = "text-xs sm:text-sm text-gray-700" > < a href = "https://grafana.nawinds.dev/public-dashboards/4235e9d4e1074087a41e1205bbc91042?from=now-3h& to = now & timezone = browser " target = "_blank" rel = "noopener noreferrer" > Статус</ a > </ span >
151+ </ div >
152+ </ div >
153+ </ div >
143154 < div className = "relative h-[calc(100vh)] w-full" >
144155 < MapContainer
145- zones = { filteredZones }
146- mapState = { mapState }
147- onMapStateChange = { handleMapStateChange }
148- onZoneClick = { handleZoneClick }
149- className = "w-full h-full"
156+ zones = { filteredZones }
157+ mapState = { mapState }
158+ onMapStateChange = { handleMapStateChange }
159+ onZoneClick = { handleZoneClick }
160+ className = "w-full h-full"
150161 />
151162
152163 < button
153- ref = { toggleButtonRef }
154- onClick = { ( ) => setFiltersVisible ( ! filtersVisible ) }
155- className = "absolute top-20 left-2 sm:top-20 sm:left-4 z-[1001] bg-white/90 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 p-2 hover:bg-white transition-colors"
156- aria-label = "Toggle filters"
164+ ref = { toggleButtonRef }
165+ onClick = { ( ) => setFiltersVisible ( ! filtersVisible ) }
166+ className = "absolute top-20 left-2 sm:top-21 sm:left-2.5 z-[1001] bg-white/90 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 p-2 hover:bg-white transition-colors"
167+ aria-label = "Toggle filters"
157168 >
158169 { filtersVisible ? (
159- < svg
160- xmlns = "http://www.w3.org/2000/svg"
161- className = "h-5 w-5 text-gray-700"
162- viewBox = "0 0 20 20"
163- fill = "currentColor"
164- >
165- < path
166- fillRule = "evenodd"
167- d = "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
168- clipRule = "evenodd"
169- />
170- </ svg >
170+ < svg
171+ xmlns = "http://www.w3.org/2000/svg"
172+ className = "h-5 w-5 text-gray-700"
173+ viewBox = "0 0 20 20"
174+ fill = "currentColor"
175+ >
176+ < path
177+ fillRule = "evenodd"
178+ d = "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
179+ clipRule = "evenodd"
180+ />
181+ </ svg >
171182 ) : (
172- < svg
173- xmlns = "http://www.w3.org/2000/svg"
174- className = "h-5 w-5 text-gray-700"
175- viewBox = "0 0 20 20"
176- fill = "currentColor"
177- >
178- < path
179- fillRule = "evenodd"
180- d = "M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z"
181- clipRule = "evenodd"
182- />
183- </ svg >
183+ < svg
184+ xmlns = "http://www.w3.org/2000/svg"
185+ className = "h-5 w-5 text-gray-700"
186+ viewBox = "0 0 20 20"
187+ fill = "currentColor"
188+ >
189+ < path
190+ fillRule = "evenodd"
191+ d = "M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z"
192+ clipRule = "evenodd"
193+ />
194+ </ svg >
184195 ) }
185196 </ button >
186197
187198 { filtersVisible && (
188- < div
189- ref = { filtersRef }
190- className = "absolute top-2 left-16 right-2 sm:top-4 sm:left-16 sm:right-auto sm:max-w-md z-[1000] bg-white/90 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200"
191- >
192- < div className = "p-3 sm:p-4" >
193- < div className = "flex flex-col gap-3" >
194- < div >
195- < h3 className = "text-xs sm:text-sm font-semibold text-gray-700 mb-2" >
196- Фильтр по свободным местам
197- </ h3 >
198- < FreeSpotsFilter
199- value = { freeSpotFilter }
200- onChange = { setFreeSpotFilter }
199+ < div
200+ ref = { filtersRef }
201+ className = "absolute top-2 left-16 right-2 sm:top-4 sm:left-16 sm:right-auto sm:max-w-md z-[1000] bg-white/90 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200"
202+ >
203+ < div className = "p-3 sm:p-4" >
204+ < div className = "flex flex-col gap-3" >
205+ < div >
206+ < h3 className = "text-xs sm:text-sm font-semibold text-gray-700 mb-2" >
207+ Фильтр по свободным местам
208+ </ h3 >
209+ < FreeSpotsFilter
210+ value = { freeSpotFilter }
211+ onChange = { setFreeSpotFilter }
212+ />
213+ </ div >
214+ < CameraSelector
215+ cameras = { cameras }
216+ selectedCameraId = { selectedCameraId }
217+ onCameraSelect = { handleCameraSelect }
201218 />
202219 </ div >
203- < CameraSelector
204- cameras = { cameras }
205- selectedCameraId = { selectedCameraId }
206- onCameraSelect = { handleCameraSelect }
207- />
208220 </ div >
209221 </ div >
210- </ div >
211222 ) }
212223
213- < div className = "absolute bottom-2 left-2 right-2 sm:bottom-4 sm:left-4 sm:right-4 z-[1000] bg-white/70 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 map-overlay" >
224+ < div
225+ className = "absolute bottom-2 left-2 right-2 sm:bottom-4 sm:left-4 sm:right-4 z-[1000] bg-white/70 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 map-overlay" >
214226 < div className = "flex items-center justify-between p-1 sm:p-2 min-w-0" >
215227 < div className = "flex items-center space-x-2 sm:space-x-3 min-w-0 flex-1 flex-wrap gap-1" >
216228 { total > 0 && (
217- < span className = "text-xs sm:text-sm text-gray-700" >
229+ < span className = "text-xs sm:text-sm text-gray-700" >
218230 Зон: { filteredZones . length } /{ total }
219231 </ span >
220232 ) }
221233 { totalCapacity > 0 && (
222- < span className = "text-xs sm:text-sm text-gray-700" >
234+ < span className = "text-xs sm:text-sm text-gray-700" >
223235 • Вместимость: { totalCapacity }
224236 </ span >
225237 ) }
226238 { totalFreeSpots > 0 && (
227- < span className = "text-xs sm:text-sm font-medium text-green-600" >
239+ < span className = "text-xs sm:text-sm font-medium text-green-600" >
228240 • Свободно: { totalFreeSpots }
229241 </ span >
230242 ) }
231243
232244 { loading === "loading" && (
233- < div className = "flex items-center space-x-1" >
234- < div className = "animate-spin rounded-full h-2 w-2 sm:h-3 sm:w-3 border-b-2 border-blue-600" > </ div >
235- < span className = "text-xs sm:text-sm text-gray-600" >
245+ < div className = "flex items-center space-x-1" >
246+ < div className = "animate-spin rounded-full h-2 w-2 sm:h-3 sm:w-3 border-b-2 border-blue-600" > </ div >
247+ < span className = "text-xs sm:text-sm text-gray-600" >
236248 Загрузка...
237249 </ span >
238- </ div >
250+ </ div >
239251 ) }
240252 </ div >
241253
242254 { error && (
243- < div className = "bg-red-50 border border-red-200 rounded-md px-1 sm:px-2 py-1 flex-shrink-0" >
244- < p className = "text-xs sm:text-sm text-red-800 whitespace-nowrap" >
245- { error . message }
246- </ p >
247- </ div >
255+ < div className = "bg-red-50 border border-red-200 rounded-md px-1 sm:px-2 py-1 flex-shrink-0" >
256+ < p className = "text-xs sm:text-sm text-red-800 whitespace-nowrap" >
257+ { error . message }
258+ </ p >
259+ </ div >
248260 ) }
249261 </ div >
250262 </ div >
0 commit comments