Commited by hamza on openclaw's belalf
Some checks failed
Build frontend / build (push) Failing after 54s
Some checks failed
Build frontend / build (push) Failing after 54s
This commit is contained in:
@ -49,6 +49,9 @@ import { getRentProperty, getSaleProperty, bookReservation, checkAvailability, g
|
||||
import AuthService from '../../services/AuthService';
|
||||
import { useFavorites } from '@/app/contexts/FavoritesContext';
|
||||
import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from '../../enums';
|
||||
import RatingForm from '../../components/ratings/RatingForm.js';
|
||||
import RatingList from '../../components/ratings/RatingList.js';
|
||||
import StarRating from '../../components/ratings/StarRating.js';
|
||||
|
||||
// Copy to clipboard that works on HTTP too
|
||||
async function copyToClipboard(text) {
|
||||
@ -177,6 +180,11 @@ export default function PropertyDetailsPage() {
|
||||
const [favLoading, setFavLoading] = useState(false);
|
||||
const [selectingEnd, setSelectingEnd] = useState(false);
|
||||
const [showLoginDialog, setShowLoginDialog] = useState(false);
|
||||
const [showRatingForm, setShowRatingForm] = useState(false);
|
||||
const [currentRating, setCurrentRating] = useState(0);
|
||||
const [currentComment, setCurrentComment] = useState('');
|
||||
const [userRating, setUserRating] = useState(null);
|
||||
const [canRate, setCanRate] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const id = params.id;
|
||||
@ -218,20 +226,29 @@ export default function PropertyDetailsPage() {
|
||||
fetchProperty();
|
||||
}, [params.id]);
|
||||
|
||||
// Fetch available date ranges
|
||||
// Fetch user rating and check if they can rate
|
||||
useEffect(() => {
|
||||
if (!property) return;
|
||||
const propId = property._raw?.id || params.id;
|
||||
console.log('[Property] Fetching available dates for:', propId);
|
||||
getAvailableDateRanges(propId)
|
||||
.then((data) => {
|
||||
const ranges = Array.isArray(data) ? data : [];
|
||||
console.log('[Property] Available date ranges:', ranges);
|
||||
setAvailableRanges(ranges);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('[Property] Failed to fetch available dates:', err);
|
||||
});
|
||||
async function fetchUserRatingAndCheck() {
|
||||
if (!property || !AuthService.isAuthenticated()) return;
|
||||
|
||||
try {
|
||||
// Check if user has already rated
|
||||
const rating = await getUserPropertyRating(property._raw?.id || parseInt(params.id), AuthService.getUserId());
|
||||
if (rating) {
|
||||
setUserRating(rating);
|
||||
setCurrentRating(rating.rating);
|
||||
setCurrentComment(rating.comment || '');
|
||||
}
|
||||
|
||||
// Check if user can rate (e.g., after renting)
|
||||
const canRateProperty = await canRateProperty(property._raw?.id || parseInt(params.id), AuthService.getUserId());
|
||||
setCanRate(canRateProperty);
|
||||
} catch (error) {
|
||||
console.error('[Property] Failed to fetch user rating:', error);
|
||||
}
|
||||
}
|
||||
|
||||
fetchUserRatingAndCheck();
|
||||
}, [property, params.id]);
|
||||
|
||||
// Set Open Graph meta tags dynamically for Facebook/Twitter sharing
|
||||
@ -754,6 +771,10 @@ export default function PropertyDetailsPage() {
|
||||
{property.reviewList.map((review, idx) => (
|
||||
<div key={idx} className="border-b border-gray-100 last:border-0 pb-4 last:pb-0">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-10 h-10 bg-gray-100 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
<User className="w-6 h-6 text-gray-600" />
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-bold text-gray-900">{review.user}</span>
|
||||
<div className="flex items-center gap-1 mt-1">
|
||||
@ -762,6 +783,7 @@ export default function PropertyDetailsPage() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">{review.date}</span>
|
||||
</div>
|
||||
<p className="text-gray-600">{review.comment}</p>
|
||||
@ -771,24 +793,32 @@ export default function PropertyDetailsPage() {
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{property.rules && property.rules.length > 0 && (
|
||||
{/* New Rating Components */}
|
||||
{AuthService.isAuthenticated() && canRate && !userRating && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.65 }}
|
||||
className="bg-amber-50 border-2 border-amber-200 rounded-xl p-4 text-center cursor-pointer hover:border-amber-300 transition-all"
|
||||
onClick={() => setShowRatingForm(true)}
|
||||
>
|
||||
<Star className="w-8 h-8 text-amber-500 mx-auto mb-2" />
|
||||
<h3 className="font-bold text-amber-700 mb-2">قيّم هذا العقار</h3>
|
||||
<<p className="text-sm text-amber-600">شارك تجربتك مع المستأجرين الآخرين</p>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.7 }}
|
||||
className="bg-white rounded-2xl p-6 shadow-sm border border-gray-100"
|
||||
className="bg-white rounded-2xl p-6 shadow-sm border border-gray-200"
|
||||
>
|
||||
<h2 className="text-xl font-bold mb-4 text-gray-900">قوانين المنزل</h2>
|
||||
<ul className="space-y-2">
|
||||
{property.rules.map((rule, idx) => (
|
||||
<li key={idx} className="flex items-center gap-2 text-gray-600">
|
||||
<div className="w-1.5 h-1.5 bg-gray-400 rounded-full" />
|
||||
{rule}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<RatingList
|
||||
propertyId={property._raw?.id || parseInt(params.id)}
|
||||
userId={AuthService.getUserId()}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
|
||||
Reference in New Issue
Block a user