Skip to content

Commit

Permalink
Add some magical things to timeline! #153
Browse files Browse the repository at this point in the history
  • Loading branch information
ckertam committed Dec 3, 2023
1 parent 85d7b12 commit 81d25c1
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 42 deletions.
8 changes: 8 additions & 0 deletions backend/frontend/src/pages/search/StoryDetailsBox.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@
.story-details-box:hover {
transform: scale(2); /* Enlarge the box when hovered */
}

.story-details-box .story-image {
max-width: 100%; /* Limit the image's width to not exceed the container's width */
max-height: 100px; /* Set a maximum height for the image */
object-fit: contain; /* Ensures the entire image is visible and maintains its aspect ratio */
display: block; /* To remove any default inline spacing */
margin: 0 auto; /* Centers the image if it's smaller than the container */
}
11 changes: 9 additions & 2 deletions backend/frontend/src/pages/search/StoryDetailsBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useState } from 'react';
import './StoryDetailsBox.css';

// Update the StoryDetailsBox component
const StoryDetailsBox = ({ story, onClick }) => {
const StoryDetailsBox = ({ story, onClick, imageUrl }) => {
const [isHovered, setIsHovered] = useState(false);

const handleMouseEnter = () => {
Expand All @@ -23,8 +23,15 @@ const StoryDetailsBox = ({ story, onClick }) => {
className={`story-details-box ${isHovered ? 'hovered' : ''}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={onClick} // Add the onClick handler here
onClick={onClick}
>
{imageUrl && (
<img
src={imageUrl}
alt={`Story titled ${story.title}`} // More descriptive alt text
className="story-image"
/>
)}
<h3 className="story-title-box">{story.title}</h3>
<p className="story-date-box">{formatDate(story)}</p>
<p className="story-author-box">by {story.author_username || 'Unknown'}</p>
Expand Down
7 changes: 4 additions & 3 deletions backend/frontend/src/pages/search/StorySearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,18 +485,19 @@ const StorySearch = () => {
center={markerPosition}
onClick={(e) => handleMarker(e)}
>
</GoogleMap>
{locationSearch && (
{locationSearch && (
<>
{console.log('Marker Position:', {
lat: locationSearch.geometry.coordinates[1],
lng: locationSearch.geometry.coordinates[0],
})}
<Marker
position={{markerPosition}}
position={{lat:locationSearch.geometry.coordinates[1],lng:locationSearch.geometry.coordinates[0]}}
/>
</>
)}
</GoogleMap>

</div>
<br />
<Button style={{backgroundColor: "#7E49FF", fontSize: "24px"}}variant="contained" type="submit" className="btn btn-primary middle">Search</Button>
Expand Down
79 changes: 58 additions & 21 deletions backend/frontend/src/pages/search/Timeline.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useParams, useNavigate } from 'react-router-dom';
import Swipeable from 'react-swipeable';
import './Timeline.css';
import StoryDetailsBox from './StoryDetailsBox';

Expand All @@ -21,12 +20,31 @@ const LocationSearch = () => {
minute: '2-digit',
};

const reverseGeocodeLocation = async (latitude, longitude) => {
try {
const response = await axios.get(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=YOUR_API_KEY`);
if (response.data.results.length > 0) {
return response.data.results[0].formatted_address;
}
} catch (error) {
console.error('Error in reverse geocoding:', error);
}
return `Latitude: ${latitude}, Longitude: ${longitude}`;
};

useEffect(() => {
const handleSearch = async () => {
console.log("locCSON",locationJSON)
if (locationJSON) {
try {
const locationData = JSON.parse(locationJSON);
setLocationName(determineLocationName(locationData)); // Update location name based on type
const locationName = await reverseGeocodeLocation(locationData.latitude, locationData.longitude);

if (locationName) {
setLocationName(locationName);
} else {
setLocationName(determineLocationName(locationData));
}

const response = await axios.get(`http://${process.env.REACT_APP_BACKEND_HOST_NAME}:8000/user/storySearchByLocation`, {
params: {
Expand All @@ -48,17 +66,23 @@ const LocationSearch = () => {
}, [locationJSON, radiusDiff]);

const determineLocationName = (locationData) => {
switch (locationData.type) {
case 'Point':
return `Latitude: ${locationData.latitude}, Longitude: ${locationData.longitude}`;
case 'LineString':
return 'Line Location';
case 'Polygon':
return 'Polygon Location';
case 'Circle':
return `Circle Location with center at Latitude: ${locationData.center.lat}, Longitude: ${locationData.center.lng}`;
default:
return 'Unknown Location';
console.log("Location Data", locationData)
if (locationData.name) {
return locationData.name;
}
else{
switch (locationData.type) {
case 'Point':
return `Latitude: ${locationData.latitude}, Longitude: ${locationData.longitude}`;
case 'LineString':
return 'Line Location';
case 'Polygon':
return 'Polygon Location';
case 'Circle':
return `Circle Location with center at Latitude: ${locationData.center.lat}, Longitude: ${locationData.center.lng}`;
default:
return 'Unknown Location';
}
}
};

Expand Down Expand Up @@ -106,21 +130,34 @@ const LocationSearch = () => {
}
return dateString;
};

const extractFirstImageUrl = (htmlContent) => {
const imgRegex = /<img.*?src=["'](.*?)["']/;
const match = htmlContent.match(imgRegex);
return match ? match[1] : null;
};

return (
<div>
<h2>Memories in {locationName}</h2>



{/* Timeline and Dots */}
<div className="timeline">
{locationStories.map((story, index) => (
<div key={story.id} className="dot" style={{ left: `${(index + 1) * 10}%` }}>
<StoryDetailsBox story={story} onClick={() => handleStoryClick(story.id)} />
<p className="story-date">{formatDate(story)}</p>
</div>
))}
</div>
{locationStories.map((story, index) => {
const imageUrl = extractFirstImageUrl(story.content);
return (
<div key={story.id} className="dot" style={{ left: `${(index + 1) * 10}%` }}>
<StoryDetailsBox
story={story}
onClick={() => handleStoryClick(story.id)}
imageUrl={imageUrl}
/>
<p className="story-date">{formatDate(story)}</p>
</div>
);
})}
</div>



Expand Down
14 changes: 4 additions & 10 deletions backend/frontend/src/pages/story/CreateStory.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,10 @@ function CreateStory() {
setLocations(storyInfo.location_ids.map(location => ({ ...location, id: location.id.toString() })));
}
setDateType(storyInfo.date_type);
switch(storyInfo.date_type) {
case 'year':
setYear(storyInfo.year);
setSeasonName(storyInfo.season_name);
break;
case 'year_interval':
setStartYear(storyInfo.start_year);
setEndYear(storyInfo.end_year);
break;
}
setYear(storyInfo.year);
setSeasonName(storyInfo.season_name);
setStartYear(storyInfo.start_year);
setEndYear(storyInfo.end_year);
setDate(storyInfo.date);
setStartDate(storyInfo.start_date);
setEndDate(storyInfo.end_date);
Expand Down
27 changes: 21 additions & 6 deletions backend/frontend/src/pages/story/StoryDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,40 +63,55 @@ function StoryDetails() {

if (location.point) {
const coords = location.point.slice(17).slice(0, -1).split(' ');
locationData = { latitude: parseFloat(coords[1]), longitude: parseFloat(coords[0]), type: 'Point' };
locationData = {latitude: parseFloat(coords[1]), longitude: parseFloat(coords[0]), type: 'Point' };
}
else if (location.line) {
const lineCoords = location.line.slice(17).slice(0, -1).split(', ');

locationData = {
type: 'LineString',
// name: location.name,
coordinates: lineCoords.map(coord => {
const [lng, lat] = coord.split(' ');
return { lat: parseFloat(lat), lng: parseFloat(lng) };
return {lat: parseFloat(lat), lng: parseFloat(lng) };
})
};
}
else if (location.polygon) {
const polyCoords = location.polygon.slice(17).slice(0, -1).split(', ');
const polyCoords = location.polygon.slice(20).slice(0, -2).split(', ');
locationData = {
type: 'Polygon',
// name: location.name,
coordinates: polyCoords.map(coord => {
const [lng, lat] = coord.split(' ');
return { lat: parseFloat(lat), lng: parseFloat(lng) };
return {lat: parseFloat(lat), lng: parseFloat(lng) };
})
};
}
else if (location.circle && location.radius) {
const circleCoords = location.circle.slice(17).slice(0, -1).split(' ');

locationData = {
type: 'Circle',
center: { lat: parseFloat(circleCoords[1]), lng: parseFloat(circleCoords[0]) },
// name: location.name,
center: {lat: parseFloat(circleCoords[1]), lng: parseFloat(circleCoords[0]) },
radius: parseFloat(location.radius)
};
}
console.log("loc name", location.name)
if (location.name) {
locationData.name = encodeURIComponent(location.name);
}

const locationJSON = JSON.stringify(locationData);
console.log("locationJSON",locationJSON)
navigate(`/timeline/${locationJSON}`);
try {
navigate(`/timeline/${locationJSON}`);
}
catch (error) {
console.log(error);
}

};


Expand Down

0 comments on commit 81d25c1

Please sign in to comment.