update some stuff
This commit is contained in:
@@ -8,7 +8,8 @@ import {
|
||||
TrashIcon,
|
||||
ArrowLeftIcon,
|
||||
MapPinIcon,
|
||||
SwatchIcon
|
||||
SwatchIcon,
|
||||
PencilIcon
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { propertiesAPI } from '../../services/api';
|
||||
import LoadingSpinner from '../../components/UI/LoadingSpinner';
|
||||
@@ -54,10 +55,19 @@ function PolygonDrawer({ isDrawing, onPolygonComplete, currentColor }) {
|
||||
if (!isDrawing) return;
|
||||
|
||||
const newPoint = [e.latlng.lat, e.latlng.lng];
|
||||
setCurrentPolygon(prev => [...prev, newPoint]);
|
||||
console.log('Adding point:', newPoint);
|
||||
setCurrentPolygon(prev => {
|
||||
const newPoly = [...prev, newPoint];
|
||||
console.log('Current polygon has', newPoly.length, 'points');
|
||||
return newPoly;
|
||||
});
|
||||
},
|
||||
dblclick() {
|
||||
dblclick(e) {
|
||||
console.log('Double click detected, drawing:', isDrawing, 'points:', currentPolygon.length);
|
||||
if (isDrawing && currentPolygon.length >= 3) {
|
||||
e.originalEvent.preventDefault();
|
||||
e.originalEvent.stopPropagation();
|
||||
console.log('Completing polygon with', currentPolygon.length, 'points');
|
||||
onPolygonComplete(currentPolygon);
|
||||
setCurrentPolygon([]);
|
||||
}
|
||||
@@ -89,11 +99,30 @@ const PropertyDetail = () => {
|
||||
const [showNameModal, setShowNameModal] = useState(false);
|
||||
const [pendingSection, setPendingSection] = useState(null);
|
||||
const [sectionName, setSectionName] = useState('');
|
||||
const [editingSection, setEditingSection] = useState(null);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchPropertyDetails();
|
||||
}, [id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Handle keyboard shortcuts for polygon drawing
|
||||
useEffect(() => {
|
||||
const handleKeyPress = (e) => {
|
||||
if (isDrawing && e.key === 'Enter') {
|
||||
// Find the PolygonDrawer component and complete the polygon
|
||||
console.log('Enter pressed during drawing mode');
|
||||
}
|
||||
if (e.key === 'Escape' && isDrawing) {
|
||||
setIsDrawing(false);
|
||||
toast.info('Drawing cancelled');
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handleKeyPress);
|
||||
return () => document.removeEventListener('keydown', handleKeyPress);
|
||||
}, [isDrawing]);
|
||||
|
||||
const fetchPropertyDetails = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -110,12 +139,14 @@ const PropertyDetail = () => {
|
||||
};
|
||||
|
||||
const handlePolygonComplete = (coordinates) => {
|
||||
console.log('handlePolygonComplete called with', coordinates.length, 'coordinates');
|
||||
if (coordinates.length < 3) {
|
||||
toast.error('Polygon needs at least 3 points');
|
||||
return;
|
||||
}
|
||||
|
||||
const area = calculateAreaInSqFt([...coordinates, coordinates[0]]);
|
||||
console.log('Calculated area:', area);
|
||||
setPendingSection({ coordinates, color: currentColor, area });
|
||||
setShowNameModal(true);
|
||||
setIsDrawing(false);
|
||||
@@ -153,6 +184,34 @@ const PropertyDetail = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const startEditSection = (section) => {
|
||||
setEditingSection(section);
|
||||
setSectionName(section.name);
|
||||
setCurrentColor(section.color);
|
||||
setShowEditModal(true);
|
||||
};
|
||||
|
||||
const saveEditedSection = () => {
|
||||
if (!sectionName.trim()) {
|
||||
toast.error('Please enter a section name');
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedSection = {
|
||||
...editingSection,
|
||||
name: sectionName,
|
||||
color: currentColor
|
||||
};
|
||||
|
||||
setLawnSections(prev => prev.map(s => s.id === editingSection.id ? updatedSection : s));
|
||||
toast.success('Section updated!');
|
||||
|
||||
// Reset
|
||||
setSectionName('');
|
||||
setEditingSection(null);
|
||||
setShowEditModal(false);
|
||||
};
|
||||
|
||||
const getTotalArea = () => {
|
||||
return lawnSections.reduce((total, section) => total + section.area, 0);
|
||||
};
|
||||
@@ -231,7 +290,8 @@ const PropertyDetail = () => {
|
||||
<div style={{ height: '600px', width: '100%' }}>
|
||||
<MapContainer
|
||||
center={mapCenter}
|
||||
zoom={hasValidCoordinates ? 19 : 13}
|
||||
zoom={hasValidCoordinates ? 21 : 13}
|
||||
maxZoom={23}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
<TileLayer
|
||||
@@ -260,13 +320,21 @@ const PropertyDetail = () => {
|
||||
<div className="text-center">
|
||||
<strong>{section.name}</strong><br />
|
||||
{section.area.toLocaleString()} sq ft<br />
|
||||
<div className="flex gap-2 mt-2">
|
||||
<button
|
||||
onClick={() => startEditSection(section)}
|
||||
className="text-blue-600 text-sm"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
onClick={() => deleteLawnSection(section.id)}
|
||||
className="text-red-600 text-sm mt-2"
|
||||
className="text-red-600 text-sm"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
</Polygon>
|
||||
))}
|
||||
@@ -282,9 +350,15 @@ const PropertyDetail = () => {
|
||||
</div>
|
||||
|
||||
{isDrawing && (
|
||||
<div className="p-4 bg-blue-50">
|
||||
<div className="p-4 bg-blue-50 border-t">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 bg-blue-600 rounded-full animate-pulse"></div>
|
||||
<p className="text-sm text-blue-800">
|
||||
<strong>Drawing Mode:</strong> Click to add points. Double-click to complete polygon.
|
||||
<strong>Drawing Mode Active:</strong> Click to add points. Double-click to complete polygon.
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-blue-600 mt-1">
|
||||
Need at least 3 points to create a section. Press ESC to cancel.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -350,6 +424,13 @@ const PropertyDetail = () => {
|
||||
<p className="text-xs text-gray-600">{section.area.toLocaleString()} sq ft</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
onClick={() => startEditSection(section)}
|
||||
className="text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
<PencilIcon className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => deleteLawnSection(section.id)}
|
||||
className="text-red-600 hover:text-red-800"
|
||||
@@ -357,6 +438,7 @@ const PropertyDetail = () => {
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
@@ -366,8 +448,8 @@ const PropertyDetail = () => {
|
||||
|
||||
{/* Name Modal */}
|
||||
{showNameModal && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
<div className="bg-white rounded-lg p-6 w-96">
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center" style={{ zIndex: 9999 }}>
|
||||
<div className="bg-white rounded-lg p-6 w-96 shadow-2xl">
|
||||
<h3 className="text-lg font-semibold mb-4">Name Your Lawn Section</h3>
|
||||
<div className="space-y-4">
|
||||
<input
|
||||
@@ -404,6 +486,68 @@ const PropertyDetail = () => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Edit Modal */}
|
||||
{showEditModal && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center" style={{ zIndex: 9999 }}>
|
||||
<div className="bg-white rounded-lg p-6 w-96 shadow-2xl">
|
||||
<h3 className="text-lg font-semibold mb-4">Edit Lawn Section</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="label">Section Name</label>
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
value={sectionName}
|
||||
onChange={(e) => setSectionName(e.target.value)}
|
||||
placeholder="e.g., Front Yard, Back Lawn"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="label">Color</label>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{SECTION_COLORS.map((color) => (
|
||||
<button
|
||||
key={color.value}
|
||||
onClick={() => setCurrentColor(color)}
|
||||
className={`w-10 h-10 rounded border-2 ${
|
||||
currentColor.value === color.value ? 'border-gray-900' : 'border-gray-300'
|
||||
}`}
|
||||
style={{ backgroundColor: color.value }}
|
||||
title={color.name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-gray-600">
|
||||
<div
|
||||
className="w-4 h-4 rounded"
|
||||
style={{ backgroundColor: currentColor.value }}
|
||||
/>
|
||||
<span>{editingSection?.area.toLocaleString()} sq ft</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-3 mt-6">
|
||||
<button onClick={saveEditedSection} className="btn-primary flex-1">
|
||||
Save Changes
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowEditModal(false);
|
||||
setEditingSection(null);
|
||||
setSectionName('');
|
||||
}}
|
||||
className="btn-secondary flex-1"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user