123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- import React, { useEffect, useRef, useState } from 'react';
- import { View, Platform, Text, StatusBar } from 'react-native';
- import { SafeAreaView } from 'react-native-safe-area-context';
- import kye from '../../../../../assets/geojson/kye.json';
- import { Header } from 'src/components';
- import { useGetKyeQuery, usePostSetKye } from '@api/travels';
- import { StoreType, storage } from 'src/storage';
- import { VECTOR_MAP_HOST } from 'src/constants';
- import { styles } from './styles';
- import * as MapLibreRN from '@maplibre/maplibre-react-native';
- let kye_fill = {
- id: 'kye_fill',
- style: {
- fillColor: 'rgba(21, 99, 123, 0.4)'
- },
- maxzoom: 12
- };
- let kye_fill_visited = {
- id: 'kye_fill_visited',
- style: {
- fillColor: 'rgba(132, 138, 68, 0.6)'
- },
- maxzoom: 12
- };
- let kye_line = {
- id: 'kye_line',
- filter: ['all'],
- style: {
- lineColor: 'rgba(14, 80, 109, 1)',
- lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 0.8, 4, 1, 5, 1.5, 12, 3],
- lineWidthTransition: { duration: 300, delay: 0 }
- },
- maxzoom: 16
- };
- const EarthScreen = () => {
- const token = (storage.get('token', StoreType.STRING) as string) || '';
- const { data } = useGetKyeQuery(token, !!token);
- const { mutateAsync } = usePostSetKye();
- const [visited, setVisited] = useState<number[]>([]);
- const [score, setScore] = useState({ base: 0, percentage: 0 });
- const [quadrantsAll, setQuadrantsAll] = useState<number>(1);
- const generateFilter = (ids: number[]) => {
- if (!ids || !ids.length) return ['==', 'id', -1];
- return [
- 'any',
- ...ids.map((id) => {
- if (id > 612) {
- return ['>=', 'id', 613];
- } else {
- return ['==', 'id', id];
- }
- })
- ];
- };
- const [filter, setFilter] = useState<any[]>(generateFilter([]));
- const mapRef = useRef<MapLibreRN.MapViewRef>(null);
- useEffect(() => {
- if (!data || !data.regions) return;
- setQuadrantsAll(data.regions?.length);
- token && setVisited(data.visited);
- }, [data]);
- useEffect(() => {
- setFilter(generateFilter(visited));
- showScore();
- }, [visited]);
- const markQuadrant = async (qid: number) => {
- if (!token) return;
- let vis: 0 | 1 = 1;
- if (qid > 612) {
- if (Math.max(...visited) > 612) {
- vis = 0;
- }
- } else {
- if (visited.includes(qid)) {
- vis = 0;
- }
- }
- try {
- await mutateAsync(
- { token, qid, visited: vis },
- {
- onSuccess: () => {
- if (vis == 0) {
- quadRemove(qid);
- } else {
- quadAdd(qid);
- }
- }
- }
- );
- } catch (error) {
- console.error('Failed to update kye state', error);
- }
- };
- const quadAdd = (qid: number) => {
- setVisited((prevVisited) => {
- if (qid > 612) {
- const newVisited = [...prevVisited];
- for (let i = 613; i < 649; i++) {
- if (!newVisited.includes(i)) {
- newVisited.push(i);
- }
- }
- return newVisited;
- } else {
- if (!prevVisited.includes(qid)) {
- return [...prevVisited, qid];
- }
- return prevVisited;
- }
- });
- };
- const quadRemove = (qid: number) => {
- setVisited((prevVisited) => {
- if (qid > 612) {
- return prevVisited.filter((id) => id < 613 || id > 648);
- } else {
- return prevVisited.filter((id) => id !== qid);
- }
- });
- };
- const showScore = () => {
- let baseList = visited.filter((id) => id < 613);
- let score = baseList.length;
- if (Math.max(...visited) > 612) {
- score += 1;
- }
- let calc = Math.round((score / quadrantsAll) * 10000) / 100;
- setScore({ base: score, percentage: calc });
- };
- const onMapPress = async (event: any) => {
- if (!mapRef.current) return;
- try {
- const { screenPointX, screenPointY } = event.properties;
- const { features } = await mapRef.current.queryRenderedFeaturesAtPoint(
- [screenPointX, screenPointY],
- undefined,
- ['kye_fill']
- );
- if (features?.length) {
- const selectedKye = features[0];
- if (selectedKye.properties && selectedKye.properties.tt == '1') {
- markQuadrant(selectedKye.properties.id);
- }
- }
- } catch (error) {
- console.error('Failed to get coordinates on EarthScreen', error);
- }
- };
- return (
- <SafeAreaView style={{ height: '100%' }} edges={['top']}>
- <View style={styles.wrapper}>
- <Header label={'My Earth'} />
- {token && (
- <View style={styles.score}>
- <Text style={[styles.scoreText, { fontWeight: 'bold' }]}>Your score: {score.base}</Text>
- <Text style={[styles.scoreText, { fontSize: 14 }]}>{`(${score.percentage}%)`}</Text>
- </View>
- )}
- </View>
- <View
- style={[
- styles.container,
- { paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }
- ]}
- >
- <MapLibreRN.MapView
- ref={mapRef}
- style={styles.map}
- mapStyle={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
- rotateEnabled={false}
- attributionEnabled={false}
- onPress={onMapPress}
- >
- <MapLibreRN.ShapeSource id="kye" shape={kye as any}>
- <MapLibreRN.LineLayer
- id={kye_line.id}
- filter={kye_line.filter as any}
- maxZoomLevel={kye_line.maxzoom}
- style={kye_line.style as any}
- belowLayerID="waterway-name"
- />
- <MapLibreRN.FillLayer
- id={kye_fill.id}
- filter={['==', 'tt', '1']}
- style={kye_fill.style}
- maxZoomLevel={kye_fill.maxzoom}
- belowLayerID={kye_fill_visited.id}
- />
- <MapLibreRN.FillLayer
- id={kye_fill_visited.id}
- filter={filter as any}
- style={kye_fill_visited.style}
- maxZoomLevel={kye_fill_visited.maxzoom}
- belowLayerID={kye_line.id}
- />
- </MapLibreRN.ShapeSource>
- </MapLibreRN.MapView>
- </View>
- </SafeAreaView>
- );
- };
- export default EarthScreen;
|