Integrate FavoriteProperty API: add/remove/get favorites with real backend
All checks were successful
Build frontend / build (push) Successful in 42s

This commit is contained in:
Claw AI
2026-03-30 17:54:42 +00:00
parent 1f40c6a4fd
commit 3b9831a513
5 changed files with 152 additions and 33 deletions

View File

@ -32,6 +32,9 @@ import {
import Image from 'next/image';
import Link from 'next/link';
import { getRentProperties, getSaleProperties } from '../utils/api';
import { useFavorites } from '@/app/contexts/FavoritesContext';
import AuthService from '@/app/services/AuthService';
import toast, { Toaster } from 'react-hot-toast';
// Map API data to UI format
function mapApiProperty(item, index) {
@ -95,9 +98,25 @@ function extractCity(address) {
// API-only — no fallback data
const PropertyCard = ({ property, viewMode = 'grid' }) => {
const [isFavorite, setIsFavorite] = useState(false);
const { isFavorite: checkFavorite, addFavorite, removeFavorite } = useFavorites();
const [favLoading, setFavLoading] = useState(false);
const [currentImage, setCurrentImage] = useState(0);
const isFav = checkFavorite(property.id);
const toggleFavorite = async (e) => {
e.preventDefault();
e.stopPropagation();
if (!AuthService.isAuthenticated()) { toast.error('سجل الدخول أولاً'); return; }
setFavLoading(true);
if (isFav) {
await removeFavorite(property.id);
} else {
await addFavorite(property.id);
}
setFavLoading(false);
};
const formatCurrency = (amount) => {
return amount?.toLocaleString() + ' ل.س';
};
@ -150,10 +169,11 @@ const PropertyCard = ({ property, viewMode = 'grid' }) => {
)}
<div className="absolute top-2 right-2 flex gap-2">
<button
onClick={() => setIsFavorite(!isFavorite)}
onClick={toggleFavorite}
disabled={favLoading}
className="w-8 h-8 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center hover:bg-white transition-colors shadow-sm"
>
<Heart className={`w-4 h-4 ${isFavorite ? 'fill-red-500 text-red-500' : 'text-gray-600'}`} />
<Heart className={`w-4 h-4 ${isFav ? 'fill-red-500 text-red-500' : 'text-gray-600'}`} />
</button>
</div>
</div>
@ -231,10 +251,11 @@ const PropertyCard = ({ property, viewMode = 'grid' }) => {
/>
<div className="absolute top-2 right-2 flex gap-2">
<button
onClick={() => setIsFavorite(!isFavorite)}
onClick={toggleFavorite}
disabled={favLoading}
className="w-8 h-8 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center hover:bg-white transition-colors shadow-sm"
>
<Heart className={`w-4 h-4 ${isFavorite ? 'fill-red-500 text-red-500' : 'text-gray-600'}`} />
<Heart className={`w-4 h-4 ${isFav ? 'fill-red-500 text-red-500' : 'text-gray-600'}`} />
</button>
</div>
</div>
@ -622,6 +643,7 @@ export default function PropertiesPage() {
</motion.div>
)}
</div>
<Toaster position="top-center" />
</div>
);
}