import React, { useState, useEffect, useRef } from "react";
import Navbar from "./Navbar";
import Footer from "./footer";
import "leaflet/dist/leaflet.css";
const Pin = () => {
const [suggestions, setSuggestions] = useState([]);
const [selectedLocation, setSelectedLocation] = useState(null);
const [ratings, setRatings] = useState({});
const [ratingInput, setRatingInput] = useState(0);
const [commentInput, setCommentInput] = useState("");
const commentsContainerRef = useRef(null);
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const handleInputChange = async (e) => {
const value = e.target.value;
if (value.length >= 1) {
try {
await delay(2000);
const response = await fetch(
`https://photon.komoot.io/api/?q=${value}&limit=5`
);
const data = await response.json();
setSuggestions(data.features);
} catch (error) {
console.error("Error fetching data from Photon:", error);
}
} else {
setSuggestions([]);
}
};
const handleSuggestionClick = (suggestion) => {
const addressString = [
suggestion.properties.name,
suggestion.properties.city,
suggestion.properties.postcode,
suggestion.properties.country,
]
.filter((part) => part)
.join(", ");
setSelectedLocation({
id: suggestion.properties.osm_id || suggestion.properties.osm_type,
name: addressString,
});
setSuggestions([]);
};
const handleRatingSubmit = async () => {
if (selectedLocation) {
const locationName = selectedLocation.name;
const userName = localStorage.getItem('username');
try {
const response = await fetch('https://jp-backend-kc80.onrender.com/api/reviews', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
location: locationName,
rating: ratingInput,
comment: commentInput,
username: userName,
}),
});
if (response.ok) {
fetchRatings();
setRatingInput(0);
setCommentInput("");
} else {
console.error('Failed to submit rating:', response.statusText);
}
} catch (error) {
console.error('Error submitting rating:', error);
}
}
};
const fetchRatings = async () => {
try {
const response = await fetch('https://jp-backend-kc80.onrender.com/api/reviews');
if (response.ok) {
const data = await response.json();
const groupedRatings = data.reduce((acc, review) => {
if (!acc[review.location]) {
acc[review.location] = [];
}
acc[review.location].push(review);
return acc;
}, {});
setRatings(groupedRatings);
} else {
console.error('Failed to fetch ratings:', response.statusText);
}
} catch (error) {
console.error('Error fetching ratings:', error);
}
};
useEffect(() => {
fetchRatings();
}, []);
const calculateAverageRating = (locationName) => {
const locationRatings = ratings[locationName] || [];
if (locationRatings.length === 0) return 0;
const total = locationRatings.reduce((sum, entry) => sum + entry.rating, 0);
return (total / locationRatings.length).toFixed(1);
};
const sortedLocations = Object.keys(ratings)
.map((locationName) => ({
name: locationName,
averageRating: calculateAverageRating(locationName),
reviews: ratings[locationName],
}))
.sort((a, b) => b.averageRating - a.averageRating);
return (
<div style={{
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
background: 'linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab)',
backgroundSize: '400% 400%',
animation: 'gradient 15s ease infinite',
}}>
<style>
{`
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
`}
</style>
<Navbar />
<div className="container mt-4" style={{ flex: 1 }}>
<div className="row">
<div className="col-md-8 offset-md-2">
<form className="row g-3">
<div className="col-12">
<label htmlFor="inputLocation" className="form-label">
Search Location
</label>
<input
type="text"
className="form-control"
id="inputLocation"
placeholder="Enter location name"
onChange={handleInputChange}
/>
{selectedLocation && (
<p className="mt-2">
<strong>Selected Location:</strong> {selectedLocation.name}
</p>
)}
{suggestions.length > 0 && (
<ul
className="list-group mt-2"
style={{ maxHeight: "200px", overflowY: "auto" }}
>
{suggestions.map((suggestion, index) => {
const formattedAddress = [
suggestion.properties.name,
suggestion.properties.city,
suggestion.properties.postcode,
suggestion.properties.country,
]
.filter((part) => part)
.join(", ");
return (
<li
key={index}
className="list-group-item list-group-item-action"
onClick={() => handleSuggestionClick(suggestion)}
>
{formattedAddress}
</li>
);
})}
</ul>
)}
</div>
{selectedLocation && (
<div className="col-12 mt-3">
<label className="form-label mt-3">Rate this location</label>
<div>
{[1, 2, 3, 4, 5].map((value) => (
<label key={value} className="me-2">
<input
type="radio"
name="rating"
value={value}
checked={ratingInput === value}
onChange={() => setRatingInput(value)}
/>{" "}
{value}
</label>
))}
</div>
<label htmlFor="comment" className="form-label mt-2">
Comment
</label>
<textarea
className="form-control"
id="comment"
rows="3"
value={commentInput}
onChange={(e) => setCommentInput(e.target.value)}
></textarea>
<button
type="button"
className="btn btn-success mt-2"
onClick={handleRatingSubmit}
>
Submit Rating
</button>
</div>
)}
</form>
<div className="mt-4">
<h5>Top Rated Locations</h5>
<ul className="list-group" ref={commentsContainerRef} style={{ paddingBottom: '100px' }}>
{sortedLocations.map((location) => (
<li key={location.name} className="list-group-item">
<strong>{location.name}</strong> - Average Rating:{" "}
{location.averageRating}
<ul className="mt-2" style={{ maxHeight: '200px', overflowY: 'auto' }}>
{location.reviews.map((review, index) => (
<li key={index}>
{review.username}, {review.rating}/5 : {" "}
{review.comment}
</li>
))}
</ul>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
<Footer />
</div>
);
};
export default Pin;