import { yupResolver } from '@hookform/resolvers/yup'; import { useRouter } from 'next/router'; import { useEffect, useState, useMemo } from 'react'; import * as Yup from 'yup'; import cityApi from '../api/cityApi'; import { Controller, useForm } from 'react-hook-form'; import districtApi from '../api/districtApi'; import subDistrictApi from '../api/subDistrictApi'; import addressApi from '@/lib/address/api/addressApi'; import editAddressApi from '../api/editAddressApi'; import editPartnerApi from '../api/editPartnerApi'; import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'; import { toast } from 'react-hot-toast'; import Menu from '@/lib/auth/components/Menu'; import useAuth from '@/core/hooks/useAuth'; import odooApi from '@/core/api/odooApi'; import stateApi from '../api/stateApi'; import { MapPinIcon } from 'lucide-react'; import { Button } from '@chakra-ui/react'; import { useMaps } from '../../maps/stores/useMaps'; import PinPointMap from '../../maps/components/PinPointMap'; import BottomPopup from '@/core/components/elements/Popup/BottomPopup'; import { data } from 'autoprefixer'; const EditAddress = ({ id, defaultValues }) => { const auth = useAuth(); const router = useRouter(); const { register, formState: { errors }, handleSubmit, watch, setValue, getValues, control, } = useForm({ resolver: yupResolver(validationSchema), defaultValues, }); const [states, setStates] = useState([]); const [cities, setCities] = useState([]); const [districts, setDistricts] = useState([]); const [subDistricts, setSubDistricts] = useState([]); const [tempAddress, setTempAddress] = useState(getValues('addressMap')); const resetPin = useMaps((state) => state.resetPin); const setSelectedPosition = useMaps((state) => state.setSelectedPosition); const setAddressMaps = useMaps((state) => state.setAddressMaps); const setDetailAddress = useMaps((state) => state.setDetailAddress); const [showValidationPopup, setShowValidationPopup] = useState(false); const [popupMessage, setPopupMessage] = useState(""); const [selectedCityName, setSelectedCityName] = useState(""); const [normalizedDistrict, setNormalizedDistrict] = useState(""); const { addressMaps, selectedPosition, detailAddress, pinedMaps, setPinedMaps, getDefaultCenter, // penting untuk deteksi default center } = useMaps(); const normalizeName = (name = "") => { return name .toLowerCase() .replace(/\bkabupaten\b/gi, "") .replace(/\bkota\b/gi, "") .trim(); }; // Helper: cek apakah benar2 sudah PIN (bukan default center & ada addressMaps) const isPinned = useMemo(() => { if (!selectedPosition) return false; // pastikan selalu cast ke number const lat = Number(selectedPosition.lat); const lng = Number(selectedPosition.lng); // kalau hasil cast bukan angka valid if (isNaN(lat) || isNaN(lng)) return false; const dc = typeof getDefaultCenter === "function" ? getDefaultCenter() : { lat: -6.2, lng: 106.816666 }; const nearDefault = Math.abs(lat - dc.lat) < 1e-4 && Math.abs(lng - dc.lng) < 1e-4; return Boolean(addressMaps) && !nearDefault; }, [selectedPosition, addressMaps, getDefaultCenter]); // Hanya isi addressMap & lat/lng di form kalau SUDAH PIN useEffect(() => { // cek kalau form punya koordinat lama const lat = getValues("latitude"); const lng = getValues("longtitude"); const oldAddress = getValues("addressMap"); if (lat && lng) { setTempAddress(oldAddress); setValue("addressMap", oldAddress); // kalau store punya setter untuk koordinat/alamat: if (typeof setSelectedPosition === "function") { setSelectedPosition({ lat: Number(lat), lng: Number(lng) }); } if (typeof setAddressMaps === "function") { setAddressMaps(oldAddress); } } }, [setSelectedPosition, setAddressMaps, getValues, setValue]); useEffect(() => { const addr = getValues("addressMap"); if (!addr || addr.trim() === "") { resetPin(); } else { setAddressMaps(addr); const lat = getValues("latitude"); const lng = getValues("longtitude"); if (lat && lng) { setSelectedPosition({ lat: Number(lat), lng: Number(lng) }); } } }, [getValues, resetPin, setAddressMaps, setSelectedPosition]); useEffect(() => { if (Object.keys(detailAddress).length > 0) { setValue('zip', detailAddress.postalCode); const selectedState = states.find( (state) => detailAddress?.province.includes(state.label) || state.label.includes(detailAddress?.province) ); setValue('state', selectedState?.value); setValue('street', detailAddress?.street); } }, [detailAddress, setValue]); useEffect(() => { const loadProfile = async () => { const dataProfile = await addressApi({ id: auth.partnerId }); setValue('industry', dataProfile.industryId); setValue('companyType', dataProfile.companyTypeId); setValue('taxName', dataProfile.taxName); setValue('npwp', dataProfile.npwp); setValue('alamat_wajib_pajak', dataProfile.alamatWajibPajak); setValue('alamat_bisnis', dataProfile.alamatBisnis); setValue('business_name', dataProfile.name); }; if (auth) loadProfile(); }, [auth?.parentId, setValue]); // Isi ZIP/Prov dari detailAddress (JANGAN isi street) useEffect(() => { const zip = getValues("zip"); const province = getValues("state"); const street = getValues("street"); // set zip dari DB kalau kosong if (!zip && defaultValues?.zip) { setValue("zip", defaultValues.zip); } // set state dari DB kalau kosong if (!province && defaultValues?.state) { const selectedState = states.find( (state) => defaultValues.state.includes(state.label) || state.label.includes(defaultValues.state) ); if (selectedState) { setValue("state", selectedState.value); } } // set street dari DB kalau kosong if (!street && defaultValues?.street) { setValue("street", defaultValues.street); } }, [states, setValue, getValues, defaultValues]); useEffect(() => { const loadStates = async () => { let dataStates = await stateApi({ tempo: false }); dataStates = dataStates.map((state) => ({ value: state.id, label: state.name, })); setStates(dataStates); }; loadStates(); }, []); const watchState = watch('state'); useEffect(() => { setValue('city', ''); if (watchState) { const loadCities = async () => { let dataCities = await cityApi({ stateId: watchState }); dataCities = dataCities.map((city) => ({ value: city.id, label: city.name, })); setCities(dataCities); let oldCity = getValues('oldCity'); if (oldCity) { setValue('city', oldCity); setValue('oldCity', ''); } }; loadCities(); } }, [watchState, setValue, getValues]); useEffect(() => { if (!isPinned) return; if (getValues("city")) return; if (Object.keys(detailAddress || {}).length > 0) { const selectedCities = cities.find( (city) => city.label.toLowerCase() === detailAddress?.district?.toLowerCase() ) || cities.find( (city) => detailAddress?.district ?.toLowerCase() .includes(city.label.toLowerCase()) || city.label .toLowerCase() .includes(detailAddress?.district?.toLowerCase()) ); if (selectedCities) { setValue("city", selectedCities.value); } } }, [cities, detailAddress, isPinned, getValues, setValue]); const watchCity = watch('city'); useEffect(() => { if (watchCity) { const loadDistricts = async () => { let dataDistricts = await districtApi({ cityId: watchCity }); dataDistricts = dataDistricts.map((district) => ({ value: district.id, label: district.name, })); setDistricts(dataDistricts); let oldDistrict = getValues('oldDistrict'); if (oldDistrict) { setValue('oldDistrict', ''); } }; loadDistricts(); } }, [watchCity, setValue, getValues]); useEffect(() => { if (!isPinned) return; // skip kalau belum pin if (getValues("district")) return; if (Object.keys(detailAddress).length > 0) { const selectedDistrict = districts.find( (district) => detailAddress.subDistrict .toLowerCase() .includes(district.label.toLowerCase()) || district.label .toLowerCase() .includes(detailAddress.subDistrict.toLowerCase()) ); setValue('district', selectedDistrict?.value); } }, [districts, detailAddress, setValue]); const watchDistrict = watch('district'); useEffect(() => { if (watchDistrict) { const loadSubDistricts = async () => { let dataSubDistricts = await subDistrictApi({ districtId: watchDistrict, }); dataSubDistricts = dataSubDistricts.map((district) => ({ value: district.id, label: district.name, })); setSubDistricts(dataSubDistricts); let oldSubDistrict = getValues('oldSubDistrict'); if (oldSubDistrict) { setValue('subDistrict', oldSubDistrict); setValue('oldSubDistrict', ''); } }; loadSubDistricts(); } }, [watchDistrict, setValue, getValues]); useEffect(() => { if (!isPinned) return; // skip kalau belum pin if (getValues("subDistrict")) return; if (Object.keys(detailAddress).length > 0) { const selectedSubDistrict = subDistricts.find( (district) => detailAddress.village .toLowerCase() .includes(district.label.toLowerCase()) || district.label .toLowerCase() .includes(detailAddress.village.toLowerCase()) ); setValue('subDistrict', selectedSubDistrict?.value); } }, [subDistricts, detailAddress, setValue]); useEffect(() => { if (id) { setValue('id', id); } }, [id, setValue]); const onSubmitHandler = async (values) => { if (addressMaps) { if (!detailAddress){ if (defaultValues?.oldCity !== values.city) { setPopupMessage("Titik Koordinat tidak sesuai dengan Kota yang dipilih"); setShowValidationPopup(true); // console.log(detailAddress) return; } } if (detailAddress) { const cityName = normalizeName( cities.find((c) => c.value === watch("city"))?.label || "" ); const districtName = normalizeName(detailAddress?.district || ""); // console.log(cityName, '=', districtName); if (cityName && cityName !== districtName) { setPopupMessage("Titik Koordinat tidak sesuai dengan Kota yang dipilih"); setShowValidationPopup(true); return; } } } // if(!addressMaps && detailAddress){ // if (selectedCityName && selectedCityName !== detailAddress?.district?.toLowerCase()) { // setPopupMessage("Titik Koordinat tidak sesuai dengan Kota yang dipilih 3"); // setShowValidationPopup(true); // return; // } // } const data = { ...values, phone: values.mobile, state_id: parseInt(values.state, 10), city_id: parseInt(values.city, 10), district_id: parseInt(values.district, 10), sub_district_id: parseInt(values.subDistrict, 10), }; if (isPinned) { data.longtitude = selectedPosition?.lng; data.latitude = selectedPosition?.lat; data.address_map = addressMaps || values.addressMap; data.use_pin = true; } else { data.use_pin = false; // pastikan tidak ada nilai default center yang ikut terkirim delete data.longtitude; delete data.latitude; delete data.address_map; } if (!auth.company) { data.alamat_lengkap_text = values.street; } try { const address = await editAddressApi({ id, data }); console.log('Response address:', address); let isUpdated = null; const isCompanyEditingSelf = auth.company && auth.partnerId == id; if (isCompanyEditingSelf) { const dataProfile = await addressApi({ id: auth.partnerId }); const dataAlamat = { id_user: auth.id, company_type_id: dataProfile.companyTypeId, industry_id: dataProfile.industryId, tax_name: values.taxName, npwp: values.npwp, alamat_lengkap_text: values.alamat_wajib_pajak || values.street, street: values.street, email: values.email, mobile: values.mobile, }; const isUpdatedRes = await editPartnerApi({ id: auth.partnerId, data: dataAlamat, }); console.log('Response isUpdated:', isUpdatedRes); } const isSuccess = !!address?.id; if (isSuccess) { toast.success('Berhasil mengubah alamat'); router.back(); } else { const errorMsg = address?.message || isUpdated?.message || 'Gagal memperbarui alamat, silakan coba lagi.'; toast.error(errorMsg); } } catch (error) { console.error('Catch error:', error); toast.error(error?.message || 'Terjadi kesalahan tidak terduga.'); } const dataProfile = await addressApi({ id: auth.partnerId }); // console.log('ini adalah', dataProfile); }; // console.log('ini adalah', detailAddress); return ( <> setPinedMaps(false)} >
setShowValidationPopup(false)} >
{popupMessage}

Ubah Alamat

{auth?.partnerId == id &&
Utama
}
{addressMaps ? (
{addressMaps}
) : ( Pin Koordinat Alamat )}
( )} />
{errors.type?.message}
{errors.name?.message}
{errors.email?.message}
{errors.mobile?.message}
{errors.street?.message}
{errors.zip?.message}
( )} />
{errors.state?.message}
( )} />
{errors.city?.message}
( )} />
{errors.district?.message}
( )} />
); }; const validationSchema = Yup.object().shape({ type: Yup.string().required('Harus di-pilih'), name: Yup.string().min(3, 'Minimal 3 karakter').required('Harus di-isi'), // email: Yup.string().email('Format harus seperti johndoe@example.com').required('Harus di-isi'), mobile: Yup.string().required('Harus di-isi'), street: Yup.string().required('Harus di-isi'), zip: Yup.string().required('Harus di-isi'), state: Yup.string().required('Harus di-pilih'), city: Yup.string().required('Harus di-pilih'), district: Yup.string().required('Harus di-pilih'), }); const types = [ { value: 'contact', label: 'Contact Address' }, { value: 'invoice', label: 'Invoice Address' }, { value: 'delivery', label: 'Delivery Address' }, { value: 'other', label: 'Other Address' }, ]; export default EditAddress;