소스 검색

vector maps test

Viktoriia 7 달 전
부모
커밋
d51cfbb4bc
30개의 변경된 파일1168개의 추가작업 그리고 703개의 파일을 삭제
  1. 0 0
      assets/geojson/mqp.json
  2. 1 1
      src/components/TabBarButton/style.tsx
  3. 0 69
      src/database/geojsonService/index.ts
  4. 2 5
      src/database/index.ts
  5. 48 58
      src/database/tilesService/index.ts
  6. 11 1
      src/modules/api/countries/countries-api.tsx
  7. 2 1
      src/modules/api/countries/countries-query-keys.tsx
  8. 1 0
      src/modules/api/countries/queries/index.ts
  9. 17 0
      src/modules/api/countries/queries/use-get-list-countries.tsx
  10. 3 0
      src/modules/api/maps/index.ts
  11. 16 0
      src/modules/api/maps/maps-api.ts
  12. 17 0
      src/modules/api/maps/maps-query-keys.tsx
  13. 3 0
      src/modules/api/maps/queries/index.ts
  14. 23 0
      src/modules/api/maps/queries/use-post-get-visited-countries-ids.tsx
  15. 17 0
      src/modules/api/maps/queries/use-post-get-visited-dare-ids.tsx
  16. 23 0
      src/modules/api/maps/queries/use-post-get-visited-regions-ids.tsx
  17. 11 1
      src/modules/api/myDARE/dare-api.tsx
  18. 2 1
      src/modules/api/myDARE/dare-query-keys.tsx
  19. 1 0
      src/modules/api/myDARE/queries/index.ts
  20. 17 0
      src/modules/api/myDARE/queries/use-get-list-dare.tsx
  21. 1 0
      src/modules/api/regions/queries/index.ts
  22. 17 0
      src/modules/api/regions/queries/use-get-list-regions.tsx
  23. 13 1
      src/modules/api/regions/regions-api.tsx
  24. 2 1
      src/modules/api/regions/regions-query-keys.tsx
  25. 25 11
      src/screens/InAppScreens/MapScreen/FilterModal/index.tsx
  26. 6 6
      src/screens/InAppScreens/MapScreen/UniversalSearch/index.tsx
  27. 535 419
      src/screens/InAppScreens/MapScreen/index.tsx
  28. 109 52
      src/screens/InAppScreens/MapScreen/style.tsx
  29. 228 73
      src/screens/InAppScreens/ProfileScreen/UsersMap/index.tsx
  30. 17 3
      src/types/api.ts

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
assets/geojson/mqp.json


+ 1 - 1
src/components/TabBarButton/style.tsx

@@ -6,7 +6,7 @@ export const styles = StyleSheet.create({
     alignItems: 'center',
     justifyContent: 'center',
     overflow: 'hidden',
-    paddingTop: Platform.OS === 'ios' ? 4 : 0,
+    paddingTop: 0,
   },
   labelStyle: {
     marginTop: 4,

+ 0 - 69
src/database/geojsonService/index.ts

@@ -1,69 +0,0 @@
-import * as FileSystem from 'expo-file-system';
-import { Asset } from 'expo-asset';
-import { API_HOST } from 'src/constants';
-import axios from 'axios';
-import NetInfo from '@react-native-community/netinfo';
-import staticMQP from '../../../assets/geojson/mqp.json';
-
-const jsonFileName = 'mqp.json';
-const jsonFileUri = `${FileSystem.documentDirectory}${jsonFileName}`;
-
-let jsonData: any = null;
-
-const fetchLocalJsonData = async () => {
-  try {
-    const fileInfo = await FileSystem.getInfoAsync(jsonFileUri);
-    if (fileInfo.exists) {
-      const json = await FileSystem.readAsStringAsync(jsonFileUri);
-      return JSON.parse(json);
-    } else {
-      return staticMQP;
-    }
-  } catch (error) {
-    console.error('Failed to load local JSON data:', error);
-    return null;
-  }
-};
-
-const saveJsonDataToLocal = async (data: any) => {
-  try {
-    await FileSystem.writeAsStringAsync(jsonFileUri, JSON.stringify(data));
-  } catch (error) {
-    console.error('Failed to save JSON data to local storage:', error);
-  }
-};
-
-export const fetchJsonData = async () => {
-  const state = await NetInfo.fetch();
-  if (jsonData) {
-    return jsonData;
-  } else if (state.type === 'cellular') {
-    jsonData = await fetchLocalJsonData();
-    return jsonData;
-  }
-
-  try {
-    const response = await axios.get(`${API_HOST}/static/json/mqp.geojson`);
-    if (response.status !== 200) {
-      console.error('Network response error');
-    }
-    jsonData = response.data;
-    await saveJsonDataToLocal(jsonData);
-  } catch (error) {
-    console.error('Failed to fetch JSON data from server:', error);
-    jsonData = await fetchLocalJsonData();
-  }
-
-  return jsonData;
-};
-
-export const refreshJsonData = async () => {
-  jsonData = null;
-  return await fetchJsonData();
-};
-
-(async () => {
-  jsonData = await fetchJsonData();
-})();
-
-export default jsonData;

+ 2 - 5
src/database/index.ts

@@ -2,7 +2,7 @@ import * as SQLite from 'expo-sqlite/legacy';
 import NetInfo, { NetInfoState } from '@react-native-community/netinfo';
 import { StoreType, storage } from 'src/storage';
 import { fetchLimitedRanking, fetchLpi, fetchInHistory, fetchInMemoriam } from '@api/ranking';
-import { initTilesDownload } from './tilesService';
+import { initOfflineSetup } from './tilesService';
 import { downloadFlags } from './flagsService';
 import { fetchAndSaveAllTypesAndMasters } from './unMastersService';
 import { updateAvatars } from './avatarsService';
@@ -10,7 +10,6 @@ import { fetchAndSaveStatistics } from './statisticsService';
 import { saveTriumphsData } from './triumphsService';
 import { saveSeriesRankingData } from './seriesRankingService';
 import { updateDarePlacesDb, updateNmRegionsDb } from 'src/db';
-import { refreshJsonData } from './geojsonService';
 
 const db = SQLite.openDatabase('nomadManiaDb.db');
 const lastUpdateDate = storage.get('lastUpdateDate', StoreType.STRING) as string || '1990-01-01';
@@ -39,19 +38,17 @@ export const checkInternetConnection = async (): Promise<NetInfoState> => {
 };
 
 export const syncDataWithServer = async (): Promise<void> => {
-  const userId = storage.get('uid', StoreType.STRING) as string;
   const { isConnected } = await checkInternetConnection();
 
   if (isConnected) {
     console.log('Syncing data with server...');
     processSyncQueue();
-    await refreshJsonData();
     await updateMasterRanking();
     await downloadFlags();
     await updateAvatars(lastUpdateDate);
     await updateNmRegionsDb(lastUpdateNmRegions);
     await updateDarePlacesDb(lastUpdateDarePlaces);
-    await initTilesDownload(userId);
+    await initOfflineSetup();
   }
 };
 

+ 48 - 58
src/database/tilesService/index.ts

@@ -1,73 +1,63 @@
-import * as FileSystem  from 'expo-file-system';
-import { FASTEST_MAP_HOST } from 'src/constants';
+import * as FileSystem from 'expo-file-system';
+import MapLibreGL from '@maplibre/maplibre-react-native';
 
-const baseTilesDir = `${FileSystem.cacheDirectory}tiles/`;
-
-interface TileType {
-  url: string;
-  type: string;
-  maxZoom: number;
-}
+import { API_HOST, FASTEST_MAP_HOST } from 'src/constants';
 
-async function ensureDirExists(dirPath: string): Promise<void> {
-  const dirInfo = await FileSystem.getInfoAsync(dirPath);
-
-  if (!dirInfo.exists) {
-    await FileSystem.makeDirectoryAsync(dirPath, { intermediates: true });
-  }
-}
+const baseTilesDir = `${FileSystem.cacheDirectory}tiles/`;
+const STYLE_URL = `${API_HOST}/omt/app.json`;
+const PACK_NAME = 'global-map-pack';
 
-async function downloadTile(z: number, x: number, y: number, tile: TileType): Promise<void> {
+async function deleteCachedTilesIfExist(): Promise<void> {
   try {
-    const tileUrl = `${FASTEST_MAP_HOST}${tile.url}/${z}/${x}/${y}`;
-    const filePath = `${baseTilesDir}${tile.type}/${z}/${x}/${y}`;
-    await FileSystem.downloadAsync(tileUrl, filePath);
-
+    const dirInfo = await FileSystem.getInfoAsync(baseTilesDir, { size: true });
+    if (dirInfo.exists) {
+      await FileSystem.deleteAsync(baseTilesDir, { idempotent: true });
+    }
   } catch (error) {
-    console.error(`Error downloading tile ${z}/${x}/${y} for ${tile.type}:`, error);
+    console.error('Error deleting cached tiles:', error);
   }
 }
 
-async function checkTilesExistence(tileType: TileType): Promise<boolean> {
-  const dirPath = `${baseTilesDir}${tileType.type}/`;
-  const MIN_SIZE_BYTES = 1024 * 512;
+async function setupOfflineRegion(): Promise<void> {
   try {
-    const fileInfo = await FileSystem.getInfoAsync(dirPath, { size: true });
-
-    return fileInfo.exists && fileInfo.size < MIN_SIZE_BYTES;
-  } catch (error) {
-    console.error(`Error fetching directory size: ${dirPath}:`, error);
-    return true;
-  }
-}
-
-async function downloadTiles(tileType: TileType): Promise<void> {
-  await ensureDirExists(`${baseTilesDir}${tileType.type}/`);
-  const tilesExist = await checkTilesExistence(tileType);
-
-  if (tilesExist) {
-    for (let z = 2; z <= tileType.maxZoom; z++) {
-      const maxTile = Math.pow(2, z);
-
-      for (let x = 0; x < maxTile; x++) {
-        const dirPath = `${baseTilesDir}${tileType.type}/${z}/${x}`;
-        await ensureDirExists(dirPath);
-
-        for (let y = 0; y <= maxTile; y++) {
-          await downloadTile(z, x, y, tileType);
-        }
+    const bounds: [GeoJSON.Position, GeoJSON.Position] = [
+      [-180, -85],
+      [180, 85]
+    ];
+    const minZoom = 0;
+    const maxZoom = 6;
+
+    const existingPacks = await MapLibreGL.offlineManager.getPacks();
+    const pack = existingPacks.find((pack) => pack.name === PACK_NAME);
+
+    if (pack) {
+      const status = await pack.status();
+      if (status.percentage < 100) {
+        pack.resume();
       }
+    } else {
+      await MapLibreGL.offlineManager.createPack(
+        {
+          name: PACK_NAME,
+          bounds,
+          minZoom,
+          maxZoom,
+          styleURL: STYLE_URL
+        },
+        (offlineRegion, status) => {},
+        (error) => {
+          if (error) {
+            console.error('Error creating offline pack:', error);
+          }
+        }
+      );
     }
+  } catch (error) {
+    console.error('Error setting up offline pack:', error);
   }
 }
 
-export async function initTilesDownload(userId: string): Promise<void> {
-  let tileTypes: TileType[] = [
-    {url: '/tiles_osm', type: 'background', maxZoom: 5},
-    {url: '/tiles_nm/grid', type: 'grid', maxZoom: 4}
-  ];
-
-  for (const type of tileTypes) {
-    await downloadTiles(type);
-  }
+export async function initOfflineSetup(): Promise<void> {
+  await deleteCachedTilesIfExist();
+  await setupOfflineRegion();
 }

+ 11 - 1
src/modules/api/countries/countries-api.tsx

@@ -99,6 +99,15 @@ export interface PostGetUserDataReturn extends ResponseType {
   };
 }
 
+export interface PostGetListCountriesReturn extends ResponseType {
+  data: {
+    id: number;
+    name: string;
+    bbox: any;
+    flag: string;
+  }[];
+}
+
 export const countriesApi = {
   getSlow: (token: string) => request.postForm<PostGetSlowReturn>(API.GET_SLOW, { token }),
   setSlow: (data: PostSetSlow) => request.postForm<ResponseType>(API.SET_SLOW, data),
@@ -126,5 +135,6 @@ export const countriesApi = {
       country
     }),
   getCountryUserData: (id: number, token: string) =>
-    request.postForm<PostGetUserDataReturn>(API.GET_COUNTRY_USER_DATA, { id, token })
+    request.postForm<PostGetUserDataReturn>(API.GET_COUNTRY_USER_DATA, { id, token }),
+  getListCountries: () => request.postForm<PostGetListCountriesReturn>(API.GET_LIST_COUNTRIES)
 };

+ 2 - 1
src/modules/api/countries/countries-query-keys.tsx

@@ -4,5 +4,6 @@ export const countriesQueryKeys = {
   getCountryData: (id: number, token?: string) => ['getCountryData', id, token] as const,
   getUsersFromCountry: () => ['getUsersFromCountry'] as const,
   getUsersWhoVisitedCountry: () => ['getUsersWhoVisitedCountry'] as const,
-  getCountryUserData: () => ['getCountryUserData'] as const
+  getCountryUserData: () => ['getCountryUserData'] as const,
+  getListCountries: () => ['getListCountries'] as const
 };

+ 1 - 0
src/modules/api/countries/queries/index.ts

@@ -4,3 +4,4 @@ export * from './use-post-get-country-screen-data';
 export * from './use-post-get-users-from-country';
 export * from './use-post-get-users-who-visited-country';
 export * from './use-post-get-user-data-country-app';
+export * from './use-get-list-countries';

+ 17 - 0
src/modules/api/countries/queries/use-get-list-countries.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { countriesQueryKeys } from '../countries-query-keys';
+import { countriesApi, type PostGetListCountriesReturn } from '../countries-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetListCountriesQuery = (enabled: boolean) => {
+  return useQuery<PostGetListCountriesReturn, BaseAxiosError>({
+    queryKey: countriesQueryKeys.getListCountries(),
+    queryFn: async () => {
+      const response = await countriesApi.getListCountries();
+      return response.data;
+    },
+    enabled
+  });
+};

+ 3 - 0
src/modules/api/maps/index.ts

@@ -0,0 +1,3 @@
+export * from './queries';
+export * from './maps-api';
+export * from './maps-query-keys';

+ 16 - 0
src/modules/api/maps/maps-api.ts

@@ -0,0 +1,16 @@
+import { request } from '../../../utils';
+import { API } from '../../../types';
+import { ResponseType } from '../response-type';
+
+export interface PostGetVisitedIds extends ResponseType {
+  ids: number[];
+}
+
+export const mapsApi = {
+  getVisitedRegionsIds: (token: string, type: 'in' | 'by', year: number, uid: number) =>
+    request.postForm<PostGetVisitedIds>(API.GET_VISITED_REGIONS_IDS, { token, type, year, uid }),
+  getVisitedCountriesIds: (token: string, type: 'in' | 'by', year: number, uid: number) =>
+    request.postForm<PostGetVisitedIds>(API.GET_VISITED_COUNTRIES_IDS, { token, type, year, uid }),
+  getVisitedDareIds: (token: string, uid: number) =>
+    request.postForm<PostGetVisitedIds>(API.GET_VISITED_DARE_IDS, { token, uid })
+};

+ 17 - 0
src/modules/api/maps/maps-query-keys.tsx

@@ -0,0 +1,17 @@
+export const mapsQueryKeys = {
+  getVisitedRegionsIds: (token: string, type: 'in' | 'by', year: number, uid: number) => [
+    'getVisitedRegionsIds',
+    token,
+    type,
+    year,
+    uid
+  ],
+  getVisitedCountriesIds: (token: string, type: 'in' | 'by', year: number, uid: number) => [
+    'getVisitedCountriesIds',
+    token,
+    type,
+    year,
+    uid
+  ],
+  getVisitedDareIds: (token: string, uid: number) => ['getVisitedDareIds', token, uid]
+};

+ 3 - 0
src/modules/api/maps/queries/index.ts

@@ -0,0 +1,3 @@
+export * from './use-post-get-visited-regions-ids';
+export * from './use-post-get-visited-countries-ids';
+export * from './use-post-get-visited-dare-ids';

+ 23 - 0
src/modules/api/maps/queries/use-post-get-visited-countries-ids.tsx

@@ -0,0 +1,23 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { mapsQueryKeys } from '../maps-query-keys';
+import { mapsApi, type PostGetVisitedIds } from '../maps-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetVisitedCountriesIdsQuery = (
+  token: string,
+  type: 'in' | 'by',
+  year: number,
+  uid: number,
+  enabled: boolean
+) => {
+  return useQuery<PostGetVisitedIds, BaseAxiosError>({
+    queryKey: mapsQueryKeys.getVisitedCountriesIds(token, type, year, uid),
+    queryFn: async () => {
+      const response = await mapsApi.getVisitedCountriesIds(token, type, year, uid);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 17 - 0
src/modules/api/maps/queries/use-post-get-visited-dare-ids.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { mapsQueryKeys } from '../maps-query-keys';
+import { mapsApi, type PostGetVisitedIds } from '../maps-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetVisitedDareIdsQuery = (token: string, uid: number, enabled: boolean) => {
+  return useQuery<PostGetVisitedIds, BaseAxiosError>({
+    queryKey: mapsQueryKeys.getVisitedDareIds(token, uid),
+    queryFn: async () => {
+      const response = await mapsApi.getVisitedDareIds(token, uid);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 23 - 0
src/modules/api/maps/queries/use-post-get-visited-regions-ids.tsx

@@ -0,0 +1,23 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { mapsQueryKeys } from '../maps-query-keys';
+import { mapsApi, type PostGetVisitedIds } from '../maps-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetVisitedRegionsIdsQuery = (
+  token: string,
+  type: 'in' | 'by',
+  year: number,
+  uid: number,
+  enabled: boolean
+) => {
+  return useQuery<PostGetVisitedIds, BaseAxiosError>({
+    queryKey: mapsQueryKeys.getVisitedRegionsIds(token, type, year, uid),
+    queryFn: async () => {
+      const response = await mapsApi.getVisitedRegionsIds(token, type, year, uid);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 11 - 1
src/modules/api/myDARE/dare-api.tsx

@@ -28,11 +28,21 @@ export interface PostSetDARERegion {
   visits: 0 | 1;
 }
 
+export interface PostGetListDareReturn extends ResponseType {
+  data: {
+    id: number;
+    name: string;
+    bbox: any;
+    flag: string;
+  }[];
+}
+
 export const dareApi = {
   getMegaregionsDare: (token: string) =>
     request.postForm<PostGetMegaReturn>(API.GET_MEGAREGIONS_DARE, { token }),
   getRegionsDare: (megaregion: number, token: string) =>
     request.postForm<PostGetRegionsDAREReturn>(API.GET_REGIONS_DARE, { megaregion, token }),
   setDARERegion: (data: PostSetDARERegion) =>
-    request.postForm<ResponseType>(API.SET_DARE_REGION, data)
+    request.postForm<ResponseType>(API.SET_DARE_REGION, data),
+  getListDare: () => request.postForm<PostGetListDareReturn>(API.GET_LIST_DARE)
 };

+ 2 - 1
src/modules/api/myDARE/dare-query-keys.tsx

@@ -2,5 +2,6 @@ export const dareQueryKeys = {
   getMegaregionsDare: (token: string) => ['getMegaregionsDare', { token }] as const,
   getRegionsDare: (megaregion: number, token: string) =>
     ['getRegionsDare', { megaregion, token }] as const,
-  setDARERegion: () => ['setDARERegion'] as const
+  setDARERegion: () => ['setDARERegion'] as const,
+  getListDare: () => ['getListDare'] as const
 };

+ 1 - 0
src/modules/api/myDARE/queries/index.ts

@@ -1,3 +1,4 @@
 export * from './use-post-get-megaregions-dare';
 export * from './use-post-get-regions-dare';
 export * from './use-post-set-update-dare';
+export * from './use-get-list-dare';

+ 17 - 0
src/modules/api/myDARE/queries/use-get-list-dare.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { dareQueryKeys } from '../dare-query-keys';
+import { dareApi, type PostGetListDareReturn } from '../dare-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetListDareQuery = (enabled: boolean) => {
+  return useQuery<PostGetListDareReturn, BaseAxiosError>({
+    queryKey: dareQueryKeys.getListDare(),
+    queryFn: async () => {
+      const response = await dareApi.getListDare();
+      return response.data;
+    },
+    enabled
+  });
+};

+ 1 - 0
src/modules/api/regions/queries/index.ts

@@ -6,3 +6,4 @@ export * from './use-post-get-dare-region-data';
 export * from './use-post-get-users-from-region';
 export * from './use-post-get-users-who-visited-region';
 export * from './use-post-get-users-who-visited-dare';
+export * from './use-get-list-regions';

+ 17 - 0
src/modules/api/regions/queries/use-get-list-regions.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { regionQueryKeys } from '../regions-query-keys';
+import { regionsApi, type PostGetListRegionsReturn } from '../regions-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetListRegionsQuery = (enabled: boolean) => {
+  return useQuery<PostGetListRegionsReturn, BaseAxiosError>({
+    queryKey: regionQueryKeys.getListRegions(),
+    queryFn: async () => {
+      const response = await regionsApi.getListRegions();
+      return response.data;
+    },
+    enabled
+  });
+};

+ 13 - 1
src/modules/api/regions/regions-api.tsx

@@ -11,11 +11,13 @@ export interface PostGetUserDataReturn extends ResponseType {
   last_visit_year: boolean;
   no_of_visits: number;
   best_visit_quality: number;
+  bbox: any;
 }
 
 export interface PostGetUserDataDareReturn extends ResponseType {
   visited: boolean;
   first_visit_year: boolean;
+  bbox: any;
 }
 
 export interface PostGetRegionDataReturn extends ResponseType {
@@ -127,6 +129,15 @@ export interface PostGetUsersWhoVisitedDataReturn extends ResponseType {
   };
 }
 
+export interface PostGetListRegionsReturn extends ResponseType {
+  data: {
+    id: number;
+    name: string;
+    bbox: any;
+    flag: string;
+  }[];
+}
+
 export const regionsApi = {
   getRegionsWithFlag: () => request.postForm<PostGetRegionsReturn>(API.GET_REGIONS_WITH_FLAGS),
   getUserData: (region_id: number, token: string) =>
@@ -171,5 +182,6 @@ export const regionsApi = {
       sort,
       age,
       country
-    })
+    }),
+  getListRegions: () => request.postForm<PostGetListRegionsReturn>(API.GET_LIST_REGIONS)
 };

+ 2 - 1
src/modules/api/regions/regions-query-keys.tsx

@@ -6,5 +6,6 @@ export const regionQueryKeys = {
   getDareRegionData: (id: number, token?: string) => ['getNmRegionData', id, token] as const,
   getUsersFromRegion: () => ['getUsersFromRegion'] as const,
   getUsersWhoVisitedRegion: () => ['getUsersWhoVisitedRegion'] as const,
-  getUsersWhoVisitedDare: () => ['getUsersWhoVisitedDare'] as const
+  getUsersWhoVisitedDare: () => ['getUsersWhoVisitedDare'] as const,
+  getListRegions: () => ['getListRegions'] as const
 };

+ 25 - 11
src/screens/InAppScreens/MapScreen/FilterModal/index.tsx

@@ -21,10 +21,9 @@ const FilterModal = ({
   tilesTypes,
   tilesType,
   setTilesType,
-  type,
   setType,
   userId,
-  setVisitedTiles,
+  setRegionsFilter,
   setSeriesFilter,
   isPublicView,
   isLogged = true
@@ -34,10 +33,9 @@ const FilterModal = ({
   tilesTypes: any[];
   tilesType: any;
   setTilesType: (item: any) => void;
-  type: number;
   setType: (type: any) => void;
   userId: number;
-  setVisitedTiles: (tiles: string) => void;
+  setRegionsFilter: (data: { visitedLabel: 'in' | 'by'; year: number }) => void;
   setSeriesFilter?: (filter: any) => void;
   isPublicView: boolean;
   isLogged: boolean;
@@ -91,7 +89,7 @@ const FilterModal = ({
     if (isLogged && !isPublicView) {
       try {
         const filterSettings = {
-          type: tilesType.value,
+          type: tilesType.value === 2 ? 'dare' : tilesType.value === 1 ? 'countries' : 'regions',
           tilesType,
           selectedYear,
           selectedVisible,
@@ -150,28 +148,42 @@ const FilterModal = ({
         tileUrl += 'user_visited_dare/' + userId;
       }
       !isPublicView && storage.set('visitedTilesUrl', tileUrl);
-      setVisitedTiles(tileUrl);
       return;
     }
     if (selectedVisible.value === 0) {
       if (tilesType.value === 0) {
         tileUrl += 'user_visited_year/' + userId + '/' + selectedYear.value;
+        setRegionsFilter({
+          visitedLabel: 'by',
+          year: selectedYear.value
+        });
       } else if (tilesType.value === 1) {
         tileUrl += 'user_visited_un_year/' + userId + '/' + selectedYear.value;
+        setRegionsFilter({
+          visitedLabel: 'by',
+          year: selectedYear.value
+        });
       } else {
         tileUrl += 'user_visited_dare/' + userId;
       }
     } else {
       if (tilesType.value === 0) {
         tileUrl += 'user_visited_in_year/' + userId + '/' + selectedYear.value;
+        setRegionsFilter({
+          visitedLabel: 'in',
+          year: selectedYear.value
+        });
       } else if (tilesType.value === 1) {
         tileUrl += 'user_visited_un_in_year/' + userId + '/' + selectedYear.value;
+        setRegionsFilter({
+          visitedLabel: 'in',
+          year: selectedYear.value
+        });
       } else {
         tileUrl += 'user_visited_dare/' + userId;
       }
     }
     !isPublicView && storage.set('visitedTilesUrl', tileUrl);
-    setVisitedTiles(tileUrl);
   };
 
   const handleCloseFilter = () => {
@@ -246,7 +258,9 @@ const FilterModal = ({
             onPress={() => {
               saveFilterSettings();
               handleApplyFilter();
-              setType(tilesType.value);
+              setType(
+                tilesType.value === 2 ? 'dare' : tilesType.value === 1 ? 'countries' : 'regions'
+              );
               handleCloseFilter();
             }}
           />
@@ -256,13 +270,13 @@ const FilterModal = ({
               setTilesType({ label: 'NM regions', value: 0 });
               setSelectedYear(allYears[0]);
               setSelectedVisible({ label: 'visited by', value: 0 });
-              setVisitedTiles(`${FASTEST_MAP_HOST}/tiles_nm/user_visited/${userId}`);
-              setType(0);
+              setRegionsFilter({ visitedLabel: 'by', year: allYears[0].value });
+              setType('regions');
               if (!isPublicView && isLogged) {
                 storage.set(
                   'filterSettings',
                   JSON.stringify({
-                    type: 0,
+                    type: 'regions',
                     tilesType: { label: 'NM regions', value: 0 },
                     selectedYear: allYears[0],
                     selectedVisible: { label: 'visited by', value: 0 },

+ 6 - 6
src/screens/InAppScreens/MapScreen/UniversalSearch/index.tsx

@@ -23,7 +23,7 @@ const SearchModal = ({
 }: {
   searchVisible: boolean;
   handleCloseModal: () => void;
-  handleFindRegion: (id: number, type: string) => void;
+  handleFindRegion: (id: number, type: 'regions' | 'countries' | 'places') => void;
   index: number;
   searchData: any;
   setIndex: (index: number) => void;
@@ -35,7 +35,10 @@ const SearchModal = ({
     { key: 'regions', title: 'NM regions' },
     { key: 'dare', title: 'DARE places' }
   ]);
-  const [shouldOpenModal, setShouldOpenModal] = useState<{ id: number; type: string } | null>(null);
+  const [shouldOpenModal, setShouldOpenModal] = useState<{
+    id: number;
+    type: 'regions' | 'countries' | 'places';
+  } | null>(null);
   const [warningVisible, setWarningVisible] = useState(false);
 
   const renderItem = ({ item }: { item: any }) => {
@@ -51,10 +54,7 @@ const SearchModal = ({
           } else {
             handleCloseModal();
             navigation.navigate(
-              ...([
-                NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW,
-                { userId: item.id }
-              ] as never)
+              ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
             );
           }
         }}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 535 - 419
src/screens/InAppScreens/MapScreen/index.tsx


+ 109 - 52
src/screens/InAppScreens/MapScreen/style.tsx

@@ -1,16 +1,39 @@
-import { StyleSheet, Platform, Dimensions } from 'react-native';
-import { Colors } from '../../../theme';
-import { getFontSize } from 'src/utils';
+import { StyleSheet, Platform } from 'react-native';
+import { Colors } from 'src/theme';
 
 export const styles = StyleSheet.create({
   container: {
-    ...StyleSheet.absoluteFillObject,
-    alignItems: 'center',
-    justifyContent: 'flex-end',
-    paddingTop: 0
+    flex: 1
+  },
+  wrapper: {
+    marginLeft: '5%',
+    marginRight: '5%',
+    alignItems: 'center'
   },
   map: {
-    ...StyleSheet.absoluteFillObject,
+    ...StyleSheet.absoluteFillObject
+  },
+  topRightButton: {
+    top: 52,
+    right: 16
+  },
+  bottomButton: {
+    bottom: Platform.OS == 'android' ? 80 : 100,
+    width: 42,
+    height: 42,
+    borderRadius: 21
+  },
+  bottomLeftButton: {
+    left: 16
+  },
+  bottomRightButton: {
+    right: 16
+  },
+  textClose: {
+    fontSize: 12,
+    color: 'white',
+    fontWeight: '500',
+    lineHeight: 14
   },
   cornerButton: {
     position: 'absolute',
@@ -24,11 +47,11 @@ export const styles = StyleSheet.create({
     shadowColor: 'rgba(33, 37, 41, 0.12)',
     shadowOffset: { width: 0, height: 4 },
     shadowRadius: 8,
-    elevation: 5,
+    elevation: 5
   },
   topLeftButton: {
     top: 52,
-    left: 16,
+    left: 16
   },
   closeLeftButton: {
     backgroundColor: 'rgba(33, 37, 41, 0.78)',
@@ -38,44 +61,14 @@ export const styles = StyleSheet.create({
     height: 36,
     borderRadius: 18,
     flexDirection: 'row',
-    gap: 6,
+    gap: 6
   },
-  topRightButton: {
-    top: 52,
-    right: 16,
-  },
-  bottomButton: {
-    bottom: Platform.OS == 'android' ? 80 : 100,
-    width: 42,
-    height: 42,
-    borderRadius: 21,
-  },
-  bottomLeftButton: {
-    left: 16,
-  },
-  bottomRightButton: {
-    right: 16,
-  },
-  textClose: {
-    fontSize: 12,
-    color: 'white',
-    fontWeight: '500',
-    lineHeight: 14,
-  },
-  location: {
-    width: 18,
-    height: 18,
-    borderRadius: 9,
-    borderColor: 'white',
-    backgroundColor: '#ED9334',
-    shadowColor: "#212529",
-    shadowOffset: {
-      width: 0,
-      height: 4,
-    },
-    shadowOpacity: 0.12,
-    shadowRadius: 8,
-    elevation: 5,
+  avatar: {
+    borderRadius: 48 / 2,
+    width: 48,
+    height: 48,
+    borderWidth: 2,
+    borderColor: Colors.WHITE
   },
   searchContainer: {
     flexDirection: 'row',
@@ -91,11 +84,75 @@ export const styles = StyleSheet.create({
     color: Colors.DARK_BLUE,
     fontWeight: '600'
   },
-  avatar: {
-    borderRadius: 48 / 2,
-    width: 48,
-    height: 48,
+  customView: {
+    width: 200,
+    backgroundColor: 'white',
+    borderRadius: 8,
+    shadowColor: '#212529',
+    shadowOffset: { width: 0, height: 4 },
+    shadowOpacity: 0.12,
+    shadowRadius: 8,
+    elevation: 5
+  },
+  calloutContainer: {
+    alignItems: 'center',
+    paddingVertical: 15,
+    paddingHorizontal: 10
+  },
+  calloutImageContainer: {
+    width: 38,
+    height: 38,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: Colors.WHITE,
+    borderRadius: 19,
     borderWidth: 2,
-    borderColor: Colors.WHITE
+    borderColor: Colors.TEXT_GRAY,
+    marginTop: -34
   },
+  calloutImage: {
+    width: 28,
+    height: 28
+  },
+  calloutTextContainer: {
+    flex: 1,
+    gap: 4,
+    alignItems: 'center',
+    marginVertical: 10
+  },
+  seriesName: {
+    fontSize: 13,
+    fontWeight: 'bold',
+    color: Colors.DARK_BLUE,
+    textAlign: 'center'
+  },
+  markerName: {
+    fontSize: 12,
+    color: Colors.DARK_BLUE,
+    textAlign: 'center'
+  },
+  calloutButton: {
+    paddingHorizontal: 12,
+    paddingVertical: 6,
+    backgroundColor: Colors.ORANGE,
+    borderRadius: 6,
+    height: 30,
+    alignItems: 'center',
+    justifyContent: 'center'
+  },
+  calloutButtonText: {
+    color: 'white',
+    fontSize: 12,
+    fontWeight: 'bold'
+  },
+  completedContainer: { flexDirection: 'row', alignItems: 'center', gap: 6 },
+  customCallout: {
+    width: 200,
+    backgroundColor: Colors.WHITE,
+    shadowColor: '#212529',
+    shadowOffset: { width: 0, height: 4 },
+    shadowOpacity: 0.12,
+    shadowRadius: 8,
+    elevation: 5
+  }
 });

+ 228 - 73
src/screens/InAppScreens/ProfileScreen/UsersMap/index.tsx

@@ -1,15 +1,13 @@
 import {
   Platform,
   TouchableOpacity,
-  View,
   Image,
-  Animated as Animation,
   Linking,
   TextInput,
-  Dimensions
+  Dimensions,
+  StatusBar
 } from 'react-native';
 import React, { FC, useEffect, useRef, useState } from 'react';
-import MapView, { UrlTile, Marker } from 'react-native-maps';
 import * as Location from 'expo-location';
 import Animated, {
   Easing,
@@ -34,8 +32,101 @@ import SearchModal from '../../MapScreen/UniversalSearch';
 import { useGetUniversalSearch } from '@api/search';
 import { storage, StoreType } from 'src/storage';
 import { NAVIGATION_PAGES } from 'src/types';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import MapLibreGL, { CameraRef, MapViewRef } from '@maplibre/maplibre-react-native';
+import {
+  usePostGetVisitedCountriesIdsQuery,
+  usePostGetVisitedDareIdsQuery,
+  usePostGetVisitedRegionsIdsQuery
+} from '@api/maps';
+import moment from 'moment';
+
+MapLibreGL.setAccessToken(null);
+
+const generateFilter = (ids: number[]) => {
+  return ids.length ? ['any', ...ids.map((id) => ['==', 'id', id])] : ['==', 'id', -1];
+};
 
-const AnimatedMarker = Animation.createAnimatedComponent(Marker);
+let regions_visited = {
+  id: 'regions_visited',
+  type: 'fill',
+  source: 'regions',
+  'source-layer': 'regions',
+  style: {
+    fillColor: 'rgba(255, 126, 0, 1)',
+    fillOpacity: 0.5,
+    fillOutlineColor: 'rgba(14, 80, 109, 1)'
+  },
+  filter: generateFilter([]),
+  maxzoom: 12
+};
+
+let countries_visited = {
+  id: 'countries_visited',
+  type: 'fill',
+  source: 'countries',
+  'source-layer': 'countries',
+  style: {
+    fillColor: 'rgba(255, 126, 0, 1)',
+    fillOpacity: 0.5,
+    fillOutlineColor: 'rgba(14, 80, 109, 1)'
+  },
+  filter: generateFilter([]),
+  maxzoom: 12
+};
+
+let dare_visited = {
+  id: 'dare_visited',
+  type: 'fill',
+  source: 'dare',
+  'source-layer': 'dare',
+  style: {
+    fillColor: 'rgba(255, 126, 0, 1)',
+    fillOpacity: 0.5,
+    fillOutlineColor: 'rgba(255, 126, 0, 1)'
+  },
+  filter: generateFilter([]),
+  maxzoom: 12
+};
+
+let regions = {
+  id: 'regions',
+  type: 'fill',
+  source: 'regions',
+  'source-layer': 'regions',
+  style: {
+    fillColor: 'rgba(15, 63, 79, 0)',
+    fillOutlineColor: 'rgba(14, 80, 109, 1)'
+  },
+  filter: ['all'],
+  maxzoom: 16
+};
+
+let countries = {
+  id: 'countries',
+  type: 'fill',
+  source: 'countries',
+  'source-layer': 'countries',
+  style: {
+    fillColor: 'rgba(15, 63, 79, 0)',
+    fillOutlineColor: 'rgba(14, 80, 109, 1)'
+  },
+  filter: ['all'],
+  maxzoom: 16
+};
+
+let dare = {
+  id: 'dare',
+  type: 'fill',
+  source: 'dare',
+  'source-layer': 'dare',
+  style: {
+    fillColor: 'rgba(14, 80, 109, 0.6)',
+    fillOutlineColor: 'rgba(14, 80, 109, 1)'
+  },
+  filter: ['all'],
+  maxzoom: 16
+};
 
 type Props = {
   navigation: NavigationProp<any>;
@@ -47,12 +138,17 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
   const userId = route.params?.userId;
   const data = route.params?.data;
 
-  const tilesBaseURL = `${FASTEST_MAP_HOST}/tiles_osm`;
-  const gridUrl = `${FASTEST_MAP_HOST}/tiles_nm/grid`;
-  const visitedDefaultTiles = `${FASTEST_MAP_HOST}/tiles_nm/user_visited/${userId}`;
+  const [regionsVisitedFilter, setRegionsVisitedFilter] = useState(generateFilter([]));
+  const [countriesVisitedFilter, setCountriesVisitedFilter] = useState(generateFilter([]));
+  const [dareVisitedFilter, setDareVisitedFilter] = useState(generateFilter([]));
+
+  const [regionsFilter, setRegionsFilter] = useState<any>({
+    visitedLabel: 'by',
+    year: moment().year()
+  });
 
-  const mapRef = useRef<MapView>(null);
-  const strokeWidthAnim = useRef(new Animation.Value(2)).current;
+  const mapRef = useRef<MapViewRef>(null);
+  const cameraRef = useRef<CameraRef>(null);
   const [isFilterVisible, setIsFilterVisible] = useState(false);
   const [tilesType, setTilesType] = useState({ label: 'NM regions', value: 0 });
   const tilesTypes = [
@@ -60,8 +156,7 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
     { label: 'UN countries', value: 1 },
     { label: 'DARE places', value: 2 }
   ];
-  const [type, setType] = useState(0);
-  const [visitedTiles, setVisitedTiles] = useState(visitedDefaultTiles);
+  const [type, setType] = useState('regions');
   const [location, setLocation] = useState<Location.LocationObjectCoords | null>(null);
   const [askLocationVisible, setAskLocationVisible] = useState<boolean>(false);
   const [openSettingsVisible, setOpenSettingsVisible] = useState<boolean>(false);
@@ -74,22 +169,43 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
   const [searchInput, setSearchInput] = useState('');
   const { data: searchData } = useGetUniversalSearch(search, search.length > 0);
 
+  const { data: visitedRegionIds } = usePostGetVisitedRegionsIdsQuery(
+    token,
+    regionsFilter.visitedLabel,
+    regionsFilter.year,
+    +userId,
+    type === 'regions' && !!userId
+  );
+  const { data: visitedCountryIds } = usePostGetVisitedCountriesIdsQuery(
+    token,
+    regionsFilter.visitedLabel,
+    regionsFilter.year,
+    +userId,
+    type === 'countries' && !!userId
+  );
+  const { data: visitedDareIds } = usePostGetVisitedDareIdsQuery(
+    token,
+    +userId,
+    type === 'dare' && !!userId
+  );
+
+  useEffect(() => {
+    if (visitedRegionIds) {
+      setRegionsVisitedFilter(generateFilter(visitedRegionIds.ids));
+    }
+  }, [visitedRegionIds]);
+
   useEffect(() => {
-    Animation.loop(
-      Animation.sequence([
-        Animation.timing(strokeWidthAnim, {
-          toValue: 3,
-          duration: 700,
-          useNativeDriver: false
-        }),
-        Animation.timing(strokeWidthAnim, {
-          toValue: 2,
-          duration: 700,
-          useNativeDriver: false
-        })
-      ])
-    ).start();
-  }, [strokeWidthAnim]);
+    if (visitedCountryIds) {
+      setCountriesVisitedFilter(generateFilter(visitedCountryIds.ids));
+    }
+  }, [visitedCountryIds]);
+
+  useEffect(() => {
+    if (visitedDareIds) {
+      setDareVisitedFilter(generateFilter(visitedDareIds.ids));
+    }
+  }, [visitedDareIds]);
 
   const handleGetLocation = async () => {
     let { status, canAskAgain } = await Location.getForegroundPermissionsAsync();
@@ -109,15 +225,12 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
     });
     setLocation(currentLocation.coords);
 
-    mapRef.current?.animateToRegion(
-      {
-        latitude: currentLocation.coords.latitude,
-        longitude: currentLocation.coords.longitude,
-        latitudeDelta: 5,
-        longitudeDelta: 5
-      },
-      800
-    );
+    if (currentLocation.coords) {
+      cameraRef.current?.flyTo(
+        [currentLocation.coords.longitude, currentLocation.coords.latitude],
+        1000
+      );
+    }
   };
 
   const handleAcceptPermission = async () => {
@@ -154,19 +267,6 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
     setSearchVisible(true);
   };
 
-  const renderMapTiles = (url: string, zIndex: number, opacity = 1) => (
-    <UrlTile
-      key={url}
-      urlTemplate={`${url}/{z}/{x}/{y}`}
-      maximumZ={15}
-      maximumNativeZ={13}
-      shouldReplaceMapContent
-      minimumZ={0}
-      opacity={opacity}
-      zIndex={zIndex}
-    />
-  );
-
   const handleGoBack = () => {
     navigation.goBack();
   };
@@ -199,32 +299,88 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
   };
 
   return (
-    <View style={styles.container}>
-      <MapView
-        initialRegion={{
-          latitude: 0,
-          longitude: 0,
-          latitudeDelta: 180,
-          longitudeDelta: 180
-        }}
+    <SafeAreaView style={{ height: '100%' }}>
+      <StatusBar translucent backgroundColor="transparent" />
+
+      <MapLibreGL.MapView
         ref={mapRef}
-        showsMyLocationButton={false}
-        showsCompass={false}
-        zoomControlEnabled={false}
         style={styles.map}
-        mapType={Platform.OS == 'android' ? 'none' : 'standard'}
-        maxZoomLevel={15}
-        minZoomLevel={0}
+        styleJSON={API_HOST + '/omt/app.json'}
+        rotateEnabled={false}
+        attributionEnabled={false}
       >
-        {renderMapTiles(tilesBaseURL, 1)}
-        {type === 0 && renderMapTiles(gridUrl, 2)}
-        {userId && renderMapTiles(visitedTiles, 2, 0.5)}
+        {type === 'regions' && (
+          <>
+            <MapLibreGL.FillLayer
+              id={regions.id}
+              sourceID={regions.source}
+              sourceLayerID={regions['source-layer']}
+              filter={regions.filter as any}
+              style={regions.style}
+              maxZoomLevel={regions.maxzoom}
+              belowLayerID={regions_visited.id}
+            />
+            <MapLibreGL.FillLayer
+              id={regions_visited.id}
+              sourceID={regions_visited.source}
+              sourceLayerID={regions_visited['source-layer']}
+              filter={regionsVisitedFilter as any}
+              style={regions_visited.style}
+              maxZoomLevel={regions_visited.maxzoom}
+            />
+          </>
+        )}
+        {type === 'countries' && (
+          <>
+            <MapLibreGL.FillLayer
+              id={countries.id}
+              sourceID={countries.source}
+              sourceLayerID={countries['source-layer']}
+              filter={countries.filter as any}
+              style={countries.style}
+              maxZoomLevel={countries.maxzoom}
+              belowLayerID={countries_visited.id}
+            />
+            <MapLibreGL.FillLayer
+              id={countries_visited.id}
+              sourceID={countries_visited.source}
+              sourceLayerID={countries_visited['source-layer']}
+              filter={countriesVisitedFilter as any}
+              style={countries_visited.style}
+              maxZoomLevel={countries_visited.maxzoom}
+            />
+          </>
+        )}
+        {type === 'dare' && (
+          <>
+            <MapLibreGL.FillLayer
+              id={dare.id}
+              sourceID={dare.source}
+              sourceLayerID={dare['source-layer']}
+              filter={dare.filter as any}
+              style={dare.style}
+              maxZoomLevel={dare.maxzoom}
+              belowLayerID={dare_visited.id}
+            />
+            <MapLibreGL.FillLayer
+              id={dare_visited.id}
+              sourceID={dare_visited.source}
+              sourceLayerID={dare_visited['source-layer']}
+              filter={dareVisitedFilter as any}
+              style={dare_visited.style}
+              maxZoomLevel={dare_visited.maxzoom}
+            />
+          </>
+        )}
+
+        <MapLibreGL.Camera ref={cameraRef} />
         {location && (
-          <AnimatedMarker coordinate={location} anchor={{ x: 0.5, y: 0.5 }}>
-            <Animation.View style={[styles.location, { borderWidth: strokeWidthAnim }]} />
-          </AnimatedMarker>
+          <MapLibreGL.UserLocation
+            animated={true}
+            showsUserHeadingIndicator={true}
+          ></MapLibreGL.UserLocation>
         )}
-      </MapView>
+      </MapLibreGL.MapView>
 
       {!isExpanded ? (
         <TouchableOpacity
@@ -298,10 +454,9 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
         tilesTypes={tilesTypes}
         tilesType={tilesType}
         setTilesType={setTilesType}
-        type={type}
         setType={setType}
         userId={userId}
-        setVisitedTiles={setVisitedTiles}
+        setRegionsFilter={setRegionsFilter}
         isPublicView={true}
         isLogged={true}
       />
@@ -328,7 +483,7 @@ const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
         setIndex={setIndex}
         token={token}
       />
-    </View>
+    </SafeAreaView>
   );
 };
 

+ 17 - 3
src/types/api.ts

@@ -22,7 +22,9 @@ export enum API_ROUTE {
   COUNTRIES = 'countries',
   FIXERS = 'fixers',
   NOTIFICATIONS = 'notifications',
-  CHAT = 'chat'
+  CHAT = 'chat',
+  MAPS = 'maps',
+  DARE = 'dare',
 }
 
 export enum API_ENDPOINT {
@@ -140,7 +142,13 @@ export enum API_ENDPOINT {
   DELETE_CHAT = 'delete-conversation',
   UNREACT_TO_MESSAGE = 'unreact-to-message',
   GET_BLOCKED = 'get-blocked',
-  GET_UNREAD_MESSAGES_PRESENT = 'new-messages-present'
+  GET_UNREAD_MESSAGES_PRESENT = 'new-messages-present',
+  GET_VISITED_REGIONS_IDS = 'get-visited-regions-ids',
+  GET_VISITED_COUNTRIES_IDS = 'get-visited-countries-ids',
+  GET_VISITED_DARE_IDS = 'get-visited-dare-ids',
+  GET_LIST_REGIONS = 'get-list-regions',
+  GET_LIST_COUNTRIES = 'get-list-countries',
+  GET_LIST_DARE = 'get-list-dare',
 }
 
 export enum API {
@@ -257,7 +265,13 @@ export enum API {
   DELETE_CHAT = `${API_ROUTE.CHAT}/${API_ENDPOINT.DELETE_CHAT}`,
   UNREACT_TO_MESSAGE = `${API_ROUTE.CHAT}/${API_ENDPOINT.UNREACT_TO_MESSAGE}`,
   GET_BLOCKED = `${API_ROUTE.CHAT}/${API_ENDPOINT.GET_BLOCKED}`,
-  GET_UNREAD_MESSAGES_PRESENT = `${API_ROUTE.CHAT}/${API_ENDPOINT.GET_UNREAD_MESSAGES_PRESENT}`
+  GET_UNREAD_MESSAGES_PRESENT = `${API_ROUTE.CHAT}/${API_ENDPOINT.GET_UNREAD_MESSAGES_PRESENT}`,
+  GET_VISITED_REGIONS_IDS = `${API_ROUTE.MAPS}/${API_ENDPOINT.GET_VISITED_REGIONS_IDS}`,
+  GET_VISITED_COUNTRIES_IDS = `${API_ROUTE.MAPS}/${API_ENDPOINT.GET_VISITED_COUNTRIES_IDS}`,
+  GET_VISITED_DARE_IDS = `${API_ROUTE.MAPS}/${API_ENDPOINT.GET_VISITED_DARE_IDS}`,
+  GET_LIST_REGIONS = `${API_ROUTE.REGIONS}/${API_ENDPOINT.GET_LIST_REGIONS}`,
+  GET_LIST_COUNTRIES = `${API_ROUTE.COUNTRIES}/${API_ENDPOINT.GET_LIST_COUNTRIES}`,
+  GET_LIST_DARE = `${API_ROUTE.DARE}/${API_ENDPOINT.GET_LIST_DARE}`,
 }
 
 export type BaseAxiosError = AxiosError;

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.