diff --git a/frontend/src/pages/Admin/AdminDashboard.js b/frontend/src/pages/Admin/AdminDashboard.js index 9638a71..f516726 100644 --- a/frontend/src/pages/Admin/AdminDashboard.js +++ b/frontend/src/pages/Admin/AdminDashboard.js @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { Link } from 'react-router-dom'; import { UsersIcon, CogIcon, BuildingOfficeIcon, ChartBarIcon } from '@heroicons/react/24/outline'; import { adminAPI } from '../../services/api'; import LoadingSpinner from '../../components/UI/LoadingSpinner'; @@ -117,17 +118,26 @@ const AdminDashboard = () => {

Quick Actions

- - -
diff --git a/frontend/src/pages/Properties/Properties.js b/frontend/src/pages/Properties/Properties.js index 6005d7d..ed4916d 100644 --- a/frontend/src/pages/Properties/Properties.js +++ b/frontend/src/pages/Properties/Properties.js @@ -1,12 +1,254 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; +import { Link } from 'react-router-dom'; +import { PlusIcon, MapPinIcon, TrashIcon, PencilIcon } from '@heroicons/react/24/outline'; +import { propertiesAPI } from '../../services/api'; +import LoadingSpinner from '../../components/UI/LoadingSpinner'; +import toast from 'react-hot-toast'; const Properties = () => { + const [properties, setProperties] = useState([]); + const [loading, setLoading] = useState(true); + const [showCreateForm, setShowCreateForm] = useState(false); + const [formData, setFormData] = useState({ + name: '', + address: '', + latitude: '', + longitude: '', + totalArea: '' + }); + + useEffect(() => { + fetchProperties(); + }, []); + + const fetchProperties = async () => { + try { + setLoading(true); + const response = await propertiesAPI.getAll(); + setProperties(response.data.data || []); + } catch (error) { + console.error('Failed to fetch properties:', error); + toast.error('Failed to load properties'); + } finally { + setLoading(false); + } + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const propertyData = { + ...formData, + latitude: formData.latitude ? parseFloat(formData.latitude) : null, + longitude: formData.longitude ? parseFloat(formData.longitude) : null, + totalArea: formData.totalArea ? parseFloat(formData.totalArea) : null + }; + + await propertiesAPI.create(propertyData); + toast.success('Property created successfully!'); + setShowCreateForm(false); + setFormData({ name: '', address: '', latitude: '', longitude: '', totalArea: '' }); + fetchProperties(); + } catch (error) { + console.error('Failed to create property:', error); + toast.error(error.response?.data?.message || 'Failed to create property'); + } + }; + + const handleDelete = async (id, name) => { + if (window.confirm(`Are you sure you want to delete "${name}"?`)) { + try { + await propertiesAPI.delete(id); + toast.success('Property deleted successfully'); + fetchProperties(); + } catch (error) { + console.error('Failed to delete property:', error); + toast.error('Failed to delete property'); + } + } + }; + + if (loading) { + return ( +
+

Properties

+
+ +
+
+ ); + } + return (
-

Properties

-
-

Property management coming soon...

+
+
+

Properties

+

Manage your lawn care properties

+
+
+ + {/* Create Property Form */} + {showCreateForm && ( +
+

Add New Property

+
+
+
+ + setFormData({ ...formData, name: e.target.value })} + placeholder="e.g., Main Lawn, Front Yard" + /> +
+
+ + setFormData({ ...formData, address: e.target.value })} + placeholder="123 Main St, City, State" + /> +
+
+ + setFormData({ ...formData, latitude: e.target.value })} + placeholder="40.7128" + /> +
+
+ + setFormData({ ...formData, longitude: e.target.value })} + placeholder="-74.0060" + /> +
+
+ + setFormData({ ...formData, totalArea: e.target.value })} + placeholder="5000" + /> +
+
+
+ + +
+
+
+ )} + + {/* Properties List */} + {properties.length === 0 ? ( +
+ +

No Properties Yet

+

Get started by adding your first property

+ +
+ ) : ( +
+ {properties.map((property) => ( +
+
+
+

{property.name}

+ {property.address && ( +

+ + {property.address} +

+ )} +
+
+ + + + +
+
+ +
+ {property.totalArea && ( +
+ Total Area: + {property.totalArea.toLocaleString()} sq ft +
+ )} +
+ Sections: + {property.sectionCount || 0} +
+
+ Created: + + {new Date(property.createdAt).toLocaleDateString()} + +
+
+ +
+ + View Details → + +
+
+ ))} +
+ )}
); };