diff --git a/assets/image.png b/assets/image.png new file mode 100644 index 0000000..096b6db Binary files /dev/null and b/assets/image.png differ diff --git a/components/eventComponent.tsx b/components/eventComponent.tsx index 4b0cfff..092c22e 100644 --- a/components/eventComponent.tsx +++ b/components/eventComponent.tsx @@ -37,21 +37,17 @@ function EventComponent(event: Event) { } const likeEvent = async () => { - - addVote(userId, event.id).then(() => { - if(!votes || votes == null) - setVotes([]) - votes.push(userId) - setUserFollowedEvent(true) - }) + if(!votes || votes == null) + setVotes([]) + votes.push(userId) + setUserFollowedEvent(true) + addVote(userId, event.id) } const unlikeEvent = async () => { - removeVote(userId, event.id).then(() => { - setVotes(votes.filter(id => userId !== id)) - setUserFollowedEvent(false) - }) - + setVotes(votes.filter(id => userId !== id)) + setUserFollowedEvent(false) + removeVote(userId, event.id) } return ( diff --git a/components/eventListComponent.tsx b/components/eventListComponent.tsx new file mode 100644 index 0000000..d099ff0 --- /dev/null +++ b/components/eventListComponent.tsx @@ -0,0 +1,19 @@ +import { SafeAreaView } from 'react-native'; +import Event from '../models/event'; +import EventComponent from '../components/eventComponent'; +import { ScrollView } from 'react-native-gesture-handler'; + +export default function EventListComponent(props: {events: Event[]}) { + + const items = props.events.map((val) => { + return + }); + + return ( + + + {items} + + + ); +} diff --git a/components/filterComponent.tsx b/components/filterComponent.tsx index 6c9d565..5bc2de1 100644 --- a/components/filterComponent.tsx +++ b/components/filterComponent.tsx @@ -4,9 +4,8 @@ import {withNavigation} from "react-navigation"; import {useState} from "react"; import Filter from "../models/filter"; -function FilterComponent(props) { +function FilterComponent(props: {handleFilter: (newFilter: Filter) => Promise}) { const [isOpenMenu, setIsOpenMenu] = useState(false) - const [distance, setDistance] = useState(0) const [likes, setLikes] = useState(0) const [isActive, setIsActive] = useState(true) @@ -96,8 +95,8 @@ function FilterComponent(props) { @@ -566,10 +596,14 @@ const styles = StyleSheet.create({ padding: 15, borderRadius: 10, marginTop: 20, + marginLeft: 20, width: 320, height: 180, }, label: { marginTop: 20, + }, + setLocationButton: { + margin: 5, } }); diff --git a/screens/eventViewScreen.tsx b/screens/eventViewScreen.tsx index 67cda5a..835135b 100644 --- a/screens/eventViewScreen.tsx +++ b/screens/eventViewScreen.tsx @@ -1,37 +1,53 @@ -import React, { useEffect, useState } from 'react'; -import { StyleSheet, SafeAreaView, StatusBar, Text, View } from 'react-native'; +import { useEffect, useState } from 'react'; +import { View } from 'react-native'; import { getEvents } from '../services/dbService'; import Event from '../models/event'; -import EventComponent from '../components/eventComponent'; -import { ScrollView } from 'react-native-gesture-handler'; import { Spinner } from '@ui-kitten/components'; +import EventListComponent from '../components/eventListComponent'; +import Filter from '../models/filter'; +import FilterComponent from '../components/filterComponent'; -export default function EventViewScreen() { - const [events, setEvents] = useState([]); +export default function EventListWithFilterComponent(props) { + const [events, setEvents] = useState>([]); const [hasLoaded, setHasLoaded] = useState(false); + const [filter, setFilter] = useState( new Filter()); useEffect(() => { - getEvents().then(eventDocs => { - eventDocs.forEach(doc => { + const filter = new Filter(); + const passedFilter: Filter = props.navigation.state.params.filter; + filter.distance = passedFilter.distance + filter.isActive = passedFilter.isActive + filter.likes = passedFilter.likes + filter.onlyLikedByMe = passedFilter.onlyLikedByMe + filter.onlyMyEvents = passedFilter.onlyMyEvents + setFilter(filter) + getEvents(filter).then(eventDocs => { + eventDocs?.forEach(doc => { events.push(doc) }) - setEvents(events); }).then(() => { setHasLoaded(true) }) - }, [events]) + }, []) - const items = events.map((val) => { - return - }); + async function handleFilter(newFilter: Filter) { + newFilter.onlyLikedByMe = filter.onlyLikedByMe + newFilter.onlyMyEvents = filter.onlyMyEvents + setFilter(newFilter) + const eventDocs = await getEvents(newFilter); + const newEvents: Event[] = [] + eventDocs?.forEach(doc => { + newEvents.push(doc) + }) + setEvents(newEvents) + } if(hasLoaded) return ( - - - {items} - - + + + + ); return ( @@ -44,18 +60,3 @@ export default function EventViewScreen() { ); } - const styles = StyleSheet.create({ - container: { - flex: 1, - marginTop: StatusBar.currentHeight || 0, - }, - item: { - backgroundColor: '#f9c2ff', - padding: 20, - marginVertical: 8, - marginHorizontal: 16, - }, - title: { - fontSize: 32, - }, - }); diff --git a/screens/mapScreen.tsx b/screens/mapScreen.tsx index bb73184..1535815 100644 --- a/screens/mapScreen.tsx +++ b/screens/mapScreen.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import {DefaultScreenProps} from '../common/DefaultScreenProps'; import MapView, {LatLng, MapEvent, Marker} from 'react-native-maps'; -import {StyleSheet, View} from 'react-native'; +import {LogBox, StyleSheet, View} from 'react-native'; import {getEvent, getEvents} from "../services/dbService"; import BottomSheet from "reanimated-bottom-sheet"; import {Layout} from "@ui-kitten/components"; @@ -32,30 +32,31 @@ export default function MapScreen({navigation}: DefaultScreenProps) { eventDocs.forEach(doc => { events.push(doc) }) - getLoggedInUserUID().then(uid => { - if(!uid) - navigation.navigate("LoginScreen") - }) + // getLoggedInUserUID().then(uid => { + // if(!uid) + // navigation.navigate("LoginScreen") + // }) setEvents(events) setEventMarkers(prepareEventMarker(eventDocs)) } - - fetchEvents(); + fetchEvents() }, [events]) function prepareEventMarker(eventDocs: Event[]) { - return eventDocs.map(eventDoc => { - return { - id: eventDoc.id, - title: eventDoc.name, - // description: eventDoc.description, - coordinate: { - latitude: !!eventDoc.latitude ? eventDoc.latitude : eventDoc.location.latitude, - longitude: !!eventDoc.longitude ? eventDoc.longitude : eventDoc.location.longitude, + const docs = eventDocs.filter(doc => doc.location).map(eventDoc => { + console.log(eventDoc) + return { + id: eventDoc.id, + title: eventDoc.name, + // description: eventDoc.description, + coordinate: { + latitude: eventDoc?.location?.latitude, + longitude: eventDoc?.location?.longitude + } } - } - }) + }) + return docs } async function clickOnMarker(e: MapEvent) { @@ -71,12 +72,12 @@ export default function MapScreen({navigation}: DefaultScreenProps) { async function handleFilter(newFilter) { setFilter(newFilter) + const newEvents: Event[] = [] const eventDocs = await getEvents(newFilter); eventDocs.forEach(doc => { - events.push(doc) + newEvents.push(doc) }) - - setEvents(events) + setEvents(newEvents) setEventMarkers(prepareEventMarker(eventDocs)) } @@ -96,7 +97,7 @@ export default function MapScreen({navigation}: DefaultScreenProps) { > {eventMarkers.map((marker, index) => ( () const [date, setDate] = useState(`${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`) - function goToEventsScreen(){ - navigation.navigate("EventViewScreen") + function goToMyEventsScreen(){ + const eventScreenFilter = new Filter(); + eventScreenFilter.onlyMyEvents = true; + navigation.navigate("EventViewScreen", {filter: eventScreenFilter}) + } + + function goToLikedEventsScreen(){ + const eventScreenFilter = new Filter(); + eventScreenFilter.onlyLikedByMe = true; + navigation.navigate("EventViewScreen", {filter: eventScreenFilter}) } async function getCurrentUser(){ @@ -47,7 +56,8 @@ export default function ProfileScreen({ navigation }: DefaultScreenProps) { Mail: { user?.mail } Nick: { user?.nick } Created on: { date } - + + diff --git a/services/dbService.tsx b/services/dbService.tsx index bbbd587..756ad93 100644 --- a/services/dbService.tsx +++ b/services/dbService.tsx @@ -1,5 +1,5 @@ import {db} from '../firebase/firebase.config'; -import {addDoc, collection, doc, DocumentData, getDoc, getDocs, query, where, updateDoc, arrayUnion, arrayRemove, setDoc} from "firebase/firestore"; +import {addDoc, collection, doc, DocumentData, getDoc, getDocs, query, where, updateDoc, arrayUnion, arrayRemove, setDoc, QueryConstraint, Query} from "firebase/firestore"; import Event from '../models/event'; import User from '../models/user'; import firebase from "firebase/compat"; @@ -9,31 +9,30 @@ import * as Location from "expo-location"; import GeoPoint = firebase.firestore.GeoPoint; import {Alert} from "react-native"; import {boundingBoxCoordinates} from "../utils/coordinateUtils" +import { getLoggedInUserUID } from './authService'; export async function addEvent(event: Event) { try { - console.log(event); - const docRef = await addDoc(collection(db, "events"), { - id: event.id, - name: event.name, - type: event.type, - description: event.description, - startDate: event.startDate, - endDate: event.endDate, - photo: event.photo, - postTime: event.postTime, - stars: event.stars, - votes: event.votes - }); + const loggedInUser = await getLoggedInUserUID() + event.creatorId = loggedInUser! + const docRef = await addDoc(collection(db, "events"), event); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } + } +export async function getEvents(filter: Filter): Promise { + let events: Array = [] + let queryConstraints: Array = [] + const usr = await getLoggedInUserUID() -export async function getEvents(filter: Filter): Promise { - let events = [] + if(filter.onlyLikedByMe) + queryConstraints.push(where("votes", "array-contains", usr)) + + if(filter.onlyMyEvents) + queryConstraints.push(where("creatorId", "==", usr)) if(!!filter.distance && parseInt(filter.distance) > 0) { let { status } = await Location.requestForegroundPermissionsAsync(); @@ -42,17 +41,18 @@ export async function getEvents(filter: Filter): Promise { return; } const distance = parseInt(filter.distance) + let location_corrds = await Location.getCurrentPositionAsync({}); - const box = boundingBoxCoordinates(location_corrds.coords, distance); + const box = boundingBoxCoordinates(location_corrds.coords, distance); const lesserGeopoint = new GeoPoint(box.swCorner.latitude, box.swCorner.longitude); const greaterGeopoint = new GeoPoint(box.neCorner.latitude, box.neCorner.longitude); - events = await getDocs(query(collection(db, "events"), where("location", ">", lesserGeopoint), where("location", "<", greaterGeopoint))) - } - else { - events = await getDocs(query(collection(db, "events") )) + queryConstraints.push(where("location", ">", lesserGeopoint)) + queryConstraints.push(where("location", "<", greaterGeopoint)) } + + events = await getDocs(query(collection(db, "events"), ...queryConstraints)) let arr: Event[] = []; if (events.size > 0) { @@ -66,13 +66,14 @@ export async function getEvents(filter: Filter): Promise { location: doc.data().location, latitude: doc.data().latitude, longitude: doc.data().longitude, + creatorId: doc.data().creatorID, type: doc.data().type, address: doc.data().address, startDate: doc.data().startDate, endDate: doc.data().endDate, postTime: doc.data().postTime, stars: doc.data().stars, - votes: doc.data().votes + votes: doc.data().votes || [] } if(!!filter && filter.likes > 0 && event.votes.length < filter.likes) isValid = false @@ -104,7 +105,8 @@ export async function getEvent(id: string) { location: eventData?.location, latitude: eventData?.latitude, longitude: eventData?.longitude, - address: eventData?.address + address: eventData?.address, + creatorId: eventData?.creatorId } return event