처음부터 차근차근

Chart.js와 datepicker을 이용한 각 기간별 통계 본문

프로젝트/Hotel 예약 사이트 (Codeigniter)

Chart.js와 datepicker을 이용한 각 기간별 통계

_soyoung 2021. 12. 28. 17:49
반응형

chart.js를 이용해서 예약 연도별, 월별, 기간별 통계와 객실별 통계, 후기 별점 통계를 만들었다.

이미지와 같이 datepicker을 이용해 날짜를 원하는 날짜를 정하고 확인 버튼을 누르면 datepicker의 onClose 이벤트에 의해 새로 차트가 그려진다.

$( function() {
		$( ".datepicker" ).datepicker({  
			
			changeMonth: true,
			changeYear: true,
			showButtonPanel: true,
			closeText: '확인',
			dateFormat: 'yy-mm',
			onClose: function(dateText, inst) { 
				var month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
				var year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
				$(this).datepicker('setDate', new Date(year, month, 1));
				
				submitForm();
			}
		});
	});

 

 

 

 

예약 월별 통계

/~team2/month_chart 를 url을 통해 들어오면 아래의 코드를 실행한다.

function month_chart() {
			
			// 로그인 체크
			if(!$this->_checkAdminLogin()){
				return;
			}
			
			
			// 날짜를 새로 지정했을 때
			if(isset($_POST['start_date']) && isset($_POST['end_date'])) {
				
				$start_date = $_POST['start_date'];
				$end_date = $_POST['end_date'];
				
				$data = $this->_get_month_chart_info($start_date, $end_date);
				
				// 차트 타입
				$data['chart_type'] = $_POST['chart_type'];
				
			}
			// 처음 들어왔을 때
			else {
				
				// 날짜 구하기
				$start_date = date("Y-m", strtotime("-10 month", time())); // 지금으로 부터 10달 전
				$start_date .= "-01"; // 시작 달의 가장 처음 날짜를 구해야 하기 때문에 월 뒤에 1일을 붙여준다. 
				$end_date = date("Y-m-d", time()); // 현재 날짜
				$end_date = new DateTime( $end_date ); 
				$end_date = $end_date->format( 'Y-m-t' ); // 이렇게 하면 현재 월의 가장 마지막 날짜를 구할 수 있다.
                // 예를 들어 2월이면 2월 28일
				
				
				$data = $this->_get_month_chart_info($start_date, $end_date);
				
				
				// text에 찍힐 date
				$data['start_date'] = null;
				$data['end_date'] = null;
				
				// 차트 타입
				$data['chart_type'] = 'bar';
			}
			
			
			$this->_header();
			$this->load->view("admin_book_chart_month", array('data'=>$data));
			$this->_footer();
		}

 

start_date와 end_date의 post값이 없을 때 즉, month_chart 페이지를 처음 들어왔을 땐 10달 전 1일과 현재 달  마지막 날짜를 구해서 chart.js에 들어갈 데이터들을 추출한다.

 

post값이 있을 때는 start_date와 end_date를 post값 그대로 대입해서 post값 없을 때와 마찬가지로  데이터들을 추출하는데, 여기서 chart type도 post 값으로 들어오는 것을 볼 수 있다.

chart.js에서는 chart type을 코드 한줄로 쉽게 변경할 수 있기 때문에 사용의 편리함을 위해서 chart type을 정하는 버튼도 만들어 놓았다.

아래는 chart를 바꾸는 코드이다. 

<!--html 부분-->
<button type="button" class="btn btn-info" onclick="select_chart_type('bar');">막대 그래프</button>
<br><br>
<button type="button" class="btn btn-info" onclick="select_chart_type('line');">선 그래프</butto0n>

<script>
// js 부분
function select_chart_type(type) {
		document.getElementById('chart_type').value = type;
		submitForm();
	}
	
	
	function submitForm() {
		
		// end_date에 월의 마지막 날짜 붙이기
		var end_date = document.getElementById('date2').value;
		var arr = end_date.split("-");
		arr[1] = arr[1].replace("0","")
		var lastDate = new Date(arr[0], arr[1], 0).getDate();
		end_date += "-" + lastDate;
		
		
		var form = document.dateForm;
				
		
		document.getElementById('date1').value = document.getElementById('date1').value + "-01";
		document.getElementById('date2').value = end_date;
		
		if(document.getElementById('chart_type').value == "") {
			document.getElementById('chart_type').value = 'bar';
		}
		
		
		form.submit();
	}
</script>

chart type 바꾸는 버튼

 

 

아래는 chart.js에 들어갈 데이터들을 추출하는 함수이다.

function _get_month_chart_info($start_date, $end_date) {
			
            // (현재달 - 10달 1일) ~ (현재 달 마지막일) 사이에 있는 모든 예약을 구한다.
			$data['books'] = $this->Book_m->getBookByCheckIn($start_date, $end_date);
            
			// 예약이 하나도 없지않을 때
			if($data['books'] != null) {
				$data['users'] = $this->User_m->getUserByBooks($data['books']); // 예약한 사람 구하고
				$data['rooms'] = $this->Room_m->getRoomAll(); // 객실 가져오기
			}
			
			
			// chart.js data에 들어갈 값 구하기
			$data['datas'] = $this->Book_m->getBookMonthStatistic($start_date, $end_date);
			
			
			// 총 예약 수 구하기
			$tcount = 0;
			foreach ($data['datas'] as $datas) {
				$tcount += $datas->count;
			}
			$data['total_book_count'] = $tcount;
			
			
			// 총 수입 구하기
			$income = 0;
			foreach ($data['books'] as $book) {
				$income += $book->price;
			}
			$data['total_book_income'] = $income;
			
			
			//start_date와 end_date 사이에 있는 달의 개수 구하기
			$d1 = strtotime($start_date);
			$d2 = strtotime($end_date);
			$i = 0;
			while (($d1 = strtotime("+1 MONTH", $d1)) <= $d2) {
				$i++;
			}
			$between_month = $i;
			
			
			// text에 찍힐 date
            // text에 찍힐 date는 일이 찍히면 안되므로 일을 제외한 '연도-달'형식으로 만들어준다.
			$start_arr = explode('-', $start_date);
			$end_arr = explode('-', $end_date);
			$data['start_date'] = $start_arr[0]."-".$start_arr[1];
			$data['end_date'] = $end_arr[0]."-".$end_arr[1];
			
			
			// labels에 들어갈 값 구하기
            // '연도-달' 형식으로 이루어진 각 차트 기둥의 이름을 구하는 코드이다.
			$data['labels'] = array();
			$start_timestamp = strtotime($start_date);
			array_push($data['labels'], $data['start_date']);
			if($data['start_date'] != $data['end_date']) {
				for ($i = 0; $i < $between_month; $i++) {
					$start_dd = date("Y-m", strtotime("+1 month", $start_timestamp));
					array_push($data['labels'], $start_dd); 
					$start_timestamp = strtotime($start_dd."-01");
				}
			}
			
			return $data;
		}

 

 

그 다음 받아온 값을 아래와 같이 넣는다. 

type : 차트 타입

label : 각 차트의 이름

label 예시

data : 월별 예약 횟수

option : chart의 옵션사항

<!--chart 출력-->
<canvas id="myBarChart"></canvas> 

<!-- chart.js -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>	

<script>
var ctx = document.getElementById('myBarChart');
	
	var config = {
		type: '<?=$data['chart_type']?>',
		data: {
			labels: [ // Date Objects
				<?php
				foreach ($data['labels'] as $label) {
					echo "'".$label."',";
				}
				?>
			],
			datasets: [{
				label: '예약 수',
				<?php 
				// 막대 그래프일 때
				if($data['chart_type'] == 'bar') {
					echo "backgroundColor:  'rgba(75, 192, 192, 0.2)',";
					echo "borderColor: 'rgba(75, 192, 192, 1)',";
					echo "borderWidth: 1,//경계선 굵기";
				}
				// 선 그래프 일 때
				else {
					echo "backgroundColor:  'rgba(255, 99, 132, 0.2)',";
					echo "borderColor:  'rgba(255, 99, 132, 1)',";
				}
				?>
				fill: true,
				data: [
				<?php
					$count = 1;
					
					foreach ($data['labels'] as $label) {
						foreach ($data['datas'] as $val) {
							if ($val->month == $label) {
								echo "'".$val->count."',";
								$count++;
								break;
							}
							else {
								// 끝까지 못찾았을 때
								if($count == count($data['datas'])) echo "0, ";
								$count++;
							}
						}
						$count = 1;
						
					}
				?>
				],
			}]
		},
		options: {
			maintainAspectRatio: false,
			title: {
				text: 'Chart.js Time Scale'
			},
			scales: {
				yAxes: [{
					scaleLabel: {
						display: true,
						beginAtZero: true
					}
				}]
			},
		}
	};
	 
	//차트 그리기
	var myChart = new Chart(ctx, config);
</script>

 

 

 

 

 

chart.js 결과 화면

예약 월별 통계

 

예약 연도별 통계

 

예약 기간별 통계

 

객실별 통계

 

후기 별점 통계

 

반응형
Comments