diff --git a/include/controllers/default/cockpit2/api/driveronboarding/index.php b/include/controllers/default/cockpit2/api/driveronboarding/index.php new file mode 100644 index 000000000..a4dfdf180 --- /dev/null +++ b/include/controllers/default/cockpit2/api/driveronboarding/index.php @@ -0,0 +1,96 @@ +_save(); + break; + + case 'driver': + $this->_driver(); + break; + + default: + $this->_list(); + break; + } + } + + private function _driver(){ + $id_admin = c::getPagePiece( 3 ); + $driver = new Crunchbutton_Admin( $id_admin ); + if( $driver->id_admin ){ + echo json_encode( $driver->exports() ); + } else { + $this->_error( 'invalid object' ); + } + } + + private function _list(){ + $drivers = Crunchbutton_Admin::drivers(); + $list = []; + foreach( $drivers as $driver ){ + $list[] = $driver->exports(); + } + echo json_encode( $list ); + } + + + private function _save(){ + + if( $this->method() != 'post' ){ + $this->_error(); + } + + $id_admin = c::getPagePiece( 3 ); + // saves a new driver + if( !$id_admin ){ + $driver = new Crunchbutton_Admin(); + // create the new driver as inactive + $driver->active = 0; + } else { + $driver = Crunchbutton_Admin::o( $id_admin ); + } + + $driver->name = $this->request()[ 'name' ]; + $driver->phone = $this->request()[ 'phone' ]; + $driver->email = $this->request()[ 'email' ]; + + $driver->save(); + + // add the community + $id_community = $this->request()[ 'id_community' ]; + + // first remove the driver from the delivery groups + $_communities = Crunchbutton_Community::q( 'SELECT * FROM community ORDER BY name ASC' );; + foreach( $_communities as $community ){ + $group = $community->groupOfDrivers(); + if( $group->id_group ){ + $driver->removeGroup( $group->id_group ); + } + } + + if( $id_community ){ + $community = Crunchbutton_Community::o( $id_community ); + if( $community->id_community ){ + $group = $community->groupOfDrivers(); + $adminGroup = new Crunchbutton_Admin_Group(); + $adminGroup->id_admin = $driver->id_admin; + $adminGroup->id_group = $group->id_group; + $adminGroup->save(); + } + } + + echo json_encode( [ 'success' => $driver->exports() ] ); + return; + } + + private function _error( $error = 'invalid request' ){ + echo json_encode( [ 'error' => $error ] ); + exit(); + } + +} \ No newline at end of file diff --git a/include/library/Crunchbutton/Admin.php b/include/library/Crunchbutton/Admin.php index 76a1fe9e6..a45bdd620 100644 --- a/include/library/Crunchbutton/Admin.php +++ b/include/library/Crunchbutton/Admin.php @@ -475,12 +475,20 @@ class Crunchbutton_Admin extends Cana_Table { public function exports() { $permissions = []; $groups = []; + $communities = []; + if( $this->groups() ){ foreach ($this->groups() as $group) { $groups[$group->id_group] = $group->name; } } - + + if( $this->communitiesHeDeliveriesFor() ){ + foreach( $this->communitiesHeDeliveriesFor() as $community ){ + $communities[ $community->id_community ] = $community->name; + } + } + if ($this->permission()->_permissions) { foreach ($this->permission()->_permissions as $group => $perms) { foreach ($perms as $key => $value) { @@ -511,7 +519,8 @@ class Crunchbutton_Admin extends Cana_Table { 'timezone' => $this->timezone, 'testphone' => $this->testphone, 'permissions' => $permissions, - 'groups' => $groups + 'groups' => $groups, + 'communities' => $communities ]; return $ex; } diff --git a/include/views/default/cockpit2/bundle/js.phtml b/include/views/default/cockpit2/bundle/js.phtml index eb872dfa7..1c788b8cf 100644 --- a/include/views/default/cockpit2/bundle/js.phtml +++ b/include/views/default/cockpit2/bundle/js.phtml @@ -34,7 +34,6 @@ - diff --git a/include/views/default/cockpit2/frontend/drivers-onboarding-detail.phtml b/include/views/default/cockpit2/frontend/drivers-onboarding-detail.phtml index de9cd9554..dded46f6c 100644 --- a/include/views/default/cockpit2/frontend/drivers-onboarding-detail.phtml +++ b/include/views/default/cockpit2/frontend/drivers-onboarding-detail.phtml @@ -1,56 +1,56 @@
+
- - - + +
diff --git a/include/views/default/cockpit2/frontend/drivers-onboarding-list.phtml b/include/views/default/cockpit2/frontend/drivers-onboarding-list.phtml new file mode 100644 index 000000000..007553a10 --- /dev/null +++ b/include/views/default/cockpit2/frontend/drivers-onboarding-list.phtml @@ -0,0 +1,21 @@ +
+ +
+ + + + + + + + + + + + + +
Name
{{driver.name}} + +
+ +
diff --git a/include/views/default/cockpit2/frontend/drivers-onboarding.phtml b/include/views/default/cockpit2/frontend/drivers-onboarding.phtml deleted file mode 100644 index 5270562b0..000000000 --- a/include/views/default/cockpit2/frontend/drivers-onboarding.phtml +++ /dev/null @@ -1,5 +0,0 @@ -
-ready: {{ready}} -
-oi -
diff --git a/include/views/default/cockpit2/layout/html.body.phtml b/include/views/default/cockpit2/layout/html.body.phtml index a458c2127..c8c38067d 100644 --- a/include/views/default/cockpit2/layout/html.body.phtml +++ b/include/views/default/cockpit2/layout/html.body.phtml @@ -114,6 +114,11 @@
+ +
+

{{flash.getMessage()}}

+
+
{{newDriverOrders.count}}
diff --git a/www/assets/cockpit/js/cockpit.js b/www/assets/cockpit/js/cockpit.js index bffc739cb..7991b1e7d 100644 --- a/www/assets/cockpit/js/cockpit.js +++ b/www/assets/cockpit/js/cockpit.js @@ -33,7 +33,7 @@ App.NGinit = function() { } }; -var NGApp = angular.module('NGApp', [ 'ngRoute', 'ngResource'], function( $httpProvider ) { +var NGApp = angular.module('NGApp', [ 'ngRoute', 'ngResource' ], function( $httpProvider ) { $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; var param = function(obj) { var query = '', name, value, fullSubName, subName, subValue, innerObj, i; @@ -102,11 +102,16 @@ NGApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $l .when('/drivers/onboarding/', { action: 'drivers-onboarding', controller: 'DriversOnboardingCtrl', - templateUrl: 'assets/view/drivers-onboarding.html' + templateUrl: 'assets/view/drivers-onboarding-list.html' }) .when('/drivers/onboarding/new', { action: 'drivers-onboarding', - controller: 'DriversOnboardingNewCtrl', + controller: 'DriversOnboardingDetailsCtrl', + templateUrl: 'assets/view/drivers-onboarding-detail.html' + }) + .when('/drivers/onboarding/:id', { + action: 'drivers-onboarding', + controller: 'DriversOnboardingDetailsCtrl', templateUrl: 'assets/view/drivers-onboarding-detail.html' }) .otherwise({ @@ -119,7 +124,7 @@ NGApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $l }]); // global route change items -NGApp.controller('AppController', function ($scope, $route, $http, $routeParams, $rootScope, $location, $window, $timeout, MainNavigationService, AccountService, DriverOrdersService ) { +NGApp.controller('AppController', function ($scope, $route, $http, $routeParams, $rootScope, $location, $window, $timeout, MainNavigationService, AccountService, DriverOrdersService, flash ) { // define external pointers App.rootScope = $rootScope; @@ -127,6 +132,7 @@ NGApp.controller('AppController', function ($scope, $route, $http, $routeParams, App.http = $http; // define global services + $rootScope.flash = flash; $rootScope.navigation = MainNavigationService; $rootScope.isPhoneGap = App.isPhoneGap; $rootScope.server = App.server; @@ -514,3 +520,43 @@ App.dialog = { return $.magnificPopup && $.magnificPopup.instance && $.magnificPopup.instance.isOpen; } }; + +// Service to show a flash message +NGApp.factory( 'flash', function( $timeout ) { + + var message = []; + + // $rootScope.$on('$routeChangeSuccess', function() { + // clearMessage(); + // } ); + + var clearMessage = function(){ + message = false; + } + + service = {}; + service.setMessage = function( text, level ){ + var level = ( level ) ? level : 'success'; + message = { level : level, text : text }; + $timeout( function() { clearMessage() }, 5 * 1000 ); + } + + service.hasMessage = function(){ + return message != false; + } + + service.getLevel = function(){ + if( service.hasMessage() ){ + return message.level; + } + } + + service.getMessage = function(){ + if( service.hasMessage() ){ + return message.text; + } + } + + return service; + +} ); diff --git a/www/assets/cockpit/js/controllers.drivers.js b/www/assets/cockpit/js/controllers.drivers.js index 1a7699cf0..7bd2ead10 100644 --- a/www/assets/cockpit/js/controllers.drivers.js +++ b/www/assets/cockpit/js/controllers.drivers.js @@ -140,22 +140,50 @@ NGApp.controller( 'DriversShiftsCtrl', function ( $scope, DriverShiftsService ) NGApp.controller( 'DriversOnboardingCtrl', function ( $scope, DriverOnboardingService ) { $scope.ready = false; -}); -NGApp.controller( 'DriversOnboardingNewCtrl', function ( $scope, DriverOnboardingService, CommunityService ) { - - $scope.tab = { step : 1 }; - $scope.tab.change = function( step ){ - $scope.tab.step = step; - } - - $scope.ready = true; - - $scope.communities = []; - - // Load the communities and put them at scope - CommunityService.listSimple( function( data ){ - $scope.communities = data; + DriverOnboardingService.list( function( data ){ + $scope.drivers = data; + $scope.ready = true; } ); + $scope.edit = function( id_admin ){ + $scope.navigation.link( '/drivers/onboarding/' + id_admin ); + } +} ); + +NGApp.controller( 'DriversOnboardingDetailsCtrl', function ( $scope, DriverOnboardingService, CommunityService ) { + + $scope.ready = false; + + $scope.submitted = false; + + DriverOnboardingService.get( function( driver ){ + + $scope.driver = driver; + + // Load the communities and put them at scope + $scope.communities = []; + CommunityService.listSimple( function( data ){ + $scope.communities = data; + $scope.ready = true; + } ); + + } ); + + // method save that saves the driver + $scope.save = function(){ + if( $scope.form.$invalid ){ + $scope.submitted = true; + return; + } + DriverOnboardingService.save( $scope.driver, function(){ + $scope.navigation.link( '/drivers/onboarding/' ); + $scope.flash.setMessage( 'Driver saved!' ); + } ); + } + + $scope.cancel = function(){ + $scope.navigation.link( '/drivers/onboarding/' ); + } + } ); diff --git a/www/assets/cockpit/js/service.driveronboarding.js b/www/assets/cockpit/js/service.driveronboarding.js index 35027a5c1..00ee756d7 100644 --- a/www/assets/cockpit/js/service.driveronboarding.js +++ b/www/assets/cockpit/js/service.driveronboarding.js @@ -2,35 +2,40 @@ NGApp.factory( 'DriverOnboardingService', function( $rootScope, $resource, $rout var service = {}; - // Create a private resource 'orders' - var orders = $resource( App.service + 'driveronboarding/:action/:id_driver', { id_driver: '@id_driver', action: '@action' }, { + // Create a private resource 'drivers' + var drivers = $resource( App.service + 'driveronboarding/:action/:id_admin', { id_admin: '@id_admin', action: '@action' }, { // actions - 'get' : { 'method': 'GET', params : { 'action' : 'list', 'id' : 0 } }, - 'add' : { 'method': 'POST', params : { 'action' : 'delivery-accept' } }, + 'get' : { 'method': 'GET', params : { 'action' : 'driver' } }, + 'list' : { 'method': 'GET', params : { action: 'list', id_admin: null } }, + 'save' : { 'method': 'POST', params : { action: 'save' } } } ); + service.save = function( driver, callback ){ + drivers.save( driver, function( driver ){ + callback( driver ); + } ); + } + service.list = function( callback ){ - orders.query( {}, function( data ){ - var orders = []; - for( var x in data ){ - var order = data[ x ]; - if( order && order.date && order.date.date ){ - order._date = new Date( order.date.date ); - orders.push( order ); - } - } - service.newOrdersBadge(); - callback( orders ); + drivers.query( {}, function( drivers ){ + callback( drivers ); } ); } service.get = function( callback ){ - var id_driver = $routeParams.id; - orders.get( { 'id_driver': id_driver }, function( order ){ - order._date = new Date( order.date ); - callback( order ); - } ); + var id_admin = $routeParams.id; + if( id_admin && id_admin != 'new' ){ + drivers.get( { 'id_admin': id_admin }, function( driver ){ + if( driver.communities ){ + angular.forEach( driver.communities, function( name, id_community ){ + driver.id_community = id_community; + } ); + } + callback( driver ); + } ); + } + } return service; diff --git a/www/assets/cockpit/scss/cockpit.scss b/www/assets/cockpit/scss/cockpit.scss index 06dc95074..de303dd61 100644 --- a/www/assets/cockpit/scss/cockpit.scss +++ b/www/assets/cockpit/scss/cockpit.scss @@ -84,10 +84,10 @@ input[type="submit"]::-moz-focus-inner, input[type="button"]::-moz-focus-inner, html { -webkit-text-size-adjust: none; - -moz-text-size-adjust: none; - -ms-text-size-adjust: none; - -o-text-size-adjust: none; - text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + -o-text-size-adjust: none; + text-size-adjust: none; } * { @@ -113,10 +113,10 @@ html { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; - -moz-user-select: -moz-none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; + -moz-user-select: -moz-none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; } } @@ -204,6 +204,19 @@ p { } +/* INPUTS */ +.form input, .form select, .form textarea{ + font-size:1.2em; + border:1px solid #CCC; + width: 30em +} +.form.submitted .ng-invalid{ + border:1px solid red; +} +.form .error{ + color: red; + margin:3px; +} /* GLOBAL */ @@ -213,10 +226,10 @@ p { } .menu{ -webkit-transition: opacity 0.1s; - -moz-transition: opacity 0.1s; - -ms-transition: opacity 0.1s; - -o-transition: opacity 0.1s; - transition: opacity 0.1s; + -moz-transition: opacity 0.1s; + -ms-transition: opacity 0.1s; + -o-transition: opacity 0.1s; + transition: opacity 0.1s; } } @media(max-width: 768px) { @@ -288,10 +301,10 @@ p { overflow-x:hidden; -webkit-overflow-scrolling: touch; -webkit-transform: translate3d(0,0,0); - -moz-transform: translate3d(0,0,0); - -ms-transform: translate3d(0,0,0); - -o-transform: translate3d(0,0,0); - transform: translate3d(0,0,0); + -moz-transform: translate3d(0,0,0); + -ms-transform: translate3d(0,0,0); + -o-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); } .snap-content { position:absolute; @@ -316,15 +329,15 @@ p { overflow-x:hidden; -webkit-overflow-scrolling: touch; -webkit-transform: translate3d(0,0,0); - -moz-transform: translate3d(0,0,0); - -ms-transform: translate3d(0,0,0); - -o-transform: translate3d(0,0,0); - transform: translate3d(0,0,0); + -moz-transform: translate3d(0,0,0); + -ms-transform: translate3d(0,0,0); + -o-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); -webkit-transition: width 0.3s ease; - -moz-transition: width 0.3s ease; - -ms-transition: width 0.3s ease; - -o-transition: width 0.3s ease; - transition: width 0.3s ease; + -moz-transition: width 0.3s ease; + -ms-transition: width 0.3s ease; + -o-transition: width 0.3s ease; + transition: width 0.3s ease; } .snap-drawers { @@ -561,23 +574,23 @@ input { width: 100%; -webkit-transition: background linear 0.08s; - -moz-transition: background linear 0.08s; - -ms-transition: background linear 0.08s; - -o-transition: background linear 0.08s; - transition: background linear 0.08s; + -moz-transition: background linear 0.08s; + -ms-transition: background linear 0.08s; + -o-transition: background linear 0.08s; + transition: background linear 0.08s; } .button.ani-all { -webkit-transform: translate3d(0,0,0); - -moz-transform: translate3d(0,0,0); - -ms-transform: translate3d(0,0,0); - -o-transform: translate3d(0,0,0); - transform: translate3d(0,0,0); + -moz-transform: translate3d(0,0,0); + -ms-transform: translate3d(0,0,0); + -o-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); -webkit-transition: all linear 0.08s; - -moz-transition: all linear 0.08s; - -ms-transition: all linear 0.08s; - -o-transition: all linear 0.08s; - transition: all linear 0.08s; + -moz-transition: all linear 0.08s; + -ms-transition: all linear 0.08s; + -o-transition: all linear 0.08s; + transition: all linear 0.08s; } /* colors */ @@ -693,6 +706,7 @@ input { overflow: hidden; } + /* drivers order list page */ .last-updated{ font-size: 1em; @@ -988,10 +1002,10 @@ input { overflow: hidden; -webkit-transition: background .2s; - -moz-transition: background .2s; - -ms-transition: background .2s; - -o-transition: background .2s; - transition: background .2s; + -moz-transition: background .2s; + -ms-transition: background .2s; + -o-transition: background .2s; + transition: background .2s; } .wrap { @@ -1022,10 +1036,10 @@ input { overflow: hidden; -webkit-transition: background .2s; - -moz-transition: background .2s; - -ms-transition: background .2s; - -o-transition: background .2s; - transition: background .2s; + -moz-transition: background .2s; + -ms-transition: background .2s; + -o-transition: background .2s; + transition: background .2s; } .loader-frame { @@ -1041,16 +1055,16 @@ input { -webkit-transform:translate3d(0,0,0); -webkit-transform: scale(3); - -moz-transform: scale(3); - -ms-transform: scale(3); - -o-transform: scale(3); - transform: scale(3); + -moz-transform: scale(3); + -ms-transform: scale(3); + -o-transform: scale(3); + transform: scale(3); -webkit-transition: all .1s; - -moz-transition: all .1s; - -ms-transition: all .1s; - -o-transition: all .1s; - transition: all .1s; + -moz-transition: all .1s; + -ms-transition: all .1s; + -o-transition: all .1s; + transition: all .1s; } .loader { opacity: 1; @@ -1065,10 +1079,10 @@ body.loading { } body.loading .loader-frame { -webkit-transform: scale(1); - -moz-transform: scale(1); - -ms-transform: scale(1); - -o-transform: scale(1); - transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); opacity: 1; } @@ -1123,4 +1137,22 @@ strong{ font-weight: bold; } } .mfp-close { display: none !important; -} \ No newline at end of file +} + +.flash-message { + position: fixed; + font-size: 1em; + padding: 5px 15px; + display: inline-block; + text-align: center; + width: 20em; + top: .5em; + left: 50%; + margin-left: -100px; + border-radius: 5px; +} + .flash-message.success{ + background:#dff0d8; + color: #64763d; + border:1px solid #d6e9c6; + } \ No newline at end of file diff --git a/www/assets/js/directives.js b/www/assets/js/directives.js index dd020a15b..6e59c5f2e 100644 --- a/www/assets/js/directives.js +++ b/www/assets/js/directives.js @@ -443,7 +443,7 @@ NGApp.directive( 'modalReset', function( $rootScope ) { NGApp.directive( 'geoComplete', function() { return { restrict: 'A', - scope: { ngModel : '=', geoCompleteEnter : '&' }, + scope: { ngModel : '=', geoCompleteEnter : '&' }, link: function( scope, element, attrs ) { var el = document.getElementById( attrs.id ); if( typeof google == 'object' && google.maps && google.maps.places && google.maps.places.Autocomplete ){ @@ -462,4 +462,44 @@ NGApp.directive( 'geoComplete', function() { } } }; +}); + +NGApp.directive( 'phoneValidate', function () { + return { + restrict: 'A', + require: 'ngModel', + + link: function ( scope, elm, attrs, ctrl ) { + + ctrl.$parsers.unshift( function ( val ) { + + var isValid = false; + var phoneVal = val.replace( /[^0-9]/g, '' ); + + if ( phoneVal || phoneVal.length == 10) { + + var phoneVal = phoneVal.split(''), prev; + + for (x in phoneVal) { + if (!prev) { + prev = phoneVal[x]; + continue; + } + if (phoneVal[x] != prev) { + isValid = true; + } + } + } + + if( !isValid ){ + ctrl.$setValidity( 'phoneValidate', false ); + return undefined; + } else { + ctrl.$setValidity( 'phoneValidate', true ); + return val; + } + + } ); + } + }; }); \ No newline at end of file