Skip to content

Commit

Permalink
feat(places): update to API v2
Browse files Browse the repository at this point in the history
  • Loading branch information
umbopepato committed Jul 7, 2024
1 parent 3b32377 commit 8e5b6a6
Show file tree
Hide file tree
Showing 22 changed files with 245 additions and 633 deletions.
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
boost: 7dcd2de282d72e344012f7d6564d024930a6a440
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: d5c36294933aa344046699700b9ae9c2e10db18e
Expand Down
15 changes: 11 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@miblanchard/react-native-slider": "^2.2.0",
"@openspacelabs/react-native-zoomable-view": "^2.1.5",
"@orama/orama": "^2.0.0-beta.8",
"@polito/api-client": "^1.0.0-ALPHA.64",
"@polito/api-client": "^2.0.0",
"@react-native-async-storage/async-storage": "^1.18.2",
"@react-native-clipboard/clipboard": "^1.12.1",
"@react-native-community/blur": "^4.3.0",
Expand Down Expand Up @@ -107,6 +107,7 @@
"@commitlint/prompt-cli": "^17.5.0",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.12",
"@total-typescript/ts-reset": "^0.5.1",
"@trivago/prettier-plugin-sort-imports": "^3.3.0",
"@tsconfig/react-native": "^3.0.0",
"@types/color": "^3.0.3",
Expand Down
1 change: 1 addition & 0 deletions reset.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@total-typescript/ts-reset';
6 changes: 3 additions & 3 deletions src/core/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const extractSubtreeNotifications = (root: any) => {
const notifications: Notification[] = [];
const exploreNode = (node: any) => {
if (Array.isArray(node)) {
notifications.push(...node);
notifications.push(...(node as any[]));
} else if (typeof node === 'object') {
Object.values(node).forEach(exploreNode);
}
Expand Down Expand Up @@ -165,9 +165,9 @@ export const useNotifications = () => {
if (!notification || !notification.data?.polito_transazione) {
return;
}
const payload: PushNotificationPayload = JSON.parse(
const payload = JSON.parse(
notification.data?.payload ?? 'null',
);
) as PushNotificationPayload;
const transaction = notification.data.polito_transazione as TransactionId;
// Course
if (courseTransactionsMapping[transaction as CourseTransactionId]) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/providers/ApiProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export const ApiProvider = ({ children }: PropsWithChildren) => {
}));
await client.invalidateQueries();
}
const { message } = await error.response.json();
const { message } = (await error.response.json()) as { message?: string };

// The login alert is handled in the login screen
if (!error.response.url.includes('/login'))
Expand Down
6 changes: 5 additions & 1 deletion src/core/providers/PreferencesProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ export const PreferencesProvider = ({ children }: PropsWithChildren) => {
const typedKey = key as PreferenceKey;

if (objectPreferenceKeys.includes(key)) {
preferences[typedKey] = JSON.parse(value) ?? {};
(preferences[typedKey] as NonNullable<
(typeof preferences)[typeof typedKey]
>) = (JSON.parse(value) ?? {}) as NonNullable<
PreferencesContextProps[PreferenceKey]
>;
} else {
if (typedKey === 'language' && value === 'system') {
preferences[typedKey] = deviceLanguage;
Expand Down
14 changes: 11 additions & 3 deletions src/core/queries/placesHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const PLACES_QUERY_KEY = 'places';
export const PLACE_QUERY_KEY = 'place';
export const PLACE_CATEGORIES_QUERY_KEY = 'place-categories';
export const FREE_ROOMS_QUERY_KEY = 'free-rooms';
export const PLACES_SEARCH_DB_QUERY_KEY = 'places-search-db';

const usePlacesClient = (): PlacesApi => {
return new PlacesApi();
Expand All @@ -33,7 +32,13 @@ export const useGetBuildings = (siteId?: string) => {

return useQuery(
[BUILDINGS_QUERY_KEY],
() => placesClient.getBuildings({ siteId: siteId! }),
() =>
placesClient.getBuildings({ siteId: siteId! }).then(r => {
if (r.data?.length) {
r.data = r.data.filter(b => !!b.category);
}
return r;
}),
{
staleTime: Infinity,
enabled: siteId != null,
Expand Down Expand Up @@ -67,7 +72,10 @@ export const useGetSite = (siteId?: string) => {

export const useGetPlaces = (params: GetPlacesRequest) => {
const placesClient = usePlacesClient();
const key = [PLACES_QUERY_KEY, params.siteId];
if (!params.search) {
delete params.search;
}
const key = [PLACES_QUERY_KEY, JSON.stringify(params)];

return useQuery(key, () => placesClient.getPlaces(params), {
enabled: params.siteId != null,
Expand Down
107 changes: 49 additions & 58 deletions src/features/places/components/MarkersLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@ import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import { useTheme } from '@lib/ui/hooks/useTheme';
import { Theme } from '@lib/ui/types/Theme';
import { PlaceOverview } from '@polito/api-client';
import { PlaceCategory } from '@polito/api-client/models';
import { useNavigation } from '@react-navigation/native';
import { ShapeSource, SymbolLayer } from '@rnmapbox/maps';

import { capitalize } from 'lodash';

import { CATEGORIES_DATA, SUBCATEGORIES_INITIALLY_SHOWN } from '../constants';
import {
CategoryData,
PlaceOverviewWithMetadata,
SearchPlace,
isPlace,
} from '../types';
import { useFormatAgendaItem } from '../utils/formatAgendaItem';
import { notNullish } from '../../../utils/predicates';
import { DEFAULT_CATEGORY_MARKER } from '../constants';
import { usePlaceCategoriesMap } from '../hooks/usePlaceCategoriesMap';
import { SearchPlace, isPlace } from '../types';

export interface MarkersLayerProps {
selectedPoiId?: string;
Expand All @@ -39,59 +36,55 @@ export const MarkersLayer = ({
}: MarkersLayerProps) => {
const navigation = useNavigation<any>();
const { t } = useTranslation();
const { dark, fontSizes, palettes } = useTheme();
const formatAgendaItem = useFormatAgendaItem();
const pois = useMemo((): (SearchPlace & CategoryData)[] => {
const { dark, fontSizes } = useTheme();
const placeCategoriesMap = usePlaceCategoriesMap();
const pois = useMemo((): (SearchPlace & PlaceCategory)[] => {
if (!placeCategoriesMap) {
return [];
}
let result = places;
if (!search) {
result = result?.filter(
p =>
selectedPoiId === p.id ||
(categoryId != null &&
(p as PlaceOverviewWithMetadata).category?.id === categoryId) ||
(categoryId != null && p.category.id === categoryId) ||
(subCategoryId != null &&
(p as PlaceOverviewWithMetadata).category?.subCategory.id ===
subCategoryId) ||
p.category.subCategory?.id === subCategoryId) ||
(p.category.id === 'UFF'
? !!(p as PlaceOverviewWithMetadata).room?.name
: (p as PlaceOverviewWithMetadata).category?.subCategory.id &&
SUBCATEGORIES_INITIALLY_SHOWN.includes(
(p as PlaceOverviewWithMetadata).category?.subCategory.id,
)),
? !!(p as PlaceOverview).room.name
: p.category.subCategory?.id &&
placeCategoriesMap[p.category.subCategory.id]?.highlighted),
);
}
return result?.map(poi => {
const categoryData = (poi as PlaceOverviewWithMetadata).category?.id
? CATEGORIES_DATA[
(poi as PlaceOverviewWithMetadata).category
.id as keyof typeof CATEGORIES_DATA
] ?? CATEGORIES_DATA.default
: CATEGORIES_DATA.default;
const subcategoryData = (poi as PlaceOverviewWithMetadata).category
?.subCategory?.id
? (categoryData.children[
(poi as PlaceOverviewWithMetadata).category.subCategory
.id as keyof typeof categoryData.children
] as any) ?? {}
: {};
const category = placeCategoriesMap[poi.category.id] ?? {};
const subcategory = poi.category.subCategory?.id
? placeCategoriesMap[poi.category.subCategory.id]
: null;
const categoryData = {
...category,
...(subcategory ?? {}),
};
delete (categoryData as any).id;

const markerData = {
return {
...DEFAULT_CATEGORY_MARKER,
...poi,
...categoryData,
...subcategoryData,
priority:
selectedPoiId === poi.id ||
(poi as PlaceOverviewWithMetadata).agendaItem != null
selectedPoiId === poi.id
? 0
: subcategoryData?.priority ?? categoryData.priority,
: subcategory?.priority ?? category.priority,
};
if (!markerData.icon) {
markerData.icon = 'pin';
markerData.color = 'gray';
}
return markerData;
});
}, [categoryId, places, search, selectedPoiId, subCategoryId]);
}, [
categoryId,
placeCategoriesMap,
places,
search,
selectedPoiId,
subCategoryId,
]);

return (
pois && (
Expand All @@ -106,23 +99,21 @@ export const MarkersLayer = ({
properties: {
dark,
index: i,
icon: p.icon,
markerUrl: p.markerUrl,
priority: p.priority,
name: capitalize(
isPlace(p)
? `${p.room.name ?? p.category.subCategory.name}${
p.agendaItem != null
? `\n${formatAgendaItem(p.agendaItem, true)}`
: displayFloor
? `\n${t('common.floor')} ${p.floor.level}`
: ''
}`
? [
p.room.name ?? p.category.subCategory?.name,
displayFloor
? `${t('common.floor')} ${p.floor.level}`
: null,
]
.filter(notNullish)
.join('\n')
: p.name,
),
color:
palettes[p.color as keyof Theme['palettes']][
dark ? 200 : p.shade ?? 500
],
color: p.color,
},
geometry: {
type: 'Point',
Expand Down Expand Up @@ -162,7 +153,7 @@ export const MarkersLayer = ({
// Theme-independent hardcoded color
// eslint-disable-next-line react-native/no-color-literals
style={{
iconImage: ['get', 'icon'],
iconImage: ['get', 'markerUrl'],
iconSize: 0.35,
symbolSortKey: ['get', 'priority'],
textField: ['get', 'name'],
Expand Down
18 changes: 12 additions & 6 deletions src/features/places/components/PlaceCategoriesBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Image } from 'react-native';

import { faMapLocation } from '@fortawesome/free-solid-svg-icons';
import { BottomSheetMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
Expand Down Expand Up @@ -36,11 +37,12 @@ export const PlaceCategoriesBottomSheet = (props: PlacesBottomSheetProps) => {
isLoading={isLoading}
listProps={{
data: categories?.data
.flatMap(c =>
c.subCategories.map(sc => ({
...sc,
parent: formatPlaceCategory(c.name),
})),
.flatMap(
c =>
c.subCategories?.map(sc => ({
...sc,
parent: formatPlaceCategory(c.name),
})) ?? [],
)
.filter(
sc =>
Expand All @@ -50,7 +52,11 @@ export const PlaceCategoriesBottomSheet = (props: PlacesBottomSheetProps) => {
title: sc.name,
subtitle: sc.parent,
isAction: true,
leadingItem: <Icon icon={faMapLocation} size={fontSizes['2xl']} />,
leadingItem: sc.markerUrl ? (
<Image source={{ uri: sc.markerUrl }} width={30} height={30} />
) : (
<Icon icon={faMapLocation} size={fontSizes['2xl']} />
),
onPress: () => {
sheetRef.current?.close();
navigation.navigate({
Expand Down
13 changes: 8 additions & 5 deletions src/features/places/components/PlacesBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ export interface PlacesBottomSheetProps
isLoading?: boolean;
search?: string;
showSearchBar?: boolean;
onTriggerSearch?: () => void;
onSearchChange?: (newSearch: string) => void;
onSearchClear?: () => void;
onSearchTrigger?: () => void;
}

export const PlacesBottomSheet = forwardRef<
Expand All @@ -38,7 +39,8 @@ export const PlacesBottomSheet = forwardRef<
isLoading = false,
search,
onSearchChange,
onTriggerSearch,
onSearchTrigger,
onSearchClear,
showSearchBar = true,
...props
},
Expand Down Expand Up @@ -68,14 +70,15 @@ export const PlacesBottomSheet = forwardRef<
}}
onBlur={() => {
setTyping(false);
onTriggerSearch?.();
onSearchTrigger?.();
innerRef.current?.snapToIndex(1);
}}
returnKeyType="search"
onSubmitEditing={onTriggerSearch}
onSubmitEditing={onSearchTrigger}
value={search}
isClearable={!!search}
onChangeText={onSearchChange}
clearButtonMode="always"
onClear={onSearchClear}
{...textFieldProps}
/>
)}
Expand Down
Loading

0 comments on commit 8e5b6a6

Please sign in to comment.