Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Added Map to "View Location" on Trekking Page #232

Merged
merged 7 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ NODE_ENV= "development"
SENDER_EMAIL=
MAIL_SERVER_USER=
MAIL_SERVER_PASS=
MAIL_SERVER_HOST=
MAIL_SERVER_HOST=
NEXT_PUBLIC_MAPBOX_TOKEN=
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"bcryptjs": "^2.4.3",
"drizzle-kit": "^0.24.2",
"drizzle-orm": "^0.33.0",
"mapbox-gl": "^3.7.0",
"next": "14.2.5",
"next-auth": "^5.0.0-beta.22",
"nodemailer": "^6.9.15",
Expand Down
969 changes: 500 additions & 469 deletions src/app/trekking/location-detail.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/app/trekking/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function Trekking() {
};

// Extract unique districts from trekDetails
const districts = Array.from(new Set(trekDetails.map(trek => trek.district)));


const filterTreks = trekDetails.filter(trek => {
const matchesDifficulty = difficultyLevel === "" || trek.difficultyLevel.toLowerCase() === difficultyLevel.toLowerCase();
Expand Down
79 changes: 79 additions & 0 deletions src/components/ui/MapModal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.modalOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 20;
}

.modalContent {
display: flex;
width: 80%;
max-width: 900px;
background-color: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.leftColumn {
width: 90%;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
}

.mapContainer {
width: 100%;
height: 100%; /* Ensures the map fills the entire left column */
min-height: 400px; /* A minimum height to prevent collapsing */
position: relative;
}

.rightColumn {
width: fit-content;
padding: 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.rightColumn h2{
white-space: nowrap;
}

.subTitle{
white-space: nowrap;
width: fit-content;
}

.imageSection {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 8px;
width: fit-content;
}

.imageSection img {
width: 250px;
height: auto;
border-radius: 4px;
object-fit: cover;
}

.closeButton {
margin-top: 16px;
padding: 8px 16px;
background-color: #333;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}

84 changes: 84 additions & 0 deletions src/components/ui/MapModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// components/MapModal.tsx
import React, { useRef, useEffect } from 'react';
import mapboxgl from 'mapbox-gl';
import styles from './MapModal.module.css';
import 'mapbox-gl/dist/mapbox-gl.css';

// Ensure Mapbox token is defined
if (!process.env.NEXT_PUBLIC_MAPBOX_TOKEN) {
throw new Error("Mapbox access token is not defined. Please set NEXT_PUBLIC_MAPBOX_TOKEN in your environment variables.");
}

mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_TOKEN;

// Define the TrekDetails type with image as an array of strings
import { TrekDetails } from '../ui/TrekCard';

// Define the props interface, including `info` as a prop of type TrekDetails
interface MapModalProps {
isOpen: boolean;
onClose: () => void;
center?: number[];
zoom?: number;
markerLocation?: number[];
info: TrekDetails;
subTitle : string;
}

const MapModal: React.FC<MapModalProps> = ({
isOpen,
onClose,
center = [78.9629, 20.5937],
zoom = 5,
markerLocation = [78.9629, 20.5937],
info,
subTitle
}) => {
const mapContainerRef = useRef<HTMLDivElement | null>(null);
const mapRef = useRef<mapboxgl.Map | null>(null);

useEffect(() => {
if (isOpen && mapContainerRef.current) {
mapRef.current = new mapboxgl.Map({
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [center[1],center[0]],
zoom: zoom,
});

// Add the marker to the specified location
new mapboxgl.Marker()
.setLngLat([markerLocation[1],markerLocation[0]])
.addTo(mapRef.current);

return () => mapRef.current?.remove();
}
}, [isOpen, center, zoom, markerLocation]);

if (!isOpen) return null;

return (
<div className={styles.modalOverlay} onClick={onClose}>
<div className={styles.modalContent} onClick={(e) => e.stopPropagation()}>
<div className={styles.leftColumn}>
<div ref={mapContainerRef} className={styles.mapContainer} />
</div>
<div className={styles.rightColumn}>
<h2>{info.title}</h2>
<p className={styles.subTitle}>{subTitle}</p>
<h3>Address </h3>
<p>{info.address}</p>
<p></p>
<div className={styles.imageSection}>
<img src={info.image} alt={`Image`} />
</div>
<button className={styles.closeButton} onClick={onClose}>
Close
</button>
</div>
</div>
</div>
);
};

export default MapModal;
22 changes: 15 additions & 7 deletions src/components/ui/TrekCard.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"use client"; // Marking this as a client component

import React, { useState } from "react"; // Import useState for managing state
import Image from "next/image";
import styles from "./TrekCard.module.css";
import Link from "next/link";
import Roopkund from "/public/roopkund.jpg";

type TrekDetails = {
import styles from "./TrekCard.module.css";
import MapModal from '../../components/ui/MapModal';
export type TrekDetails = {
title: string;
introduction: string;
address : string;
coordinates : number[];
overview: string;
route: string[];
attractions: string[];
Expand All @@ -29,7 +29,10 @@ type CardProps = {
export default function TrekCard(props: CardProps) {
const { title, subTitle, trekDetails, readMoreLink } = props; // Destructure props
const [isExpanded, setIsExpanded] = useState(false); // State to track the expanded content

const [isMapOpen, setIsMapOpen] = useState(false);

const handleOpenMap = () => setIsMapOpen(true);
const handleCloseMap = () => setIsMapOpen(false);


return (
Expand Down Expand Up @@ -116,14 +119,19 @@ export default function TrekCard(props: CardProps) {
</div>
)}
<div className={styles["link-container2"]}>
<Link href={readMoreLink ? readMoreLink : "#"}>VIEW LOCATION</Link>
<button onClick={handleOpenMap}>VIEW LOCATION</button>
</div>
</div>
</div>

<div className={styles["image-container"]}>
<img src={trekDetails.image} alt={title} width={300} height={200} />
</div>


<MapModal isOpen={isMapOpen} onClose={handleCloseMap} center={trekDetails.coordinates} markerLocation= {trekDetails.coordinates}zoom={10} info= {trekDetails} subTitle = {subTitle}/>


</section>
);
}
Loading