ui phase 9
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
'use client';
|
||||
import { FunctionComponent, useState } from 'react';
|
||||
import { FunctionComponent, useEffect, useState } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import Stack from '@mui/material/Stack';
|
||||
@@ -28,6 +28,8 @@ export interface AddressFormProps {
|
||||
submitting?: boolean;
|
||||
onSubmit: (input: CreateAddressInput) => void;
|
||||
onCancel?: () => void;
|
||||
/** Reports whether any field differs from `initial` — drives a host `FormDialogShell`'s discard-confirm. */
|
||||
onDirtyChange?: (dirty: boolean) => void;
|
||||
}
|
||||
|
||||
// Only prefill the region when we have the province — a city id without its province can't drive
|
||||
@@ -50,21 +52,41 @@ function initialPin(initial?: AddressFormInitial): LatLng | null {
|
||||
* `CreateAddressInput` carrying the picked coordinates. Reused for create and edit.
|
||||
* @component AddressForm
|
||||
*/
|
||||
const AddressForm: FunctionComponent<AddressFormProps> = ({ initial, submitting = false, onSubmit, onCancel }) => {
|
||||
const AddressForm: FunctionComponent<AddressFormProps> = ({ initial, submitting = false, onSubmit, onCancel, onDirtyChange }) => {
|
||||
const t = useTranslations('address');
|
||||
const tc = useTranslations('common');
|
||||
|
||||
const [title, setTitle] = useState(initial?.title ?? '');
|
||||
const initialTitle = initial?.title ?? '';
|
||||
const initialAddressLine = initial?.addressLine ?? '';
|
||||
const initialIsPrimary = initial?.isPrimary ?? false;
|
||||
|
||||
const [title, setTitle] = useState(initialTitle);
|
||||
const [region, setRegion] = useState<CascadingRegionValue>(() => initialRegion(initial));
|
||||
const [addressLine, setAddressLine] = useState(initial?.addressLine ?? '');
|
||||
const [addressLine, setAddressLine] = useState(initialAddressLine);
|
||||
const [pin, setPin] = useState<LatLng | null>(() => initialPin(initial));
|
||||
const [isPrimary, setIsPrimary] = useState(initial?.isPrimary ?? false);
|
||||
const [isPrimary, setIsPrimary] = useState(initialIsPrimary);
|
||||
|
||||
const [titleError, setTitleError] = useState(false);
|
||||
const [cityError, setCityError] = useState(false);
|
||||
const [lineError, setLineError] = useState(false);
|
||||
const [pinError, setPinError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!onDirtyChange) return;
|
||||
const initialPinValue = initialPin(initial);
|
||||
const dirty =
|
||||
title !== initialTitle ||
|
||||
addressLine !== initialAddressLine ||
|
||||
isPrimary !== initialIsPrimary ||
|
||||
region.provinceId !== (initial?.provinceId ?? null) ||
|
||||
region.cityId !== (initial?.cityId ?? null) ||
|
||||
region.districtId !== (initial?.districtId ?? null) ||
|
||||
pin?.latitude !== initialPinValue?.latitude ||
|
||||
pin?.longitude !== initialPinValue?.longitude;
|
||||
onDirtyChange(dirty);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- `initial` is a stable prefill snapshot (the caller re-keys the form on edit-target change), not reactive state to track.
|
||||
}, [title, addressLine, isPrimary, region, pin]);
|
||||
|
||||
const handleSubmit = () => {
|
||||
const titleInvalid = title.trim().length === 0;
|
||||
const cityInvalid = region.cityId == null;
|
||||
|
||||
Reference in New Issue
Block a user