diff --git a/src/actions/lbdashboard/bidOverviewActions.js b/src/actions/lbdashboard/bidOverviewActions.js
new file mode 100644
index 0000000000..2027a8b6c9
--- /dev/null
+++ b/src/actions/lbdashboard/bidOverviewActions.js
@@ -0,0 +1,62 @@
+import axios from 'axios';
+import { ENDPOINTS } from '~/utils/URL';
+import {
+ FETCH_UNIT_DETAILS_REQUEST,
+ FETCH_UNIT_DETAILS_SUCCESS,
+ FETCH_UNIT_DETAILS_FAILURE,
+ SUBMIT_BID_REQUEST,
+ SUBMIT_BID_SUCCESS,
+ SUBMIT_BID_FAILURE,
+ NOTIFICATION_SUCCESS,
+ NOTIFICATION_FAILURE,
+} from '../../constants/lbdashboard/bidOverviewConstants';
+
+export const fetchUnitDetails = listingId => async (dispatch) => {
+ try {
+ dispatch({ type: FETCH_UNIT_DETAILS_REQUEST });
+ const url = ENDPOINTS.LB_BID_OVERVIEW(listingId);
+ const { data } = await axios.get(url);
+ dispatch({
+ type: FETCH_UNIT_DETAILS_SUCCESS,
+ payload: data.listingDetail,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: FETCH_UNIT_DETAILS_FAILURE,
+ payload: error.response?.data?.message || error.message,
+ });
+ return null;
+ }
+};
+
+export const submitBid = (listingId, bidData) => async (dispatch) => {
+ try {
+ dispatch({ type: SUBMIT_BID_REQUEST });
+ const url = ENDPOINTS.LB_SUBMIT_BID(listingId);
+ console.log('Submitting bid to:', url);
+ console.log('Request body:', bidData);
+ const { data } = await axios.post(url, bidData);
+ dispatch({
+ type: SUBMIT_BID_SUCCESS,
+ payload: data.bid,
+ });
+ if(data.notifications) {
+ dispatch({
+ type: NOTIFICATION_SUCCESS,
+ payload: data.notifications,
+ });
+ console.log('Notifications:', data.notifications);
+ }
+ return data;
+ } catch (error) {
+ dispatch({
+ type: SUBMIT_BID_FAILURE,
+ payload: error.response?.data?.message || error.message,
+ });
+ dispatch({
+ type: NOTIFICATION_FAILURE,
+ payload: error.response?.data?.message || error.message,
+ });
+ }
+};
\ No newline at end of file
diff --git a/src/components/LBDashboard/BiddingOverview/BiddingOverview.jsx b/src/components/LBDashboard/BiddingOverview/BiddingOverview.jsx
index 8413f1e24e..abecedb061 100644
--- a/src/components/LBDashboard/BiddingOverview/BiddingOverview.jsx
+++ b/src/components/LBDashboard/BiddingOverview/BiddingOverview.jsx
@@ -1,44 +1,51 @@
import { useState, useEffect } from 'react';
-import { Link } from 'react-router-dom';
+import { Link, useParams } from 'react-router-dom';
import styles from './BiddingOverview.module.css';
-
import logo from '../../../assets/images/logo2.png';
+import { useSelector, useDispatch } from 'react-redux';
+import { fetchUnitDetails, submitBid } from '../../../actions/lbdashboard/bidOverviewActions';
+import Header from '../../Header/Header';
+import { BsChat } from 'react-icons/bs';
+import { IoNotificationsOutline } from 'react-icons/io5';
+import { FiUser } from 'react-icons/fi';
+import Modal from 'react-bootstrap/Modal';
+import Button from 'react-bootstrap/Button';
function BiddingOverview() {
+ const { listingId } = useParams();
+ const dispatch = useDispatch();
+
+ const userId = useSelector(state => state.auth.user.userid);
+ const auth = useSelector(state => state.auth);
+ const firstName = auth.firstName || auth.user?.firstName || auth.user?.username || 'User';
+ const unitDetails = useSelector(state => state.bidOverview.unitDetails);
+ const notifications = useSelector(state => state.bidOverview.notifications);
+ const loading = useSelector(state => state.bidOverview.loading);
+ const error = useSelector(state => state.bidOverview.error);
+ const darkMode = useSelector(state => state.theme.darkMode);
+
const [rentingFrom, setRentingFrom] = useState('');
const [rentingTo, setRentingTo] = useState('');
const [name, setName] = useState('');
const [biddingPrice, setBiddingPrice] = useState('');
const [currentImageIndex, setCurrentImageIndex] = useState(0);
+ const [imageScale, setImageScale] = useState(1);
- const unitDetails = {
- unitNumber: '405',
- villageName: 'Earthbag Village',
- description:
- "If you wish to book it in advance bid your price and leave your details below and we'll get back to you if you are our highest bidder. Make sure your starting date is at least 2 weeks from now.",
- currentBid: '40$',
- unitAmenities: [
- { id: 'ua1', text: 'Artistic Interiors' },
- { id: 'ua2', text: 'Artistic Interiors' },
- { id: 'ua3', text: 'Artistic Interiors' },
- ],
+ // Header state
+ const [selectedVillage, setSelectedVillage] = useState('Village 1');
+ const [showNotifications, setShowNotifications] = useState(false);
- villageAmenities: [
- 'Central Tropical',
- 'Eco-Conscious Water System',
- 'Solar Power Infrastructure',
- 'Passive Heating and Cooling',
- 'Community Gardens',
- 'Rainwater Harvesting Systems',
- 'Workshops and Demonstration Spaces',
- ],
- images: [
- 'https://www.chromethemer.com/backgrounds/google/images/beautiful-morning-4k-google-background.jpg',
- 'https://wallpaper.forfun.com/fetch/1d/1d033e2b725d21df94f9f6f8c289a2ba.jpeg',
- ],
- };
+ const flatNotifications = Array.isArray(notifications) ? notifications.flat() : [];
+ const notificationCount = flatNotifications.length;
+
+ useEffect(() => {
+ if (listingId) {
+ dispatch(fetchUnitDetails(listingId));
+ }
+ }, [dispatch, listingId]);
const navigateImages = direction => {
+ if (!unitDetails.images || unitDetails.images.length === 0) return;
if (direction === 'next') {
setCurrentImageIndex(prevIndex =>
prevIndex === unitDetails.images.length - 1 ? 0 : prevIndex + 1,
@@ -51,237 +58,306 @@ function BiddingOverview() {
};
const handleBiddingPriceChange = ({ target: { value } }) => {
- // Allow only empty string or digits
if (value === '' || /^\d+$/.test(value)) {
setBiddingPrice(value);
}
};
- useEffect(() => {
- const fetchUnitDetails = async () => {
- try {
- // Placeholder for API call
- } catch (error) {
- // Handle error fetching unit details if needed (e.g., send to a logging service)
- }
- };
-
- fetchUnitDetails();
- }, []);
-
const handleSubmit = e => {
e.preventDefault();
- // Handle form submission logic here
- // Example: Send data to backend API
+ if (!rentingFrom || !rentingTo || !name || !biddingPrice) {
+ alert('Please fill in all fields.');
+ return;
+ }
+ const bidData = {
+ user_id: userId,
+ property_id: listingId,
+ bid_amount: Number.parseInt(biddingPrice, 10),
+ start_date: rentingFrom,
+ end_date: rentingTo,
+ };
+ dispatch(submitBid(listingId, bidData));
+ alert('Bid submitted successfully!');
+ setRentingFrom('');
+ setRentingTo('');
+ setName(firstName || '');
+ setBiddingPrice('');
};
+ if (loading || !unitDetails) {
+ return
Loading...
;
+ }
+ if (error) {
+ return Error: {error}
;
+ }
+
return (
-
-
-

-
-
-
-
-
+
+ {/* Top site-wide header */}
+
+
+
+ {/* Logo */}
+
+

+
+
+
+ {/* ── Inlined LBDashboardHeader ── */}
+
-
-
WELCOME USER_NAME
- {/* Replace USER_NAME */}
-
-
-
+ {/* Right: welcome + icons */}
+
+
WELCOME {firstName.toUpperCase()}
+
+ {/* Chat */}
+
+
+
-
-
-
-
- Current bid: {unitDetails.currentBid} /night
-
-
-

+ {/* Notifications */}
-
-
- {unitDetails.images.map((image, index) => (
- setCurrentImageIndex(index)}
- onKeyDown={e => {
- // Added for accessibility
- if (e.key === 'Enter' || e.key === ' ') {
- setCurrentImageIndex(index);
- }
- }}
- role="button" // Added for accessibility
- tabIndex={0} // Added for accessibility
- aria-label={`Go to image ${index + 1}`}
- />
- ))}
-
-
-
-
-
-
Available amenities in this Unit:
-
- {/* FIXED: Use the unique 'id' property as the key */}
- {unitDetails.unitAmenities.map(amenity => (
- - {amenity.text}
- ))}
-
-
-
-
-
Village level amenities:
-
- {unitDetails.villageAmenities.map(amenity => (
- // Using unique amenity string as key is correct here
- - {amenity}
- ))}
-
-
-
-
-
-
- View on Property Map
+ {/* User */}
+
+
+
-
-
-
Unit {unitDetails.unitNumber}
- {unitDetails.villageName}
-
+ {/* Notifications modal */}
+
setShowNotifications(false)} centered>
+
+ Notifications
+
+
+ {flatNotifications.length > 0 ? (
+
+ {flatNotifications.map((notif, idx) => (
+ -
+ {notif.message ? notif.message : 'No message available'}
+
+ ))}
+
+ ) : (
+ No notifications.
+ )}
+
+
+
+
+
+ {/* ── End inlined header ── */}
-
{unitDetails.description}
+
+
+ {/* Left column */}
+
+
Current bid: {unitDetails.bidAmount} /night
-