|
|
|
@@ -11,38 +11,17 @@ |
|
|
|
</BCardHeader> |
|
|
|
<BCardBody class="card-body"> |
|
|
|
<BRow> |
|
|
|
<BCol class="col-sm-6"> |
|
|
|
<div class="mb-3"> |
|
|
|
<label class="form-label">طول جغرافیایی</label> |
|
|
|
<input |
|
|
|
type="text" |
|
|
|
v-model="lat" |
|
|
|
class="form-control" |
|
|
|
:class="{ 'is-invalid': errors.lat }" |
|
|
|
placeholder="طول جغرافیای " |
|
|
|
@input="clearError('lat')" |
|
|
|
/> |
|
|
|
<small v-if="errors.lat" class="text-danger"> |
|
|
|
{{ errors.lat }} |
|
|
|
</small> |
|
|
|
</div> |
|
|
|
</BCol> |
|
|
|
<BCol class="col-sm-6"> |
|
|
|
<div class="mb-3"> |
|
|
|
<label class="form-label">عرض جغرافیایی</label> |
|
|
|
<input |
|
|
|
type="text" |
|
|
|
v-model="long" |
|
|
|
class="form-control" |
|
|
|
placeholder="عرض جغرافیایی" |
|
|
|
:class="{ 'is-invalid': errors.long }" |
|
|
|
@input="clearError('long')" |
|
|
|
/> |
|
|
|
<small v-if="errors.long" class="text-danger"> |
|
|
|
{{ errors.long }} |
|
|
|
</small> |
|
|
|
</div> |
|
|
|
<BCol class="col-sm-12"> |
|
|
|
<BCard> |
|
|
|
<div id="map" style="height: 300px"></div> |
|
|
|
|
|
|
|
<!-- Display the address of the location --> |
|
|
|
<div v-if="mapAddress" class="address"> |
|
|
|
<strong>آدرس:</strong> {{ mapAddress }} |
|
|
|
</div> |
|
|
|
</BCard> |
|
|
|
</BCol> |
|
|
|
<!-- Form fields for city, town, postcode, title, and address --> |
|
|
|
<BCol class="col-sm-6"> |
|
|
|
<div class="mb-3"> |
|
|
|
<label class="form-label">استان</label> |
|
|
|
@@ -98,7 +77,7 @@ |
|
|
|
v-model="title" |
|
|
|
type="text" |
|
|
|
class="form-control" |
|
|
|
placeholder="کد پستی" |
|
|
|
placeholder="عنوان" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</BCol> |
|
|
|
@@ -111,8 +90,7 @@ |
|
|
|
placeholder="آدرس" |
|
|
|
@input="clearError('address')" |
|
|
|
:class="{ 'is-invalid': errors.address }" |
|
|
|
> |
|
|
|
</textarea> |
|
|
|
></textarea> |
|
|
|
<small v-if="errors.address" class="text-danger"> |
|
|
|
{{ errors.address }} |
|
|
|
</small> |
|
|
|
@@ -120,7 +98,7 @@ |
|
|
|
</BCol> |
|
|
|
</BRow> |
|
|
|
</BCardBody> |
|
|
|
<BcardFooter> |
|
|
|
<BCardFooter> |
|
|
|
<div class="text-center btn-page"> |
|
|
|
<div |
|
|
|
@click="createAddress" |
|
|
|
@@ -136,17 +114,34 @@ |
|
|
|
<span v-if="!loading">ثبت</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</BcardFooter> |
|
|
|
</BCardFooter> |
|
|
|
</BCard> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import { ref } from "vue"; |
|
|
|
import L from "leaflet"; |
|
|
|
import "leaflet/dist/leaflet.css"; |
|
|
|
import { ref, toRef, watch, watchEffect, nextTick } from "vue"; |
|
|
|
import { toast } from "vue3-toastify"; |
|
|
|
import "vue3-toastify/dist/index.css"; |
|
|
|
import ApiServiece from "@/services/ApiService"; |
|
|
|
|
|
|
|
export default { |
|
|
|
setup() { |
|
|
|
props: { |
|
|
|
showCard: { |
|
|
|
type: Boolean, |
|
|
|
}, |
|
|
|
orderId: { |
|
|
|
type: Number, |
|
|
|
}, |
|
|
|
initMap: { |
|
|
|
type: Boolean, |
|
|
|
}, |
|
|
|
}, |
|
|
|
setup(props) { |
|
|
|
const localShowCard = toRef(props.showCard); |
|
|
|
const localOrderId = toRef(props.orderId); |
|
|
|
const loading = ref(false); |
|
|
|
const title = ref(); |
|
|
|
const address = ref(); |
|
|
|
@@ -155,7 +150,18 @@ export default { |
|
|
|
const city = ref(); |
|
|
|
const town = ref(); |
|
|
|
const postcode = ref(); |
|
|
|
const addrerssId = ref(); |
|
|
|
const errors = ref({}); |
|
|
|
watch( |
|
|
|
() => props.showCard, |
|
|
|
(newVal) => (localShowCard.value = newVal) |
|
|
|
); |
|
|
|
|
|
|
|
watch( |
|
|
|
() => props.orderId, |
|
|
|
(newVal) => (localOrderId.value = newVal) |
|
|
|
); |
|
|
|
|
|
|
|
const validateForm = () => { |
|
|
|
errors.value = {}; |
|
|
|
if (!address.value) |
|
|
|
@@ -187,12 +193,31 @@ export default { |
|
|
|
formData.append("town", town.value); |
|
|
|
formData.append("postcode", postcode.value); |
|
|
|
ApiServiece.post(`wholesale/my-addresses`, formData) |
|
|
|
.then(() => { |
|
|
|
.then((resp) => { |
|
|
|
loading.value = false; |
|
|
|
|
|
|
|
toast.success("!آدرس با موفقیت اضافه شد", { |
|
|
|
position: "top-right", |
|
|
|
autoClose: 1000, |
|
|
|
}); |
|
|
|
|
|
|
|
console.log(resp); |
|
|
|
addrerssId.value = resp.data.data.id; |
|
|
|
}) |
|
|
|
.then(() => { |
|
|
|
if (!localShowCard.value && localOrderId.value) { |
|
|
|
ApiServiece.post( |
|
|
|
`wholesale/orders/${localOrderId.value}/addresses`, |
|
|
|
{ |
|
|
|
user_address_id: addrerssId.value, |
|
|
|
} |
|
|
|
).then(() => { |
|
|
|
toast.success("!این آدرس به سفارش اضافه گردید", { |
|
|
|
position: "top-right", |
|
|
|
autoClose: 1000, |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
}) |
|
|
|
.catch(() => { |
|
|
|
loading.value = false; |
|
|
|
@@ -203,6 +228,166 @@ export default { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
const customIcon = new L.Icon({ |
|
|
|
iconUrl: require("@/assets/images/location.svg"), |
|
|
|
iconSize: [32, 32], |
|
|
|
iconAnchor: [16, 32], |
|
|
|
popupAnchor: [0, -32], |
|
|
|
}); |
|
|
|
const currentLocation = ref([0, 0]); |
|
|
|
const markerPosition = ref([32.6523, 51.6714]); |
|
|
|
const zoom = ref(13); |
|
|
|
const typedAddress = ref(""); |
|
|
|
const mapAddres = ref(null); |
|
|
|
let mapInstance = null; |
|
|
|
let marker = null; |
|
|
|
const getAddressFromLatLng = (lat, lng) => { |
|
|
|
const url = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&addressdetails=1`; |
|
|
|
|
|
|
|
fetch(url) |
|
|
|
.then((response) => response.json()) |
|
|
|
.then((data) => { |
|
|
|
if (data && data.address) { |
|
|
|
mapAddres.value = `${data.address.road || ""}, ${ |
|
|
|
data.address.city || "" |
|
|
|
}, ${data.address.country || ""}`; |
|
|
|
} |
|
|
|
}) |
|
|
|
.catch(() => { |
|
|
|
mapAddres.value = "Unable to fetch address."; |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
// Function to search an address and get its location |
|
|
|
const searchAddress = () => { |
|
|
|
if (!typedAddress.value.trim()) return; |
|
|
|
|
|
|
|
const url = `https://nominatim.openstreetmap.org/search?q=${typedAddress.value}&format=json&addressdetails=1`; |
|
|
|
|
|
|
|
fetch(url) |
|
|
|
.then((response) => response.json()) |
|
|
|
.then((data) => { |
|
|
|
if (data && data[0]) { |
|
|
|
const { lat, lon } = data[0]; |
|
|
|
const latLng = [lat, lon]; |
|
|
|
|
|
|
|
currentLocation.value = latLng; |
|
|
|
markerPosition.value = latLng; |
|
|
|
updateMapPosition(); |
|
|
|
getAddressFromLatLng(lat, lon); // Get the address for the new location |
|
|
|
} else { |
|
|
|
address.value = "Address not found. Please try again."; |
|
|
|
} |
|
|
|
}) |
|
|
|
.catch(() => { |
|
|
|
address.value = "Error fetching location."; |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
const getCurrentLocation = () => { |
|
|
|
if (navigator.geolocation) { |
|
|
|
navigator.geolocation.getCurrentPosition((position) => { |
|
|
|
currentLocation.value = [ |
|
|
|
position.coords.latitude, |
|
|
|
position.coords.longitude, |
|
|
|
]; |
|
|
|
|
|
|
|
lat.value = position.coords.latitude; |
|
|
|
long.value = position.coords.longitude; |
|
|
|
|
|
|
|
markerPosition.value = currentLocation.value; |
|
|
|
|
|
|
|
updateMapPosition(); |
|
|
|
getAddressFromLatLng(lat.value, long.value); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
alert("Geolocation is not supported by this browser."); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// Update the map's position based on the current location |
|
|
|
const updateMapPosition = () => { |
|
|
|
if (mapInstance) { |
|
|
|
mapInstance.setView(currentLocation.value, zoom.value); |
|
|
|
} |
|
|
|
if (marker) { |
|
|
|
marker.setLatLng(currentLocation.value); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const initMap = () => { |
|
|
|
const defaultLocation = [32.6523, 51.6714]; |
|
|
|
const savedLocation = JSON.parse(localStorage.getItem("userLocation")); |
|
|
|
const handleError = () => { |
|
|
|
console.error("An error occurred, using Isfahan as default."); |
|
|
|
setMapToLocation(defaultLocation); |
|
|
|
}; |
|
|
|
|
|
|
|
if (savedLocation) { |
|
|
|
setMapToLocation(savedLocation); |
|
|
|
} else if (navigator.geolocation) { |
|
|
|
navigator.geolocation.getCurrentPosition((position) => { |
|
|
|
const userLocation = [ |
|
|
|
position.coords.latitude, |
|
|
|
position.coords.longitude, |
|
|
|
]; |
|
|
|
|
|
|
|
localStorage.setItem("userLocation", JSON.stringify(userLocation)); |
|
|
|
setMapToLocation(userLocation); |
|
|
|
}, handleError); |
|
|
|
} else { |
|
|
|
console.error( |
|
|
|
"Geolocation is not supported, using Isfahan as default." |
|
|
|
); |
|
|
|
handleError(); |
|
|
|
} |
|
|
|
|
|
|
|
function setMapToLocation(location) { |
|
|
|
if (!mapInstance) { |
|
|
|
mapInstance = L.map("map").setView(location, zoom.value); |
|
|
|
|
|
|
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { |
|
|
|
attribution: |
|
|
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', |
|
|
|
}).addTo(mapInstance); |
|
|
|
|
|
|
|
marker = L.marker(location, { |
|
|
|
draggable: false, |
|
|
|
icon: customIcon, |
|
|
|
}) |
|
|
|
.addTo(mapInstance) |
|
|
|
.bindPopup("موقعیت شما") |
|
|
|
.openPopup(); |
|
|
|
|
|
|
|
mapInstance.on("click", (e) => { |
|
|
|
const latLng = e.latlng; |
|
|
|
marker.setLatLng(latLng); |
|
|
|
lat.value = latLng.lat; |
|
|
|
long.value = latLng.lng; |
|
|
|
|
|
|
|
localStorage.setItem( |
|
|
|
"userLocation", |
|
|
|
JSON.stringify([lat.value, long.value]) |
|
|
|
); // Save new location |
|
|
|
getAddressFromLatLng(lat.value, long.value); |
|
|
|
}); |
|
|
|
|
|
|
|
nextTick(() => { |
|
|
|
if (!mapInstance) { |
|
|
|
mapInstance.invalidateSize(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
watchEffect(() => { |
|
|
|
setTimeout(() => { |
|
|
|
initMap(); |
|
|
|
getCurrentLocation(); |
|
|
|
}, 3000); |
|
|
|
}); |
|
|
|
|
|
|
|
return { |
|
|
|
clearError, |
|
|
|
errors, |
|
|
|
@@ -215,7 +400,24 @@ export default { |
|
|
|
city, |
|
|
|
title, |
|
|
|
loading, |
|
|
|
localShowCard, |
|
|
|
localOrderId, |
|
|
|
currentLocation, |
|
|
|
markerPosition, |
|
|
|
zoom, |
|
|
|
typedAddress, |
|
|
|
mapAddres, |
|
|
|
searchAddress, |
|
|
|
}; |
|
|
|
}, |
|
|
|
}; |
|
|
|
</script> |
|
|
|
<style scoped> |
|
|
|
#map { |
|
|
|
height: 300px; |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
.address { |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
</style> |