('countries');
34 | export const $isCountriesTab = createStore(true);
35 | export const $isSortTab = createStore(false);
36 |
--------------------------------------------------------------------------------
/src/@/dashboard/types.ts:
--------------------------------------------------------------------------------
1 | type ProgressBar = {
2 | width: string;
3 | };
4 |
5 | type MapPreview = {
6 | backgroundImage: string;
7 | };
8 |
9 | export type CountryInfo = {
10 | id: number;
11 | code: string;
12 | flag: string;
13 | name: string;
14 | joinDate: string;
15 | progressPercent: number;
16 | progressBarStyle: ProgressBar;
17 | bubbleProgressClass: string;
18 | progressDescription: string;
19 | mapPreviewStyle: MapPreview;
20 | };
21 |
22 | export type Tabs = 'countries' | 'sort';
23 |
--------------------------------------------------------------------------------
/src/@/dashboard/ui/index.ts:
--------------------------------------------------------------------------------
1 | export { Dashboard } from './dashboard';
2 |
--------------------------------------------------------------------------------
/src/@/dashboard/ui/search-sort-results.tsx:
--------------------------------------------------------------------------------
1 | import { useStore } from 'effector-react';
2 | import React from 'react';
3 |
4 | import { getInverted } from '~/lib/effector-kit';
5 |
6 | import {
7 | $isPopupOpen,
8 | $noSearchResults,
9 | changePopupStatus,
10 | } from '@/dashboard/model';
11 |
12 | import { CountryList } from './country-list';
13 | import { CountryPopupDetails } from './county-popup';
14 |
15 | export const NotFound = () => Countries not found
;
16 | // View
17 | const onChangeView = changePopupStatus.prepend(getInverted);
18 |
19 | const CountriesFound = () => {
20 | const isPopupOpen = useStore($isPopupOpen);
21 |
22 | return isPopupOpen ? (
23 |
24 |
31 |
32 |
33 | ) : (
34 |
35 | );
36 | };
37 |
38 | export const SearchResults = () => (
39 | <>{useStore($noSearchResults) ? : }>
40 | );
41 |
--------------------------------------------------------------------------------
/src/@/history-modal/lib/index.ts:
--------------------------------------------------------------------------------
1 | export { getHistoryGraphData } from './get-history-graph-data';
2 |
--------------------------------------------------------------------------------
/src/@/history-modal/model.ts:
--------------------------------------------------------------------------------
1 | import { Interval } from 'date-fns';
2 | import { createEvent, createStore } from 'effector';
3 |
4 | import { DailyStats } from '~/api/types';
5 | import { IntervalUnit } from '~/lib/date-fns-kit/types';
6 |
7 | import { defaultInterval } from '@/sidebar/constants';
8 |
9 | import { StatsDataType } from './types';
10 |
11 | export const changeHistoryDataType = createEvent();
12 | export const closeHistoryModal = createEvent();
13 | export const changeHistoryIntervalUnit = createEvent();
14 | export const nextHistoryInterval = createEvent();
15 | export const previousHistoryInterval = createEvent();
16 |
17 | export const $historyDataType = createStore(null);
18 | export const $isOpenHistoryModal = createStore(false);
19 | export const $historyIntervalUnit = createStore('week');
20 | export const $historyInterval = createStore(defaultInterval);
21 | export const $isCurrentHistoryInterval = createStore(true);
22 | export const $isNextHistoryIntervalAvailable = createStore(false);
23 | export const $isPreviousHistoryIntervalAvailable = createStore(false);
24 | export const $historyData = createStore(null);
25 | export const $historyDataPending = createStore(false);
26 | export const $historyPlaceName = createStore(null);
27 |
--------------------------------------------------------------------------------
/src/@/history-modal/types.ts:
--------------------------------------------------------------------------------
1 | import { ConnectionStatus } from '~/api/types';
2 |
3 | export type StatsDataType = 'country' | 'school';
4 |
5 | export type HistoryGraphData = {
6 | daysData: HistoryGraphItem[];
7 | speedSum: number;
8 | itemsCount: number;
9 | maxSpeed: number;
10 | };
11 |
12 | export type HistoryGraphItem = {
13 | date: string;
14 | speedFormatted?: string;
15 | speed?: number;
16 | status?: ConnectionStatus;
17 | };
18 |
--------------------------------------------------------------------------------
/src/@/history-modal/ui/index.ts:
--------------------------------------------------------------------------------
1 | export { HistoryModal } from './history-modal';
2 |
--------------------------------------------------------------------------------
/src/@/map/effects/add-loader-fx.ts:
--------------------------------------------------------------------------------
1 | import { createEffect } from 'effector';
2 | import mapboxGL from 'mapbox-gl';
3 |
4 | import { setLoader } from '@/map/model';
5 | import { Map } from '@/map/types';
6 |
7 | export const addLoaderToMapFx = createEffect((map: Map | null) => {
8 | if (!map) return;
9 |
10 | // Create loader (should be wrapped in a container)
11 | const loader = document.createElement('div');
12 | loader.className = 'map-loader';
13 | const loaderWrapper = document.createElement('div');
14 | loaderWrapper.append(loader);
15 |
16 | // Add loader
17 | const loaderMarker = new mapboxGL.Marker(loaderWrapper)
18 | .setLngLat(map.getCenter())
19 | .addTo(map);
20 |
21 | // Always display the loader in the center
22 | map.on('zoom', () => {
23 | if (loaderMarker) {
24 | loaderMarker.setLngLat(map.getCenter());
25 | }
26 | });
27 |
28 | map.on('move', () => {
29 | if (loaderMarker) {
30 | loaderMarker.setLngLat(map.getCenter());
31 | }
32 | });
33 |
34 | setLoader(loaderMarker);
35 | });
36 |
--------------------------------------------------------------------------------
/src/@/map/effects/change-style-fx.ts:
--------------------------------------------------------------------------------
1 | import { createEffect } from 'effector';
2 |
3 | import { styleUrls } from '@/map/constants';
4 | import { Map, Style } from '@/map/types';
5 |
6 | export const changeStyleFx = createEffect(
7 | ({ map, style }: { map: Map; style: Style }) => {
8 | map.setStyle(styleUrls[style]);
9 | }
10 | );
11 |
--------------------------------------------------------------------------------
/src/@/map/effects/index.ts:
--------------------------------------------------------------------------------
1 | export { addLoaderToMapFx } from './add-loader-fx';
2 | export { initMapFx } from './init-map-fx';
3 | export { removeLoaderFromMapFx } from './remove-loader-fx';
4 | export { changeStyleFx } from './change-style-fx';
5 |
--------------------------------------------------------------------------------
/src/@/map/effects/init-map-fx.ts:
--------------------------------------------------------------------------------
1 | import { createEffect } from 'effector';
2 | import mapboxGL from 'mapbox-gl';
3 |
4 | import { API_MAPBOX_ACCESS_TOKEN } from '~/env';
5 |
6 | import { defaultCenter, defaultZoom, styleUrls } from '@/map/constants';
7 | import { changeMap, onStyleLoaded } from '@/map/model';
8 | import { InitMapOptions } from '@/map/types';
9 |
10 | export const initMapFx = createEffect(
11 | ({ style, container, center, zoom }: InitMapOptions) => {
12 | mapboxGL.accessToken = API_MAPBOX_ACCESS_TOKEN;
13 |
14 | const map = new mapboxGL.Map({
15 | style: styleUrls[style],
16 | center: center ?? defaultCenter,
17 | zoom: zoom ?? defaultZoom,
18 | container,
19 | });
20 |
21 | map.on('load', () => {
22 | changeMap(map);
23 | });
24 |
25 | map.on('styledata', () => {
26 | onStyleLoaded();
27 | });
28 | }
29 | );
30 |
--------------------------------------------------------------------------------
/src/@/map/effects/remove-loader-fx.ts:
--------------------------------------------------------------------------------
1 | import { createEffect } from 'effector';
2 |
3 | import { Marker } from '@/map/types';
4 |
5 | export const removeLoaderFromMapFx = createEffect((loader: Marker | null) => {
6 | loader?.remove();
7 | });
8 |
--------------------------------------------------------------------------------
/src/@/map/model.ts:
--------------------------------------------------------------------------------
1 | import { createEvent, createStore } from 'effector';
2 |
3 | import { GlobalStats } from '~/api/types';
4 |
5 | import {
6 | defaultGlobalStats,
7 | defaultMapType,
8 | defaultStyle,
9 | stylePaintData,
10 | } from './constants';
11 | import { Center, Map, MapType, Marker, Style, StylePaintData } from './types';
12 |
13 | export const changeMap = createEvent