diff --git a/api/getPropertiesData.js b/api/getPropertiesData.js
new file mode 100644
index 0000000..c2a26f1
--- /dev/null
+++ b/api/getPropertiesData.js
@@ -0,0 +1,15 @@
+const PROPERTIES_URL = 'http://localhost:3000/api/properties';
+
+export const getPropertiesData = async () => {
+ try {
+ const response = await fetch(PROPERTIES_URL);
+ if (!response.ok) {
+ throw new Error(`Response status: ${response.status}`);
+ }
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error(`Error fetching properties:`, error);
+ throw error;
+ }
+};
diff --git a/api/index.js b/api/index.js
new file mode 100644
index 0000000..c979625
--- /dev/null
+++ b/api/index.js
@@ -0,0 +1 @@
+export * from './getPropertiesData';
diff --git a/src/components/PropertyListing/PropertyListing.jsx b/src/components/PropertyListing/PropertyListing.jsx
index ed43fb5..ad2c694 100644
--- a/src/components/PropertyListing/PropertyListing.jsx
+++ b/src/components/PropertyListing/PropertyListing.jsx
@@ -1,33 +1,71 @@
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import PropertyCard from '../PropertyCard';
import './PropertyListing.scss';
-
-const DUMMY_PROPERTY = {
- id: 73864112,
- bedrooms: 3,
- summary: 'Property 1 Situated moments from the River Thames in Old Chelsea...',
- displayAddress: '1 CHEYNE WALK, CHELSEA, SW3',
- propertyType: 'Flat',
- price: 1950000,
- branchName: 'M2 Property, London',
- propertyUrl: '/property-for-sale/property-73864112.html',
- contactUrl: '/property-for-sale/contactBranch.html?propertyId=73864112',
- propertyTitle: '3 bedroom flat for sale',
- mainImage:
- 'https://media.rightmove.co.uk/dir/crop/10:9-16:9/38k/37655/53588679/37655_CAM170036_IMG_01_0000_max_476x317.jpg',
-};
+import { getPropertiesData } from '../../../api/getPropertiesData';
const PropertyListing = () => {
+ const [properties, setProperties] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ setProperties(await getPropertiesData());
+ } catch (err) {
+ setError('Failed to load properties');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+ fetchData();
+ }, []);
+
+ if (error) {
+ return (
+
+ {error}
+
+ );
+ }
+
+ if (!isLoading && properties.length === 0) {
+ return No properties found.
;
+ }
+
return (
-
- {Array(5)
- .fill(DUMMY_PROPERTY)
- .map((property, index) => (
- -
-
-
- ))}
-
+ <>
+ {isLoading ? (
+
+ Loading...
+
+ ) : (
+
+
+ Properties
+
+
+ {properties.map((property, index) => (
+ -
+
+
+ ))}
+
+
+ )}
+ >
);
};
diff --git a/src/components/PropertyListing/tests/PropertyListing.spec.jsx b/src/components/PropertyListing/tests/PropertyListing.spec.jsx
index 807d63b..08869a8 100644
--- a/src/components/PropertyListing/tests/PropertyListing.spec.jsx
+++ b/src/components/PropertyListing/tests/PropertyListing.spec.jsx
@@ -3,11 +3,52 @@ import { render, screen } from '@testing-library/react';
import { within } from '@testing-library/dom';
import PropertyListing from '../PropertyListing';
+const mockProperties = [
+ {
+ id: 1,
+ bedrooms: 2,
+ summary: 'Summary for property 1.',
+ displayAddress: '123 Dummy Street, Testville',
+ propertyType: 'Detached',
+ price: 100000,
+ branchName: 'Test Branch',
+ propertyUrl: '/property-for-sale/property-1.html',
+ contactUrl: '/property-for-sale/contactBranch.html?propertyId=1',
+ propertyTitle: '2 bedroom detached house for sale',
+ mainImage: 'https://dummyimage.com/000000.jpg&text=Property+1',
+ },
+ {
+ id: 2,
+ bedrooms: 3,
+ summary: 'Summary for property 2.',
+ displayAddress: '456 Example Avenue, Mocktown',
+ propertyType: 'Flat',
+ price: 200000,
+ branchName: 'Mock Branch',
+ propertyUrl: '/property-for-sale/property-2.html',
+ contactUrl: '/property-for-sale/contactBranch.html?propertyId=2',
+ propertyTitle: '3 bedroom flat for sale',
+ mainImage: 'https://dummyimage.com/000000.jpg&text=Property+2',
+ },
+];
+
describe('PropertyListing', () => {
- it('should render five property cards', async () => {
+ beforeEach(() => {
+ global.fetch = jest.fn(() =>
+ Promise.resolve({
+ ok: true,
+ json: () => Promise.resolve(mockProperties),
+ })
+ );
+ });
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+ it('should render the property cards correctly', async () => {
render();
const propertiesList = screen.getByRole('list');
const propertyCards = await within(propertiesList).findAllByRole('listitem');
- expect(propertyCards).toHaveLength(5);
+ expect(propertyCards).toHaveLength(mockProperties.length);
});
});