Skip to content

Commit

Permalink
add location favorites
Browse files Browse the repository at this point in the history
  • Loading branch information
bwees committed Aug 31, 2024
1 parent 0265038 commit 7b84e7e
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 6 deletions.
37 changes: 36 additions & 1 deletion app/components/sheets/route_planning/InputRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Ionicons from '@expo/vector-icons/Ionicons';
import useAppStore from "../../../data/app_state";
import SheetHeader from "../../ui/SheetHeader";
import { MyLocationSuggestion, SearchSuggestion } from "utils/interfaces";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { FontAwesome, MaterialCommunityIcons } from "@expo/vector-icons";
import SuggestionInput from "app/components/ui/SuggestionInput";
import SegmentedControl from "@react-native-segmented-control/segmented-control";
import TimeInput from "app/components/ui/TimeInput";
Expand All @@ -14,6 +14,8 @@ import { useQueryClient } from "@tanstack/react-query";
import TripPlanCell from "app/components/ui/TripPlanCell";
import * as Location from 'expo-location';
import { Linking } from "react-native";
import { addFavoriteLocationMutation, removeFavoriteLocationMutation, useFavoriteLocations } from "app/data/storage_query";
import { suggestionEqual } from "app/utils";

interface SheetProps {
sheetRef: React.RefObject<BottomSheetModal>
Expand Down Expand Up @@ -55,6 +57,21 @@ const InputRoute: React.FC<SheetProps> = ({ sheetRef }) => {
return false
})

// Favorite Location
const { data: favoriteLocations } = useFavoriteLocations();
const addLocationFavorite = addFavoriteLocationMutation();
const removeLocationFavorite = removeFavoriteLocationMutation();

function toggleFavoriteLocation(location: SearchSuggestion) {
if (favoriteLocations &&
(favoriteLocations as SearchSuggestion[]).find((item) => suggestionEqual(item, location)))
{
removeLocationFavorite.mutate(location)
} else {
addLocationFavorite.mutate(location)
}
}

useEffect(() => {

if (suggestionOutput) {
Expand Down Expand Up @@ -267,6 +284,24 @@ const InputRoute: React.FC<SheetProps> = ({ sheetRef }) => {
{/* Subtitle */}
{ suggestion.subtitle && <Text style={{ color: theme.subtitle, fontSize: 14 }}>{suggestion.subtitle}</Text> }
</View>

{/* Favorite Location */}
{ suggestion.type != "my-location" &&
<TouchableOpacity
onPress={(e) => {
e.stopPropagation()
toggleFavoriteLocation(suggestion)
}}
style={{ paddingLeft: 16, zIndex: 10000 }}
>
{ (favoriteLocations as SearchSuggestion[]).find((item) => suggestionEqual(item, suggestion)) ?
<FontAwesome name="star" size={24} color="#ffcc01" />
:
<FontAwesome name="star-o" size={24} color={theme.subtitle} />
}
</TouchableOpacity>
}

</TouchableOpacity>
)}
/>
Expand Down
11 changes: 7 additions & 4 deletions app/components/ui/SuggestionInput.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useSearchSuggestion } from "app/data/api_query"
import useAppStore from "app/data/app_state"
import { useFavoriteLocations } from "app/data/storage_query"
import { memo, useEffect, useState } from "react"
import { View, TextInput, Keyboard, Platform } from "react-native"
import { MyLocationSuggestion, SearchSuggestion } from "utils/interfaces"
Expand All @@ -21,6 +22,7 @@ const SuggestionInput: React.FC<Props> = ({ location, icon, onFocus, outputName,
const [searchTerm, setSearchTerm] = useState("");

const { data: suggestions, isLoading } = useSearchSuggestion(searchTerm);
const { data: favoriteLocations } = useFavoriteLocations();

useEffect(() => {
setSuggestionLoading(isLoading);
Expand All @@ -40,11 +42,12 @@ const SuggestionInput: React.FC<Props> = ({ location, icon, onFocus, outputName,

useEffect(() => {
if (searchTerm.trim() == "" && suggestionsOutput) {
setSuggestions([MyLocationSuggestion]);
setSuggestions([MyLocationSuggestion, ...favoriteLocations]);
return
}

suggestionsOutput && setSuggestions(suggestions ?? []);
}, [suggestions])
}, [suggestions, favoriteLocations])

return (
<View
Expand Down Expand Up @@ -85,7 +88,7 @@ const SuggestionInput: React.FC<Props> = ({ location, icon, onFocus, outputName,
setSearchTerm(text);
setSuggestionsOutput(outputName);
if (text.trim() == "") {
setSuggestions([MyLocationSuggestion]);
setSuggestions([MyLocationSuggestion, ...favoriteLocations]);
return
}
setSuggestions([]);
Expand All @@ -96,7 +99,7 @@ const SuggestionInput: React.FC<Props> = ({ location, icon, onFocus, outputName,
setSearchTerm("");
}
if (searchTerm.trim() == "") {
setSuggestions([MyLocationSuggestion]);
setSuggestions([MyLocationSuggestion, ...favoriteLocations]);
} else {
setSuggestions(suggestions ?? [])
}
Expand Down
61 changes: 60 additions & 1 deletion app/data/storage_query.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { IMapRoute } from "utils/interfaces";
import { IMapRoute, SearchSuggestion } from "utils/interfaces";
import { useRoutes } from "./api_query";
import { suggestionEqual } from "app/utils";

export const useFavorites = (allowUpdate: boolean = true) => {
const routesQuery = useRoutes();
Expand Down Expand Up @@ -145,5 +146,63 @@ export const defaultGroupMutation = () => {
}
});

return mutation;
}

export const useFavoriteLocations = () => {
const query = useQuery({
queryKey: ["favoriteLocations"],
queryFn: async () => {
const favorites = await AsyncStorage.getItem("favoriteLocations")
if (!favorites) return [];

return JSON.parse(favorites);
},
staleTime: Infinity
});

return query;
}

export const addFavoriteLocationMutation = () => {
const queryClient = useQueryClient();

const mutation = useMutation({
mutationKey: ["addFavoriteLocation"],
mutationFn: async (location: SearchSuggestion) => {
const favorites = await AsyncStorage.getItem('favoriteLocations')

var favoritesArray = JSON.parse(favorites ?? "[]");

favoritesArray.push(location);
console.log(favoritesArray.length)

await AsyncStorage.setItem('favoriteLocations', JSON.stringify(favoritesArray));
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["favoriteLocations"] });
}
});

return mutation;
}

export const removeFavoriteLocationMutation = () => {
const queryClient = useQueryClient();

const mutation = useMutation({
mutationKey: ["removeFavoriteLocations"],
mutationFn: async (location: SearchSuggestion) => {
const favorites = await AsyncStorage.getItem('favoriteLocations')

var favoritesArray = JSON.parse(favorites ?? "[]");
const newFavorites = favoritesArray.filter((fav: SearchSuggestion) => !suggestionEqual(fav, location));
await AsyncStorage.setItem('favoriteLocations', JSON.stringify(newFavorites));
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["favoriteLocations"] });
}
});

return mutation;
}
10 changes: 10 additions & 0 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Appearance } from "react-native";
import { SearchSuggestion } from "utils/interfaces";

// given a hex code without the #, return a lighter version of it
export function getLighterColor(color: string): string {
Expand Down Expand Up @@ -40,4 +41,13 @@ export async function getColorScheme(): Promise<string> {
default:
return colorScheme == "dark" ? "dark" : "light"
}
}

export function suggestionEqual(lhs: SearchSuggestion, rhs: SearchSuggestion) {
if (lhs.type != rhs.type) return false

if (lhs.type == "map") return rhs.placeId == lhs.placeId
if (lhs.type == "stop") return rhs.stopCode == lhs.stopCode

return false
}

0 comments on commit 7b84e7e

Please sign in to comment.