1083 lines
54 KiB
PHP
Executable File
1083 lines
54 KiB
PHP
Executable File
@extends('app.app')
|
|
@section('title')
|
|
Add Zone
|
|
@endsection
|
|
@section('customcss')
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" integrity="sha512-gc3xjCmIy673V6MyOAZhIW93xhM9ei1I+gLbmFjUHIjocENRsLX/QUE1htk5q1XV2D/iie/VQ8DXI6Vu8bexvQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vanilla-picker@2.12.1/dist/vanilla-picker.csp.css" integrity="sha256-ITHmamcImsZ/Je1xrdtDLZVvRSpj1Zokb6uHXORB824=" crossorigin="anonymous">
|
|
@endsection
|
|
@section('content')
|
|
<div class="container-fluid">
|
|
<div class="content">
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div class="card bg-light">
|
|
<div class="card-header">
|
|
<p class="card-title text-bold mb-0">Add New Zone</p>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-sm-5">
|
|
<h6>Zone Information</h6>
|
|
<div class="mb-3">
|
|
<label for="add-zone_name" class="form-label">Name</label>
|
|
<input type="text" class="form-control form-control-sm" name="add-zone_name" id="add-zone_name">
|
|
</div>
|
|
@if ($is_su)
|
|
<div class="mb-3">
|
|
<label for="add-zone_client" class="form-label">Company</label>
|
|
<select name="add-zone_client" id="add-zone_client" class="form-control select2">
|
|
<option value="">Choose</option>
|
|
@foreach ($clients as $client)
|
|
<option value="{{ $client->id }}" selected>{{ $client->name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
@endif
|
|
<div class="mb-3">
|
|
<label for="add-zone_type" class="form-label">Zone Type</label>
|
|
<select name="add-zone_type" id="add-zone_type" class="form-control select2">
|
|
<option value="">Choose</option>
|
|
@foreach ($types as $type)
|
|
<option value="{{ $type->id }}">{{ $type->name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="add-workflow_zone_type" class="form-label">Workflow Zone
|
|
Type</label>
|
|
<select name="add-workflow_zone_type" id="add-workflow_zone_type" class="form-control select2">
|
|
<option value="">Choose</option>
|
|
@foreach ($workflows as $workflow)
|
|
<option value="{{ $workflow->id }}">{{ $workflow->name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
{{-- <div class="mb-3">
|
|
<label for="add-shiptocode" class="form-label">Kode Pos</label>
|
|
<input type="number" class="form-control form-control-sm" name="add-shiptocode" id="add-shiptocode" placeholder="postcode">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="add-prid" class="form-label">Provinsi</label>
|
|
<select class="form-control form-control-sm select2" name="add-prid" id="add-prid">
|
|
<option value="">Select Province</option>
|
|
@foreach ($provs as $prov)
|
|
<option value="{{ $prov->kodeProv }}">
|
|
{{ $prov->nmProvinsiKel }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="add-ktid" class="form-label">Kabupaten/Kota</label>
|
|
<select class="form-control form-control-sm select2" name="add-ktid" id="add-ktid">
|
|
<option value="">Select City</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="add-kcid" class="form-label">Kecamatan</label>
|
|
<select class="form-control form-control-sm select2" name="add-kcid" id="add-kcid">
|
|
<option value="">Select District</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="add-klid" class="form-label">Desa/Kelurahan</label>
|
|
<select class="form-control form-control-sm select2" name="add-klid" id="add-klid">
|
|
<option value="">Select Village</option>
|
|
</select>
|
|
</div> --}}
|
|
<div class="mb-4">
|
|
<label for="add-fulladdress" class="form-label">Full Address</label>
|
|
<textarea name="add-fulladdress" id="add-fulladdress" class="form-control form-control-sm" rows="3"></textarea>
|
|
</div>
|
|
<h6>Lainnya</h6>
|
|
<div class="mb-4">
|
|
<label for="add-status" class="form-label">Status</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="add-status">
|
|
<label class="form-check-label" for="add-status"><span class="text-dark" id="add-txtStatus">Inactive</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-7">
|
|
<h6>Draw Zona</h6>
|
|
<div class="mb-3">
|
|
<div class="row">
|
|
<div class="col-3">
|
|
<label for="add-boundary_color" class="form-label">Color</label>
|
|
<input type="color" class="form-control form-control-sm" name="add-boundary_color" id="add-boundary_color" placeholder="hex codes">
|
|
</div>
|
|
<div class="col-9">
|
|
<label for="add-boundary_hex" class="form-label"> </label>
|
|
<input type="text" class="form-control form-control-sm" name="add-boundary_hex" id="add-boundary_hex" value="#000000" placeholder="hex codes">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<label for="add-boundary_type" class="form-label">Boundary</label>
|
|
<select id="add-boundary_type" name="add-boundary_type" class="form-control select2">
|
|
<option value="">Choose</option>
|
|
@foreach ($boundarys as $boundary)
|
|
@php
|
|
if ($boundary['id'] == \App\Models\Zone::ZONE_BOUNDARY_POLYGON) {
|
|
continue;
|
|
}
|
|
@endphp
|
|
<option value="{{ $boundary['id'] }}">{{ $boundary['name'] }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="add-group_boundary_circle col-6 mb-3 d-none">
|
|
<label for="add-boundary_radius" class="form-label">Radius
|
|
(meter)</label>
|
|
<input type="text" class="form-control form-control-sm" name="add-boundary_radius" id="add-boundary_radius">
|
|
</div>
|
|
<div class="add-group_boundary_circle col-6 d-none">
|
|
<label for="add-boundary_lat" class="form-label">Latitude</label>
|
|
<input type="text" class="form-control form-control-sm" name="add-boundary_lat" id="add-boundary_lat">
|
|
</div>
|
|
<div class="add-group_boundary_circle col-6 d-none">
|
|
<label for="add-boundary_lng" class="form-label">Longitude</label>
|
|
<input type="text" class="form-control form-control-sm" name="add-boundary_lng" id="add-boundary_lng">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="mapDraw" style="width:55vw;height:50vh;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-12">
|
|
<a href="{{ route('view_zone') }}" class="btn btn-sm btn-secondary">Cancel</a>
|
|
<button id="btnSubmitNewZone" class="btn btn-sm btn-danger">Save Zone</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('customjs')
|
|
<script src="{{ asset('assets/vendor/leaflet-1.7.1/leaflet-src.js') }}"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/vanilla-picker@2.12.1/dist/vanilla-picker.min.js" integrity="sha256-V1zh/sQiwo4NO4mg4WqQF9j79hDt7MBbTi3klxV3ZK4=" crossorigin="anonymous"></script>
|
|
<script>
|
|
'use strict'
|
|
|
|
const State = {
|
|
isDrawPolygonManual: 0,
|
|
storage_lara: "{{ asset('storage') }}/",
|
|
zone_status: {
|
|
active: "{{ App\Models\Zone::STATUS_ACTIVE }}",
|
|
inactive: "{{ App\Models\Zone::STATUS_INACTIVE }}",
|
|
},
|
|
boundary_type: {
|
|
circle: "{{ App\Models\Zone::ZONE_BOUNDARY_CIRCLE }}",
|
|
polygon: "{{ App\Models\Zone::ZONE_BOUNDARY_POLYGON }}",
|
|
rectangle: "{{ App\Models\Zone::ZONE_BOUNDARY_RECTANGLE }}",
|
|
},
|
|
boundary_type_choose: null,
|
|
boundary_latlngs: null, // [{lat,lng}].
|
|
boundary_radius: null, // in meters. only circle
|
|
boundary_bounds: null, // {northEast:{lat,lng},southWest:{lat,lng}}. only polygon,rectangle
|
|
delay_typing: 1500,
|
|
eventRemoveToolbarDraw: null,
|
|
};
|
|
|
|
const Wrapper = {
|
|
activate: function() {
|
|
Wrapper.event();
|
|
Leaflet.activate();
|
|
ZNew.activate();
|
|
},
|
|
event: function() {
|
|
$('#add-status').bind('change', function() {
|
|
if ($(this).is(':checked'))
|
|
$('#add-txtStatus').html('Active')
|
|
else
|
|
$('#add-txtStatus').html('Inactive')
|
|
});
|
|
},
|
|
};
|
|
|
|
const Req = {
|
|
geo_addr: function(data, isAlert = false, cb = null) {
|
|
return new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: "{{ route('api_osm_geo_addr') }}",
|
|
method: 'POST',
|
|
crossDomain: true,
|
|
processData: true,
|
|
headers: {
|
|
'x-api-key': Helper.getCookie('_trtk'),
|
|
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
|
},
|
|
data: data,
|
|
success: (resp, textStatus, jqXHR) => {
|
|
if (cb) cb(resp);
|
|
if (resp.meta.type != 'success') {
|
|
resolve({
|
|
type: 'fail'
|
|
});
|
|
if (isAlert) Helper.toast('Warning', 'just now', resp.meta
|
|
.message);
|
|
return false;
|
|
}
|
|
resolve({
|
|
type: 'success',
|
|
resp: resp,
|
|
});
|
|
},
|
|
error: (jqXHR, textStatus, error) => {
|
|
if (cb) cb(jqXHR.responseJSON);
|
|
if (jqXHR.status >= 500) {
|
|
if (isAlert) Helper.toast('Error', 'just now',
|
|
'please try again');
|
|
} else {
|
|
if (isAlert) Helper.toast('Error', 'just now', jqXHR
|
|
.responseJSON.meta.message);
|
|
}
|
|
resolve({
|
|
type: 'error'
|
|
});
|
|
}
|
|
})
|
|
})
|
|
},
|
|
list_city: function(data, isAlert = false, cb = null) {
|
|
return new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: "{{ route('api_region_list_city') }}",
|
|
method: 'GET',
|
|
crossDomain: true,
|
|
processData: true,
|
|
headers: {
|
|
'x-api-key': Helper.getCookie('_trtk'),
|
|
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
|
},
|
|
data: data,
|
|
success: (resp, textStatus, jqXHR) => {
|
|
if (cb) cb(resp);
|
|
if (resp.meta.type != 'success') {
|
|
resolve({
|
|
type: 'fail',
|
|
msg: resp.meta.message,
|
|
});
|
|
if (isAlert) Helper.toast('Warning', 'just now', resp.meta
|
|
.message);
|
|
return false;
|
|
}
|
|
resolve({
|
|
type: 'success',
|
|
resp: resp,
|
|
});
|
|
},
|
|
error: (jqXHR, textStatus, error) => {
|
|
if (cb) cb(jqXHR.responseJSON);
|
|
if (jqXHR.status >= 500) {
|
|
if (isAlert) Helper.toast('Error', 'just now',
|
|
'please try again');
|
|
} else {
|
|
if (isAlert) Helper.toast('Error', 'just now', jqXHR
|
|
.responseJSON.meta.message);
|
|
}
|
|
resolve({
|
|
type: 'error',
|
|
msg: jqXHR.responseJSON.meta.message,
|
|
});
|
|
}
|
|
})
|
|
})
|
|
},
|
|
list_district: function(data, isAlert = false, cb = null) {
|
|
return new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: "{{ route('api_region_list_district') }}",
|
|
method: 'GET',
|
|
crossDomain: true,
|
|
processData: true,
|
|
headers: {
|
|
'x-api-key': Helper.getCookie('_trtk'),
|
|
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
|
},
|
|
data: data,
|
|
success: (resp, textStatus, jqXHR) => {
|
|
if (cb) cb(resp);
|
|
if (resp.meta.type != 'success') {
|
|
resolve({
|
|
type: 'fail',
|
|
msg: resp.meta.message,
|
|
});
|
|
if (isAlert) Helper.toast('Warning', 'just now', resp.meta
|
|
.message);
|
|
return false;
|
|
}
|
|
resolve({
|
|
type: 'success',
|
|
resp: resp,
|
|
});
|
|
},
|
|
error: (jqXHR, textStatus, error) => {
|
|
if (cb) cb(jqXHR.responseJSON);
|
|
if (jqXHR.status >= 500) {
|
|
if (isAlert) Helper.toast('Error', 'just now',
|
|
'please try again');
|
|
} else {
|
|
if (isAlert) Helper.toast('Error', 'just now', jqXHR
|
|
.responseJSON.meta.message);
|
|
}
|
|
resolve({
|
|
type: 'error',
|
|
msg: jqXHR.responseJSON.meta.message,
|
|
});
|
|
}
|
|
})
|
|
})
|
|
},
|
|
list_village: function(data, isAlert = false, cb = null) {
|
|
return new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: "{{ route('api_region_list_village') }}",
|
|
method: 'GET',
|
|
crossDomain: true,
|
|
processData: true,
|
|
headers: {
|
|
'x-api-key': Helper.getCookie('_trtk'),
|
|
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
|
},
|
|
data: data,
|
|
success: (resp, textStatus, jqXHR) => {
|
|
if (cb) cb(resp);
|
|
if (resp.meta.type != 'success') {
|
|
resolve({
|
|
type: 'fail',
|
|
msg: resp.meta.message,
|
|
});
|
|
if (isAlert) Helper.toast('Warning', 'just now', resp.meta
|
|
.message);
|
|
return false;
|
|
}
|
|
resolve({
|
|
type: 'success',
|
|
resp: resp,
|
|
});
|
|
},
|
|
error: (jqXHR, textStatus, error) => {
|
|
if (cb) cb(jqXHR.responseJSON);
|
|
if (jqXHR.status >= 500) {
|
|
if (isAlert) Helper.toast('Error', 'just now',
|
|
'please try again');
|
|
} else {
|
|
if (isAlert) Helper.toast('Error', 'just now', jqXHR
|
|
.responseJSON.meta.message);
|
|
}
|
|
resolve({
|
|
type: 'error',
|
|
msg: jqXHR.responseJSON.meta.message,
|
|
});
|
|
}
|
|
})
|
|
})
|
|
},
|
|
}
|
|
|
|
const Leaflet = {
|
|
map: null,
|
|
activate: function() {
|
|
// centering java archipelago => .setView([-7.1451449, 109.9776078], 6.5);
|
|
// centering indonesia country => .setView([-1.38116, 117.6168817], 5.4);
|
|
Leaflet.map = L.map('mapDraw').setView([-8.90507, 125.9945732], 9);
|
|
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
|
|
attribution: 'Map data © <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
|
maxZoom: 20,
|
|
minZoom: 4,
|
|
id: 'mapbox/streets-v11',
|
|
tileSize: 512,
|
|
zoomOffset: -1,
|
|
accessToken: 'pk.eyJ1IjoibWV1c2luZmlybWFyeSIsImEiOiJja3lsd2xveDAydGhqMnVxaHJsZ2ZncG8yIn0.f7MJAyawHUdCegw7sWjrww',
|
|
}).addTo(Leaflet.map);
|
|
Leaflet.events();
|
|
},
|
|
events: function() {
|
|
Leaflet.map.on('click', function(e) {
|
|
if (State.isDrawPolygonManual) {
|
|
Leaflet.drawPolygon(e.latlng.lat, e.latlng.lng, {});
|
|
}
|
|
})
|
|
},
|
|
addCircles: function(locs = [], cb = null) {
|
|
if (locs.constructor === Array) {
|
|
let circles = [];
|
|
for (let i = 0; i < locs.length; i++) {
|
|
let circle = L.circle([locs[i].lat, locs[i].lng], locs[i]?.options);
|
|
circle.bindPopup(locs[i]?.label || '');
|
|
circle.bindTooltip(locs[i]?.label || '');
|
|
circles.push(circle);
|
|
if (cb) cb(circle);
|
|
circle.addTo(Leaflet.map);
|
|
}
|
|
return circles;
|
|
} else if (locs.constructor === Object) {
|
|
let circle = L.circle([locs.lat, locs.lng], locs?.options);
|
|
circle.bindPopup(locs?.label || '');
|
|
circle.bindTooltip(locs?.label || '');
|
|
if (cb) cb(circle);
|
|
circle.addTo(Leaflet.map);
|
|
return circle;
|
|
}
|
|
},
|
|
addPolylines: function(locs = [], cb = null) {
|
|
let latLngs = [];
|
|
for (let i = 0; i < locs.length; i++) {
|
|
latLngs.push([locs[i].lat, locs[i].lng]);
|
|
}
|
|
let polyline = L.polyline(latLngs, locs[0]?.options).addTo(Leaflet.map);
|
|
|
|
if (cb) cb(polyline);
|
|
return polyline;
|
|
},
|
|
addPolygons: function(locs = [], cb = null) {
|
|
let latLngs = [];
|
|
for (let i = 0; i < locs.length; i++) {
|
|
latLngs.push([locs[i].lat, locs[i].lng]);
|
|
}
|
|
let polygon = L.polygon(latLngs, locs[0]?.options).addTo(Leaflet.map);
|
|
|
|
if (cb) cb(polygon);
|
|
return polygon;
|
|
},
|
|
drawPolygon: function(lat, lng, options = {}) {
|
|
let polygon = L.polygon([
|
|
[lat, lng]
|
|
], options).addTo(Leaflet.map);
|
|
return polygon;
|
|
},
|
|
// draw boundary by mouse
|
|
createDrawLayer: function() {
|
|
let drawnItems = new L.FeatureGroup().addTo(Leaflet.map);
|
|
return drawnItems;
|
|
},
|
|
createDrawControl: function(options) {
|
|
// example
|
|
// let options = {
|
|
// edit: {
|
|
// featureGroup: drawnItems,
|
|
// poly: {
|
|
// allowIntersection: true, // draw while moving
|
|
// },
|
|
// },
|
|
// draw: {
|
|
// polygon: {
|
|
// allowIntersection: true, // draw while moving
|
|
// showArea: true,
|
|
// },
|
|
// marker: false,
|
|
// circlemarker: false,
|
|
// polyline: false,
|
|
// },
|
|
// };
|
|
|
|
let drawControl = new L.Control.Draw(options);
|
|
return drawControl;
|
|
},
|
|
createDrawToolbar: function(drawnItems, drawControl) {
|
|
// after finish not saved
|
|
Leaflet.map.addControl(drawControl);
|
|
|
|
Leaflet.map.on(L.Draw.Event.CREATED, function(e) {
|
|
// validate can create 1 shape only
|
|
if (!State.boundary_type_choose) { // if null
|
|
drawnItems.addLayer(e.layer);
|
|
ZNew.handleBoundaryDraw(e);
|
|
}
|
|
});
|
|
|
|
Leaflet.map.on(L.Draw.Event.EDITED, function(e) {
|
|
ZNew.handleBoundaryDraw(e);
|
|
});
|
|
|
|
Leaflet.map.on(L.Draw.Event.DELETED, function(e) {
|
|
ZNew.handleBoundaryDraw(e);
|
|
});
|
|
|
|
// remove marker, circle, event listener and all about this marker
|
|
State.eventRemoveToolbarDraw = new CustomEvent('eventRemoveToolbarDraw', {
|
|
drawnItems,
|
|
drawControl,
|
|
});
|
|
window.addEventListener('eventRemoveToolbarDraw', function handler(e) {
|
|
Leaflet.map.removeEventListener(L.Draw.Event.CREATED);
|
|
Leaflet.map.removeEventListener(L.Draw.Event.EDITED);
|
|
Leaflet.map.removeEventListener(L.Draw.Event.DELETED);
|
|
Leaflet.map.removeControl(drawControl);
|
|
Leaflet.map.removeLayer(drawnItems);
|
|
e.currentTarget.removeEventListener(e.type,
|
|
handler); // window.removeEventListener('remove', this.handler, true);
|
|
State.eventRemoveToolbarDraw = null;
|
|
State.boundary_type_choose = null;
|
|
State.boundary_latlngs = null;
|
|
ZNew.toggleInputCircle(false, false);
|
|
});
|
|
},
|
|
injectShapeToLDraw: function(obj) {
|
|
/**@argument
|
|
* create shape / vector layer
|
|
* convert the layer toGeoJSON/toGeoJson with precision default is 6
|
|
* set L.Draw toolbar/control layer
|
|
* convert the geoJSON shape/vector layer to leaflet geoJSON format
|
|
* add the shape/vector leaflet geoJSON format layer to L.Draw toolbar/control layer
|
|
**/
|
|
|
|
// for L.Draw
|
|
let shapeOpts = {
|
|
color: obj.boundary_hex_color,
|
|
fillOpacity: 0.4,
|
|
showRadius: true,
|
|
};
|
|
let drawnItems = Leaflet.createDrawLayer();
|
|
let drawControlOpts = {
|
|
edit: {
|
|
featureGroup: drawnItems,
|
|
},
|
|
draw: {
|
|
polygon: false,
|
|
marker: false,
|
|
circle: false,
|
|
rectangle: false,
|
|
circlemarker: false,
|
|
polyline: false,
|
|
},
|
|
};
|
|
// for layer (Shape / Vector)
|
|
let fitBounds = [],
|
|
circle = null,
|
|
polygon = null,
|
|
shapeGeoJSON = null;
|
|
let label = `<b>${obj.name}</b><br>${obj.fulladdress}`;
|
|
let boundaryOpts = {
|
|
mdata: obj,
|
|
color: obj.boundary_hex_color,
|
|
fillColor: obj.boundary_hex_color,
|
|
radius: obj.boundary_radius,
|
|
};
|
|
// for geoJSON
|
|
let style = {
|
|
color: obj.boundary_hex_color,
|
|
fillColor: obj.boundary_hex_color,
|
|
fillOpacity: 0.4,
|
|
radius: obj.boundary_radius,
|
|
showRadius: true,
|
|
}
|
|
|
|
// initDate
|
|
State.boundary_latlngs = obj.boundary_latlngs
|
|
State.boundary_radius = obj.boundary_radius
|
|
State.boundary_bounds = obj.boundary_bounds
|
|
|
|
// about shape/vector layer
|
|
if (obj.boundary_type == State.boundary_type.circle) {
|
|
State.boundary_type_choose = State.boundary_type.circle;
|
|
circle = L.circle([obj.boundary_latlngs[0].lat, obj.boundary_latlngs[0]
|
|
.lng
|
|
], boundaryOpts);
|
|
shapeGeoJSON = circle.toGeoJSON(6);
|
|
shapeGeoJSON.properties.radius = circle.getRadius();
|
|
let corner = L.latLng(obj.boundary_latlngs[0].lat, obj.boundary_latlngs[0]
|
|
.lng);
|
|
fitBounds.push(L.latLngBounds(corner, corner));
|
|
drawControlOpts.draw.circle = {
|
|
shapeOptions: {
|
|
...shapeOpts
|
|
},
|
|
};
|
|
} else if (obj.boundary_type == State.boundary_type.polygon) {
|
|
State.boundary_type_choose = State.boundary_type.polygon;
|
|
let latLngs = [];
|
|
for (let latLng of obj.boundary_latlngs) {
|
|
latLngs.push([latLng.lat, latLng.lng]);
|
|
let corner = L.latLng(latLng.lat, latLng.lng);
|
|
fitBounds.push(L.latLngBounds(corner, corner));
|
|
}
|
|
polygon = L.polygon(latLngs, boundaryOpts);
|
|
shapeGeoJSON = polygon.toGeoJSON(6);
|
|
drawControlOpts.draw.polygon = {
|
|
shapeOptions: {
|
|
...shapeOpts
|
|
},
|
|
};
|
|
} else if (obj.boundary_type == State.boundary_type.rectangle) {
|
|
State.boundary_type_choose = State.boundary_type.polygon;
|
|
let latLngs = [];
|
|
for (let latLng of obj.boundary_latlngs) {
|
|
latLngs.push([latLng.lat, latLng.lng]);
|
|
let corner = L.latLng(latLng.lat, latLng.lng);
|
|
fitBounds.push(L.latLngBounds(corner, corner));
|
|
}
|
|
polygon = L.polygon(latLngs, boundaryOpts);
|
|
shapeGeoJSON = polygon.toGeoJSON(6);
|
|
drawControlOpts.draw.rectangle = {
|
|
shapeOptions: {
|
|
...shapeOpts
|
|
},
|
|
};
|
|
} else {
|
|
Helper.toast('Error', 'just now', 'unknown boundary type');
|
|
return false;
|
|
}
|
|
|
|
// about L.Draw control/toolbar layer
|
|
let drawControl = Leaflet.createDrawControl(drawControlOpts);
|
|
Leaflet.createDrawToolbar(drawnItems, drawControl);
|
|
|
|
// about convert shape/vector geoJSON to leaflet geoJSON format
|
|
let layers = [];
|
|
let geoJsonGroup = L.geoJSON(shapeGeoJSON, {
|
|
style: style,
|
|
pointToLayer: (feature, latlng) => {
|
|
if (feature.properties.radius) {
|
|
return new L.Circle(latlng, feature.properties.radius);
|
|
} else {
|
|
return new L.Marker(latlng);
|
|
}
|
|
},
|
|
onEachFeature: (feature, layer) => {
|
|
layers.push(layer);
|
|
},
|
|
});
|
|
|
|
// add shape/vector layer to L.Draw control/toolbar layer
|
|
// Would benefit from https://github.com/Leaflet/Leaflet/issues/4461
|
|
function addNonGroupLayers(sourceLayer, targetGroup) {
|
|
if (sourceLayer instanceof L.LayerGroup) {
|
|
sourceLayer.eachLayer(function(layer) {
|
|
addNonGroupLayers(layer, targetGroup);
|
|
});
|
|
} else {
|
|
targetGroup.addLayer(sourceLayer);
|
|
}
|
|
}
|
|
addNonGroupLayers(geoJsonGroup, drawnItems);
|
|
|
|
// set center
|
|
Leaflet.map.fitBounds(fitBounds);
|
|
},
|
|
clearLayer: function(type = 'all', cb = null) {
|
|
if (type == 'all') {
|
|
if (State.eventRemoveToolbarDraw) window.dispatchEvent(State.eventRemoveToolbarDraw);
|
|
if (cb) cb();
|
|
} else if (type == 'eventRemoveToolbarDraw') {
|
|
if (State.eventRemoveToolbarDraw) {
|
|
window.dispatchEvent(State.eventRemoveToolbarDraw);
|
|
if (cb) cb();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const ZNew = {
|
|
activate: function() {
|
|
ZNew.event();
|
|
},
|
|
event: function() {
|
|
$('#btnSubmitNewZone').on('click', function() {
|
|
let data = ZNew.getData();
|
|
let oneKmInMeters = 2000; // 1000 meters
|
|
let squareKminSquareMeter = 2000000; // 100 hectare || 1000000 square meter | 1 square kilometer
|
|
// if (data.boundary_type == State.boundary_type.circle) {
|
|
// if (data.boundary_diameter > oneKmInMeters) {
|
|
// Helper.toast('Warning', 'just now', 'Maksimal diameter 1 Km');
|
|
// return false;
|
|
// }
|
|
// } else if (data.boundary_type == State.boundary_type.rectangle) {
|
|
// if (data.boundary_area > squareKminSquareMeter) {
|
|
// Helper.toast('Warning', 'just now', 'Maksimal area 1 Km');
|
|
// return false;
|
|
// }
|
|
// } else if (data.boundary_type == State.boundary_type.polygon) {
|
|
// if (data.boundary_area > squareKminSquareMeter) {
|
|
// Helper.toast('Warning', 'just now', 'Maksimal area 1 Km');
|
|
// return false;
|
|
// }
|
|
// }
|
|
ZNew.submitData(data);
|
|
});
|
|
|
|
$('#add-boundary_type').on('change', function(e) {
|
|
Leaflet.clearLayer('eventRemoveToolbarDraw');
|
|
|
|
let type = $('#add-boundary_type').val();
|
|
let options = {},
|
|
shapeOptions = {};
|
|
let drawnItems = Leaflet.createDrawLayer();
|
|
|
|
shapeOptions.color = $('#add-boundary_hex').val();
|
|
shapeOptions.fillOpacity = 0.4;
|
|
shapeOptions.showRadius = true;
|
|
|
|
if (type == State.boundary_type.circle) {
|
|
options = {
|
|
edit: {
|
|
featureGroup: drawnItems,
|
|
},
|
|
draw: {
|
|
circle: {
|
|
shapeOptions: {
|
|
...shapeOptions
|
|
},
|
|
},
|
|
marker: false,
|
|
polygon: false,
|
|
rectangle: false,
|
|
circlemarker: false,
|
|
polyline: false,
|
|
},
|
|
};
|
|
ZNew.toggleInputCircle(true, false);
|
|
} else if (type == State.boundary_type.polygon) {
|
|
options = {
|
|
edit: {
|
|
featureGroup: drawnItems,
|
|
},
|
|
draw: {
|
|
polygon: {
|
|
shapeOptions: {
|
|
...shapeOptions
|
|
},
|
|
},
|
|
marker: false,
|
|
circle: false,
|
|
rectangle: false,
|
|
circlemarker: false,
|
|
polyline: false,
|
|
},
|
|
};
|
|
} else if (type == State.boundary_type.rectangle) {
|
|
options = {
|
|
edit: {
|
|
featureGroup: drawnItems,
|
|
},
|
|
draw: {
|
|
rectangle: {
|
|
shapeOptions: {
|
|
...shapeOptions
|
|
},
|
|
},
|
|
marker: false,
|
|
polygon: false,
|
|
circle: false,
|
|
circlemarker: false,
|
|
polyline: false,
|
|
},
|
|
};
|
|
} else {
|
|
Helper.toast('Warning', 'just now', 'please choose boundary type');
|
|
return false;
|
|
}
|
|
|
|
let drawControl = Leaflet.createDrawControl(options);
|
|
Leaflet.createDrawToolbar(drawnItems, drawControl);
|
|
});
|
|
|
|
let addrChangeTimeout = null;
|
|
$('#add-fulladdress').on('keyup', async function(e) {
|
|
clearTimeout(addrChangeTimeout);
|
|
// do ajax and set center
|
|
addrChangeTimeout = setTimeout(() => {
|
|
let data = {
|
|
address: $('#add-fulladdress').val(),
|
|
country_code: 'id',
|
|
}
|
|
Req.geo_addr(data, false, function(resp) {
|
|
if (resp.meta.type == 'success' && resp.data) {
|
|
if (resp.data.lat && resp.data.lng) {
|
|
Leaflet.map.setView([resp.data.lat, resp.data.lng], 16);
|
|
}
|
|
}
|
|
});
|
|
}, State.delay_typing);
|
|
});
|
|
$('#add-boundary_color').on('input', function(e) {
|
|
$('#add-boundary_hex').val(this.value);
|
|
});
|
|
$('#add-boundary_hex').on('input', function(e) {
|
|
$('#add-boundary_color').val(this.value);
|
|
});
|
|
|
|
function createPOI() {
|
|
let rad = $('#add-boundary_radius').val();
|
|
let lat = $('#add-boundary_lat').val();
|
|
let lng = $('#add-boundary_lng').val();
|
|
if (rad.length < 1 || lat.length < 1 || lng.length < 1) return false;
|
|
Leaflet.clearLayer('eventRemoveToolbarDraw');
|
|
const obj = {
|
|
boundary_hex_color: $('#add-boundary_hex').val(),
|
|
name: '',
|
|
fulladdress: '',
|
|
boundary_radius: Number(rad),
|
|
boundary_latlngs: [{
|
|
lat: lat,
|
|
lng: lng,
|
|
}, ],
|
|
boundary_bounds: '',
|
|
boundary_type: State.boundary_type.circle,
|
|
createDrawToolbar: State.createDrawToolbar,
|
|
};
|
|
Leaflet.injectShapeToLDraw(obj);
|
|
ZNew.toggleInputCircle(true, rad, {
|
|
lat,
|
|
lng
|
|
});
|
|
}
|
|
let radTimeout = null;
|
|
$('#add-boundary_radius').on('keyup', function() {
|
|
radTimeout = setTimeout(() => {
|
|
createPOI();
|
|
}, State.delay_typing);
|
|
});
|
|
let latTimeout = null;
|
|
$('#add-boundary_lat').on('keyup', function() {
|
|
latTimeout = setTimeout(() => {
|
|
createPOI();
|
|
}, State.delay_typing);
|
|
});
|
|
let lngTimeout = null;
|
|
$('#add-boundary_lng').on('keyup', function() {
|
|
lngTimeout = setTimeout(() => {
|
|
createPOI();
|
|
}, State.delay_typing);
|
|
});
|
|
|
|
$('#add-prid').on('change', async function(e) {
|
|
let list_city = await Req.list_city({
|
|
kodeProv: $('#add-prid').val(),
|
|
}, true);
|
|
if (list_city.type == 'success') {
|
|
$('#add-ktid').html('<option value="">Select City</option>');
|
|
$('#add-kcid').html('<option value="">Select District</option>');
|
|
$('#add-klid').html('<option value="">Select Village</option>');
|
|
for (let city of list_city.resp.data) {
|
|
$('#add-ktid').append('<option value="' + city.kodeKab + '">' + city.nmKotamadyaKel + '</option>');
|
|
}
|
|
}
|
|
});
|
|
$('#add-ktid').on('change', async function(e) {
|
|
let list_district = await Req.list_district({
|
|
kodeKab: $('#add-ktid').val(),
|
|
}, true);
|
|
if (list_district.type == 'success') {
|
|
$('#add-kcid').html('<option value="">Select District</option>');
|
|
for (let district of list_district.resp.data) {
|
|
$('#add-kcid').append('<option value="' + district.kodeKec + '">' + district.nmKecamatanKel + '</option>');
|
|
}
|
|
}
|
|
});
|
|
$('#add-kcid').on('change', async function(e) {
|
|
let list_village = await Req.list_village({
|
|
kodeKec: $('#add-kcid').val(),
|
|
}, true);
|
|
if (list_village.type == 'success') {
|
|
$('#add-klid').html('<option value="">Select Village</option>');
|
|
for (let village of list_village.resp.data) {
|
|
$('#add-klid').append('<option value="' + village.kodeKel + '">' + village.nmKelurahan + '</option>');
|
|
}
|
|
}
|
|
});
|
|
},
|
|
getData: function() {
|
|
let data = {};
|
|
data.zone_name = $('#add-zone_name').val();
|
|
data.zone_client = $('#add-zone_client').val();
|
|
data.zone_type = $('#add-zone_type').val();
|
|
data.workflow_zone_type = $('#add-workflow_zone_type').val();
|
|
data.shiptocode = $('#add-shiptocode').val();
|
|
data.prid = $('#add-prid').val();
|
|
data.ktid = $('#add-ktid').val();
|
|
data.kcid = $('#add-kcid').val();
|
|
data.klid = $('#add-klid').val();
|
|
data.fulladdress = $('#add-fulladdress').val();
|
|
data.boundary_hex_color = $('#add-boundary_hex').val();
|
|
data.boundary_type = $('#add-boundary_type').val();
|
|
|
|
if (State.boundary_latlngs) {
|
|
data.boundary_latlngs = [...State.boundary_latlngs];
|
|
} else {
|
|
data.boundary_latlngs = null;
|
|
}
|
|
data.boundary_bounds = State.boundary_bounds;
|
|
data.boundary_radius = State.boundary_radius;
|
|
|
|
// https://gist.github.com/takvol/f4288261fba112030fb0fbfe11724f04
|
|
if (data.boundary_type == State.boundary_type.circle) {
|
|
data.boundary_diameter = data.boundary_radius * 2;
|
|
data.boundary_area = 0;
|
|
data.boundary_ha = 0;
|
|
} else if (data.boundary_type == State.boundary_type.rectangle) {
|
|
data.boundary_radius = 0;
|
|
data.boundary_diameter = 0;
|
|
data.boundary_area = L.GeometryUtil.geodesicArea(data.boundary_latlngs); // in square meter
|
|
data.boundary_ha = L.GeometryUtil.readableArea(data.boundary_area, true).replace(' ha', ''); // in ha
|
|
} else if (data.boundary_type == State.boundary_type.polygon) {
|
|
data.boundary_radius = 0;
|
|
data.boundary_diameter = 0;
|
|
data.boundary_area = L.GeometryUtil.geodesicArea(data.boundary_latlngs); // in square meter
|
|
data.boundary_ha = L.GeometryUtil.readableArea(data.boundary_area, true).replace(' ha', ''); // in ha
|
|
} else {
|
|
data.boundary_radius = 0;
|
|
data.boundary_diameter = 0;
|
|
data.boundary_area = 0;
|
|
data.boundary_ha = 0;
|
|
}
|
|
|
|
if ($('#add-status').prop('checked')) {
|
|
data.status = State.zone_status.active;
|
|
} else {
|
|
data.status = State.zone_status.inactive;
|
|
}
|
|
return data;
|
|
},
|
|
submitData: async function(data) {
|
|
return new Promise((resolve, reject) => {
|
|
if (typeof $('#btnSubmitNewZone').attr('disabed') != 'undefined') {
|
|
resolve({
|
|
type: 'fail'
|
|
});
|
|
return false;
|
|
}
|
|
$('#btnSubmitNewZone').attr('disabed', true);
|
|
$.ajax({
|
|
url: "{{ route('api_add_zone') }}",
|
|
method: 'POST',
|
|
crossDomain: true,
|
|
processData: true,
|
|
headers: {
|
|
'x-api-key': Helper.getCookie('_trtk'),
|
|
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
|
},
|
|
data: data,
|
|
success: (data, textStatus, jqXHR) => {
|
|
$('#btnSubmitNewZone').removeAttr('disabed');
|
|
if (data.meta.type != 'success') {
|
|
resolve({
|
|
type: 'fail'
|
|
});
|
|
Helper.toast('Warning', 'just now', data.meta.message);
|
|
return false;
|
|
}
|
|
Helper.toast('Success', 'just now', 'success add new zone');
|
|
window.location.href = "{{ route('view_zone') }}"
|
|
resolve({
|
|
type: 'success'
|
|
});
|
|
},
|
|
error: (jqXHR, textStatus, error) => {
|
|
$('#btnSubmitNewZone').removeAttr('disabed');
|
|
if (jqXHR.status >= 500) {
|
|
Helper.toast('Error', 'just now', 'please try again');
|
|
} else {
|
|
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
|
.message);
|
|
}
|
|
resolve({
|
|
type: 'error'
|
|
});
|
|
}
|
|
})
|
|
})
|
|
},
|
|
handleBoundaryDraw: function(e) {
|
|
if (e.type == L.Draw.Event.CREATED) {
|
|
|
|
} else if (e.type == L.Draw.Event.EDITED) {
|
|
e.layerType = State.boundary_type_choose;
|
|
e.layer = e.layers._layers[Object.keys(e.layers._layers)[0]];
|
|
} else if (e.type == L.Draw.Event.DELETED) {
|
|
State.boundary_type_choose = null;
|
|
State.boundary_latlngs = null;
|
|
State.boundary_radius = null;
|
|
State.boundary_bounds = null;
|
|
return true;
|
|
}
|
|
|
|
if (e.layerType == State.boundary_type.circle) {
|
|
State.boundary_type_choose = State.boundary_type.circle;
|
|
State.boundary_latlngs = [{
|
|
lat: e.layer._latlng.lat,
|
|
lng: e.layer._latlng.lng,
|
|
}];
|
|
State.boundary_radius = e.layer._mRadius;
|
|
ZNew.toggleInputCircle(true, State.boundary_radius, {
|
|
lat: e.layer._latlng.lat,
|
|
lng: e.layer._latlng.lng
|
|
});
|
|
} else if (e.layerType == State.boundary_type.polygon) {
|
|
State.boundary_type_choose = State.boundary_type.polygon;
|
|
State.boundary_latlngs = [];
|
|
for (let i in e.layer._latlngs[0]) {
|
|
State.boundary_latlngs.push({
|
|
lat: e.layer._latlngs[0][i].lat,
|
|
lng: e.layer._latlngs[0][i].lng,
|
|
})
|
|
}
|
|
State.boundary_bounds = {
|
|
northEast: {
|
|
lat: e.layer._bounds._northEast.lat,
|
|
lng: e.layer._bounds._northEast.lng,
|
|
},
|
|
southWest: {
|
|
lat: e.layer._bounds._southWest.lat,
|
|
lng: e.layer._bounds._southWest.lng,
|
|
},
|
|
};
|
|
} else if (e.layerType == State.boundary_type.rectangle) {
|
|
State.boundary_type_choose = State.boundary_type.rectangle;
|
|
State.boundary_latlngs = [];
|
|
for (let i in e.layer._latlngs[0]) {
|
|
State.boundary_latlngs.push({
|
|
lat: e.layer._latlngs[0][i].lat,
|
|
lng: e.layer._latlngs[0][i].lng,
|
|
})
|
|
}
|
|
State.boundary_bounds = {
|
|
northEast: {
|
|
lat: e.layer._bounds._northEast.lat,
|
|
lng: e.layer._bounds._northEast.lng,
|
|
},
|
|
southWest: {
|
|
lat: e.layer._bounds._southWest.lat,
|
|
lng: e.layer._bounds._southWest.lng,
|
|
},
|
|
};
|
|
}
|
|
},
|
|
toggleInputCircle: function(isShow = null, rad = null, opt = {}) {
|
|
if (isShow) {
|
|
$('.add-group_boundary_circle').removeClass('d-none');
|
|
} else {
|
|
$('.add-group_boundary_circle').addClass('d-none');
|
|
}
|
|
|
|
if (rad) {
|
|
$('#add-boundary_radius').val(rad);
|
|
} else {
|
|
$('#add-boundary_radius').val('');
|
|
}
|
|
|
|
if (opt.lat) {
|
|
$('#add-boundary_lat').val(opt.lat);
|
|
} else {
|
|
$('#add-boundary_lat').val('');
|
|
}
|
|
|
|
if (opt.lng) {
|
|
$('#add-boundary_lng').val(opt.lng);
|
|
} else {
|
|
$('#add-boundary_lng').val('');
|
|
}
|
|
},
|
|
}
|
|
|
|
Wrapper.activate();
|
|
</script>
|
|
@endsection
|