forked from kevinowino869/mitrobill
map and customer geo location added
added map and customer geo location, we advice you to change/edit the customer coordinates according to their location, so that you can see where the customer is located on the Map
This commit is contained in:
@ -11,10 +11,10 @@
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
{if $_c['country_code_phone']!= ''}
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
{else}
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
{/if}
|
||||
<input type="text" class="form-control" name="username" required
|
||||
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
|
||||
@ -38,10 +38,10 @@
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
{if $_c['country_code_phone']!= ''}
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
{else}
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
{/if}
|
||||
<input type="text" class="form-control" name="phonenumber"
|
||||
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
|
||||
@ -51,8 +51,9 @@
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Password')}</label>
|
||||
<div class="col-md-9">
|
||||
<input type="password" class="form-control" autocomplete="off" required id="password" value="{rand(000000,999999)}"
|
||||
name="password" onmouseleave="this.type = 'password'" onmouseenter="this.type = 'text'">
|
||||
<input type="password" class="form-control" autocomplete="off" required id="password"
|
||||
value="{rand(000000,999999)}" name="password" onmouseleave="this.type = 'password'"
|
||||
onmouseenter="this.type = 'text'">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -72,6 +73,17 @@
|
||||
<textarea name="address" id="address" class="form-control"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Coordinates')}</label>
|
||||
<div class="col-md-9">
|
||||
<input name="coordinates" id="coordinates" class="form-control" value=""
|
||||
placeholder="6.465422, 3.406448">
|
||||
<span class="help-block">
|
||||
<small>{Lang::T('Latitude and Longitude coordinates for map must be separate with comma
|
||||
","')}</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Service Type')}</label>
|
||||
<div class="col-md-9">
|
||||
@ -110,16 +122,16 @@
|
||||
</center>
|
||||
</form>
|
||||
{literal}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var customFieldsContainer = document.getElementById('custom-fields-container');
|
||||
var addCustomFieldButton = document.getElementById('add-custom-field');
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var customFieldsContainer = document.getElementById('custom-fields-container');
|
||||
var addCustomFieldButton = document.getElementById('add-custom-field');
|
||||
|
||||
addCustomFieldButton.addEventListener('click', function() {
|
||||
var fieldIndex = customFieldsContainer.children.length;
|
||||
var newField = document.createElement('div');
|
||||
newField.className = 'form-group';
|
||||
newField.innerHTML = `
|
||||
addCustomFieldButton.addEventListener('click', function () {
|
||||
var fieldIndex = customFieldsContainer.children.length;
|
||||
var newField = document.createElement('div');
|
||||
newField.className = 'form-group';
|
||||
newField.innerHTML = `
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="custom_field_name[]" placeholder="Name">
|
||||
</div>
|
||||
@ -130,17 +142,17 @@
|
||||
<button type="button" class="remove-custom-field btn btn-danger btn-sm">-</button>
|
||||
</div>
|
||||
`;
|
||||
customFieldsContainer.appendChild(newField);
|
||||
});
|
||||
|
||||
customFieldsContainer.addEventListener('click', function(event) {
|
||||
if (event.target.classList.contains('remove-custom-field')) {
|
||||
var fieldContainer = event.target.parentNode.parentNode;
|
||||
fieldContainer.parentNode.removeChild(fieldContainer);
|
||||
}
|
||||
});
|
||||
customFieldsContainer.appendChild(newField);
|
||||
});
|
||||
</script>
|
||||
|
||||
customFieldsContainer.addEventListener('click', function (event) {
|
||||
if (event.target.classList.contains('remove-custom-field')) {
|
||||
var fieldContainer = event.target.parentNode.parentNode;
|
||||
fieldContainer.parentNode.removeChild(fieldContainer);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{/literal}
|
||||
|
||||
|
||||
|
@ -12,10 +12,10 @@
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
{if $_c['country_code_phone']!= ''}
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
{else}
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
{/if}
|
||||
<input type="text" class="form-control" name="username" value="{$d['username']}"
|
||||
required
|
||||
@ -41,10 +41,10 @@
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
{if $_c['country_code_phone']!= ''}
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
<span class="input-group-addon" id="basic-addon1">+</span>
|
||||
{else}
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
<span class="input-group-addon" id="basic-addon1"><i
|
||||
class="glyphicon glyphicon-phone-alt"></i></span>
|
||||
{/if}
|
||||
<input type="text" class="form-control" name="phonenumber" value="{$d['phonenumber']}"
|
||||
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
|
||||
@ -77,6 +77,16 @@
|
||||
<textarea name="address" id="address" class="form-control">{$d['address']}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Coordinates')}</label>
|
||||
<div class="col-md-9">
|
||||
<input name="coordinates" id="coordinates" class="form-control" value="{$d['coordinates']}">
|
||||
<span class="help-block">
|
||||
<small>{Lang::T('Latitude and Longitude coordinates for map must be separate with comma
|
||||
","')}</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Service Type')}</label>
|
||||
<div class="col-md-9">
|
||||
@ -97,19 +107,20 @@
|
||||
<div class="panel-body">
|
||||
<!--Customers Attributes edit start -->
|
||||
{if $customFields}
|
||||
{foreach $customFields as $customField}
|
||||
<div class="form-group">
|
||||
<label class="col-md-4 control-label"
|
||||
for="{$customField.field_name}">{$customField.field_name}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" type="text" name="custom_fields[{$customField.field_name}]"
|
||||
id="{$customField.field_name}" value="{$customField.field_value}">
|
||||
</div>
|
||||
<label class="col-md-2">
|
||||
<input type="checkbox" name="delete_custom_fields[]" value="{$customField.field_name}"> Delete
|
||||
</label>
|
||||
</div>
|
||||
{/foreach}
|
||||
{foreach $customFields as $customField}
|
||||
<div class="form-group">
|
||||
<label class="col-md-4 control-label"
|
||||
for="{$customField.field_name}">{$customField.field_name}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" type="text" name="custom_fields[{$customField.field_name}]"
|
||||
id="{$customField.field_name}" value="{$customField.field_value}">
|
||||
</div>
|
||||
<label class="col-md-2">
|
||||
<input type="checkbox" name="delete_custom_fields[]" value="{$customField.field_name}">
|
||||
Delete
|
||||
</label>
|
||||
</div>
|
||||
{/foreach}
|
||||
{/if}
|
||||
<!--Customers Attributes edit end -->
|
||||
<!-- Customers Attributes add start -->
|
||||
@ -133,16 +144,16 @@
|
||||
</form>
|
||||
|
||||
{literal}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var customFieldsContainer = document.getElementById('custom-fields-container');
|
||||
var addCustomFieldButton = document.getElementById('add-custom-field');
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var customFieldsContainer = document.getElementById('custom-fields-container');
|
||||
var addCustomFieldButton = document.getElementById('add-custom-field');
|
||||
|
||||
addCustomFieldButton.addEventListener('click', function() {
|
||||
var fieldIndex = customFieldsContainer.children.length;
|
||||
var newField = document.createElement('div');
|
||||
newField.className = 'form-group';
|
||||
newField.innerHTML = `
|
||||
addCustomFieldButton.addEventListener('click', function () {
|
||||
var fieldIndex = customFieldsContainer.children.length;
|
||||
var newField = document.createElement('div');
|
||||
newField.className = 'form-group';
|
||||
newField.innerHTML = `
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="custom_field_name[]" placeholder="Name">
|
||||
</div>
|
||||
@ -153,17 +164,17 @@
|
||||
<button type="button" class="remove-custom-field btn btn-danger btn-sm">-</button>
|
||||
</div>
|
||||
`;
|
||||
customFieldsContainer.appendChild(newField);
|
||||
});
|
||||
|
||||
customFieldsContainer.addEventListener('click', function(event) {
|
||||
if (event.target.classList.contains('remove-custom-field')) {
|
||||
var fieldContainer = event.target.parentNode.parentNode;
|
||||
fieldContainer.parentNode.removeChild(fieldContainer);
|
||||
}
|
||||
});
|
||||
customFieldsContainer.appendChild(newField);
|
||||
});
|
||||
</script>
|
||||
|
||||
customFieldsContainer.addEventListener('click', function (event) {
|
||||
if (event.target.classList.contains('remove-custom-field')) {
|
||||
var fieldContainer = event.target.parentNode.parentNode;
|
||||
fieldContainer.parentNode.removeChild(fieldContainer);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{/literal}
|
||||
|
||||
{include file="sections/footer.tpl"}
|
@ -37,6 +37,9 @@
|
||||
onclick="this.select()">
|
||||
</li>
|
||||
{/if}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Coordinates')}</b> <span class="pull-right">{Lang::T($d['coordinates'])}</span>
|
||||
</li>
|
||||
<!--Customers Attributes view start -->
|
||||
{if $customFields}
|
||||
{foreach $customFields as $customField}
|
||||
@ -74,16 +77,13 @@
|
||||
</ul>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<a href="{$_url}customers/list" class="btn btn-primary btn-sm btn-block">{Lang::T('Back')}</a>
|
||||
<a href="{$_url}customers/delete/{$d['id']}" id="{$d['id']}"
|
||||
class="btn btn-danger btn-block btn-sm"
|
||||
onclick="return confirm('{Lang::T('Delete')}?')"><span class="fa fa-trash"></span></a>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<a href="{$_url}customers/sync/{$d['id']}"
|
||||
onclick="return confirm('This will sync Customer to Mikrotik?')"
|
||||
class="btn btn-info btn-sm btn-block">{Lang::T('Sync')}</a>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<a href="{$_url}message/send/{$d['id']}" class="btn btn-success btn-sm btn-block">{Lang::T('Send
|
||||
Message')}</a>
|
||||
<div class="col-xs-8">
|
||||
<a href="{$_url}customers/edit/{$d['id']}"
|
||||
class="btn btn-warning btn-sm btn-block">{Lang::T('Edit')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
46
ui/ui/map-customer.tpl
Normal file
46
ui/ui/map-customer.tpl
Normal file
@ -0,0 +1,46 @@
|
||||
{include file="sections/header.tpl"}
|
||||
|
||||
<!-- Map container div -->
|
||||
<div id="map" style="width: 800px; height: 600px; margin: 20px auto"></div>
|
||||
|
||||
{literal}
|
||||
<script>
|
||||
window.onload = function() {
|
||||
var map = L.map('map').setView([51.505, -0.09], 13);
|
||||
var group = L.featureGroup().addTo(map);
|
||||
|
||||
var customers = {/literal}{$customers|json_encode}{literal};
|
||||
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||
subdomains: 'abcd',
|
||||
maxZoom: 20
|
||||
}).addTo(map);
|
||||
|
||||
customers.forEach(function(customer) {
|
||||
var name = customer.id;
|
||||
var name = customer.name;
|
||||
var info = customer.info;
|
||||
var coordinates = customer.coordinates;
|
||||
var balance = customer.balance;
|
||||
var address = customer.address;
|
||||
|
||||
// Create a popup for the marker
|
||||
var popupContent = "<strong>Customer Name</strong>: " + name + "<br>" +
|
||||
"<strong>Customer Info</strong>: " + info + "<br>" +
|
||||
"<strong>Customer Balance</strong>: " + balance + "<br>" +
|
||||
"<strong>Address</strong>: " + address + "<br>" +
|
||||
"<strong>Coordinates</strong>: " + coordinates + "<br>" +
|
||||
"<a href='{$_url}customers/view/"+ customer.id +"'>More Info</a><br>";
|
||||
|
||||
// Add marker to map
|
||||
var marker = L.marker(JSON.parse(coordinates)).addTo(group);
|
||||
marker.bindTooltip(name).bindPopup(popupContent);
|
||||
});
|
||||
|
||||
map.fitBounds(group.getBounds());
|
||||
}
|
||||
</script>
|
||||
{/literal}
|
||||
|
||||
{include file="sections/footer.tpl"}
|
@ -234,6 +234,20 @@
|
||||
</ul>
|
||||
</li>
|
||||
{$_MENU_AFTER_REPORTS}
|
||||
<li class="{if $_system_menu eq 'map'}active{/if} treeview">
|
||||
<a href="#">
|
||||
<i class="ion ion-ios-location"></i> <span>{Lang::T('Map')}</span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li {if $_routes[1] eq 'customer' }class="active" {/if}><a
|
||||
href="{$_url}map/customer">{Lang::T('Customer Location')}</a></li>
|
||||
{$_MENU_MAP}
|
||||
</ul>
|
||||
</li>
|
||||
{$_MENU_AFTER_MAP}
|
||||
<li class="{if $_system_menu eq 'message'}active{/if} treeview">
|
||||
<a href="#">
|
||||
<i class="ion ion-android-chat"></i> <span>{Lang::T('Send Message')}</span>
|
||||
|
Reference in New Issue
Block a user