해당 게시글은 개인 프로젝트인 "광고 관리 플랫폼 대행사 센터 제작" 중
#133 "대시보드 기능 기획", #135 "대시보드 기능 구현 - 대행사 대시보드" 이슈를 다루고 있습니다.
    @Transactional(readOnly = true)
    public List<DashboardStatisticsDto> setTestDashboard(LocalDate startDate, LocalDate lastDate) {
        LocalDate defaultLastDate = LocalDate.parse(LocalDate.now().minusDays(1)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        LocalDate startDateBeforeSevenDays = defaultLastDate.minusDays(6);
        LocalDate startDateBeforeThirtyDays = defaultLastDate.minusDays(30);
        if (lastDate == null) {
            lastDate = defaultLastDate;
        }
        if (startDate == null) {
            startDate = startDateBeforeThirtyDays;
        }
        return statisticsQueryRepository.dashboardTestQuery(startDate, lastDate);
    }
    @Transactional(readOnly = true)
    public Page<DashboardStatisticsDto> setTestDashboardTable(LocalDate startDate, LocalDate lastDate, Pageable pageable) {
        LocalDate defaultLastDate = LocalDate.parse(LocalDate.now().minusDays(1)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        LocalDate startDateBeforeSevenDays = defaultLastDate.minusDays(6);
        LocalDate startDateBeforeThirtyDays = defaultLastDate.minusDays(30);
        if (lastDate == null) {
            lastDate = defaultLastDate;
        }
        if (startDate == null) {
            startDate = startDateBeforeThirtyDays;
        }
        List<DashboardStatisticsDto> resultList =  statisticsQueryRepository.dashboardTestQuery2(startDate, lastDate);
        final int start = (int)pageable.getOffset();
        final int end = Math.min((start + pageable.getPageSize()), resultList.size());
        final Page<DashboardStatisticsDto> resultPage = new PageImpl<>(resultList.subList(start, end), pageable, resultList.size());
        return resultPage;
    }
    public List<DashboardStatisticsDto> dashboardTestQuery(@Param("startDate") LocalDate startDate,
                                                           @Param("lastDate") LocalDate lastDate
    ) {
        List<DashboardStatisticsDto> results = jpaQueryFactory
                .select(Projections.fields(DashboardStatisticsDto.class,
                        performance.spend.sum().as("spend"),
						performance.createdAt.as("startDate")
                ))
                .from(performance)
                .leftJoin(performance.creative, creative)
                .where(
                        performance.createdAt.between(startDate, lastDate),
                        creative.deleted.eq(false)
                )
                .groupBy(performance.createdAt)
                .fetch();
        for (DashboardStatisticsDto result : results) {
            Long spend = result.getSpend();
            result.setSpendIndicator(spend);
        }
        return results;
    }
    public List<DashboardStatisticsDto> dashboardTestQuery2(@Param("startDate") LocalDate startDate,
                                                           @Param("lastDate") LocalDate lastDate
    ) {
        List<DashboardStatisticsDto> results = jpaQueryFactory
                .select(Projections.fields(DashboardStatisticsDto.class,
                        performance.spend.sum().as("spend"),
						performance.createdAt.as("startDate")
                ))
                .from(performance)
                .leftJoin(performance.creative, creative)
                .where(
                        performance.createdAt.between(startDate, lastDate),
                        creative.deleted.eq(false)
                )
                .groupBy(performance.createdAt)
                .orderBy(performance.createdAt.desc())
                .fetch();
        for (DashboardStatisticsDto result : results) {
            Long spend = result.getSpend();
            result.setSpendIndicator(spend);
        }
        return results;
    }
    @GetMapping()
    public String dashboard(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate lastDate,
            Model model,
            ModelMap map,
            @PageableDefault(size = 10, sort = "startDate", direction = Sort.Direction.DESC) Pageable pageable
            ) {
        List<DashboardStatisticsDto> results = dashboardService.setTestDashboard(startDate, lastDate);
        Page<DashboardStatisticsDto> resultpages = dashboardService.setTestDashboardTable(startDate, lastDate, pageable);
        List<Integer> barNumbers = paginationService.getPaginationBarNumbers(pageable.getPageNumber(), resultpages.getTotalPages());
        model.addAttribute("results", results);
        model.addAttribute("resultpages", resultpages);
        map.addAttribute("paginationBarNumbers", barNumbers);
        return "dashboard/index";
    }

var data = /*[[ ${results} ]]*/[]; // controller에서 보낸 model 
<script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
    $(document).ready(function () {
        var dayList = []; // x축
        var spendList = []; // y축
        var data = /*[[ ${results} ]]*/[]; // controller에서 보낸 model 'results'
		// 반복문으로 results 내의 startDate와 spend 데이터를 주입
        for (var i = 0; i < data.length; i++) {
            dayList.push(data[i].startDate);
            spendList.push(data[i].spend);
        }
        const ctx = document.getElementById('myChart').getContext('2d');
        const chart = new Chart(ctx, {
            type: 'bar', //chart 타입
            data: {
                labels: dayList,
                datasets: [{
                    fill: false,
                    data: spendList,
                    backgroundColor: [
                        'rgb(95,192,153)',
                    ],
                    borderColor: [
                        'rgba(125,134,173,0)',
                    ],
                    borderWidth: 1,
                    barPercentage: 0.5
                }]
            },
            options: {
				// 차트 범례 삭제
                plugins: {
                    legend: {
                        display: false
                    },
                },
                scales: {
                    y: {
                        grid: {
                            drawOnChartArea: true,  //선 지우기
                            drawTicks: false,   //축의 숫자 옆 눈금 지우기
                            drawBorder: true,
                            borderDash: [3, 3]	//y축 선 실선으로 길이 3,간격 3으로
                        },
                        ticks: {
                            padding: 10,
                            beginAtZero: true
                        }
                    },
                    x: {
                        grid: {
                            display: false,
                            drawBorder: false,
                            drawTicks: false
                        },
                        ticks: {
                            padding: 10
                        }
                    }
                }
            }
        });
    });
    /*]]>*/
</script>

