diff --git a/backend/internal/handlers/venues/venues.go b/backend/internal/handlers/venues/venues.go index 02bc537..292738b 100644 --- a/backend/internal/handlers/venues/venues.go +++ b/backend/internal/handlers/venues/venues.go @@ -226,7 +226,6 @@ func (s *Service) GetVenuesByIDs(c *fiber.Ctx) error { "error": "Missing venue IDs", }) } - // Split the IDs into a slice idStrings := strings.Split(ids, ",") @@ -256,6 +255,7 @@ func (s *Service) GetVenuesByIDs(c *fiber.Ctx) error { 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") diff --git a/backend/internal/storage/postgres/venues.go b/backend/internal/storage/postgres/venues.go index 8a6e202..7813057 100644 --- a/backend/internal/storage/postgres/venues.go +++ b/backend/internal/storage/postgres/venues.go @@ -206,60 +206,17 @@ func (db *DB) GetVenuesByLocation(ctx context.Context, latitude float64, longitu FROM venue WHERE ST_DWithin( location::geography, - ST_MakePoint($1, $2)::geography, - $3 - ); + ST_MakePoint($1, $2)::geography, $3) limit 20 ` - rows, err := db.conn.Query(ctx, query, longitude, latitude, radiusInMeters) + 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() // No need to handle rows.Close()'s return, just defer the call - - venues := []models.Venue{} - for rows.Next() { - var venue models.Venue - if err := rows.Scan( - &venue.VenueID, - &venue.Name, - &venue.Address, - &venue.City, - &venue.State, - &venue.ZipCode, - &venue.Latitude, - &venue.Longitude, - &venue.VenueType, - &venue.TotalRating, - &venue.Price, - &venue.AvgMainstream, - &venue.AvgPrice, - &venue.AvgExclusive, - &venue.AvgEnergy, - &venue.MondayHours, - &venue.TuesdayHours, - &venue.WednesdayHours, - &venue.ThursdayHours, - &venue.FridayHours, - &venue.SaturdayHours, - &venue.SundayHours, - &venue.CreatedAt, - &venue.UpdatedAt, - ); err != nil { - log.Printf("Error scanning row: %v", err) - return nil, fmt.Errorf("row scan error: %w", err) - } - venues = append(venues, venue) - } - - // Check for errors in row iteration - if err := rows.Err(); err != nil { - log.Printf("Row iteration error: %v", err) - return nil, fmt.Errorf("row iteration error: %w", err) - } - - return venues, nil + 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) { diff --git a/frontend/assets/location.svg b/frontend/assets/location.svg new file mode 100644 index 0000000..1ce6c94 --- /dev/null +++ b/frontend/assets/location.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/screens/HomeScreen.tsx b/frontend/screens/HomeScreen.tsx index 403f2a5..be2a9a6 100644 --- a/frontend/screens/HomeScreen.tsx +++ b/frontend/screens/HomeScreen.tsx @@ -3,23 +3,31 @@ import { ScrollView, View, StyleSheet } from "react-native"; import SearchBar from "@/components/Map/SearchBar"; import EventsScrollable from "./explore/EventsScrollable"; -const HomeScreen: React.FC = () => { - return ( - - - - - - - - - - - - - +interface HomeScreenProps { + showSearchBar?: boolean; +} + +const HomeScreen: React.FC = ({ showSearchBar = true }) => { + return ( + + {showSearchBar && ( + + - ); + )} + + + + + + + + + + + + + ); }; const styles = StyleSheet.create({ diff --git a/frontend/screens/MapScreen.tsx b/frontend/screens/MapScreen.tsx index e4cdcba..82a9567 100644 --- a/frontend/screens/MapScreen.tsx +++ b/frontend/screens/MapScreen.tsx @@ -10,61 +10,70 @@ import { Venue } from "@/types/Venue"; import { useAuth } from "@/context/AuthContext"; import React from "react"; import HomeScreen from "./HomeScreen"; +import EventCard from "./explore/EventCard"; const MapScreen: React.FC = () => { const [allVenues, setAllVenues] = useState([]); const [selectedVenue, setSelectedVenue] = useState(null); + const [mapKey, setMapKey] = useState(0); const { user, accessToken } = useAuth(); const modalRef = React.useRef(null); - - const fetchVenues = async (): Promise => { if (!accessToken || !user?.location) { console.log("No access token available or user location available"); return; } - try { - const locationRes = await fetch( `${API_DOMAIN}/profiles/${user.user_id}/location`, { method: "GET", headers: { - "Authorization": `Bearer ${accessToken}`, + Authorization: `Bearer ${accessToken}`, }, } ); if (!locationRes.ok) - throw new Error(`Error fetching user location: ${locationRes.statusText}`); + throw new Error( + `Error fetching user location: ${locationRes.statusText}` + ); const { latitude, longitude } = await locationRes.json(); - - - - // Fetch venues by location + // Fetch venues by location const radius = 80000; // 80,000 meters (80 km) const venuesRes = await fetch( `${API_DOMAIN}/venues/location?latitude=${latitude}&longitude=${longitude}&radius=${radius}`, + // `${API_DOMAIN}/venues`, { method: "GET", headers: { - "Authorization": `Bearer ${accessToken}`, + Authorization: `Bearer ${accessToken}`, }, } ); - if (!venuesRes.ok) + if (!venuesRes.ok) { throw new Error(`Error fetching venues: ${venuesRes.statusText}`); + } const venues: Venue[] = await venuesRes.json(); + console.log(venues[1]); setAllVenues(venues); + setMapKey((prevKey) => prevKey + 1); } catch (err) { console.error("Failed to fetch venues by location:", err); } + }; + const getPriceRepresentation = (price: number | undefined): string => { + // Fallback to 1 star if price is undefined or 0 + if (!price || price === 0) { + return "$"; + } + // Return the correct number of dollar signs + return "$".repeat(price); }; useEffect(() => { @@ -81,29 +90,36 @@ const MapScreen: React.FC = () => { modalRef.current?.open(); }; - // // Get the current day of the week for displaying venue hours - // const getCurrentDayHours = (venue: Venue): string => { - // const days = [ - // "monday_hours", - // "tuesday_hours", - // "wednesday_hours", - // "thursday_hours", - // "friday_hours", - // "saturday_hours", - // "sunday_hours", - // ]; - // const today = new Date().getDay(); - // return venue[days[today - 1]] || "Hours not available"; - // }; + // Get the current day of the week for displaying venue hours + const getCurrentDayHours = (venue: Venue): string | number => { + const days = [ + "monday_hours", + "tuesday_hours", + "wednesday_hours", + "thursday_hours", + "friday_hours", + "saturday_hours", + "sunday_hours", + ]; + const today = new Date().getDay(); + const dayKey = days[today - 1] as keyof Venue; + + if (venue[dayKey] == "NULL") { + return "Hours not available"; + } + + return venue[dayKey] || "Hours not available"; + }; return ( {/* Floating Search Bar */} - + {/* Map */} { style={styles.markerImage} resizeMode="contain" /> + {/* */} ))} @@ -173,9 +190,7 @@ const MapScreen: React.FC = () => { {/* Stand-in Rating */} - {selectedVenue.total_rating - ? selectedVenue.total_rating.toFixed(1) - : "4.2"} + {selectedVenue.total_rating} {/* Star Icon */} @@ -189,35 +204,35 @@ const MapScreen: React.FC = () => { | {/* Money Sign */} - $$$ + + {getPriceRepresentation(selectedVenue?.price)} + {/* Divider */} | - {/* Open Status */} - {/* + {/* Hours for the Day */} + {getCurrentDayHours(selectedVenue)} - */} - 🟢 Open + + + + {/* Centered EventCard */} + + ) : ( - // TODO: Replace with Ben's explore page - // Venue List View - // - // All Venues - // {allVenues.map((venue) => ( - // handleMarkerPress(venue)} - // style={styles.venueItem} - // > - // {venue.name} - // {venue.address} - // - // ))} - // - + )} @@ -352,9 +367,16 @@ const styles = StyleSheet.create({ }, statusText: { fontSize: 18, - color: "#00FF00", + color: "#FFFFFF", marginLeft: 5, }, + eventCardContainer: { + width: "100%", + justifyContent: "center", + alignItems: "center", + marginTop: 20, + paddingHorizontal: 10, // Add some padding for aesthetic spacing + }, }); export default MapScreen; diff --git a/frontend/types/Venue.ts b/frontend/types/Venue.ts index 0217d78..7ea4768 100644 --- a/frontend/types/Venue.ts +++ b/frontend/types/Venue.ts @@ -10,4 +10,12 @@ export interface Venue { created_at: string; total_rating: number; price: number; + monday_hours: string; + tuesday_hours: string; + wednesday_hours: string; + thursday_horus: string; + friday_hours: string; + saturday_hours: string; + sunday_hours: string; + } \ No newline at end of file