From 18d35a0ad23aed1d00cbd55ad424b5fbc893ff10 Mon Sep 17 00:00:00 2001 From: Suriya Date: Thu, 9 Jul 2026 12:10:32 +0530 Subject: [PATCH] fix: customer edit dialog field names + safe stub - pre-fill from confirmed fields (name/phone/email) - submit stubbed to toast until PATCH /admin/customers/:id exists - flagged in comment for Phase 3 backend work Co-Authored-By: Claude Sonnet 5 --- src/pages/nearle/customers/customers.js | 399 ++---------------------- 1 file changed, 34 insertions(+), 365 deletions(-) diff --git a/src/pages/nearle/customers/customers.js b/src/pages/nearle/customers/customers.js index d479019..5468ef6 100644 --- a/src/pages/nearle/customers/customers.js +++ b/src/pages/nearle/customers/customers.js @@ -1,5 +1,4 @@ -import { React, useState, useEffect, useRef, useMemo } from 'react'; -import axios from 'axios'; +import { React, useState, useEffect, useRef } from 'react'; import { FaRegEdit } from 'react-icons/fa'; import LoaderWithImage from 'components/nearle_components/LoaderWithImage'; @@ -23,7 +22,6 @@ import { DialogContent, Button, TextField, - Autocomplete, Avatar, Paper, useMediaQuery, @@ -39,10 +37,6 @@ import { MdOutlineHowToReg, MdOutlinePlace } from 'react-icons/md'; -import Geocode from 'react-geocode'; -import LocationOnIcon from '@mui/icons-material/LocationOn'; -import parse from 'autosuggest-highlight/parse'; -import { debounce } from '@mui/material/utils'; // project imports import Loader from 'components/Loader'; import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar'; @@ -108,23 +102,6 @@ const AccentAvatar = ({ color, selected, size = 24, children }) => ( ); -// ==============================|| google address ||============================== // -const GOOGLE_MAPS_API_KEY = process.env.REACT_APP_GOOGLE_MAPS_API_KEY; - -function loadScript(src, position, id) { - if (!position) { - return; - } - - const script = document.createElement('script'); - script.setAttribute('async', ''); - script.setAttribute('id', id); - script.src = src; - position.appendChild(script); -} - -const autocompleteService = { current: null }; - // ==============================|| MUI TABLE - ENHANCED ||============================== // export default function Customers() { @@ -138,138 +115,9 @@ export default function Customers() { const [locaName, setLocoName] = useState('All'); const [selectedCustomer, setSelectedCustomer] = useState({}); // to edit const [open, setOpen] = useState(false); - const [address, setAddress] = useState(''); - const [latlong, setLatlong] = useState({}); - const [city, setCity] = useState(''); - const [postcode, setPostcode] = useState(''); - const [state, setState] = useState(''); - const [suburb, setSuburb] = useState(''); const [searchword, setSearchword] = useState(''); const [debouncedSearch, setDebouncedSearch] = useState(''); - // ==============================|| for google address ||============================== // - const [value, setValue] = useState(null); - const [inputValue, setInputValue] = useState(''); - const [options, setOptions] = useState([]); - const loaded = useRef(false); - if (typeof window !== 'undefined' && !loaded.current) { - if (!document.querySelector('#google-maps')) { - loadScript( - `https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAPS_API_KEY}&libraries=places`, - document.querySelector('head'), - 'google-maps' - ); - } - - loaded.current = true; - } - const fetch = useMemo( - () => - debounce((request, callback) => { - autocompleteService.current.getPlacePredictions(request, callback); - }, 400), - [] - ); - useEffect(() => { - let active = true; - - if (!autocompleteService.current && window.google) { - autocompleteService.current = new window.google.maps.places.AutocompleteService(); - } - if (!autocompleteService.current) { - return undefined; - } - - if (inputValue === '') { - setOptions(value ? [value] : []); - return undefined; - } - - fetch({ input: inputValue }, (results) => { - if (active) { - let newOptions = []; - - if (value) { - newOptions = [value]; - } - - if (results) { - newOptions = [...newOptions, ...results]; - } - - setOptions(newOptions); - } - }); - - return () => { - active = false; - }; - }, [value, inputValue, fetch]); - - Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY); - useEffect(() => { - try { - console.log('selected address =>', address); - Geocode.fromAddress(address).then( - (response) => { - console.log('lat long response =>', response.results[0]); - if (response.status == 'OK') { - const { lat, lng } = response.results[0].geometry.location; - setLatlong({ - lat, - lng - }); - // setSelectedCustomer({ - // ...selectedCustomer, - // latitude: lat, - // longitude: lng - // }); - if (response.results[0].address_components) { - let place = response.results[0]; - let city1, zipcode1, state1, suburb1; - for (let i = 0; i < place.address_components.length; i++) { - for (let j = 0; j < place.address_components[i].types.length; j++) { - switch (place.address_components[i].types[j]) { - case 'locality': - city1 = place.address_components[i].long_name; - break; - case 'administrative_area_level_1': - state1 = place.address_components[i].long_name; - break; - case 'postal_code': - zipcode1 = place.address_components[i].long_name; - break; - case 'sublocality': - suburb1 = place.address_components[i].long_name; - break; - } - } - } - setCity(city1 || ''); - setState(state1 || ''); - setPostcode(zipcode1 || ''); - setSuburb(suburb1 || ''); - setSelectedCustomer((prev) => ({ - ...prev, - city: city1 || '', - state: state1 || '', - postcode: zipcode1 || '', - suburb: suburb1 || '', - latitude: lat || '', - longitude: lng || '' - })); - } - } - }, - (error) => { - console.log(error); - } - ); - } catch (err) { - console.log(err); - } - }, [address]); - // ==============================|| getallcustomers (customers) ||============================== // const { @@ -325,67 +173,16 @@ export default function Customers() { useEffect(() => { console.log('pageCount', pageCount); }, [pageCount]); - // ==============================|| updateCustomer (post)||============================== // + // ==============================|| updateCustomer (PATCH) ||============================== // + // TEMPORARY: PATCH /admin/customers/:id doesn't exist yet — it wasn't part + // of the endpoints built alongside GET /admin/customers. Once it ships, + // this becomes: + // axios.patch(`${process.env.REACT_APP_URL}/admin/customers/${selectedCustomer.appcustomerid}`, + // { name: selectedCustomer.name, phone: selectedCustomer.phone, email: selectedCustomer.email }) + // Stub avoids sending a request that would 404 — same pattern used for + // cancelOrder/cancelDeliveryAPI before the cancel endpoint shipped. const updateCustomer = async () => { - console.log('selectedCustomer', selectedCustomer); - - if (!selectedCustomer.firstname) { - OpenToast('Enter Door NO', 'warning', 1500); - } else if (!selectedCustomer.contactno) { - OpenToast('Enter Contact Number ', 'warning', 1500); - } else if (!selectedCustomer.address) { - OpenToast('Enter Valid Address', 'warning', 1500); - } else if (!selectedCustomer.suburb) { - OpenToast('Enter Suburb', 'warning', 1500); - } else if (!selectedCustomer.city) { - OpenToast('Enter City ', 'warning', 1500); - } else if (!selectedCustomer.state) { - OpenToast('Enter State', 'warning', 1500); - } else if (!selectedCustomer.postcode) { - OpenToast('Enter PostCode', 'warning', 1500); - } else if (!selectedCustomer.landmark) { - OpenToast('Enter Landmark', 'warning', 1500); - } else if (!selectedCustomer.latitude) { - OpenToast('Enter Latitude', 'warning', 1500); - } else if (!selectedCustomer.longitude) { - OpenToast('Enter Longitude', 'warning', 1500); - } else { - try { - // NOTE: no Doormile "update customer" endpoint has been specified — - // this still calls the old /customers/update path and will fail - // against api.doormile.com. Left as-is rather than guessed at. - const postUpdateResponse = await axios.put(`${process.env.REACT_APP_URL}/customers/update`, { - customerid: selectedCustomer.customerid, - configid: 1, - firstname: selectedCustomer.firstname, - applocationid: selectedCustomer.applocationid, - profileimage: '', - dialcode: '+91', - contactno: selectedCustomer.contactno, - devicetype: '', - deviceid: '', - customertoken: '123', - address: selectedCustomer.address, - suburb: suburb, - city: city, - state: state, - postcode: postcode, - landmark: selectedCustomer.landmark, - doorno: selectedCustomer.doorno, - latitude: selectedCustomer.latitude.toString(), - longitude: selectedCustomer.longitude.toString() - }); - - console.log('postUpdateResponse', postUpdateResponse); - if (postUpdateResponse.data.status) { - OpenToast(postUpdateResponse.data.message, 'success', 1500); - setOpen(false); - getallcustomersRefetch(); - } - } catch (error) { - console.log('postUpdate error', error); - } - } + OpenToast('Customer edit coming soon', 'info', 3000); }; const KPI_META = [ { key: 'total', label: 'Total Customers', color: '#C01227', icon: MdOutlineGroups, value: pageCount?.Total ?? 0 }, @@ -780,36 +577,36 @@ export default function Customers() { Customer - Edit {selectedCustomer?.firstname || 'Customer'} + Edit {selectedCustomer?.name || 'Customer'} - - Customer Name + + Name { - setSelectedCustomer({ - ...selectedCustomer, - firstname: e.target.value - }); + setSelectedCustomer((prev) => ({ + ...prev, + name: e.target.value + })); }} /> - - Contact Number + + Phone ({ ...prev, - contactno: value + phone: value })); }} /> - Address - (typeof option === 'string' ? option : option?.description || '')} - filterOptions={(x) => x} - options={options} - autoComplete - includeInputInList - filterSelectedOptions - value={selectedCustomer?.address} - noOptionsText="No locations" - onChange={(event, newValue) => { - setOptions(newValue ? [newValue, ...options] : options); - setValue(newValue); - console.log('newValue', newValue || ''); - setAddress(newValue?.description); - setSelectedCustomer({ - ...selectedCustomer, - address: newValue?.description - }); - }} - onInputChange={(event, newInputValue) => { - setInputValue(newInputValue); - }} - renderInput={(params) => } - renderOption={(props, option) => { - const matches = option.structured_formatting.main_text_matched_substrings || []; - - const parts = parse( - option.structured_formatting.main_text, - matches.map((match) => [match.offset, match.offset + match.length]) - ); - - return ( -
  • - - - - - - {parts?.map((part, index) => ( - - {part.text} - - ))} - - {option?.structured_formatting.secondary_text} - - - -
  • - ); - }} - /> -
    - - Location + Email { - const value = e.target.value; setSelectedCustomer((prev) => ({ ...prev, - suburb: value + email: e.target.value })); - // setSuburb(e.target.value); }} /> - - City + + Total Bookings + + + + Joined { - const value = e.target.value; - setSelectedCustomer((prev) => ({ - ...prev, - city: value - })); - // setCity(e.target.value); - }} + disabled + value={selectedCustomer?.createdat ? new Date(selectedCustomer.createdat).toLocaleDateString() : '—'} /> - - State - { - const value = e.target.value; - setSelectedCustomer((prev) => ({ - ...prev, - state: value - })); - // setState(e.target.value); - }} - /> - - - Postcode - { - const value = e.target.value; - setSelectedCustomer((prev) => ({ - ...prev, - postcode: value - })); - // setPostcode(e.target.value); - }} - /> - - - Landmark - { - setSelectedCustomer({ - ...selectedCustomer, - landmark: e.target.value - }); - }} - /> - - - Latitude - - - - Longitude - -