diff --git a/frontend/wasted-app/credentials.ts b/frontend/wasted-app/credentials.ts index bad5c1b5..2ffa522b 100644 --- a/frontend/wasted-app/credentials.ts +++ b/frontend/wasted-app/credentials.ts @@ -1 +1,2 @@ export const GOOGLE_MAPS_API_KEY = "" +export const GOOGLE_IOS_CLIENT_ID = "" diff --git a/frontend/wasted-app/src/api/food.ts b/frontend/wasted-app/src/api/food.ts index d8e57da1..6ab73c1f 100644 --- a/frontend/wasted-app/src/api/food.ts +++ b/frontend/wasted-app/src/api/food.ts @@ -1,4 +1,5 @@ import {Food, FoodSortObject, FoodType} from "./interfaces" +import {Pagination} from "./pagination" import {WASTED_SERVER_URL} from "./urls" export const getFoodTypeByFoodId = async (id: string): Promise => { @@ -12,14 +13,27 @@ export const getFoodTypeByFoodId = async (id: string): Promise => { } } -export const getAllFood = async (sortObject?: FoodSortObject): Promise => { +export const getAllFood = async ({ + sortObject, + pagination +}: { + sortObject?: FoodSortObject + pagination?: Pagination +}): Promise => { try { - let response + let queryString = `${WASTED_SERVER_URL}/Food` + + if (sortObject || pagination) { + queryString += "?" + } if (sortObject) { - response = await fetch(`${WASTED_SERVER_URL}/Food?sortOrder=${sortObject.sortType}`) - } else { - response = await fetch(`${WASTED_SERVER_URL}/Food`) + queryString += `&sortOrder=${sortObject.sortType}` } + if (pagination) { + queryString += `&PageNumber=${pagination.pageNumber}&PageSize=${pagination.pageSize}` + } + + const response = await fetch(queryString) const data = await response.json() return data } catch (error) { diff --git a/frontend/wasted-app/src/api/pagination.ts b/frontend/wasted-app/src/api/pagination.ts new file mode 100644 index 00000000..57b79c57 --- /dev/null +++ b/frontend/wasted-app/src/api/pagination.ts @@ -0,0 +1,4 @@ +export interface Pagination { + pageNumber: number + pageSize: number +} diff --git a/frontend/wasted-app/src/api/restaurant.ts b/frontend/wasted-app/src/api/restaurant.ts index 3df5752f..b8124043 100644 --- a/frontend/wasted-app/src/api/restaurant.ts +++ b/frontend/wasted-app/src/api/restaurant.ts @@ -1,16 +1,30 @@ -import {Credentials, Food, Restaurant, RestaurantRegisterRequest, RestaurantSortObject} from "./interfaces" +import {Coordinates, Credentials, Food, Restaurant, RestaurantRegisterRequest, RestaurantSortObject} from "./interfaces" +import {Pagination} from "./pagination" import {WASTED_SERVER_URL} from "./urls" -export const getAllRestaurants = async (sortObject?: RestaurantSortObject): Promise => { +export const getAllRestaurants = async ({ + sortObject, + pagination +}: { + sortObject?: RestaurantSortObject + pagination?: Pagination +}): Promise => { try { let queryString = `${WASTED_SERVER_URL}/Restaurant` + + if (sortObject || pagination) { + queryString += "?" + } if (sortObject?.sortType) { - queryString += `?sortOrder=${sortObject.sortType}` + queryString += `sortOrder=${sortObject.sortType}` if (sortObject.coordinates) { queryString += `&Longitude=${sortObject.coordinates.longitude.toString()}&Latitude=${sortObject.coordinates.latitude.toString()}` } } else if (sortObject?.coordinates) { - queryString += `?&Longitude=${sortObject.coordinates.longitude.toString()}&Latitude=${sortObject.coordinates.latitude.toString()}` + queryString += `&Longitude=${sortObject.coordinates.longitude.toString()}&Latitude=${sortObject.coordinates.latitude.toString()}` + } + if (pagination) { + queryString += `&PageNumber=${pagination.pageNumber}&PageSize=${pagination.pageSize}` } const response = await fetch(queryString) const data = await response.json() @@ -31,9 +45,20 @@ export const getAllFoodByRestaurantId = async (id: string): Promise => { } } -export const getRestaurantById = async (id: string): Promise => { +export const getRestaurantById = async ({ + idRestaurant, + coordinates +}: { + idRestaurant: string + coordinates?: Coordinates +}): Promise => { try { - const response = await fetch(`${WASTED_SERVER_URL}/Restaurant/${id}`) + let queryString = `${WASTED_SERVER_URL}/Restaurant/${idRestaurant}` + + if (coordinates) { + queryString += `?&Longitude=${coordinates.longitude.toString()}&Latitude=${coordinates.latitude.toString()}` + } + const response = await fetch(queryString) const data = await response.json() return data } catch (error) { diff --git a/frontend/wasted-app/src/components/food-item/food-item.tsx b/frontend/wasted-app/src/components/food-item/food-item.tsx index 6a97b57b..7fe125df 100644 --- a/frontend/wasted-app/src/components/food-item/food-item.tsx +++ b/frontend/wasted-app/src/components/food-item/food-item.tsx @@ -2,6 +2,7 @@ import React, {useEffect, useState} from "react" import {Colors, Image, Text, TouchableOpacity, View} from "react-native-ui-lib" import {getRestaurantById} from "../../api" import {Restaurant} from "../../api/interfaces" +import {useLocation} from "../../hooks/use-location" import {formatPrice} from "../../utils/currency" import {timeAgoFull} from "../../utils/date" import {FoodItemProps} from "./interfaces" @@ -9,9 +10,12 @@ import {FoodItemProps} from "./interfaces" export const FoodItem = ({food, onPress}: FoodItemProps) => { const {name, idRestaurant, currentPrice, startingPrice, imageURL, createdAt} = food const [restaurant, setRestaurant] = useState({} as Restaurant) + const {location} = useLocation() const fetchRestaurant = async () => { - setRestaurant(await getRestaurantById(idRestaurant)) + setRestaurant( + await getRestaurantById({idRestaurant, coordinates: {latitude: location.latitude, longitude: location.longitude}}) + ) } useEffect(() => { diff --git a/frontend/wasted-app/src/components/foods-list/foods-list.tsx b/frontend/wasted-app/src/components/foods-list/foods-list.tsx index c09f81a4..ba012f5c 100644 --- a/frontend/wasted-app/src/components/foods-list/foods-list.tsx +++ b/frontend/wasted-app/src/components/foods-list/foods-list.tsx @@ -5,7 +5,7 @@ import {navigateToFoodInfo} from "../../services/navigation" import {FoodItem} from "../food-item" import {FoodsListProps} from "./interfaces" -export const FoodsList = ({componentId, foods}: FoodsListProps) => { +export const FoodsList = ({componentId, foods, onEndReached}: FoodsListProps) => { const renderItem = ({item}: ListRenderItemInfo) => { return ( { ) } - return item.id} /> + return ( + item.id} + onEndReachedThreshold={0} + onEndReached={onEndReached} + /> + ) } diff --git a/frontend/wasted-app/src/components/foods-list/interfaces.ts b/frontend/wasted-app/src/components/foods-list/interfaces.ts index 0cce411d..96cabd97 100644 --- a/frontend/wasted-app/src/components/foods-list/interfaces.ts +++ b/frontend/wasted-app/src/components/foods-list/interfaces.ts @@ -3,4 +3,5 @@ import {Food} from "../../api/interfaces" export interface FoodsListProps extends NavigationComponentProps { foods: Food[] + onEndReached: () => void } diff --git a/frontend/wasted-app/src/components/horizontal-list/horizontal-list.tsx b/frontend/wasted-app/src/components/horizontal-list/horizontal-list.tsx index 9fe3dff3..c13f352b 100644 --- a/frontend/wasted-app/src/components/horizontal-list/horizontal-list.tsx +++ b/frontend/wasted-app/src/components/horizontal-list/horizontal-list.tsx @@ -4,7 +4,7 @@ import {FlatList} from "react-native-gesture-handler" import {View} from "react-native-ui-lib" import {HorizontalListProps} from "./interfaces" -export const HorizontalList = ({items, renderItem}: HorizontalListProps) => { +export const HorizontalList = ({items, renderItem, onEndReached}: HorizontalListProps) => { return ( @@ -16,6 +16,8 @@ export const HorizontalList = ({items, renderItem}: HorizontalListProps) => { renderItem={renderItem} initialNumToRender={4} keyExtractor={item => item.id} + onEndReached={onEndReached} + onEndReachedThreshold={0} /> diff --git a/frontend/wasted-app/src/components/horizontal-list/interfaces.ts b/frontend/wasted-app/src/components/horizontal-list/interfaces.ts index 1e881151..c74b65e9 100644 --- a/frontend/wasted-app/src/components/horizontal-list/interfaces.ts +++ b/frontend/wasted-app/src/components/horizontal-list/interfaces.ts @@ -1,4 +1,5 @@ export interface HorizontalListProps { items: any renderItem: (item: any) => JSX.Element + onEndReached: () => void } diff --git a/frontend/wasted-app/src/components/price-indicator/price-indicator.tsx b/frontend/wasted-app/src/components/price-indicator/price-indicator.tsx index a2995401..1b2b3d28 100644 --- a/frontend/wasted-app/src/components/price-indicator/price-indicator.tsx +++ b/frontend/wasted-app/src/components/price-indicator/price-indicator.tsx @@ -7,7 +7,7 @@ import {PriceIndicatorProps} from "./interfaces" export const PriceIndicator = ({currentPrice, minimumPrice, maximumPrice}: PriceIndicatorProps) => { const [containerWidth, setContainerWidth] = useState(100) - const progress = (currentPrice - minimumPrice) / (maximumPrice - minimumPrice) + const progress = currentPrice === minimumPrice ? 1 : (currentPrice - minimumPrice) / (maximumPrice - minimumPrice) const getContainerWidth = (event: LayoutChangeEvent) => { setContainerWidth(event.nativeEvent.layout.width) diff --git a/frontend/wasted-app/src/components/restaurants-list/interfaces.ts b/frontend/wasted-app/src/components/restaurants-list/interfaces.ts index b276376e..73041257 100644 --- a/frontend/wasted-app/src/components/restaurants-list/interfaces.ts +++ b/frontend/wasted-app/src/components/restaurants-list/interfaces.ts @@ -3,4 +3,5 @@ import {Restaurant} from "../../api/interfaces" export interface RestaurantsListProps extends NavigationComponentProps { restaurants: Restaurant[] + onEndReached: () => void } diff --git a/frontend/wasted-app/src/components/restaurants-list/restaurants-list.tsx b/frontend/wasted-app/src/components/restaurants-list/restaurants-list.tsx index 5c2976e6..ac75684d 100644 --- a/frontend/wasted-app/src/components/restaurants-list/restaurants-list.tsx +++ b/frontend/wasted-app/src/components/restaurants-list/restaurants-list.tsx @@ -5,7 +5,7 @@ import {navigateToRestaurantInfo} from "../../services/navigation" import {RestaurantItem} from "../restaurant-item/" import {RestaurantsListProps} from "./interfaces" -export const RestaurantsList = ({componentId, restaurants}: RestaurantsListProps) => { +export const RestaurantsList = ({componentId, restaurants, onEndReached}: RestaurantsListProps) => { const renderItem = ({item}: ListRenderItemInfo) => { return ( item.id} /> + item.id} + onEndReachedThreshold={0} + onEndReached={onEndReached} + /> ) } diff --git a/frontend/wasted-app/src/components/sections/cheapest-food/cheapest-food.tsx b/frontend/wasted-app/src/components/sections/cheapest-food/cheapest-food.tsx index 6c3c3a92..697e1b6a 100644 --- a/frontend/wasted-app/src/components/sections/cheapest-food/cheapest-food.tsx +++ b/frontend/wasted-app/src/components/sections/cheapest-food/cheapest-food.tsx @@ -1,39 +1,43 @@ import React, {useEffect, useState} from "react" import {ListRenderItemInfo} from "react-native" -import {Image, Text, TouchableOpacity, View} from "react-native-ui-lib" +import {Text, View} from "react-native-ui-lib" import {getAllFood} from "../../../api/food" import {Food, FoodSortType} from "../../../api/interfaces" import {navigateToFoodInfo} from "../../../services/navigation" import {formatPrice} from "../../../utils/currency" import {HorizontalList} from "../../horizontal-list" +import {HorizontalListItem} from "../horizontal-list-item" import {CheapestFoodProps} from "./interfaces" export const CheapestFood = ({componentId}: CheapestFoodProps) => { const [food, setFood] = useState([] as Food[]) + const [pageNumber, setPageNumber] = useState(1) const fetchFood = async () => { - setFood(await getAllFood({sortType: FoodSortType.PRICE})) + setFood(await getAllFood({sortObject: {sortType: FoodSortType.PRICE}})) } const renderItem = ({item}: ListRenderItemInfo) => ( - navigateToFoodInfo(componentId, {food: item, componentId})}> - - {item.name} - - - {formatPrice(item.currentPrice)} - - - + navigateToFoodInfo(componentId, {componentId, food: item})} + /> ) + const onEndReached = async () => { + const newFood = await getAllFood({ + sortObject: {sortType: FoodSortType.PRICE}, + pagination: {pageNumber: pageNumber + 1, pageSize: 10} + }) + + if (newFood.length) { + setFood(food.concat(newFood)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { fetchFood() }, []) @@ -43,7 +47,7 @@ export const CheapestFood = ({componentId}: CheapestFoodProps) => { 💵 Cheapest food - + ) } diff --git a/frontend/wasted-app/src/components/sections/horizontal-list-item/horizontal-list-item.tsx b/frontend/wasted-app/src/components/sections/horizontal-list-item/horizontal-list-item.tsx new file mode 100644 index 00000000..9bc83eef --- /dev/null +++ b/frontend/wasted-app/src/components/sections/horizontal-list-item/horizontal-list-item.tsx @@ -0,0 +1,28 @@ +import React from "react" +import {Image, Text, TouchableOpacity, View} from "react-native-ui-lib" +import {HorizontalListItemProps} from "./interfaces" + +export const HorizontalListItem = ({name, imageURL, tag, onPress}: HorizontalListItemProps) => { + return ( + + + + {name} + + {tag && ( + + + {tag} + + + )} + + ) +} diff --git a/frontend/wasted-app/src/components/sections/horizontal-list-item/index.ts b/frontend/wasted-app/src/components/sections/horizontal-list-item/index.ts new file mode 100644 index 00000000..1131fedd --- /dev/null +++ b/frontend/wasted-app/src/components/sections/horizontal-list-item/index.ts @@ -0,0 +1 @@ +export {HorizontalListItem} from "./horizontal-list-item" diff --git a/frontend/wasted-app/src/components/sections/horizontal-list-item/interfaces.ts b/frontend/wasted-app/src/components/sections/horizontal-list-item/interfaces.ts new file mode 100644 index 00000000..4f818aa9 --- /dev/null +++ b/frontend/wasted-app/src/components/sections/horizontal-list-item/interfaces.ts @@ -0,0 +1,6 @@ +export interface HorizontalListItemProps { + imageURL: string + name: string + tag?: string + onPress: () => void +} diff --git a/frontend/wasted-app/src/components/sections/latest-food/latest-food.tsx b/frontend/wasted-app/src/components/sections/latest-food/latest-food.tsx index 0d34b883..1149d70c 100644 --- a/frontend/wasted-app/src/components/sections/latest-food/latest-food.tsx +++ b/frontend/wasted-app/src/components/sections/latest-food/latest-food.tsx @@ -1,39 +1,43 @@ import React, {useEffect, useState} from "react" import {ListRenderItemInfo} from "react-native" -import {Image, Text, TouchableOpacity, View} from "react-native-ui-lib" +import {Text, View} from "react-native-ui-lib" import {getAllFood} from "../../../api/food" import {Food, FoodSortType} from "../../../api/interfaces" import {navigateToFoodInfo} from "../../../services/navigation" import {timeAgo} from "../../../utils/date" import {HorizontalList} from "../../horizontal-list" +import {HorizontalListItem} from "../horizontal-list-item" import {LatestFoodProps} from "./interfaces" export const LatestFood = ({componentId}: LatestFoodProps) => { const [food, setFood] = useState([] as Food[]) + const [pageNumber, setPageNumber] = useState(1) const fetchFood = async () => { - setFood(await getAllFood({sortType: FoodSortType.TIME})) + setFood(await getAllFood({sortObject: {sortType: FoodSortType.TIME}})) } const renderItem = ({item}: ListRenderItemInfo) => ( - navigateToFoodInfo(componentId, {food: item, componentId})}> - - {item.name} - - - {timeAgo(item.createdAt)} - - - + navigateToFoodInfo(componentId, {componentId, food: item})} + /> ) + const onEndReached = async () => { + const newFood = await getAllFood({ + sortObject: {sortType: FoodSortType.TIME}, + pagination: {pageNumber: pageNumber + 1, pageSize: 10} + }) + + if (newFood.length) { + setFood(food.concat(newFood)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { fetchFood() }, []) @@ -43,7 +47,7 @@ export const LatestFood = ({componentId}: LatestFoodProps) => { ⏰ Latest food - + ) } diff --git a/frontend/wasted-app/src/components/sections/near-restaurants/near-restaurants.tsx b/frontend/wasted-app/src/components/sections/near-restaurants/near-restaurants.tsx index 0b955251..fbcf0b04 100644 --- a/frontend/wasted-app/src/components/sections/near-restaurants/near-restaurants.tsx +++ b/frontend/wasted-app/src/components/sections/near-restaurants/near-restaurants.tsx @@ -1,53 +1,56 @@ import React, {useEffect, useState} from "react" import {ListRenderItemInfo} from "react-native" -import {Image, Text, TouchableOpacity, View} from "react-native-ui-lib" +import {Text, View} from "react-native-ui-lib" import {getAllRestaurants} from "../../../api" import {Restaurant, RestaurantSortType} from "../../../api/interfaces" import {navigateToRestaurantInfo} from "../../../services/navigation" import {formatDistance} from "../../../utils/coordinates" import {HorizontalList} from "../../horizontal-list" +import {HorizontalListItem} from "../horizontal-list-item" import {NearRestaurantsProps} from "./interfaces" export const NearRestaurants = ({componentId, location}: NearRestaurantsProps) => { const [restaurants, setRestaurants] = useState([] as Restaurant[]) + const [pageNumber, setPageNumber] = useState(1) const fetchRestaurants = async () => { setRestaurants( await getAllRestaurants({ - sortType: RestaurantSortType.DIST, - coordinates: {longitude: location.longitude, latitude: location.latitude} + sortObject: { + sortType: RestaurantSortType.DIST, + coordinates: {longitude: location.longitude, latitude: location.latitude} + } }) ) } const renderItem = ({item}: ListRenderItemInfo) => ( - - navigateToRestaurantInfo(componentId, { - componentId, - restaurant: item - }) - } - > - - {item.name} - - - {`${formatDistance(item.distanceToUser)} km`} - - - + navigateToRestaurantInfo(componentId, {componentId, restaurant: item})} + /> ) + const onEndReached = async () => { + const newRestaurants = await getAllRestaurants({ + sortObject: { + sortType: RestaurantSortType.DIST, + coordinates: {longitude: location.longitude, latitude: location.latitude} + }, + pagination: { + pageNumber: pageNumber + 1, + pageSize: 10 + } + }) + + if (newRestaurants.length) { + setRestaurants(restaurants.concat(newRestaurants)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { fetchRestaurants() }, []) @@ -57,7 +60,7 @@ export const NearRestaurants = ({componentId, location}: NearRestaurantsProps) = 📍 Restaurants near you - + ) } diff --git a/frontend/wasted-app/src/components/sections/popular-restaurants/popular-restaurants.tsx b/frontend/wasted-app/src/components/sections/popular-restaurants/popular-restaurants.tsx index 0dd8b114..f17d672e 100644 --- a/frontend/wasted-app/src/components/sections/popular-restaurants/popular-restaurants.tsx +++ b/frontend/wasted-app/src/components/sections/popular-restaurants/popular-restaurants.tsx @@ -1,47 +1,54 @@ import React, {useEffect, useState} from "react" import {ListRenderItemInfo} from "react-native" -import {Image, Text, TouchableOpacity, View} from "react-native-ui-lib" +import {Text, View} from "react-native-ui-lib" import {getAllRestaurants} from "../../../api" import {Restaurant, RestaurantSortType} from "../../../api/interfaces" import {navigateToRestaurantInfo} from "../../../services/navigation" import {HorizontalList} from "../../horizontal-list" +import {HorizontalListItem} from "../horizontal-list-item" import {PopularRestaurantsProps} from "./interfaces" export const PopularRestaurants = ({componentId, location}: PopularRestaurantsProps) => { const [restaurants, setRestaurants] = useState([] as Restaurant[]) + const [pageNumber, setPageNumber] = useState(1) const fetchRestaurants = async () => { setRestaurants( await getAllRestaurants({ - sortType: RestaurantSortType.NAME, - coordinates: {longitude: location.longitude, latitude: location.latitude} + sortObject: { + sortType: RestaurantSortType.NAME, + coordinates: {longitude: location.longitude, latitude: location.latitude} + } }) ) } const renderItem = ({item}: ListRenderItemInfo) => ( - - navigateToRestaurantInfo(componentId, { - componentId, - restaurant: item - }) - } - > - - {item.name} - + navigateToRestaurantInfo(componentId, {componentId, restaurant: item})} + /> ) + const onEndReached = async () => { + const newRestaurants = await getAllRestaurants({ + sortObject: { + sortType: RestaurantSortType.NAME, + coordinates: {longitude: location.longitude, latitude: location.latitude} + }, + pagination: { + pageNumber: pageNumber + 1, + pageSize: 10 + } + }) + + if (newRestaurants.length) { + setRestaurants(restaurants.concat(newRestaurants)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { fetchRestaurants() }, []) @@ -51,7 +58,7 @@ export const PopularRestaurants = ({componentId, location}: PopularRestaurantsPr ⭐️ Popular restaurants - + ) } diff --git a/frontend/wasted-app/src/screens/food-info/food-info.tsx b/frontend/wasted-app/src/screens/food-info/food-info.tsx index 3ed48330..31a37d39 100644 --- a/frontend/wasted-app/src/screens/food-info/food-info.tsx +++ b/frontend/wasted-app/src/screens/food-info/food-info.tsx @@ -6,6 +6,7 @@ import {Chip, Colors, ExpandableSection, Image, Text, TouchableOpacity, View} fr import {getRestaurantById} from "../../api" import {DecreaseType, Restaurant} from "../../api/interfaces" import {PriceIndicator} from "../../components/price-indicator" +import {useLocation} from "../../hooks/use-location" import {navigateToRestaurantInfo} from "../../services/navigation" import {formatPrice} from "../../utils/currency" import {convertMinsToHrsMins, formatDate, formatTime, timeAgoFull} from "../../utils/date" @@ -14,6 +15,7 @@ import {FoodInfoProps} from "./interfaces" export const FoodInfo = ({componentId, food, showRestaurantLink = true}: FoodInfoProps) => { const [restaurant, setRestaurant] = useState({} as Restaurant) const [descriptionExpanded, setDescriptionExpanded] = useState(true) + const {location} = useLocation() const { name, @@ -33,7 +35,12 @@ export const FoodInfo = ({componentId, food, showRestaurantLink = true}: FoodInf } = food const fetchRestaurant = async () => { - setRestaurant((await getRestaurantById(idRestaurant)) as Restaurant) + setRestaurant( + (await getRestaurantById({ + idRestaurant, + coordinates: {latitude: location.latitude, longitude: location.longitude} + })) as Restaurant + ) } useEffect(() => { diff --git a/frontend/wasted-app/src/screens/restaurant-info/restaurant-info.tsx b/frontend/wasted-app/src/screens/restaurant-info/restaurant-info.tsx index 319f2728..60b4958a 100644 --- a/frontend/wasted-app/src/screens/restaurant-info/restaurant-info.tsx +++ b/frontend/wasted-app/src/screens/restaurant-info/restaurant-info.tsx @@ -79,7 +79,7 @@ export const RestaurantInfo = ({componentId, restaurant}: RestaurantInfoProps) = paddingV-s2 style={styles.shadowButton} onPress={() => - navigateToFoodList(componentId, {restaurantId: restaurant.id, restaurantName: restaurant.name}) + navigateToFoodList(componentId, {idRestaurant: restaurant.id, restaurantName: restaurant.name}) } > diff --git a/frontend/wasted-app/src/screens/restaurant-login/restaurant-login.tsx b/frontend/wasted-app/src/screens/restaurant-login/restaurant-login.tsx index d861893f..04d5c120 100644 --- a/frontend/wasted-app/src/screens/restaurant-login/restaurant-login.tsx +++ b/frontend/wasted-app/src/screens/restaurant-login/restaurant-login.tsx @@ -1,19 +1,19 @@ -import {GoogleSignin, GoogleSigninButton, User, statusCodes} from "@react-native-google-signin/google-signin" +import {GoogleSignin, GoogleSigninButton, statusCodes} from "@react-native-google-signin/google-signin" import React, {useEffect, useState} from "react" import {StyleSheet} from "react-native" import {Button, Colors, Incubator, Text, View} from "react-native-ui-lib" import {useDispatch} from "react-redux" +import {GOOGLE_IOS_CLIENT_ID} from "../../../credentials" import {setUser} from "../../actions/authentication" import {loginRestaurant} from "../../api" import {PasswordInput} from "../../components/password-input" import {navigateToRestaurantRegistration, setRestaurantRoot} from "../../services/navigation" import {RestaurantLoginProps} from "./interfaces" -GoogleSignin.configure({iosClientId: "834850407777-uv37m0m83itkc63p628t4hs52vabfrnh.apps.googleusercontent.com"}) +GoogleSignin.configure({iosClientId: GOOGLE_IOS_CLIENT_ID}) export const RestaurantLogin = ({componentId}: RestaurantLoginProps) => { const dispatch = useDispatch() - const [userInfo, setUserInfo] = useState({} as User) const [email, setEmail] = useState("") const [password, setPassword] = useState("") @@ -29,7 +29,7 @@ export const RestaurantLogin = ({componentId}: RestaurantLoginProps) => { const restaurantId = await loginRestaurant({email, password}) if (valid) { if (restaurantId) { - setRestaurantRoot({restaurantId}) + setRestaurantRoot({idRestaurant: restaurantId}) setError("") } else { setError("Login failed. We haven't found a registered account with these credentials.") @@ -45,7 +45,6 @@ export const RestaurantLogin = ({componentId}: RestaurantLoginProps) => { const userInfo = await GoogleSignin.signIn() dispatch(setUser(userInfo)) - setUserInfo(userInfo) setEmail(userInfo.user.email) setError("Please input password") } catch (error: any) { diff --git a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/baseInfo.tsx b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/baseInfo.tsx index d41603b8..da0abc46 100644 --- a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/baseInfo.tsx +++ b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/baseInfo.tsx @@ -1,6 +1,6 @@ import React, {useEffect, useState} from "react" import {StyleSheet} from "react-native" -import {Colors, Incubator, LoaderScreen, Picker, Text, View} from "react-native-ui-lib" +import {Colors, Incubator, LoaderScreen, Picker, View} from "react-native-ui-lib" import {FoodType} from "../../../../api/interfaces" import {getAllTypesOfFood} from "../../../../api/type-of-food" import {Props} from "./interfaces" diff --git a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/finalStep.tsx b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/finalStep.tsx index b0b7b1c9..ef64795b 100644 --- a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/finalStep.tsx +++ b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/finalStep.tsx @@ -1,8 +1,7 @@ import moment from "moment" import React, {useState} from "react" import {Alert} from "react-native" -import {Navigation} from "react-native-navigation" -import {View, Button, Text} from "react-native-ui-lib" +import {Button, Text, View} from "react-native-ui-lib" import {addNewFood} from "../../../../api/food" import {Props} from "./interfaces" @@ -15,7 +14,7 @@ export const FinalStep = ({food}: Props) => { ...food, startingPrice: food.currentPrice, createdAt: moment().add(2, "hours").toISOString(), - startDecreasingAt: food.startDecreasingAt + startDecreasingAt: moment(food.startDecreasingAt).add(2, "hours").toISOString() }) setLoading(false) Alert.alert("Food successfully added!", "Please refresh the food list to see it added.") diff --git a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/priceDecreasing.tsx b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/priceDecreasing.tsx index b524049e..ec1c3f8b 100644 --- a/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/priceDecreasing.tsx +++ b/frontend/wasted-app/src/screens/restaurant/addFood/Wizard.Steps/priceDecreasing.tsx @@ -1,6 +1,6 @@ import moment from "moment" import React, {useEffect, useState} from "react" -import {Checkbox, DateTimePicker, Slider, Stepper, View, Text} from "react-native-ui-lib" +import {Checkbox, DateTimePicker, Slider, Stepper, Text, View} from "react-native-ui-lib" import {DecreaseType} from "../../../../api/interfaces" import {Props} from "./interfaces" @@ -14,11 +14,9 @@ interface IPriceDecreasing { } export const PriceDecreasing = ({food, setFood}: Props) => { - const [minimumPrice, setMinimumPrice] = useState(food.currentPrice) const [time, setTime] = useState(new Date()) const [date, setDate] = useState(new Date()) const [decreaseType, setDecreaseType] = useState(food.decreaseType) - const [decreaseStep, setDecreaseStep] = useState(0) const [priceDecreasing, setPriceDecreasing] = useState({ startDecreasingAt: food.startDecreasingAt, @@ -29,13 +27,7 @@ export const PriceDecreasing = ({food, setFood}: Props) => { decreaseType: food.decreaseType }) - const onChangeStartDecreasingAt = (startDecreasingAt: Date) => { - setPriceDecreasing({...priceDecreasing, startDecreasingAt: startDecreasingAt.toDateString()}) - setFood({...food, startDecreasingAt: startDecreasingAt.toDateString()}) - } - const onChangeMinimumPrice = (minimumPrice: number) => { - setMinimumPrice(minimumPrice) setPriceDecreasing({...priceDecreasing, minimumPrice}) setFood({...food, minimumPrice}) } @@ -65,9 +57,10 @@ export const PriceDecreasing = ({food, setFood}: Props) => { newDate.setFullYear(date.getFullYear()) newDate.setMonth(date.getMonth()) newDate.setDate(date.getDate()) - newDate.setTime(time.getTime()) + newDate.setHours(time.getHours()) + newDate.setMinutes(time.getMinutes()) - const momentDate = moment(newDate).add(2, "hours") + const momentDate = moment(newDate) setPriceDecreasing({...priceDecreasing, startDecreasingAt: momentDate.toISOString()}) setFood({...food, startDecreasingAt: momentDate.toISOString()}) @@ -111,7 +104,6 @@ export const PriceDecreasing = ({food, setFood}: Props) => { label="Amount" onValueChange={() => { onChangeDecreaseType(DecreaseType.AMOUNT) - setDecreaseStep(0) }} /> { label="Percent" onValueChange={() => { onChangeDecreaseType(DecreaseType.PERCENT) - setDecreaseStep(0) }} /> @@ -138,7 +129,6 @@ export const PriceDecreasing = ({food, setFood}: Props) => { value={0} step={0.01} onValueChange={x => { - setDecreaseStep(x) decreaseType === DecreaseType.AMOUNT ? onChangeAmountPerInterval(x) : onChangePercentPerInterval(x) }} /> diff --git a/frontend/wasted-app/src/screens/restaurant/addFood/addFood.tsx b/frontend/wasted-app/src/screens/restaurant/addFood/addFood.tsx index aeb8eaa3..a992180b 100644 --- a/frontend/wasted-app/src/screens/restaurant/addFood/addFood.tsx +++ b/frontend/wasted-app/src/screens/restaurant/addFood/addFood.tsx @@ -10,13 +10,13 @@ import {PriceDecreasing} from "./Wizard.Steps/priceDecreasing" const completedStepIndex = 3 -export const AddFood = ({restaurantId}: AddFoodScreenProps) => { +export const AddFood = ({idRestaurant}: AddFoodScreenProps) => { const [activeIndex, setActiveIndex] = useState(0) const [food, setFood] = useState({ id: "0", name: "", description: "", - idRestaurant: restaurantId, + idRestaurant: idRestaurant, startingPrice: 0, minimumPrice: 0, currentPrice: 0.5, diff --git a/frontend/wasted-app/src/screens/restaurant/addFood/interfaces.ts b/frontend/wasted-app/src/screens/restaurant/addFood/interfaces.ts index bcbe609d..3d7f7867 100644 --- a/frontend/wasted-app/src/screens/restaurant/addFood/interfaces.ts +++ b/frontend/wasted-app/src/screens/restaurant/addFood/interfaces.ts @@ -1,7 +1,7 @@ import {NavigationComponentProps} from "react-native-navigation" export interface AddFoodScreenOwnProps { - restaurantId: string + idRestaurant: string } export interface AddFoodScreenProps extends NavigationComponentProps, AddFoodScreenOwnProps {} diff --git a/frontend/wasted-app/src/screens/restaurant/food/food.tsx b/frontend/wasted-app/src/screens/restaurant/food/food.tsx index ca390094..e8545586 100644 --- a/frontend/wasted-app/src/screens/restaurant/food/food.tsx +++ b/frontend/wasted-app/src/screens/restaurant/food/food.tsx @@ -4,16 +4,23 @@ import {LoaderScreen} from "react-native-ui-lib" import {Colors} from "react-native/Libraries/NewAppScreen" import {getRestaurantById} from "../../../api" import {Restaurant} from "../../../api/interfaces" +import {useLocation} from "../../../hooks/use-location" import {setHomeRoot} from "../../../services/navigation" import {FoodList} from "../../user/restaurants/food-list" import {FoodScreenProps} from "./interfaces" -export const Food = ({componentId, restaurantId}: FoodScreenProps) => { +export const Food = ({componentId, idRestaurant}: FoodScreenProps) => { const [restaurant, setRestaurant] = useState({} as Restaurant) const [loading, setLoading] = useState(true) + const {location} = useLocation() const fetchRestaurantById = async () => { - setRestaurant(await getRestaurantById(restaurantId)) + setRestaurant( + await getRestaurantById({ + idRestaurant: idRestaurant, + coordinates: {latitude: location.latitude, longitude: location.longitude} + }) + ) setLoading(false) } @@ -32,7 +39,7 @@ export const Food = ({componentId, restaurantId}: FoodScreenProps) => { {loading ? ( ) : ( - + )} ) diff --git a/frontend/wasted-app/src/screens/restaurant/food/interfaces.ts b/frontend/wasted-app/src/screens/restaurant/food/interfaces.ts index 0195e3a3..012c312a 100644 --- a/frontend/wasted-app/src/screens/restaurant/food/interfaces.ts +++ b/frontend/wasted-app/src/screens/restaurant/food/interfaces.ts @@ -1,7 +1,7 @@ import {NavigationComponentProps} from "react-native-navigation" export interface FoodScreenOwnProps { - restaurantId: string + idRestaurant: string } export interface FoodScreenProps extends NavigationComponentProps, FoodScreenOwnProps {} diff --git a/frontend/wasted-app/src/screens/restaurant/profile/interfaces.ts b/frontend/wasted-app/src/screens/restaurant/profile/interfaces.ts index 16f6e0e1..5f9de045 100644 --- a/frontend/wasted-app/src/screens/restaurant/profile/interfaces.ts +++ b/frontend/wasted-app/src/screens/restaurant/profile/interfaces.ts @@ -1,7 +1,7 @@ import {NavigationComponentProps} from "react-native-navigation" export interface ProfileOwnProps { - restaurantId: string + idRestaurant: string } export interface ProfileProps extends NavigationComponentProps, ProfileOwnProps {} diff --git a/frontend/wasted-app/src/screens/restaurant/profile/profile.tsx b/frontend/wasted-app/src/screens/restaurant/profile/profile.tsx index b3f11caf..575d4ae5 100644 --- a/frontend/wasted-app/src/screens/restaurant/profile/profile.tsx +++ b/frontend/wasted-app/src/screens/restaurant/profile/profile.tsx @@ -3,12 +3,13 @@ import {Navigation} from "react-native-navigation" import {Button, Colors, Image, LoaderScreen, Text, TextField, View} from "react-native-ui-lib" import {getRestaurantById, updateRestaurant as updateRestaurantCall} from "../../../api" import {Restaurant} from "../../../api/interfaces" +import {useLocation} from "../../../hooks/use-location" import {setHomeRoot} from "../../../services/navigation" import {ProfileProps} from "./interfaces" -export const Profile = ({restaurantId}: ProfileProps) => { +export const Profile = ({idRestaurant}: ProfileProps) => { const [restaurant, setRestaurant] = useState({ - id: restaurantId, + id: idRestaurant, name: "", coords: { latitude: 0.0, @@ -23,6 +24,7 @@ export const Profile = ({restaurantId}: ProfileProps) => { const [updatedRestaurant, setUpdatedRestaurant] = useState(restaurant) const [loading, setLoading] = useState(true) const [isSaveButtonDisabled, setIsSaveButtonDisabled] = useState(false) + const {location} = useLocation() useEffect(() => { fetchRestaurantInfo() @@ -36,7 +38,10 @@ export const Profile = ({restaurantId}: ProfileProps) => { }, []) const fetchRestaurantInfo = async () => { - const response = await getRestaurantById(restaurantId) + const response = await getRestaurantById({ + idRestaurant, + coordinates: {latitude: location.latitude, longitude: location.longitude} + }) if (response !== null) { setRestaurant(response) diff --git a/frontend/wasted-app/src/screens/user/food/food.tsx b/frontend/wasted-app/src/screens/user/food/food.tsx index 210fb257..1ce1a651 100644 --- a/frontend/wasted-app/src/screens/user/food/food.tsx +++ b/frontend/wasted-app/src/screens/user/food/food.tsx @@ -17,10 +17,11 @@ export const Food = ({componentId}: FoodProps) => { const [sortVisible, setSortVisible] = useState(false) const [sortType, setSortType] = useState(FoodSortType.NAME) const [ascending, setAscending] = useState(true) + const [pageNumber, setPageNumber] = useState(1) const fetchFoods = async ({sortType}: FoodSortObject = {sortType: FoodSortType.NAME}) => { setLoading(true) - setFoods(await getAllFood({sortType: directionalSortType(sortType)})) + setFoods(await getAllFood({sortObject: {sortType: directionalSortType(sortType)}})) setLoading(false) } @@ -31,6 +32,18 @@ export const Food = ({componentId}: FoodProps) => { return sortType } + const onEndReached = async () => { + const newFood = await getAllFood({ + sortObject: {sortType: directionalSortType(sortType)}, + pagination: {pageNumber: pageNumber + 1, pageSize: 10} + }) + + if (newFood.length) { + setFoods(foods.concat(newFood)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { setRenderedFoods(foods) }, [foods]) @@ -41,6 +54,7 @@ export const Food = ({componentId}: FoodProps) => { }, [searchValue]) useEffect(() => { + setPageNumber(1) fetchFoods({sortType}) }, [ascending, sortType]) @@ -94,7 +108,7 @@ export const Food = ({componentId}: FoodProps) => { {loading ? ( ) : ( - + )} Sort by diff --git a/frontend/wasted-app/src/screens/user/restaurants/food-list/food-list.tsx b/frontend/wasted-app/src/screens/user/restaurants/food-list/food-list.tsx index 81719bb9..b8df25cc 100644 --- a/frontend/wasted-app/src/screens/user/restaurants/food-list/food-list.tsx +++ b/frontend/wasted-app/src/screens/user/restaurants/food-list/food-list.tsx @@ -8,13 +8,13 @@ import {EmptyList} from "../../../../components/empty-list" import {SimpleFoodsList} from "../../../../components/simple-foods-list" import {FoodListProps} from "./interfaces" -export const FoodList = ({componentId, restaurantId, restaurantName, isRestaurant = false}: FoodListProps) => { +export const FoodList = ({componentId, idRestaurant, restaurantName, isRestaurant = false}: FoodListProps) => { const [foods, setFoods] = useState([] as Food[]) const [loading, setLoading] = useState(true) const [refreshing, setRefreshing] = useState(false) const fetchFoods = async () => { - const response = await getAllFoodByRestaurantId(restaurantId) + const response = await getAllFoodByRestaurantId(idRestaurant) setFoods(response) setRefreshing(false) setLoading(false) diff --git a/frontend/wasted-app/src/screens/user/restaurants/food-list/interfaces.ts b/frontend/wasted-app/src/screens/user/restaurants/food-list/interfaces.ts index 32c26ec9..c317f40c 100644 --- a/frontend/wasted-app/src/screens/user/restaurants/food-list/interfaces.ts +++ b/frontend/wasted-app/src/screens/user/restaurants/food-list/interfaces.ts @@ -2,7 +2,7 @@ import {NavigationComponentProps} from "react-native-navigation" export interface FoodListOwnProps { restaurantName: string - restaurantId: string + idRestaurant: string isRestaurant?: boolean } diff --git a/frontend/wasted-app/src/screens/user/restaurants/restaurants.tsx b/frontend/wasted-app/src/screens/user/restaurants/restaurants.tsx index 30e46f96..d73b3c3e 100644 --- a/frontend/wasted-app/src/screens/user/restaurants/restaurants.tsx +++ b/frontend/wasted-app/src/screens/user/restaurants/restaurants.tsx @@ -1,17 +1,17 @@ import React, {useEffect, useState} from "react" import {StyleSheet} from "react-native" -import GetLocation, {Location} from "react-native-get-location" import {Navigation} from "react-native-navigation" import {Button, Colors, Incubator, LoaderScreen, RadioButton, RadioGroup, Text, View} from "react-native-ui-lib" import {getAllRestaurants} from "../../../api" import {Restaurant, RestaurantSortType} from "../../../api/interfaces" import {RestaurantsList} from "../../../components/restaurants-list" +import {useLocation} from "../../../hooks/use-location" import {setHomeRoot} from "../../../services/navigation" import {HOME_BUTTON} from "../home-button" import {RestaurantListProps} from "./interfaces" export const RestaurantList = ({componentId}: RestaurantListProps) => { - const [location, setLocation] = useState({} as Location) + const {location} = useLocation() const [restaurants, setRestaurants] = useState([] as Restaurant[]) const [renderedRestaurants, setRenderedRestaurants] = useState([] as Restaurant[]) const [loading, setLoading] = useState(true) @@ -19,22 +19,16 @@ export const RestaurantList = ({componentId}: RestaurantListProps) => { const [sortVisible, setSortVisible] = useState(false) const [sortType, setSortType] = useState(RestaurantSortType.DIST) const [ascending, setAscending] = useState(true) - - const fetchLocation = async () => { - setLocation( - await GetLocation.getCurrentPosition({ - enableHighAccuracy: true, - timeout: 15000 - }) - ) - } + const [pageNumber, setPageNumber] = useState(1) const fetchRestaurants = async () => { setLoading(true) setRestaurants( await getAllRestaurants({ - sortType: directionalSortType(), - coordinates: {longitude: location.longitude, latitude: location.latitude} + sortObject: { + sortType: directionalSortType(), + coordinates: {longitude: location.longitude, latitude: location.latitude} + } }) ) setLoading(false) @@ -56,8 +50,25 @@ export const RestaurantList = ({componentId}: RestaurantListProps) => { return sortType } + const onEndReached = async () => { + const newRestaurants = await getAllRestaurants({ + sortObject: { + sortType: directionalSortType(), + coordinates: {longitude: location.longitude, latitude: location.latitude} + }, + pagination: { + pageNumber: pageNumber + 1, + pageSize: 10 + } + }) + + if (newRestaurants.length) { + setRestaurants(restaurants.concat(newRestaurants)) + setPageNumber(pageNumber + 1) + } + } + useEffect(() => { - fetchLocation() Navigation.mergeOptions(componentId, {topBar: {leftButtons: [HOME_BUTTON]}}) const listener = Navigation.events().registerNavigationButtonPressedListener(({buttonId}) => { if (buttonId === "GO_BACK") { @@ -68,12 +79,6 @@ export const RestaurantList = ({componentId}: RestaurantListProps) => { return () => listener.remove() }, []) - useEffect(() => { - if (location.longitude) { - fetchRestaurants() - } - }, [location]) - useEffect(() => { if (restaurants.length) { setRenderedRestaurants(restaurants) @@ -88,6 +93,7 @@ export const RestaurantList = ({componentId}: RestaurantListProps) => { useEffect(() => { if (location.longitude) { + setPageNumber(1) fetchRestaurants() } }, [ascending, sortType]) @@ -131,7 +137,7 @@ export const RestaurantList = ({componentId}: RestaurantListProps) => { {loading ? ( ) : ( - + )} Sort by diff --git a/frontend/wasted-app/src/utils/date.ts b/frontend/wasted-app/src/utils/date.ts index 67042e1f..a007dbce 100644 --- a/frontend/wasted-app/src/utils/date.ts +++ b/frontend/wasted-app/src/utils/date.ts @@ -10,7 +10,7 @@ export const formatDate = (string: string) => { } export const formatTime = (string: string) => { - const date = new Date(moment(string).subtract(2, "hours").toISOString()) + const date = new Date(moment(string).toISOString()) const hour = date.getHours() const minutes = date.getMinutes() @@ -41,7 +41,7 @@ export const timeAgoFull = (string: string) => { }) const date = new Date(string) - return moment(date).subtract(2, "hours").fromNow() + return moment(date).fromNow() } export const timeAgo = (string: string) => { @@ -65,7 +65,7 @@ export const timeAgo = (string: string) => { }) const date = new Date(string) - return moment(date).subtract(2, "hours").fromNow() + return moment(date).fromNow() } export const convertMinsToHrsMins = (mins: number) => {