|
Server : Apache/2.4.18 (Ubuntu) System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 User : oppastar ( 1041) PHP Version : 7.0.33-0ubuntu0.16.04.15 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, Directory : /var/www/laciasmara.com/public_html/shop/application/views/development/ |
Upload File : |
<html>
<head>
<title>Place Autocomplete map</title>
<style>
.address-management {
max-width: 800px;
margin: 0 auto;
}
.saved-addresses {
margin-bottom: 20px;
}
.address-item {
margin-bottom: 15px;
}
.address-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
background: #f9f9f9;
}
.address-card.default {
border-color: #007bff;
background: #e7f3ff;
}
.address-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.default-badge {
background: #007bff;
color: white;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
}
.address-actions {
margin-top: 10px;
}
.address-actions button {
margin-right: 10px;
padding: 5px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.modal-content {
background: white;
margin: 2% auto;
padding: 20px;
border-radius: 8px;
max-width: 90%;
max-height: 90%;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.close {
font-size: 24px;
cursor: pointer;
color: #666;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.row {
display: flex;
gap: 15px;
}
.col-md-6 {
flex: 1;
}
.form-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
}
.form-actions button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.form-actions button[type="submit"] {
background: #007bff;
color: white;
}
#map {
border: 1px solid #ddd;
border-radius: 4px;
}
/* Responsive */
@media (max-width: 768px) {
.row {
flex-direction: column;
}
.modal-content {
margin: 5% auto;
padding: 15px;
}
}
</style>
</head>
<body>
<div class="address-management">
<!-- Existing Addresses -->
<div class="saved-addresses">
<h4>Alamat Tersimpan</h4>
<div id="address-list">
<!-- Akan diisi dengan JavaScript -->
</div>
<button type="button" class="btn btn-primary" onclick="showAddressForm()">
+ Tambah Alamat Baru
</button>
</div>
<!-- Add New Address Modal -->
<div id="address-modal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Tambah Alamat Baru</h3>
<span class="close" onclick="hideAddressForm()">×</span>
</div>
<div class="modal-body">
<form id="address-form">
<div class="form-group">
<label>Label Alamat</label>
<input type="text" id="address-label" name="label" placeholder="Rumah, Kantor, dll" required>
</div>
<div class="form-group">
<label>Nama Penerima</label>
<input type="text" id="recipient-name" name="recipient_name" required>
</div>
<div class="form-group">
<label>Nomor Telepon</label>
<input type="tel" id="recipient-phone" name="phone" required>
</div>
<div class="form-group">
<label>Cari Alamat</label>
<input type="text" id="address-search" placeholder="Cari alamat..." class="form-control">
</div>
<!-- Map Container -->
<div id="map" style="height: 400px; width: 100%; margin: 10px 0;"></div>
<!-- Address Details (Auto-filled) -->
<div class="address-details">
<div class="form-group">
<label>Alamat Lengkap</label>
<textarea id="full-address" name="address" rows="3" required></textarea>
</div>
<div class="row">
<div class="col-md-6">
<label>Provinsi</label>
<input type="text" id="province" name="province" readonly>
</div>
<div class="col-md-6">
<label>Kota</label>
<input type="text" id="city" name="city" readonly>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Kecamatan</label>
<input type="text" id="district" name="district" readonly>
</div>
<div class="col-md-6">
<label>Kelurahan</label>
<input type="text" id="subdistrict" name="subdistrict" readonly>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Kode Pos</label>
<input type="text" id="postal-code" name="postal_code" readonly>
</div>
<div class="col-md-6">
<label>
<input type="checkbox" id="is-default" name="is_default">
Jadikan alamat utama
</label>
</div>
</div>
</div>
<!-- Hidden fields untuk coordinates -->
<input type="hidden" id="latitude" name="latitude">
<input type="hidden" id="longitude" name="longitude">
<div class="form-actions">
<button type="button" onclick="hideAddressForm()">Batal</button>
<button type="submit">Simpan Alamat</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script async src="https://maps.googleapis.com/maps/api/js?key=<?php echo $this->config->item('google_maps_api_key'); ?>&loading=async&libraries=places,marker&callback=initMap&language=id®ion=ID&v=beta" defer></script>
<script>
let map;
let marker;
let autocomplete;
let geocoder;
// Initialize Map
async function initMap() {
try {
// Request needed libraries
const {
Map
} = await google.maps.importLibrary("maps");
const {
AdvancedMarkerElement
} = await google.maps.importLibrary("marker");
// Default location (Jakarta)
const defaultLocation = {
lat: -6.2088,
lng: 106.8456
};
// Create map
map = new Map(document.getElementById('map'), {
center: defaultLocation,
zoom: 13,
mapId: '1873c42fd77c25f9fad736e6',
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false
});
// Create marker
marker = new AdvancedMarkerElement({
map: map,
position: defaultLocation,
gmpDraggable: true,
title: 'Drag untuk memilih lokasi'
});
// Initialize geocoder
geocoder = new google.maps.Geocoder();
// Setup autocomplete - Wait for DOM to be ready
setupAutocomplete();
// Setup event listeners
setupEventListeners();
// Try to get user's current location
getCurrentLocation();
} catch (error) {
console.error('Error initializing map:', error);
// Fallback to old API if new one fails
initMapFallback();
}
}
// Fallback to old API
function initMapFallback() {
console.log('Using fallback map initialization');
// Default location (Jakarta)
const defaultLocation = {
lat: -6.2088,
lng: 106.8456
};
// Create map with old API
map = new google.maps.Map(document.getElementById('map'), {
center: defaultLocation,
zoom: 13,
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false
});
// Create marker with old API
marker = new google.maps.Marker({
position: defaultLocation,
map: map,
draggable: true,
title: 'Drag untuk memilih lokasi'
});
// Initialize geocoder
geocoder = new google.maps.Geocoder();
// Setup autocomplete
setupAutocomplete();
// Setup event listeners
setupEventListeners();
// Try to get user's current location
getCurrentLocation();
}
// Setup Autocomplete - Use regular input with traditional Autocomplete as fallback
function setupAutocomplete() {
// Try to use the new PlaceAutocompleteElement first
const autocompleteElement = document.getElementById('address-search');
if (!autocompleteElement) {
console.error('Autocomplete element not found');
return;
}
// setupNewAutocomplete(autocompleteElement);
setupTraditionalAutocomplete(autocompleteElement);
}
function setupNewAutocomplete(autocompleteElement) {
try {
// Create PlaceAutocompleteElement
const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement({
includedRegionCodes: ['ID']
});
// Replace the input element with PlaceAutocompleteElement
autocompleteElement.parentNode.replaceChild(placeAutocomplete, autocompleteElement);
// Set the same ID and classes for styling
placeAutocomplete.id = 'address-search';
placeAutocomplete.className = 'form-control';
placeAutocomplete.placeholder = 'Cari alamat...';
// Use addEventListener instead of addListener for web components
placeAutocomplete.addEventListener('place_changed', function() {
const place = placeAutocomplete.getPlace();
console.log('Selected place:', place);
if (!place.geometry) {
alert('Alamat tidak ditemukan');
return;
}
// Update map and marker
map.setCenter(place.geometry.location);
map.setZoom(17);
// Set marker position based on marker type
if (marker.position !== undefined) {
// AdvancedMarkerElement
marker.position = place.geometry.location;
} else {
// Traditional Marker
marker.setPosition(place.geometry.location);
}
// Fill address details
fillAddressDetails(place);
});
// Store reference for later use
autocomplete = placeAutocomplete;
} catch (error) {
console.error('Error setting up new autocomplete:', error);
setupTraditionalAutocomplete(autocompleteElement);
}
}
function setupTraditionalAutocomplete(searchInput) {
// Auto complete diisi dengan google.maps.places.Autocomplete
autocomplete = new google.maps.places.Autocomplete(searchInput, {
componentRestrictions: {
country: 'ID'
},
fields: ['formatted_address', 'geometry', 'address_components', 'name'],
});
autocomplete.addListener('place_changed', function() {
const place = autocomplete.getPlace();
console.log('Selected place:', place);
if (!place.geometry) {
alert('Alamat tidak ditemukan');
return;
}
// Update map and marker
map.setCenter(place.geometry.location);
map.setZoom(17);
// Set marker position based on marker type
if (marker.position !== undefined) {
// AdvancedMarkerElement
marker.position = place.geometry.location;
} else {
// Traditional Marker
marker.setPosition(place.geometry.location);
}
// Fill address details
fillAddressDetails(place);
});
}
// Setup Event Listeners
function setupEventListeners() {
// Marker drag event
marker.addListener('dragend', function() {
let position;
if (marker.position && marker.position.lat) {
// AdvancedMarkerElement
position = marker.position;
} else {
// Traditional Marker
position = marker.getPosition();
}
reverseGeocode(position);
});
// Map click event
map.addListener('click', function(event) {
if (marker.position !== undefined) {
// AdvancedMarkerElement
marker.position = event.latLng;
} else {
// Traditional Marker
marker.setPosition(event.latLng);
}
reverseGeocode(event.latLng);
});
// Form submit event
if (document.getElementById('address-form')) {
document.getElementById('address-form').addEventListener('submit', function(e) {
e.preventDefault();
saveAddress();
});
}
}
// Get Current Location
function getCurrentLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
const userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
map.setCenter(userLocation);
if (marker.position !== undefined) {
// AdvancedMarkerElement
marker.position = userLocation;
} else {
// Traditional Marker
marker.setPosition(userLocation);
}
reverseGeocode(userLocation);
},
function(error) {
console.log('Error getting location:', error);
}
);
}
}
// Reverse Geocoding
function reverseGeocode(location) {
geocoder.geocode({
location: location
}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
fillAddressFromGeocoding(results[0]);
}
} else {
console.log('Geocoder failed:', status);
}
});
}
// Fill Address Details from Places API
function fillAddressDetails(place) {
if (document.getElementById('full-address')) {
document.getElementById('full-address').value = place.formatted_address;
}
if (document.getElementById('latitude')) {
document.getElementById('latitude').value = place.geometry.location.lat();
}
if (document.getElementById('longitude')) {
document.getElementById('longitude').value = place.geometry.location.lng();
}
// Parse address components
const components = place.address_components;
let addressData = {
province: '',
city: '',
district: '',
subdistrict: '',
postal_code: ''
};
if (components) {
components.forEach(function(component) {
const types = component.types;
if (types.includes('administrative_area_level_1')) {
addressData.province = component.long_name;
} else if (types.includes('administrative_area_level_2')) {
addressData.city = component.long_name;
} else if (types.includes('administrative_area_level_3')) {
addressData.district = component.long_name;
} else if (types.includes('administrative_area_level_4')) {
addressData.subdistrict = component.long_name;
} else if (types.includes('postal_code')) {
addressData.postal_code = component.long_name;
}
});
}
// Fill form fields
if (document.getElementById('province')) {
document.getElementById('province').value = addressData.province;
}
if (document.getElementById('city')) {
document.getElementById('city').value = addressData.city;
}
if (document.getElementById('district')) {
document.getElementById('district').value = addressData.district;
}
if (document.getElementById('subdistrict')) {
document.getElementById('subdistrict').value = addressData.subdistrict;
}
if (document.getElementById('postal-code')) {
document.getElementById('postal-code').value = addressData.postal_code;
}
}
// Fill Address from Geocoding (when marker is dragged)
function fillAddressFromGeocoding(result) {
if (document.getElementById('full-address')) {
document.getElementById('full-address').value = result.formatted_address;
}
if (document.getElementById('latitude')) {
document.getElementById('latitude').value = result.geometry.location.lat();
}
if (document.getElementById('longitude')) {
document.getElementById('longitude').value = result.geometry.location.lng();
}
// Parse similar to fillAddressDetails
const components = result.address_components;
let addressData = {
province: '',
city: '',
district: '',
subdistrict: '',
postal_code: ''
};
components.forEach(function(component) {
const types = component.types;
if (types.includes('administrative_area_level_1')) {
addressData.province = component.long_name;
} else if (types.includes('administrative_area_level_2')) {
addressData.city = component.long_name;
} else if (types.includes('administrative_area_level_3')) {
addressData.district = component.long_name;
} else if (types.includes('administrative_area_level_4')) {
addressData.subdistrict = component.long_name;
} else if (types.includes('postal_code')) {
addressData.postal_code = component.long_name;
}
});
if (document.getElementById('province')) {
document.getElementById('province').value = addressData.province;
}
if (document.getElementById('city')) {
document.getElementById('city').value = addressData.city;
}
if (document.getElementById('district')) {
document.getElementById('district').value = addressData.district;
}
if (document.getElementById('subdistrict')) {
document.getElementById('subdistrict').value = addressData.subdistrict;
}
if (document.getElementById('postal-code')) {
document.getElementById('postal-code').value = addressData.postal_code;
}
}
// Save Address
function saveAddress() {
const formData = new FormData(document.getElementById('address-form'));
fetch('<?php echo base_url('development/save_address'); ?>', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Alamat berhasil disimpan!');
hideAddressForm();
loadSavedAddresses();
document.getElementById('address-form').reset();
} else {
alert('Gagal menyimpan alamat. Silakan coba lagi.');
}
})
.catch(error => {
console.error('Error:', error);
alert('Terjadi kesalahan. Silakan coba lagi.');
});
}
// Show/Hide Address Form
function showAddressForm() {
if (document.getElementById('address-modal')) {
document.getElementById('address-modal').style.display = 'block';
// Resize map when modal is shown
setTimeout(() => {
google.maps.event.trigger(map, 'resize');
}, 100);
}
}
function hideAddressForm() {
if (document.getElementById('address-modal')) {
document.getElementById('address-modal').style.display = 'none';
}
}
// Load Saved Addresses
function loadSavedAddresses() {
fetch('<?php echo base_url('development/get_addresses'); ?>')
.then(response => response.json())
.then(data => {
const addressList = document.getElementById('address-list');
if (addressList) {
addressList.innerHTML = '';
data.addresses.forEach(address => {
const addressItem = createAddressItem(address);
addressList.appendChild(addressItem);
});
}
})
.catch(error => {
console.error('Error loading addresses:', error);
});
}
// Create Address Item HTML
function createAddressItem(address) {
const div = document.createElement('div');
div.className = 'address-item';
div.innerHTML = `
<div class="address-card ${address.is_default ? 'default' : ''}">
<div class="address-header">
<strong>${address.label}</strong>
${address.is_default ? '<span class="default-badge">Utama</span>' : ''}
</div>
<div class="address-details">
<p><strong>${address.recipient_name}</strong> | ${address.phone}</p>
<p>${address.address}</p>
<p>${address.district}, ${address.city}, ${address.province} ${address.postal_code}</p>
</div>
<div class="address-actions">
<button onclick="selectAddress(${address.id})">Pilih</button>
<button onclick="editAddress(${address.id})">Edit</button>
<button onclick="deleteAddress(${address.id})">Hapus</button>
</div>
</div>
`;
return div;
}
// Select Address for Shipping
function selectAddress(addressId) {
// Implementation depends on your checkout flow
console.log('Selected address:', addressId);
// You might want to store this in a hidden field or session
}
// Load addresses when page loads
document.addEventListener('DOMContentLoaded', function() {
if (typeof loadSavedAddresses === 'function') {
loadSavedAddresses();
}
});
</script>
</body>
</html>