All materials
TrekList.jsx
jsxTrekList.jsx
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { fetchTreks } from '../api';
export default function TrekList() {
const [treks, setTreks] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchTreks()
.then(setTreks)
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <p className="text-stone-500">Loading treks...</p>;
if (error) return <p className="text-red-600">Error: {error}</p>;
return (
<div>
<h1 className="text-3xl font-bold text-stone-800 mb-6">Our Treks</h1>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{treks.map(trek => (
<TrekCard key={trek.id} trek={trek} />
))}
</div>
</div>
);
}
function TrekCard({ trek }) {
return (
<div className="bg-white rounded-lg shadow-sm border border-stone-200 p-6 hover:shadow-md transition-shadow">
<h2 className="text-xl font-semibold text-stone-800">{trek.name}</h2>
<p className="text-stone-500 mt-1">{trek.destination}</p>
<div className="mt-4 flex flex-wrap gap-3 text-sm text-stone-600">
<span>{trek.duration_days} days</span>
<span>·</span>
<span>Max {trek.max_group_size} people</span>
<span>·</span>
<span className="capitalize">{trek.difficulty}</span>
</div>
<div className="mt-3 text-sm">
<span className="text-stone-800 font-medium">NPR {trek.price_npr?.toLocaleString()}</span>
<span className="text-stone-400 mx-2">/</span>
<span className="text-stone-600">USD {trek.price_usd}</span>
</div>
<div className="mt-4 flex gap-3">
<Link
to={`/treks/${trek.id}`}
className="text-sm text-amber-700 hover:text-amber-800 font-medium"
>
Details
</Link>
<Link
to={`/book/${trek.id}`}
className="text-sm bg-amber-600 text-white px-4 py-1.5 rounded hover:bg-amber-700 transition-colors"
>
Book Now
</Link>
</div>
</div>
);
}