diff --git a/css/bts_timesheet.css b/css/bts_timesheet.css
index 3bb35c4..07563fa 100644
--- a/css/bts_timesheet.css
+++ b/css/bts_timesheet.css
@@ -8,6 +8,14 @@ body {
z-index: -1;
}
+.blink_me {
+ animation: blinker 0.3s linear infinite;
+}
+
+@keyframes blinker {
+ 50% { opacity: 0; }
+}
+
.titlebar_gradient {
/* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#f6e6b4+0,ed9017+100 */
background: rgb(246,230,180); /* Old browsers */
@@ -17,6 +25,14 @@ body {
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f6e6b4', endColorstr='#ed9017',GradientType=0 ); /* IE6-9 */
}
+
+.sheettitle h1:hover{
+ text-decoration: underline;
+ font-weight: bolder;
+ cursor: pointer;
+ animation: blinker 1s linear infinite;
+}
+
.timesheets {
width: calc(100vw - 300px);
height: 100vh;
@@ -673,13 +689,15 @@ div.brate,
div.bstaff,
div.bclient,
div.bconfirmed,
+div.bsave,
+div.brating,
div.bdelete {
width: 10%;
height: 30px;
}
div.btos {
- width: 20%;
+ width: 15%;
}
div.brate{
@@ -693,11 +711,34 @@ div.brate{
div.bdelete,
+div.bsave,
div.bconfirmed {
text-align:center;
width: 5%;
}
+div.brating{
+ text-align: center;
+ cursor: pointer;
+}
+
+
+.brating {
+ unicode-bidi: bidi-override;
+ direction: rtl;
+}
+.brating > span:hover:before,
+.brating > span:hover ~ span:before {
+ content: "\2605";
+ position: absolute;
+}
+
+
+div.bsave.saved span{
+ display: none;
+}
+
+
/* short code for the table */
div.btos select,
div.bstart input,
diff --git a/html/job.html b/html/job.html
index ec58727..7369381 100644
--- a/html/job.html
+++ b/html/job.html
@@ -3,26 +3,28 @@
-
+ [bts_type_of_service]
[bts_rate_options]
[bts_select_staff]
[bts_select_client]
-
+
+
+ ☆
+ ☆
+ ☆
+ ☆
+ ☆
+
+
+
+
+
\ No newline at end of file
diff --git a/js/bts_timesheet.js b/js/bts_timesheet.js
index b5cf5d3..15da342 100644
--- a/js/bts_timesheet.js
+++ b/js/bts_timesheet.js
@@ -254,8 +254,28 @@
jQuery('div.workspace').append(this.el);
this.load_data(data);
dtp_init();
+ this.init_start_rating();
}
+ init_start_rating(){
+ var self = this;
+ this.el.find("div.brating span").click(function(){
+ var r = $(this).attr('data-rating');
+ self.set_rating(r);
+ })
+
+ this.el.find("div.brating").mouseenter(function(){
+ //change to all hollow star
+ $(this).find('span').html('☆');
+ });
+
+ this.el.find("div.brating").mouseleave(function(){
+ self.set_rating(self.data.rating);
+ });
+
+ }
+
+
load_data(data)
{
this.set_job_id(data.id);
@@ -347,6 +367,27 @@
return;
return this.el.find('div.bconfirmed input').prop('checked', val!=0);
}
+ get_rating(){
+ var count =0;
+ this.el.find('div.brating span').each(function(i,e){
+ if ($(e).html()=='★')
+ count +=1;
+ });
+ return count;
+ }
+ set_rating(num){
+ if (!(1 <= num && num <=5))
+ return;
+ this.data.rating=num;
+ this.el.find('div.brating span').each(function(i,e){
+ var rating = $(e).attr('data-rating');
+ var rating = parseInt(rating);
+ if (rating <= num)
+ $(e).html('★');
+ else
+ $(e).html('☆');
+ });
+ }
get_record_from_ui(){
var record = {};
@@ -410,19 +451,240 @@
$(s).trigger('click');
}
- setTimeout(function(){
- set_modal_title('warning', 'suck title');
- set_modal_content('warning', 'fucking details');
- open_modal('warning');
- }, 1000);
+// setTimeout(function(){
+// set_modal_title('warning', 'suck title');
+// set_modal_content('warning', 'fucking details');
+// //open_modal('warning');
+// }, 1000);
+//
+// setTimeout(function(){
+// set_modal_title('error', 'error title');
+// set_modal_content('error', 'error details');
+// //open_modal('error');
+// }, 5000);
+
+ $(document).on('mouseenter', 'div.week1 div', function(){
+ $(this).addClass('blink_me');
+ get_week2_partner(this).addClass('blink_me');
+ });
+ $(document).on('mouseleave', 'div.week1 div', function(){
+ $(this).removeClass('blink_me');
+ get_week2_partner(this).removeClass('blink_me');
+ });
+
+ function get_week2_partner(div){
+ var index = $(div).index()+1;
+ return $('div.week2 div:nth-child('+index+')');
+ }
+
+ function init_weekdays(){
+ var curr = new Date; // get current date
+ // First day is the day of the month - the day of the week
+ var first = curr.getDate() - curr.getDay() + 1; //+1 we want Mon as first
+ var last = first + 6; // last day is the first day + 6
+
+ //var firstday = new Date(curr.setDate(first)); //Mon
+ //var lastday = new Date(curr.setDate(last)); //Sun
+
+ var pos = 1; //first lot
+ for (var i=first; i<=last; i++)
+ {
+ var d1 = new Date(curr.setDate(i));
+ var d2 = new Date(curr.setDate(i+7));
+ set_day_number(1,pos, d1); //week 1
+ set_day_number(2,pos, d2); //week 2
+ pos +=1;
+ }
+ }
+
+ function set_day_number(week, index, date){
+ var selector = 'span[name="w'+week+'d'+index+'"]';
+ $(selector).html(date.getDate());
+ $(selector).data({date:date});
+ }
+
+ function format_date(date) {
+ var monthNames = [
+ "January", "February", "March",
+ "April", "May", "June", "July",
+ "August", "September", "October",
+ "November", "December"
+ ];
+
+ var day = date.getDate();
+ var monthIndex = date.getMonth();
+ var year = date.getFullYear();
+
+ return day + ' ' + monthNames[monthIndex] + ' ' + year;
+ }
+ function set_today(){
+ var selector = 'div.sheettitle span[name="today"]';
+ var curr = new Date;
+ $(selector).html(format_date(curr));
+ }
+
+ Date.prototype.get_week_number = function(){
+ var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
+ var dayNum = d.getUTCDay() || 7;
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
+ var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
+ return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
+ };
+
+ function set_week_number(){
+ var date = $('span[name="w1d1"]').data().date;
+ console.log("date %o", date);
+ var num = date.get_week_number();
+ $('div.weekly span[name="week1"]').html(num);
+ $('div.weekly span[name="week2"]').html(num+1);
+ }
+
+ $('div.prevweek.left').click(function(){
+ $('div.weekdays span.weekday').each(function(i, e){
+ var date = $(e).data().date;
+ var newdate = new Date(date.setDate(date.getDate() -7 ));
+ $(e).html(newdate.getDate());
+ $(e).data({data:newdate});
+ });
+ set_week_number();
+ load_timesheet();
+ });
+ $('div.nextweek.right').click(function(){
+ $('div.weekdays span.weekday').each(function(i, e){
+ var date = $(e).data().date;
+ var newdate = new Date(date.setDate(date.getDate() +7 ));
+ $(e).html(newdate.getDate());
+ $(e).data({data:newdate});
+ });
+ set_week_number();
+ load_timesheet();
+ });
+
+ $('div.weekly div.weekname.prev').click(function(){
+ if (!confirm ('copy entire week to next week? '))
+ return;
+ });
+
+ $('div.weekly div.weekname.next').click(function(){
+ if (!confirm ('copy entire week to previous week? '))
+ return;
+ });
+
+ $('div.week1 > div').click(function(){
+ if (!confirm ('copy to next week'))
+ return;
+ });
+
+ $('div.sheettitle h1').click(function(){
+ reset_title_to_today();
+ })
+
+ function reset_title_to_today(){
+ set_today();
+ init_weekdays();
+ set_week_number();
+ load_timesheet();
+ }
+
+
+ function load_timesheet()
+ {
+ clear_workspace();
+ var first = $('span[name="w1d1"]').data().date;
+ var last = $('span[name="w2d7"]').data().date;
+ $.post(bts().ajax_url, { // POST request
+ _ajax_nonce: bts().nonce, // nonce
+ action: "list_job", // action
+ start: format_date(first),
+ finish: format_date(last),
+ }, function(response, status, xhr){
+ if (response.status =='success'){
+ response.jobs.forEach(function(job){
+ new Job(job);
+ });
+ //filter it if reqired
+ do_filter_workspace();
+ }else{
+ alert('error loading job');
+ }
+ });
+
+ }
+
+ function format_date(date){
+ var dd = date.getDate();
+ var mm = date.getMonth() + 1; //January is 0!
- setTimeout(function(){
- set_modal_title('error', 'error title');
- set_modal_content('error', 'error details');
- open_modal('error');
- }, 5000);
+ var yyyy = date.getFullYear();
+ if (dd < 10) {
+ dd = '0' + dd;
+ }
+ if (mm < 10) {
+ mm = '0' + mm;
+ }
+ return yyyy + '-' + mm + '-' +dd ;
+ }
+ function clear_workspace()//clear all timesheet jobs
+ {
+ $('div.workspace > div.divTable').remove();
+ //clear datetime picker
+ $('div.xdsoft_datetimepicker').remove();
+ }
+
+ $('button[name="confirmschedule"]').click(function(){
+ $('span.ticon.ticon-save').trigger('click');
+ });
+
+
+ $(document).on('click','div.userlist', debounce(do_filter_workspace));
+
+ function do_filter_workspace(){
+ var staffs =[];
+ $('div.stafflist div.peopleitem :checked').each(function(i, e){
+ var id = $(e).parent().attr('data-id');
+ //console.log("%o, id=%s", e, id);
+ staffs.push(id.substring(1));
+ });
+
+ var clients =[];
+ $('div.clientlist div.peopleitem :checked').each(function(i, e){
+ var id = $(e).parent().attr('data-id');
+ //console.log("%o, id=%s", e, id);
+ clients.push(id.substring(1));
+ });
+
+ console.log('staffs %o' , staffs);
+ console.log('clients %o' , clients);
+
+ filter_workspace(staffs, clients);
+ }
+
+ function filter_workspace(staffs, clients){
+
+ //if both array is empty
+ if( (staffs === undefined || staffs.length ==0) &&
+ (clients===undefined || clients.length ==0)){
+ //show all
+ $('div.workspace div.divTable').show();
+ return;
+ }
+
+ //filter some of them;
+ $('div.workspace div.divTable').each(function(i,e){
+ var job = $(e).data().job;
+ var s = job.get_staff();
+ var c = job.get_client();
+
+ if (staffs.indexOf(s) ==-1 && clients.indexOf(c) ==-1)
+ $(this).fadeOut();
+ else
+ $(this).fadeIn();
+ });
+ }
+
+ reset_title_to_today();
/*________________________________________________________________________*/
});
})(jQuery);
diff --git a/ts.php b/ts.php
index 668c101..0575558 100644
--- a/ts.php
+++ b/ts.php
@@ -41,6 +41,8 @@ class AcareOffice{
add_shortcode( 'bts_rate_options', array($this, 'bts_rate_options'));
add_shortcode( 'bts_select_staff', array($this, 'bts_select_staff'));
add_shortcode( 'bts_select_client', array($this, 'bts_select_client'));
+ add_shortcode( 'bts_type_of_service', array($this, 'bts_type_of_service'));
+
add_action('wp_ajax_list_staff', array($this,'list_staff' ));
add_action('wp_ajax_list_client', array($this,'list_client' ));
@@ -227,6 +229,21 @@ class AcareOffice{
return $result;
}
+ public function bts_type_of_service($attr){
+ $result = '
+ ';
+ return $result;
+ }
+
//generate template based on html file
private function template($id, $file)
{
@@ -411,12 +428,34 @@ class AcareOffice{
//ajax browse job with different filters
function list_job(){
check_ajax_referer('acaresydney');
- $r = $_POST['record'];
- $response = array();
+ $start = $_POST['start'];
+ $finish = $_POST['finish'];
+ $response = array(
+ 'status'=>'success',
+ 'jobs' => [],
+ );
+
+ $sql = "SELECT * FROM $this->table_name WHERE start>='%s' and start <='%s'";
+ $jobs = $this->db->get_results($this->db->prepare ($sql, array($start, $finish)));
+
+ if (! empty($jobs)){
+ $response['status'] = 'success';
+ foreach( $jobs as $s){
+ $response['jobs'][] = array(
+ 'id' => $s->id,
+ 'tos' => $s->tos,
+ 'start'=> $s->start,
+ 'finish'=> $s->finish,
+ 'rate'=> $s->rate,
+ 'staff'=> $s->staff,
+ 'client'=> $s->client,
+ 'ack' => $s->ack,
+ );
+ }
+ }
wp_send_json($response);
wp_die();
}
-
}
$bb = new AcareOffice();