@@ -11,12 +11,12 @@ import {
1111} from "@macrostrat/map-interface" ;
1212import { buildMacrostratStyle } from "@macrostrat/map-styles" ;
1313import { mergeStyles } from "@macrostrat/mapbox-utils" ;
14- import { useDarkMode , useAPIResult , DarkModeButton } from "@macrostrat/ui-components" ;
14+ import { useDarkMode , DarkModeButton } from "@macrostrat/ui-components" ;
1515import mapboxgl from "mapbox-gl" ;
1616import { useCallback , useEffect , useState , useMemo } from "react" ;
1717import { tileserverDomain } from "@macrostrat-web/settings" ;
1818import "../main.sass" ;
19- import { BlankImage , apiURL , useRockdAPI } from "../index" ;
19+ import { createCheckins , useRockdAPI } from "../index" ;
2020import "./main.sass" ;
2121import "@macrostrat/style-system" ;
2222import { LngLatCoords } from "@macrostrat/map-interface" ;
@@ -97,220 +97,21 @@ function WeaverMap({
9797 mapboxToken ?: string ;
9898} ) {
9999 const style = useMapStyle ( type , mapboxToken ) ;
100- const [ sort , setSort ] = useState ( "likes" ) ;
101100
102101 // overlay
103- const [ isOpenSelected , setOpenSelected ] = useState ( true ) ;
104-
105102 const [ inspectPosition , setInspectPosition ] =
106103 useState < mapboxgl . LngLat | null > ( null ) ;
107104
108105 const onSelectPosition = useCallback ( ( position : mapboxgl . LngLat ) => {
109106 setInspectPosition ( position ) ;
110- setOpenSelected ( true ) ;
111107 } , [ ] ) ;
112108
113- let selectedResult = getCheckins ( inspectPosition ?. lat - .05 , inspectPosition ?. lat + .05 , inspectPosition ?. lng - .05 , inspectPosition ?. lng + .05 ) ;
114-
115- function FeatureDetails ( ) {
116- // return null;
117- const mapRef = useMapRef ( ) ;
118- const map = mapRef . current ;
119- const [ bounds , setBounds ] = useState ( map ?. getBounds ( ) ) ;
120- let checkins = [ ] ;
121- let result ;
122-
123- if ( ! map ) {
124- result = getCheckins ( 0 , 0 , 0 , 0 ) ;
125- } else if ( bounds ) {
126- result = getCheckins ( bounds . getSouth ( ) , bounds . getNorth ( ) , bounds . getWest ( ) , bounds . getEast ( ) ) ;
127- } else {
128- result = getCheckins ( 0 , 0 , 0 , 0 ) ;
129- }
130-
131- if ( ! bounds && map ) {
132- setBounds ( map . getBounds ( ) ) ;
133- }
134-
135- count ++ ;
136-
137- // add selected checkin markers
138- useEffect ( ( ) => {
139- let selectedCheckins = selectedResult ?. success . data ;
140- let selectedCords = [ ] ;
141- let finalCheckins = null ;
142-
143- let previousSelected = document . querySelectorAll ( '.selected_pin' ) ;
144- previousSelected . forEach ( ( marker ) => {
145- marker . remove ( ) ;
146- } ) ;
147-
148- if ( selectedCheckins ?. length > 0 && inspectPosition ) {
149- finalCheckins = createCheckins ( selectedCheckins , mapRef , "explore/blue-marker.png" , sort ) ;
150-
151- selectedCheckins . forEach ( ( checkin ) => {
152- selectedCords . push ( [ checkin . lng , checkin . lat ] ) ;
153- } ) ;
154-
155- let selectedStop = 0 ;
156- selectedCords . forEach ( ( coord ) => {
157- selectedStop ++ ;
158- // marker
159- const el = document . createElement ( 'div' ) ;
160- el . className = 'selected_pin' ;
161-
162- // Create marker
163- new mapboxgl . Marker ( el )
164- . setLngLat ( coord )
165- . addTo ( map ) ;
166- } ) ;
167- }
168- } , [ selectedResult ] ) ;
169-
170- // Update bounds on move
171- useEffect ( ( ) => {
172- if ( map ) {
173- const listener = ( ) => {
174- setBounds ( map . getBounds ( ) ) ;
175- } ;
176- map . on ( "moveend" , listener ) ;
177- return ( ) => {
178- map . off ( "moveend" , listener ) ;
179- } ;
180- }
181- } , [ bounds ] ) ;
182-
183- if ( result == null ) return h ( Spinner ) ;
184- result = result . success . data ;
185-
186- checkins = createCheckins ( result , mapRef , "explore/red-circle.png" , sort ) ;
187-
188- let selectedCheckins = selectedResult ?. success . data ;
189-
190- if ( selectedCheckins ?. length > 0 && inspectPosition ) {
191- console . log ( "returning selected" )
192- return h ( "div" , { className : 'checkin-container' } , createCheckins ( selectedCheckins , mapRef , "explore/blue-circle.png" , sort ) ) ;
193- }
194-
195- return h ( "div" , { className : 'checkin-container' } , [
196- h ( 'div' , checkins )
197- ] ) ;
198-
199- function createCheckins ( result , mapRef , marker , sort ) {
200- let checkins = [ ] ;
201- const map = mapRef ?. current ;
202- let stop = 0 ;
203-
204- let pinClass = "marker-number" ;
205- if ( marker . includes ( "circle" ) ) {
206- pinClass = "circle-number" ;
207- }
208-
209- result . forEach ( ( checkin ) => {
210- // format rating
211- let ratingArr = [ ] ;
212- for ( var i = 0 ; i < checkin . rating ; i ++ ) {
213- ratingArr . push ( h ( Icon , { className : "star" , icon : "star" , style : { color : 'white' } } ) ) ;
214- }
215-
216- for ( var i = 0 ; i < 5 - checkin . rating ; i ++ ) {
217- ratingArr . push ( h ( Icon , { className : "star" , icon : "star-empty" , style : { color : 'white' } } ) ) ;
218- }
219-
220- let image ;
221- const showImage = checkin . photo ;
222-
223- if ( showImage ) {
224- image = h ( BlankImage , { className : 'observation-img' , src : "https://rockd.org/api/v1/protected/image/" + checkin . person_id + "/thumb_large/" + checkin . photo } ) ;
225- } else {
226- image = h ( "div" , { className : 'no-image' } , [
227- h ( 'h1' , "Details" ) ,
228- h ( Icon , { className : 'details-image' , icon : "arrow-right" , style : { color : 'white' } } )
229- ] ) ;
230- }
231-
232- // for trips
233- let stop_name = checkin ?. name ?? null ;
234- let LngLatProps = {
235- position : {
236- lat : checkin . lat ,
237- lng : checkin . lng
238- } ,
239- precision : 3 ,
240- zoom : 10
241- } ;
242-
243- let temp = h ( 'div' , {
244- className : 'checkin' ,
245- onClick : ( ) => {
246- map . flyTo ( { center : [ checkin . lng , checkin . lat ] , zoom : 12 } ) ;
247- setInspectPosition ( { lat : checkin . lat , lng : checkin . lng } ) ;
248- console . log ( "inspect position set" )
249- } ,
250- onMouseEnter : ( ) => {
251- // marker
252- const el = document . createElement ( 'div' ) ;
253- el . className = 'marker_pin' ;
254-
255- // Create marker
256- new mapboxgl . Marker ( el )
257- . setLngLat ( [ checkin . lng , checkin . lat ] )
258- . addTo ( map ) ;
259- } ,
260- onMouseLeave : ( ) => {
261- let previous = document . querySelectorAll ( '.marker_pin' ) ;
262- previous . forEach ( ( marker ) => {
263- marker . remove ( ) ;
264- } ) ;
265- }
266- } , [
267- h ( 'h1' , { className : 'stop-name' } , stop_name ) ,
268- h ( 'div' , { className : 'checkin-header' } , [
269- h ( 'h3' , { className : 'profile-pic' } , h ( BlankImage , { src : apiURL + "protected/gravatar/" + checkin . person_id , className : "profile-pic" } ) ) ,
270- h ( 'div' , { className : 'checkin-info' } , [
271- h ( 'h3' , { className : 'name' } , checkin . first_name + " " + checkin . last_name ) ,
272- h ( 'h4' , { className : 'edited' } , checkin . created ) ,
273- h ( 'p' , "Near " + checkin . near ) ,
274- LngLatCoords ( LngLatProps ) ,
275- h ( 'h3' , { className : 'rating' } , ratingArr ) ,
276- ] ) ,
277- // pin,
278- ] ) ,
279- h ( 'p' , { className : 'description' } , checkin . notes ) ,
280- h ( 'a' , { className : 'checkin-link' , href : "/checkin/" + checkin . checkin_id , target : "_blank" } , [
281- image ,
282- showImage ? h ( 'div' , { className : "image-details" } , [
283- h ( 'h1' , "Details" ) ,
284- h ( Icon , { className : 'details-image' , icon : "arrow-right" , style : { color : 'white' } } )
285- ] ) : null
286- ] ) ,
287- h ( 'div' , { className : 'checkin-footer' } , [
288- h ( 'div' , { className : 'likes-container' } , [
289- h ( Icon , { className : 'likes-icon' , icon : "thumbs-up" , style : { color : 'white' } } ) ,
290- h ( 'h3' , { className : 'likes' } , checkin . likes ) ,
291- ] ) ,
292- h ( 'div' , { className : 'observations-container' } , [
293- h ( Icon , { className : 'observations-icon' , icon : "camera" , style : { color : 'white' } } ) ,
294- h ( 'h3' , { className : 'likes' } , checkin . observations . length ) ,
295- ] ) ,
296- h ( 'div' , { className : 'comments-container' } , [
297- h ( Icon , { className : 'comments-icon' , icon : "comment" , style : { color : 'white' } } ) ,
298- h ( 'h3' , { className : 'comments' } , checkin . comments ) ,
299- ] )
300- ] ) ,
301- ] ) ;
302-
303- checkins . push ( temp ) ;
304- } ) ;
305-
306- return checkins ;
307- }
308- }
309-
310- let featuredCheckin = h ( FeatureDetails ) ;
109+ const selectedResult = getSelectedCheckins ( inspectPosition ?. lat - .05 , inspectPosition ?. lat + .05 , inspectPosition ?. lng - .05 , inspectPosition ?. lng + .05 ) ?. success . data ;
110+ const featuredCheckin = h ( FeatureDetails , { setInspectPosition} ) ;
111+ const selectedCheckin = h ( SelectedCheckins , { selectedResult, inspectPosition, setInspectPosition} ) ;
311112 let overlay ;
312113
313- let LngLatProps = {
114+ const LngLatProps = {
314115 position : {
315116 lat : inspectPosition ?. lat ?? 0 ,
316117 lng : inspectPosition ?. lng ?? 0
@@ -319,22 +120,27 @@ function WeaverMap({
319120 zoom : 10
320121 } ;
321122
322- if ( inspectPosition && selectedResult ?. success . data . length > 0 ) {
123+ if ( inspectPosition && selectedResult . length > 0 ) {
323124 overlay = h ( "div.sidebox" , [
324125 h ( 'div.title' , [
325126 h ( 'div' , { className : "selected-center" } , [
326127 h ( "h1" , "Selected Checkins" ) ,
327128 h ( 'h3' , { className : "coordinates" } , LngLatCoords ( LngLatProps ) )
328129 ] ) ,
130+ h ( DarkModeButton , { className : "dark-btn" , showText : true } )
329131 ] ) ,
330132 h ( "button" , {
331133 className : "close-btn" ,
332134 onClick : ( ) => {
333- setOpenSelected ( false )
334135 setInspectPosition ( null ) ;
136+
137+ let previousSelected = document . querySelectorAll ( '.selected_pin' ) ;
138+ previousSelected . forEach ( ( marker ) => {
139+ marker . remove ( ) ;
140+ } ) ;
335141 }
336142 } , "X" ) ,
337- h ( "div.overlay-div" , featuredCheckin ) ,
143+ h ( "div.overlay-div" , selectedCheckin ) ,
338144 ] ) ;
339145 } else {
340146 overlay = h ( "div.sidebox" , [
@@ -415,11 +221,100 @@ function getCheckins(lat1, lat2, lng1, lng2) {
415221 "&maxlng=" + maxLng ) ;
416222}
417223
418- function getPersonCheckins ( personId ) {
419- return useRockdAPI ( "protected/checkins?person_id=" + personId ) ;
224+ function getSelectedCheckins ( lat1 , lat2 , lng1 , lng2 ) {
225+ // abitrary bounds around click point
226+ let minLat = Math . floor ( lat1 * 100 ) / 100 ;
227+ let maxLat = Math . floor ( lat2 * 100 ) / 100 ;
228+ let minLng = Math . floor ( lng1 * 100 ) / 100 ;
229+ let maxLng = Math . floor ( lng2 * 100 ) / 100 ;
230+
231+ // return 10 pages of results
232+ return useRockdAPI ( "protected/checkins?minlat=" + minLat +
233+ "&maxlat=" + maxLat +
234+ "&minlng=" + minLng +
235+ "&maxlng=" + maxLng + "&all=10" ) ;
420236}
421237
422- function getTaxonCheckins ( taxonId ) {
423- // not sure how to use api yet
424- return useAPIResult ( "https://rockd.org/api/v1/protected/checkins?taxon_id=" + taxonId ) ;
238+ function SelectedCheckins ( { selectedResult, inspectPosition, setInspectPosition} ) {
239+ const mapRef = useMapRef ( ) ;
240+ const map = mapRef . current ;
241+
242+ // add selected checkin markers
243+ useEffect ( ( ) => {
244+ let selectedCords = [ ] ;
245+
246+ let previousSelected = document . querySelectorAll ( '.selected_pin' ) ;
247+ previousSelected . forEach ( ( marker ) => {
248+ marker . remove ( ) ;
249+ } ) ;
250+
251+ // if selected checkins
252+ if ( selectedResult ?. length > 0 && inspectPosition ) {
253+ selectedResult . forEach ( ( checkin ) => {
254+ selectedCords . push ( [ checkin . lng , checkin . lat ] ) ;
255+ } ) ;
256+
257+ let selectedStop = 0 ;
258+ selectedCords . forEach ( ( coord ) => {
259+ selectedStop ++ ;
260+ // marker
261+ const el = document . createElement ( 'div' ) ;
262+ el . className = 'selected_pin' ;
263+
264+ // Create marker
265+ new mapboxgl . Marker ( el )
266+ . setLngLat ( coord )
267+ . addTo ( map ) ;
268+ } ) ;
269+ }
270+ } , [ selectedResult ] ) ;
271+
272+ return h ( "div" , { className : 'checkin-container' } , createCheckins ( selectedResult , mapRef , setInspectPosition ) ) ;
273+ }
274+
275+ function FeatureDetails ( { setInspectPosition} ) {
276+ // return null;
277+ const mapRef = useMapRef ( ) ;
278+ const map = mapRef . current ;
279+ const [ bounds , setBounds ] = useState ( map ?. getBounds ( ) ) ;
280+ let checkins = [ ] ;
281+ let result ;
282+
283+ if ( ! map ) {
284+ result = getCheckins ( 0 , 0 , 0 , 0 ) ;
285+ } else if ( bounds ) {
286+ const distance = Math . abs ( bounds . getEast ( ) - bounds . getWest ( ) ) ;
287+ const newEast = bounds . getEast ( ) - distance * .2 ;
288+ result = getCheckins ( bounds . getSouth ( ) , bounds . getNorth ( ) , bounds . getWest ( ) , newEast ) ;
289+ } else {
290+ result = getCheckins ( 0 , 0 , 0 , 0 ) ;
291+ }
292+
293+ if ( ! bounds && map ) {
294+ setBounds ( map . getBounds ( ) ) ;
295+ }
296+
297+ count ++ ;
298+
299+ // Update bounds on move
300+ useEffect ( ( ) => {
301+ if ( map ) {
302+ const listener = ( ) => {
303+ setBounds ( map . getBounds ( ) ) ;
304+ } ;
305+ map . on ( "moveend" , listener ) ;
306+ return ( ) => {
307+ map . off ( "moveend" , listener ) ;
308+ } ;
309+ }
310+ } , [ bounds ] ) ;
311+
312+ if ( result == null ) return h ( Spinner ) ;
313+ result = result . success . data ;
314+
315+ checkins = createCheckins ( result , mapRef , setInspectPosition ) ;
316+
317+ return h ( "div" , { className : 'checkin-container' } , [
318+ h ( 'div' , checkins )
319+ ] ) ;
425320}
0 commit comments