diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/api/odooApi.js | 2 | ||||
| -rw-r--r-- | src/lib/address/api/editPartnerApi.js | 12 | ||||
| -rw-r--r-- | src/lib/address/components/EditAddress.jsx | 150 | ||||
| -rw-r--r-- | src/lib/maps/components/PinPointMap.jsx | 139 |
4 files changed, 180 insertions, 123 deletions
diff --git a/src/core/api/odooApi.js b/src/core/api/odooApi.js index 2bff42e2..ab3dedb0 100644 --- a/src/core/api/odooApi.js +++ b/src/core/api/odooApi.js @@ -65,7 +65,7 @@ const odooApi = async (method, url, data = {}, headers = {}) => { let res = await axios(axiosParameter); - if (res.data.status.code === 401) { + if (res.data?.status?.code === 401) { if (connectionAttempt < maxConnectionAttempt) { await renewToken(); return odooApi(method, url, data, headers); diff --git a/src/lib/address/api/editPartnerApi.js b/src/lib/address/api/editPartnerApi.js new file mode 100644 index 00000000..866ee9d2 --- /dev/null +++ b/src/lib/address/api/editPartnerApi.js @@ -0,0 +1,12 @@ +import odooApi from '@/core/api/odooApi' + +const editPartnerApi = async ({ id, data }) => { + const dataPartner = await odooApi('POST', `/api/v1/partner/${id}`, data, { + headers: { + 'Content-Type': 'application/json', + } + }); + return dataPartner; +} + +export default editPartnerApi;
\ No newline at end of file diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx index 9f038b74..cfb35fbd 100644 --- a/src/lib/address/components/EditAddress.jsx +++ b/src/lib/address/components/EditAddress.jsx @@ -8,6 +8,7 @@ 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'; @@ -20,6 +21,7 @@ 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(); @@ -41,12 +43,14 @@ const EditAddress = ({ id, defaultValues }) => { const [cities, setCities] = useState([]); const [districts, setDistricts] = useState([]); const [subDistricts, setSubDistricts] = useState([]); - const [pinedMaps, setPinedMaps] = useState(false); const [tempAddress, setTempAddress] = useState(getValues('addressMap')); - const { addressMaps, selectedPosition, detailAddress } = useMaps(); - - console.log('ini adalah',); + const { addressMaps, + selectedPosition, + detailAddress, + pinedMaps, + setPinedMaps } = useMaps(); + useEffect(() => { if (addressMaps) { setTempAddress(addressMaps); @@ -55,20 +59,20 @@ const EditAddress = ({ id, defaultValues }) => { setValue('latitude', selectedPosition.lat); } }, [addressMaps, selectedPosition, setValue]); - + 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) + state.label.includes(detailAddress?.province) ); setValue('state', selectedState?.value); - setValue('street', detailAddress?.route); + setValue('street', detailAddress?.street); } }, [detailAddress, setValue]); - + useEffect(() => { const loadProfile = async () => { const dataProfile = await addressApi({ id: auth.partnerId }); @@ -85,7 +89,7 @@ const EditAddress = ({ id, defaultValues }) => { }; if (auth) loadProfile(); }, [auth?.parentId]); - + useEffect(() => { const loadStates = async () => { let dataStates = await stateApi({ tempo: false }); @@ -97,7 +101,7 @@ const EditAddress = ({ id, defaultValues }) => { }; loadStates(); }, []); - + const watchState = watch('state'); useEffect(() => { setValue('city', ''); @@ -118,7 +122,7 @@ const EditAddress = ({ id, defaultValues }) => { loadCities(); } }, [watchState, setValue, getValues]); - + useEffect(() => { if (Object.keys(detailAddress).length > 0) { const selectedCities = cities.find( @@ -126,23 +130,23 @@ const EditAddress = ({ id, defaultValues }) => { detailAddress?.district .toLowerCase() .includes(city.label.toLowerCase()) || - city.label + city.label .toLowerCase() .includes(detailAddress?.district.toLowerCase()) - ); - setValue('city', selectedCities?.value); - } - }, [cities, detailAddress, setValue]); - - const watchCity = watch('city'); - useEffect(() => { - if (watchCity) { - // setValue('district', ''); - const loadDistricts = async () => { - let dataDistricts = await districtApi({ cityId: watchCity }); - dataDistricts = dataDistricts.map((district) => ({ - value: district.id, - label: district.name, + ); + setValue('city', selectedCities?.value); + } + }, [cities, detailAddress, setValue]); + + const watchCity = watch('city'); + useEffect(() => { + if (watchCity) { + // setValue('district', ''); + 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'); @@ -154,7 +158,7 @@ const EditAddress = ({ id, defaultValues }) => { loadDistricts(); } }, [watchCity, setValue, getValues]); - + useEffect(() => { if (Object.keys(detailAddress).length > 0) { const selectedDistrict = districts.find( @@ -169,9 +173,9 @@ const EditAddress = ({ id, defaultValues }) => { setValue('district', selectedDistrict?.value); } }, [districts, detailAddress, setValue]); - - - + + + const watchDistrict = watch('district'); useEffect(() => { if (watchDistrict) { @@ -204,23 +208,29 @@ const EditAddress = ({ id, defaultValues }) => { detailAddress.village .toLowerCase() .includes(district.label.toLowerCase()) || - district.label + district.label .toLowerCase() .includes(detailAddress.village.toLowerCase()) - ); + ); - setValue('subDistrict', selectedSubDistrict?.value); + setValue('subDistrict', selectedSubDistrict?.value); } }, [subDistricts, detailAddress, setValue]); + useEffect(() => { + if (id) { + setValue('id', id); + } + }, [id, setValue]); + const onSubmitHandler = async (values) => { const data = { ...values, phone: values.mobile, - state_id: values.state, - city_id: values.city, - district_id: values.district, - sub_district_id: values.subDistrict, + 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), longtitude: selectedPosition?.lng, latitude: selectedPosition?.lat, address_map: addressMaps, @@ -230,37 +240,57 @@ const EditAddress = ({ id, defaultValues }) => { } try { const address = await editAddressApi({ id, data }); - let dataAlamat; - let isUpdated = true; - if (auth.company) { - if (auth?.partnerId == id) { - dataAlamat = { - id_user: auth.partnerId, - alamat_lengkap_text: values.alamat_wajib_pajak, - street: values.street, - }; - isUpdated = await odooApi( - 'PUT', - `/api/v1/partner/${auth.parentId}`, - dataAlamat - ); - } + console.log('Response address:', address); + + let isUpdated = null; + + // Jika company dan partnerId sama dengan id, maka update data alamat wajib pajak + 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 isUpdated = await editPartnerApi({ + id: auth.partnerId, + data: dataAlamat, + }); + + console.log('Response isUpdated:', isUpdated); } - // if (isUpdated?.id) { - if (address?.id && (auth.company && auth?.partnerId == id ? isUpdated?.id : true)) { + + // Validasi kondisi sukses + const isSuccess = !!address?.id; + + if (isSuccess) { toast.success('Berhasil mengubah alamat'); router.back(); } else { - toast.error('Terjadi kesalahan internal'); - router.back(); + const errorMsg = + address?.message || + isUpdated?.message || + 'Gagal memperbarui alamat, silakan coba lagi.'; + toast.error(errorMsg); } } catch (error) { - console.log(error); - toast.error('Terjadi kesalahan internal'); - router.back(); + 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); + // if (isUpdated?.id) { // if (address?.id && auth.company ? isUpdated?.id : true) { diff --git a/src/lib/maps/components/PinPointMap.jsx b/src/lib/maps/components/PinPointMap.jsx index acd5ab92..fde1f36c 100644 --- a/src/lib/maps/components/PinPointMap.jsx +++ b/src/lib/maps/components/PinPointMap.jsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useRef } from 'react'; +import React, { useState, useCallback, useRef, useEffect } from 'react'; import { GoogleMap, useJsApiLoader, @@ -8,49 +8,46 @@ import { import { useMaps } from '../stores/useMaps'; import { LocateFixed, MapPinIcon } from 'lucide-react'; import { Button } from '@chakra-ui/react'; -import { useForm } from 'react-hook-form'; const containerStyle = { width: '100%', height: '400px', }; -const center = { - lat: -6.2, // Default latitude (Jakarta) - lng: 106.816666, // Default longitude (Jakarta) +const defaultCenter = { + lat: -6.2, + lng: 106.816666, }; const PinpointLocation = () => { const { isLoaded } = useJsApiLoader({ - googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_API_KEY, // Pastikan API key ada di .env.local + googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_API_KEY, libraries: ['places'], }); - const { addressMaps, setAddressMaps, selectedPosition, setSelectedPosition, setDetailAddress, setPinedMaps } = - useMaps(); + const { + addressMaps, + setAddressMaps, + selectedPosition, + setSelectedPosition, + setDetailAddress, + setPinedMaps, + } = useMaps(); const [tempAddress, setTempAddress] = useState(''); - const [tempPosition, setTempPosition] = useState(center); - const { setValue } = useForm(); + const [tempPosition, setTempPosition] = useState(defaultCenter); + const [markerIcon, setMarkerIcon] = useState(null); const autocompleteRef = useRef(null); - const onMapClick = useCallback((event) => { - const lat = event.latLng.lat(); - const lng = event.latLng.lng(); - setTempPosition({ lat, lng }); - getAddress(lat, lng); - }, []); - - const handlePlaceSelect = () => { - const place = autocompleteRef.current.getPlace(); - if (place && place.geometry) { - const lat = place.geometry.location.lat(); - const lng = place.geometry.location.lng(); - setTempPosition({ lat, lng }); - setTempAddress(place.formatted_address); + useEffect(() => { + if (isLoaded && window.google) { + setMarkerIcon({ + url: 'https://cdn.pixabay.com/photo/2014/04/03/10/03/google-309740_1280.png', + scaledSize: new window.google.maps.Size(25, 40), + }); } - }; + }, [isLoaded]); const getAddressComponent = (components, type) => { const component = components.find((comp) => comp.types.includes(type)); @@ -63,43 +60,59 @@ const PinpointLocation = () => { `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${process.env.NEXT_PUBLIC_GOOGLE_API_KEY}` ); const data = await response.json(); + if (data.results[0]) { const addressComponents = data.results[0].address_components; + const formattedAddress = data.results[0].formatted_address; + const details = { - route : getAddressComponent(addressComponents, 'route')+' '+getAddressComponent(addressComponents, 'street_number')+' '+getAddressComponent(addressComponents, 'administrative_area_level_7')+' '+getAddressComponent(addressComponents, 'administrative_area_level_6'), - province: getAddressComponent( - addressComponents, - 'administrative_area_level_1' - ), - district: getAddressComponent( - addressComponents, - 'administrative_area_level_2' - ), - subDistrict: getAddressComponent( - addressComponents, - 'administrative_area_level_3' - ), - village: getAddressComponent( - addressComponents, - 'administrative_area_level_4' - ), + street: + getAddressComponent(addressComponents, 'route') + + ' ' + + getAddressComponent(addressComponents, 'street_number'), + province: getAddressComponent(addressComponents, 'administrative_area_level_1'), + district: getAddressComponent(addressComponents, 'administrative_area_level_2'), + subDistrict: getAddressComponent(addressComponents, 'administrative_area_level_3'), + village: getAddressComponent(addressComponents, 'administrative_area_level_4'), postalCode: getAddressComponent(addressComponents, 'postal_code'), }; + setDetailAddress(details); - setTempAddress(data.results[0].formatted_address); + setTempAddress(formattedAddress); } } catch (error) { console.error('Error fetching address:', error); } }; + const onMapClick = useCallback((event) => { + const lat = event.latLng.lat(); + const lng = event.latLng.lng(); + const newPosition = { lat, lng }; + setTempPosition(newPosition); + getAddress(lat, lng); + }, []); + + const handlePlaceSelect = () => { + const place = autocompleteRef.current.getPlace(); + if (place && place.geometry) { + const lat = place.geometry.location.lat(); + const lng = place.geometry.location.lng(); + const newPosition = { lat, lng }; + setTempPosition(newPosition); + setTempAddress(place.formatted_address); + getAddress(lat, lng); + } + }; + const handleUseCurrentLocation = () => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const lat = position.coords.latitude; const lng = position.coords.longitude; - setTempPosition({ lat, lng }); + const newPosition = { lat, lng }; + setTempPosition(newPosition); getAddress(lat, lng); }, (error) => { @@ -115,18 +128,16 @@ const PinpointLocation = () => { alert('Silahkan pilih lokasi terlebih dahulu'); return; } - // console.log('tempPosition', tempPosition.lat); - getAddress(tempPosition.lat, tempPosition.lng); + setSelectedPosition(tempPosition); setAddressMaps(tempAddress); - setPinedMaps(false) + setPinedMaps(false); }; - console.log('set selected position',selectedPosition); - return ( <div className='w-full'> <h3>Tentukan Pinpoint Lokasi</h3> + <div style={{ marginBottom: '10px' }}> {isLoaded ? ( <Autocomplete @@ -152,15 +163,20 @@ const PinpointLocation = () => { zoom={15} onClick={onMapClick} > - <Marker - position={tempPosition} - draggable={true} - onDragEnd={(e) => onMapClick(e)} - icon={{ - url: 'https://maps.google.com/mapfiles/ms/icons/red-pushpin.png', - scaledSize: new window.google.maps.Size(40, 40), - }} - /> + {markerIcon && ( + <Marker + position={tempPosition} + draggable={true} + onDragEnd={(e) => { + const lat = e.latLng.lat(); + const lng = e.latLng.lng(); + const newPosition = { lat, lng }; + setTempPosition(newPosition); + getAddress(lat, lng); + }} + icon={markerIcon} + /> + )} </GoogleMap> ) : ( <p>Loading map...</p> @@ -169,16 +185,15 @@ const PinpointLocation = () => { <div style={{ marginTop: '20px' }}> <Button variant='solid' onClick={handleUseCurrentLocation}> - <LocateFixed class='h-6 w-6 text-gray-500 mr-2' /> Gunakan Lokasi Saat - ini + <LocateFixed className='h-6 w-6 text-gray-500 mr-2' /> Gunakan Lokasi Saat Ini </Button> </div> <div style={{ marginTop: '10px' }}> <p>PinPoint :</p> <div className='flex gap-x-2 shadow-md rounded-sm text-gray-500 p-3 items-center'> - <MapPinIcon class='h-8 w-8 text-gray-500 mr-3' /> - <label> {tempAddress}</label> + <MapPinIcon className='h-8 w-8 text-gray-500 mr-3' /> + <label>{tempAddress || 'Pilih lokasi di peta'}</label> </div> </div> |
