updates on the issue and the another thing updates on the ai optimization
This commit is contained in:
88
src/components/assistant/DoormileAI/AIAddressStep.jsx
Normal file
88
src/components/assistant/DoormileAI/AIAddressStep.jsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import AddressAutocomplete from '@/components/doormile/AddressAutocomplete';
|
||||
|
||||
// ==============================|| Doormile AI — the address turn ||============================== //
|
||||
//
|
||||
// The address step, as a real search field rather than a line typed into the
|
||||
// chat box.
|
||||
//
|
||||
// It used to be an ordinary `text` step: the assistant asked for "the full
|
||||
// address" and the operator typed one into the composer, which was then
|
||||
// geocoded blind. Two things were wrong with that. They got no suggestions, so
|
||||
// an area or street had to be remembered and spelled the way the geocoder
|
||||
// wanted; and when it missed, all that came back was "I couldn't find that
|
||||
// address", with no sight of what it HAD found.
|
||||
//
|
||||
// This is the same `AddressAutocomplete` the Create Order page uses, so the
|
||||
// two surfaces resolve an address the same way and cannot drift.
|
||||
//
|
||||
// Picking from the list also hands the flow the coordinates the operator
|
||||
// actually chose, rather than whatever a second geocode of the same words
|
||||
// returns — see the `place` branch in orderFlow's resolve. That matters: the
|
||||
// dispatch optimiser routes on coordinates, and re-geocoding a label can
|
||||
// legitimately return a different place.
|
||||
//
|
||||
// Typing free text and pressing the composer still works. This is an extra way
|
||||
// in, not a replacement for one.
|
||||
const AIAddressStep = ({ step, isBusy, onChoose, onCancel }) => {
|
||||
const [text, setText] = useState('');
|
||||
const [picked, setPicked] = useState(null);
|
||||
|
||||
return (
|
||||
<div className="w-full border border-slate-200/90 rounded-2xl bg-white p-3.5 sm:p-4 mb-3.5 shadow-3xs space-y-3">
|
||||
<div className="text-xs font-bold text-slate-800">{step.ask}</div>
|
||||
|
||||
<AddressAutocomplete
|
||||
id={`ai-address-${step.id}`}
|
||||
value={text}
|
||||
disabled={isBusy}
|
||||
onChange={(v) => {
|
||||
setText(v);
|
||||
// Editing after a pick invalidates it. Those coordinates belonged to
|
||||
// the old selection and must not ride along with new words — that is
|
||||
// how a booking ends up located somewhere nobody chose.
|
||||
setPicked(null);
|
||||
}}
|
||||
onPlaceSelected={(place) => {
|
||||
setPicked(place);
|
||||
setText(place?.formatted_address || place?.name || '');
|
||||
}}
|
||||
/>
|
||||
|
||||
{picked && (
|
||||
<div className="text-[11px] text-emerald-700 font-medium">
|
||||
Location set — {picked.city || picked.suburb || 'coordinates captured'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
disabled={isBusy || !text.trim()}
|
||||
onClick={() => onChoose(text.trim(), picked ? { place: picked } : undefined)}
|
||||
className="px-4 py-2 bg-brand hover:bg-brand-dark text-white font-semibold text-xs rounded-xl shadow-xs active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed transition-all cursor-pointer"
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="px-3 py-2 text-slate-500 hover:text-slate-800 text-xs font-medium cursor-pointer"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
AIAddressStep.propTypes = {
|
||||
step: PropTypes.shape({ id: PropTypes.string, ask: PropTypes.string }).isRequired,
|
||||
isBusy: PropTypes.bool,
|
||||
onChoose: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AIAddressStep;
|
||||
Reference in New Issue
Block a user