Snaplocal / client /src /components /Recommendations.jsx
Kuruva Laxmi
SnapLocal MVP - Complete platform with 4 MVP features
0f8617c
Raw
History Blame Contribute Delete
5.08 kB
import { useState, useEffect } from 'react';
import api from '../api/api';
import { Star, MapPin, Sparkles, TrendingUp, Loader2 } from 'lucide-react';
import { Link } from 'react-router-dom';
const Recommendations = () => {
const [recs, setRecs] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchRecs = async () => {
try {
// Fetch recommendations (mocking some user preferences or using defaults)
const response = await api.get('/recommendations?specialty=portrait');
setRecs(response.data);
setLoading(false);
} catch (error) {
console.error('Failed to fetch recommendations:', error);
setLoading(false);
}
};
fetchRecs();
}, []);
if (loading) return <div className="flex justify-center py-10"><Loader2 className="animate-spin text-blue-600" /></div>;
if (recs.length === 0) return null;
return (
<section className="py-10">
<div className="flex items-center justify-between mb-8 px-4">
<div>
<div className="flex items-center space-x-2 text-blue-600 mb-1">
<Sparkles size={16} className="fill-current" />
<span className="text-[10px] font-black uppercase tracking-widest">AI Matching Engine</span>
</div>
<h2 className="text-3xl font-black text-gray-900">Recommended for You</h2>
</div>
<Link to="/search" className="text-blue-600 font-bold text-sm hover:underline">View all experts</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 px-4">
{recs.map((pg) => (
<Link
key={pg._id}
to={`/photographer/${pg._id}`}
className="group bg-white rounded-[2.5rem] p-4 shadow-xl shadow-gray-200/50 hover:shadow-2xl hover:-translate-y-2 transition-all duration-500 border border-gray-100 flex flex-col"
>
<div className="relative h-64 w-full rounded-[2rem] overflow-hidden mb-6 shadow-inner">
<img src={pg.profilePicture} className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" alt="" />
<div className="absolute top-4 right-4 bg-white/90 backdrop-blur-md px-4 py-2 rounded-2xl shadow-xl flex items-center space-x-1">
<TrendingUp size={14} className="text-green-500" />
<span className="text-[10px] font-black uppercase tracking-widest text-gray-900">{Math.round(pg.recommendationScore)}% Match</span>
</div>
</div>
<div className="px-2 pb-2">
<div className="flex justify-between items-start mb-2">
<div>
<h3 className="text-xl font-black text-gray-900 leading-tight">{pg.firstName} {pg.lastName}</h3>
<p className="text-[10px] text-blue-600 font-black uppercase tracking-widest mt-1">{pg.specialty}</p>
</div>
<div className="flex items-center bg-amber-50 text-amber-600 px-3 py-1 rounded-xl shadow-sm border border-amber-100">
<Star size={12} className="fill-current mr-1" />
<span className="text-xs font-black">{pg.rating?.toFixed(1) || 4.9}</span>
</div>
</div>
<p className="text-gray-400 text-xs font-bold uppercase tracking-widest mb-6 flex items-center">
<MapPin size={12} className="mr-1" /> {pg.address?.split(',')[0] || 'Local'}
</p>
<div className="flex items-center justify-between border-t border-gray-50 pt-5 mt-auto">
<div>
<span className="text-[10px] text-gray-400 font-black uppercase block tracking-tighter">Starting at</span>
<span className="text-2xl font-black text-gray-900">${pg.price}<span className="text-xs text-gray-400 font-bold">/hr</span></span>
</div>
<div className="bg-gray-900 text-white px-6 py-3 rounded-2xl font-black text-[10px] uppercase tracking-widest group-hover:bg-blue-600 transition shadow-xl">
Book Now
</div>
</div>
</div>
</Link>
))}
</div>
</section>
);
};
export default Recommendations;