added a swicher on the properties
Some checks failed
Build frontend / build (push) Failing after 40s

This commit is contained in:
mouazkh
2026-05-26 22:53:18 +03:00
parent 01b966c1d2
commit 29de55196a
2 changed files with 46 additions and 25 deletions

View File

@ -5,11 +5,12 @@ import { motion } from 'framer-motion';
import { useRouter } from 'next/navigation';
import {
Calendar, Clock, CheckCircle, XCircle, Eye, Loader2, Search,
MapPin, DollarSign, Home, ArrowLeft, CreditCard, Timer,
MapPin, DollarSign, Home, ArrowLeft, CreditCard, Timer, Star,
} from 'lucide-react';
import toast, { Toaster } from 'react-hot-toast';
import AuthService from '../services/AuthService';
import { getRentProperties, getUserReservations, payDeposit } from '../utils/api';
import { addPropertyRating } from '../utils/ratings';
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
@ -106,12 +107,17 @@ function ReservationCard({ r, onViewDetails, onPay, payingId }) {
const beds = propBeds(p, r);
const baths = propBaths(p, r);
const isOwnerConfirmed = STATUS_MAP[r.status] === 'ownerConfirmed';
const canRate = STATUS_MAP[r.status] === 'depositPaid' || STATUS_MAP[r.status] === 'completed';
const hasTimeWindow = r.ownerApprovalDate && p?.allowedPaymentPeriod;
const deadline = hasTimeWindow
? new Date(r.ownerApprovalDate).getTime() + parseTimeSpan(p.allowedPaymentPeriod)
: null;
const isExpired = deadline ? Date.now() > deadline : false;
const isPaying = payingId === r.id;
const [showRating, setShowRating] = useState(false);
const [ratingValue, setRatingValue] = useState(0);
const [ratingComment, setRatingComment] = useState('');
const [submittingRating, setSubmittingRating] = useState(false);
return (
<motion.div initial={{ opacity:0,y:20 }} animate={{ opacity:1,y:0 }}
@ -139,7 +145,7 @@ function ReservationCard({ r, onViewDetails, onPay, payingId }) {
<div className="text-sm font-medium">{new Date(r.endDate).toLocaleDateString('ar')}</div>
</div>
</div>
{hasTimeWindow && <div className="bg-blue-50 p-3 rounded-xl mb-3">
{isOwnerConfirmed && hasTimeWindow && <div className="bg-blue-50 p-3 rounded-xl mb-3">
<div className="flex items-center justify-between mb-1">
<span className="text-sm text-blue-800 font-medium flex items-center gap-1"><Timer className="w-4 h-4"/> متبقي للدفع:</span>
<CountdownTimer deadline={deadline} />
@ -156,6 +162,42 @@ function ReservationCard({ r, onViewDetails, onPay, payingId }) {
{isPaying ? <Loader2 className="w-4 h-4 animate-spin"/> : <CreditCard className="w-4 h-4"/>} {isPaying ? 'جاري الدفع...' : 'ادفع الآن'}
</button>}
</div>
{canRate && !showRating && <button onClick={() => setShowRating(true)}
className="w-full mt-3 bg-amber-50 text-amber-700 py-2 rounded-xl text-sm font-medium hover:bg-amber-100 transition-colors flex items-center justify-center gap-2">
<Star className="w-4 h-4"/> قيّم هذا العقار
</button>}
{canRate && showRating && <div className="mt-3 bg-amber-50 p-3 rounded-xl">
<div className="flex gap-1 justify-center mb-2">
{[1,2,3,4,5].map(n => (
<button key={n} onClick={() => setRatingValue(n)}
className={`p-1 rounded-full transition-colors ${n <= ratingValue ? 'text-amber-500' : 'text-gray-300'}`}>
<Star className={`w-6 h-6 ${n <= ratingValue ? 'fill-amber-500' : ''}`} />
</button>
))}
</div>
<textarea value={ratingComment} onChange={e => setRatingComment(e.target.value)}
placeholder="أكتب تعليقك (اختياري)"
className="w-full p-2 text-sm border border-amber-200 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-amber-500 mb-2" rows={2} />
<div className="flex gap-2">
<button onClick={async () => {
if (!ratingValue) return toast.error('اختر تقييماً');
setSubmittingRating(true);
try {
await addPropertyRating({ reservationId: r.id, cleanRating: ratingValue, servicesRating: ratingValue, ownerBehaviorRating: ratingValue, experienceRating: ratingValue, comment: ratingComment || null });
toast.success('تم إرسال التقييم');
setShowRating(false);
setRatingValue(0);
setRatingComment('');
} catch (e) { toast.error(e?.message || 'فشل إرسال التقييم'); }
finally { setSubmittingRating(false); }
}} disabled={submittingRating}
className="flex-1 bg-amber-500 text-white py-1.5 rounded-lg text-sm font-medium hover:bg-amber-600 transition-colors disabled:bg-gray-300">
{submittingRating ? 'جاري الإرسال...' : 'إرسال التقييم'}
</button>
<button onClick={() => { setShowRating(false); setRatingValue(0); setRatingComment(''); }}
className="px-4 py-1.5 bg-gray-200 text-gray-700 rounded-lg text-sm hover:bg-gray-300 transition-colors">إلغاء</button>
</div>
</div>}
</div>
</motion.div>
);
@ -206,7 +248,7 @@ function DetailsModal({ r, isOpen, onClose, onPay, payingId }) {
<h3 className="font-bold text-amber-700 mb-3 flex items-center gap-2"><DollarSign className="w-5 h-5"/> المعلومات المالية</h3>
<div className="flex justify-between font-bold"><span className="text-gray-900">الإجمالي</span><span className="text-amber-600 text-lg">{r.totalPrice?.toLocaleString()??''}</span></div>
</div>
{hasTimeWindow && <div className="bg-blue-50 p-4 rounded-xl">
{isOwnerConfirmed && hasTimeWindow && <div className="bg-blue-50 p-4 rounded-xl">
<div className="flex items-center justify-between mb-2">
<span className="text-blue-800 font-medium flex items-center gap-2"><Timer className="w-5 h-5"/> متبقي للدفع:</span>
<CountdownTimer deadline={deadline} />