Skip to content

Commit

Permalink
Feature/final map (#83)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris <125088905+wyattchris@users.noreply.github.com>
  • Loading branch information
abyan-n and wyattchris authored Dec 4, 2024
1 parent 3585c0b commit 1a7cdbb
Show file tree
Hide file tree
Showing 17 changed files with 613 additions and 338 deletions.
23 changes: 23 additions & 0 deletions backend/internal/handlers/profiles/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,26 @@ func (s *Service) GetUserVisitedVenues(c *fiber.Ctx) error {

return c.Status(fiber.StatusOK).JSON(venues)
}

func (s *Service) GetUserLocation(c *fiber.Ctx) error {
userID := c.Params("userId")
if userID == "" {
return fiber.NewError(fiber.StatusBadRequest, "User ID is required")
}

userUUID, err := uuid.Parse(userID)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid User ID format")
}

// Fetch latitude and longitude from the store
location, err := s.store.GetUserLocation(c.Context(), userUUID)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch user location")
}

// Return the latitude and longitude
return c.Status(fiber.StatusOK).JSON(location)
}


1 change: 1 addition & 0 deletions backend/internal/handlers/profiles/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ func Routes(app *fiber.App, params types.Params) {
protected.Get("/reviewed-venues/:userId", service.GetUserReviewsWithVenueData)
protected.Get("/saved-venues/:userId", service.GetUserSavedVenues)
protected.Get("/visited-venues/:userId", service.GetUserVisitedVenues)
protected.Get("/:userId/location", service.GetUserLocation)

}
1 change: 1 addition & 0 deletions backend/internal/handlers/venues/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func Routes(app *fiber.App, params types.Params) {
//Endpoints
protected.Get("/", service.GetAllVenuesWithFilter)
protected.Get("/batch", service.GetVenuesByIDs)
protected.Get("/location", service.GetVenuesByLocation)
protected.Get("/persona/:venueId", service.GetVenuePersona)

protected.Get("/search", service.GetVenuesFromName)
Expand Down
34 changes: 34 additions & 0 deletions backend/internal/handlers/venues/venues.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,37 @@ func (s *Service) GetVenuesByIDs(c *fiber.Ctx) error {
// Return the list of venues
return c.Status(fiber.StatusOK).JSON(venues)
}

func (s *Service) GetVenuesByLocation(c *fiber.Ctx) error {
// Parse latitude
latitude := c.QueryFloat("latitude")
fmt.Print(latitude)
if latitude == 0 {
log.Printf("Invalid or missing latitude parameter: %v", latitude)
return fiber.NewError(fiber.StatusBadRequest, "Invalid or missing latitude parameter")
}

// Parse longitude
longitude := c.QueryFloat("longitude")
if longitude == 0 {
log.Printf("Invalid or missing longitude parameter: %v", longitude)
return fiber.NewError(fiber.StatusBadRequest, "Invalid or missing longitude parameter")
}

// Parse radius with default value of 1000
radius := c.QueryInt("radius", 1000)
if radius <= 0 {
log.Printf("Invalid radius parameter: %d", radius)
return fiber.NewError(fiber.StatusBadRequest, "Invalid radius parameter")
}

// Fetch venues by location
venues, err := s.store.GetVenuesByLocation(c.Context(), latitude, longitude, radius)
if err != nil {
log.Printf("Error fetching venues by location: %v | Latitude: %f | Longitude: %f | Radius: %d", err, latitude, longitude, radius)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch venues by location")
}

// Return the list of venues as JSON
return c.Status(fiber.StatusOK).JSON(venues)
}
6 changes: 6 additions & 0 deletions backend/internal/models/location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package models

type Location struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}
21 changes: 21 additions & 0 deletions backend/internal/storage/postgres/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,24 @@ func (db *DB) GetUserVisitedVenues(ctx context.Context, userID uuid.UUID) ([]mod

return venues, rows.Err()
}

func (db *DB) GetUserLocation(ctx context.Context, userID uuid.UUID) (models.Location, error) {
query := `
SELECT
ST_Y(location::geometry) AS latitude,
ST_X(location::geometry) AS longitude
FROM users
WHERE user_id = $1
`

var location models.Location
row := db.conn.QueryRow(ctx, query, userID)
if err := row.Scan(&location.Latitude, &location.Longitude); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return models.Location{}, fmt.Errorf("no location found for user_id: %s", userID)
}
return models.Location{}, err
}

return location, nil
}
44 changes: 44 additions & 0 deletions backend/internal/storage/postgres/venues.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func (db *DB) GetAllVenues(ctx context.Context) ([]models.Venue, error) {
saturday_hours, sunday_hours, ST_Y(location::geometry) AS latitude, ST_X(location::geometry) AS longitude FROM venue`
rows, err := db.conn.Query(ctx, query)
if err != nil {
fmt.Print("hello")
return []models.Venue{}, err
}
defer rows.Close()
Expand Down Expand Up @@ -183,6 +184,49 @@ func (db *DB) GetVenuesByIDs(ctx context.Context, venueIDs []uuid.UUID) ([]model
return venues, rows.Err()
}

func (db *DB) GetVenuesByLocation(ctx context.Context, latitude float64, longitude float64, radiusInMeters int) ([]models.Venue, error) {
query := `
SELECT
venue_id,
name,
address,
city,
state,
zip_code,
ST_Y(location::geometry) AS latitude,
ST_X(location::geometry) AS longitude,
venue_type,
total_rating,
price,
avg_mainstream,
avg_price,
avg_exclusive,
avg_energy,
monday_hours,
tuesday_hours,
wednesday_hours,
thursday_hours,
friday_hours,
saturday_hours,
sunday_hours,
created_at,
COALESCE(updated_at, '9999-12-31 23:59:59') AS updated_at
FROM venue
WHERE ST_DWithin(
location::geography,
ST_MakePoint($1, $2)::geography, $3) limit 20
`

rows, err := db.conn.Query(ctx, query, latitude, longitude, radiusInMeters)
if err != nil {
log.Printf("Database query failed: %v | Query: %s | Params: longitude=%f, latitude=%f, radius=%d", err, query, longitude, latitude, radiusInMeters)
return nil, fmt.Errorf("database query error: %w", err)
}
defer rows.Close()
arr, err := pgx.CollectRows(rows, pgx.RowToStructByName[models.Venue])
return arr, err
}

func (db *DB) GetAllVenuesWithFilter(ctx context.Context, where string, sort string) ([]models.Venue, error) {
query := `SELECT venue_id, name, address, city, state, zip_code, created_at, venue_type, updated_at, price, total_rating,
avg_energy, avg_mainstream, avg_exclusive, avg_price, monday_hours, tuesday_hours, wednesday_hours, thursday_hours, friday_hours,
Expand Down
2 changes: 2 additions & 0 deletions backend/internal/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Profile interface {
GetUserReviewsWithVenueData(ctx context.Context, userID uuid.UUID) ([]models.ReviewWithVenue, error)
GetUserSavedVenues(context.Context, uuid.UUID) ([]models.Venue, error)
GetUserVisitedVenues(context.Context, uuid.UUID) ([]models.Venue, error)
GetUserLocation(ctx context.Context, userID uuid.UUID) (models.Location, error)
}

type UserRating interface {
Expand All @@ -52,6 +53,7 @@ type Venues interface {
GetVenuesFromName(context.Context, string) ([]models.Venue, error)
GetAllVenues(ctx context.Context) ([]models.Venue, error)
GetVenuesByIDs(ctx context.Context, ids []uuid.UUID) ([]models.Venue, error)
GetVenuesByLocation(ctx context.Context, latitude float64, longitude float64, radiusInMeters int) ([]models.Venue, error)
}

type VenueRatings interface {
Expand Down
Binary file added frontend/assets/custom-marker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/assets/location.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/rating-star.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 26 additions & 64 deletions frontend/components/Map/BottomModal.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
import React from "react";
import {
View,
Text,
StyleSheet,
Modal,
TouchableWithoutFeedback,
TouchableOpacity,
Dimensions,
FlatList,
} from "react-native";
import { useNavigation } from "@react-navigation/native";
import { BottomTabNavProps } from "@/types/NavigationTypes";

const { height: screenHeight } = Dimensions.get("window");
import { View, Text, StyleSheet, Modal, TouchableWithoutFeedback } from "react-native";
import { Venue } from "@/types/Venue";

interface BottomModalProps {
visible: boolean;
onClose: () => void;
venues: Array<{ venue_id: string; name: string; address: string }>;
venue: Venue | null;
}

const BottomModal: React.FC<BottomModalProps> = ({
visible,
onClose,
venues,
}) => {
const navigation = useNavigation<BottomTabNavProps>();
const BottomModal: React.FC<BottomModalProps> = ({ visible, onClose, venue }) => {
if (!venue) return null;

return (
<Modal
Expand All @@ -38,27 +22,14 @@ const BottomModal: React.FC<BottomModalProps> = ({
<View style={styles.overlay}>
<View style={styles.modalContainer}>
<View style={styles.tabIndicator} />
<Text style={styles.sectionTitle}>Happening Today</Text>

<FlatList
data={venues}
keyExtractor={(item) => item.venue_id}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => {
onClose();
navigation.navigate("Venue", { venue: item });
}}
>
<View style={styles.venueItem}>
<Text style={styles.venueName}>{item.name}</Text>
<Text style={styles.venueAddress}>{item.address}</Text>
</View>
</TouchableOpacity>
)}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.listContent}
/>
<Text style={styles.venueName}>{venue.name}</Text>
<Text style={styles.venueDetails}>
{venue.address}
</Text>
{/* <Text style={styles.rating}>⭐ {venue.rating} | 💲{venue.price}</Text> */}
{/* <Text style={styles.status}>
{venue.isOpen ? "Open Now" : "Closed"}
</Text> */}
</View>
</View>
</TouchableWithoutFeedback>
Expand All @@ -69,15 +40,14 @@ const BottomModal: React.FC<BottomModalProps> = ({
const styles = StyleSheet.create({
overlay: {
flex: 1,
backgroundColor: "rgba(0, 0, 0, 0.4)",
backgroundColor: "rgba(0, 0, 0, 0.5)",
justifyContent: "flex-end",
},
modalContainer: {
backgroundColor: "#1c1c1e",
padding: 16,
padding: 20,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
height: screenHeight * 0.5,
},
tabIndicator: {
width: 40,
Expand All @@ -87,32 +57,24 @@ const styles = StyleSheet.create({
marginBottom: 8,
borderRadius: 2,
},
sectionTitle: {
color: "#fff",
venueName: {
fontSize: 18,
fontWeight: "bold",
marginBottom: 8,
fontFamily: "Archivo_700Bold"
},
listContent: {
paddingBottom: 20,
color: "#fff",
},
venueItem: {
backgroundColor: "#333",
padding: 10,
borderRadius: 8,
marginBottom: 10,
venueDetails: {
fontSize: 14,
color: "#bbb",
marginVertical: 4,
},
venueName: {
rating: {
fontSize: 14,
color: "#fff",
fontSize: 16,
fontWeight: "bold",
fontFamily: "Archivo_700Bold"
marginVertical: 4,
},
venueAddress: {
color: "#bbb",
status: {
fontSize: 14,
fontFamily: "Archivo_500Medium"
// color: venue.isOpen ? "#4caf50" : "#f44336",
},
});

Expand Down
28 changes: 15 additions & 13 deletions frontend/components/Map/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,30 @@ const styles = StyleSheet.create({
searchContainer: {
flexDirection: "row",
alignItems: "center",
padding: 10,
backgroundColor: "#1c1c1c",
width: "100%",
position: "absolute",
top: 0,
top: 20,
left: 20,
right: 20,
zIndex: 1,
// borderBottomWidth: 1,
// borderBottomColor: "#555",
backgroundColor: "#333",
borderRadius: 20,
padding: 10,
shadowColor: "#000",
shadowOpacity: 0.2,
shadowOffset: { width: 0, height: 3 },
shadowRadius: 5,
elevation: 5,
},
searchIcon: {
paddingRight: 10,
marginRight: 10,
},
searchInput: {
flex: 1,
height: 40,
borderColor: "#555",
borderWidth: 1,
borderRadius: 10,
paddingLeft: 10,
color: "#fff",
backgroundColor: "#1e1e1e",
fontFamily: "Archivo_500Medium"
backgroundColor: "#444",
borderRadius: 10,
paddingHorizontal: 10,
},
});

Expand Down
Loading

0 comments on commit 1a7cdbb

Please sign in to comment.