グラフページを対象期間ごとに掘り下げる形に変更
This commit is contained in:
		@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
 | 
			
		||||
use App\Ejaculation;
 | 
			
		||||
use App\User;
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use Carbon\CarbonInterface;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Support\Facades\Auth;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
@@ -63,80 +64,56 @@ SQL
 | 
			
		||||
        return view('user.profile')->with(compact('user', 'ejaculations', 'tags'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function stats($name)
 | 
			
		||||
    public function statsAll($name)
 | 
			
		||||
    {
 | 
			
		||||
        $user = User::where('name', $name)->first();
 | 
			
		||||
        if (empty($user)) {
 | 
			
		||||
            abort(404);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $dateUntil = now()->addMonth()->startOfMonth();
 | 
			
		||||
        $availableMonths = $this->makeStatsAvailableMonths($user);
 | 
			
		||||
        $graphData = $this->makeGraphData($user);
 | 
			
		||||
 | 
			
		||||
        $groupByDay = Ejaculation::select(DB::raw(
 | 
			
		||||
            <<<'SQL'
 | 
			
		||||
to_char(ejaculated_date, 'YYYY/MM/DD') AS "date",
 | 
			
		||||
count(*) AS "count"
 | 
			
		||||
SQL
 | 
			
		||||
        ))
 | 
			
		||||
            ->where('user_id', $user->id)
 | 
			
		||||
            ->where('ejaculated_date', '<', $dateUntil)
 | 
			
		||||
            ->groupBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
 | 
			
		||||
            ->orderBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
 | 
			
		||||
            ->get();
 | 
			
		||||
        return view('user.stats.all')->with(compact('user', 'graphData', 'availableMonths'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        $groupByHour = Ejaculation::select(DB::raw(
 | 
			
		||||
            <<<'SQL'
 | 
			
		||||
to_char(ejaculated_date, 'HH24') AS "hour",
 | 
			
		||||
count(*) AS "count"
 | 
			
		||||
SQL
 | 
			
		||||
        ))
 | 
			
		||||
            ->where('user_id', $user->id)
 | 
			
		||||
            ->where('ejaculated_date', '<', $dateUntil)
 | 
			
		||||
            ->groupBy(DB::raw("to_char(ejaculated_date, 'HH24')"))
 | 
			
		||||
            ->orderBy(DB::raw('1'))
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        $dailySum = [];
 | 
			
		||||
        $monthlySum = [];
 | 
			
		||||
        $yearlySum = [];
 | 
			
		||||
        $dowSum = array_fill(0, 7, 0);
 | 
			
		||||
        $hourlySum = array_fill(0, 24, 0);
 | 
			
		||||
 | 
			
		||||
        // 年間グラフ用の配列初期化
 | 
			
		||||
        if ($groupByDay->first() !== null) {
 | 
			
		||||
            $year = Carbon::createFromFormat('Y/m/d', $groupByDay->first()->date)->year;
 | 
			
		||||
            $currentYear = date('Y');
 | 
			
		||||
            for (; $year <= $currentYear; $year++) {
 | 
			
		||||
                $yearlySum[$year] = 0;
 | 
			
		||||
            }
 | 
			
		||||
    public function statsYearly($name, $year)
 | 
			
		||||
    {
 | 
			
		||||
        $user = User::where('name', $name)->first();
 | 
			
		||||
        if (empty($user)) {
 | 
			
		||||
            abort(404);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($groupByDay as $data) {
 | 
			
		||||
            $date = Carbon::createFromFormat('Y/m/d', $data->date);
 | 
			
		||||
            $yearAndMonth = $date->format('Y/m');
 | 
			
		||||
        $availableMonths = $this->makeStatsAvailableMonths($user);
 | 
			
		||||
        $graphData = $this->makeGraphData(
 | 
			
		||||
            $user,
 | 
			
		||||
            Carbon::createFromDate($year, 1, 1, config('app.timezone'))->startOfDay(),
 | 
			
		||||
            Carbon::createFromDate($year, 1, 1, config('app.timezone'))->addYear()->startOfDay()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
            $dailySum[$date->timestamp] = $data->count;
 | 
			
		||||
            $yearlySum[$date->year] += $data->count;
 | 
			
		||||
            $dowSum[$date->dayOfWeek] += $data->count;
 | 
			
		||||
            $monthlySum[$yearAndMonth] = ($monthlySum[$yearAndMonth] ?? 0) + $data->count;
 | 
			
		||||
        return view('user.stats.yearly')
 | 
			
		||||
            ->with(compact('user', 'graphData', 'availableMonths'))
 | 
			
		||||
            ->with('currentYear', (int) $year);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function statsMonthly($name, $year, $month)
 | 
			
		||||
    {
 | 
			
		||||
        $user = User::where('name', $name)->first();
 | 
			
		||||
        if (empty($user)) {
 | 
			
		||||
            abort(404);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($groupByHour as $data) {
 | 
			
		||||
            $hour = (int)$data->hour;
 | 
			
		||||
            $hourlySum[$hour] += $data->count;
 | 
			
		||||
        }
 | 
			
		||||
        $availableMonths = $this->makeStatsAvailableMonths($user);
 | 
			
		||||
        $graphData = $this->makeGraphData(
 | 
			
		||||
            $user,
 | 
			
		||||
            Carbon::createFromDate($year, $month, 1, config('app.timezone'))->startOfDay(),
 | 
			
		||||
            Carbon::createFromDate($year, $month, 1, config('app.timezone'))->addMonth()->startOfDay()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $graphData = [
 | 
			
		||||
            'dailySum' => $dailySum,
 | 
			
		||||
            'dowSum' => $dowSum,
 | 
			
		||||
            'monthlySum' => $monthlySum,
 | 
			
		||||
            'yearlyKey' => array_keys($yearlySum),
 | 
			
		||||
            'yearlySum' => array_values($yearlySum),
 | 
			
		||||
            'hourlyKey' => array_keys($hourlySum),
 | 
			
		||||
            'hourlySum' => array_values($hourlySum),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        return view('user.stats')->with(compact('user', 'graphData'));
 | 
			
		||||
        return view('user.stats.monthly')
 | 
			
		||||
            ->with(compact('user', 'graphData', 'availableMonths'))
 | 
			
		||||
            ->with('currentYear', (int) $year)
 | 
			
		||||
            ->with('currentMonth', (int) $month);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function okazu($name)
 | 
			
		||||
@@ -191,4 +168,99 @@ SQL
 | 
			
		||||
 | 
			
		||||
        return view('user.likes')->with(compact('user', 'likes'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function makeStatsAvailableMonths(User $user): array
 | 
			
		||||
    {
 | 
			
		||||
        $availableMonths = [];
 | 
			
		||||
        $oldest = $user->ejaculations()->orderBy('ejaculated_date')->first();
 | 
			
		||||
        if (isset($oldest)) {
 | 
			
		||||
            $oldestMonth = $oldest->ejaculated_date->startOfMonth();
 | 
			
		||||
            $currentMonth = now()->startOfMonth();
 | 
			
		||||
            for ($month = $currentMonth; $oldestMonth <= $currentMonth; $month = $month->subMonth()) {
 | 
			
		||||
                if (!isset($availableMonths[$month->year])) {
 | 
			
		||||
                    $availableMonths[$month->year] = [];
 | 
			
		||||
                }
 | 
			
		||||
                $availableMonths[$month->year][] = $month->month;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $availableMonths;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function makeGraphData(User $user, CarbonInterface $dateSince = null, CarbonInterface $dateUntil = null): array
 | 
			
		||||
    {
 | 
			
		||||
        if ($dateUntil === null) {
 | 
			
		||||
            $dateUntil = now()->addMonth()->startOfMonth();
 | 
			
		||||
        }
 | 
			
		||||
        $dateCondition = [
 | 
			
		||||
            ['ejaculated_date', '<', $dateUntil],
 | 
			
		||||
        ];
 | 
			
		||||
        if ($dateSince !== null) {
 | 
			
		||||
            $dateCondition[] = ['ejaculated_date', '>=', $dateSince];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $groupByDay = Ejaculation::select(DB::raw(
 | 
			
		||||
            <<<'SQL'
 | 
			
		||||
to_char(ejaculated_date, 'YYYY/MM/DD') AS "date",
 | 
			
		||||
count(*) AS "count"
 | 
			
		||||
SQL
 | 
			
		||||
        ))
 | 
			
		||||
            ->where('user_id', $user->id)
 | 
			
		||||
            ->where($dateCondition)
 | 
			
		||||
            ->groupBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
 | 
			
		||||
            ->orderBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        $groupByHour = Ejaculation::select(DB::raw(
 | 
			
		||||
            <<<'SQL'
 | 
			
		||||
to_char(ejaculated_date, 'HH24') AS "hour",
 | 
			
		||||
count(*) AS "count"
 | 
			
		||||
SQL
 | 
			
		||||
        ))
 | 
			
		||||
            ->where('user_id', $user->id)
 | 
			
		||||
            ->where($dateCondition)
 | 
			
		||||
            ->groupBy(DB::raw("to_char(ejaculated_date, 'HH24')"))
 | 
			
		||||
            ->orderBy(DB::raw('1'))
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        $dailySum = [];
 | 
			
		||||
        $monthlySum = [];
 | 
			
		||||
        $yearlySum = [];
 | 
			
		||||
        $dowSum = array_fill(0, 7, 0);
 | 
			
		||||
        $hourlySum = array_fill(0, 24, 0);
 | 
			
		||||
 | 
			
		||||
        // 年間グラフ用の配列初期化
 | 
			
		||||
        if ($groupByDay->first() !== null) {
 | 
			
		||||
            $year = Carbon::createFromFormat('Y/m/d', $groupByDay->first()->date)->year;
 | 
			
		||||
            $currentYear = date('Y');
 | 
			
		||||
            for (; $year <= $currentYear; $year++) {
 | 
			
		||||
                $yearlySum[$year] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($groupByDay as $data) {
 | 
			
		||||
            $date = Carbon::createFromFormat('Y/m/d', $data->date);
 | 
			
		||||
            $yearAndMonth = $date->format('Y/m');
 | 
			
		||||
 | 
			
		||||
            $dailySum[$date->timestamp] = $data->count;
 | 
			
		||||
            $yearlySum[$date->year] += $data->count;
 | 
			
		||||
            $dowSum[$date->dayOfWeek] += $data->count;
 | 
			
		||||
            $monthlySum[$yearAndMonth] = ($monthlySum[$yearAndMonth] ?? 0) + $data->count;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($groupByHour as $data) {
 | 
			
		||||
            $hour = (int)$data->hour;
 | 
			
		||||
            $hourlySum[$hour] += $data->count;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'dailySum' => $dailySum,
 | 
			
		||||
            'dowSum' => $dowSum,
 | 
			
		||||
            'monthlySum' => $monthlySum,
 | 
			
		||||
            'yearlyKey' => array_keys($yearlySum),
 | 
			
		||||
            'yearlySum' => array_values($yearlySum),
 | 
			
		||||
            'hourlyKey' => array_keys($hourlySum),
 | 
			
		||||
            'hourlySum' => array_values($hourlySum),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								resources/assets/js/user/stats.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										78
									
								
								resources/assets/js/user/stats.js
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
import CalHeatMap from 'cal-heatmap';
 | 
			
		||||
import Chart from 'chart.js';
 | 
			
		||||
import {addMonths, format, startOfMonth, subMonths} from 'date-fns';
 | 
			
		||||
import {addMonths, format} from 'date-fns';
 | 
			
		||||
 | 
			
		||||
const graphData = JSON.parse(document.getElementById('graph-data').textContent);
 | 
			
		||||
 | 
			
		||||
@@ -90,53 +90,35 @@ function createMonthlyGraphData(from) {
 | 
			
		||||
    return {keys, values};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new CalHeatMap().init({
 | 
			
		||||
    itemSelector: '#cal-heatmap',
 | 
			
		||||
    domain: 'month',
 | 
			
		||||
    subDomain: 'day',
 | 
			
		||||
    domainLabelFormat: '%Y/%m',
 | 
			
		||||
    weekStartOnMonday: false,
 | 
			
		||||
    start: new Date().setMonth(new Date().getMonth() - 9),
 | 
			
		||||
    range: 10,
 | 
			
		||||
    data: graphData.dailySum,
 | 
			
		||||
    legend: [1, 2, 3, 4]
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 直近1年の月間グラフのデータを準備
 | 
			
		||||
const monthlyTermFrom = subMonths(startOfMonth(new Date()), 11);
 | 
			
		||||
const {keys: monthlyKey, values: monthlySum} = createMonthlyGraphData(monthlyTermFrom);
 | 
			
		||||
 | 
			
		||||
const monthlyGraph = createLineGraph('monthly-graph', monthlyKey, monthlySum);
 | 
			
		||||
createLineGraph('yearly-graph', graphData.yearlyKey, graphData.yearlySum);
 | 
			
		||||
createBarGraph('hourly-graph', graphData.hourlyKey, graphData.hourlySum);
 | 
			
		||||
createBarGraph('dow-graph', ['日', '月', '火', '水', '木', '金', '土'], graphData.dowSum);
 | 
			
		||||
 | 
			
		||||
// 月間グラフの期間セレクターを準備
 | 
			
		||||
const monthlyTermSelector = document.getElementById('monthly-term');
 | 
			
		||||
const earliestYear = [...new Set(Object.keys(graphData.monthlySum).map(v => v.substr(0, 4)))].shift();
 | 
			
		||||
for (let year = earliestYear; year <= new Date().getFullYear(); year++) {
 | 
			
		||||
    const opt = document.createElement('option');
 | 
			
		||||
    opt.setAttribute('value', year);
 | 
			
		||||
    opt.textContent = `${year}年`;
 | 
			
		||||
    monthlyTermSelector.insertBefore(opt, monthlyTermSelector.firstChild);
 | 
			
		||||
}
 | 
			
		||||
if (monthlyTermSelector.children.length) {
 | 
			
		||||
    monthlyTermSelector.selectedIndex = 0;
 | 
			
		||||
function getCurrentYear() {
 | 
			
		||||
    const year = location.pathname.split('/').pop();
 | 
			
		||||
    return /^(20[0-9]{2})$/.test(year) ? year : null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
monthlyTermSelector.addEventListener('change', function (e) {
 | 
			
		||||
    let monthlyTermFrom;
 | 
			
		||||
    if (e.target.selectedIndex === 0) {
 | 
			
		||||
        // 今年のデータを表示する時は、直近12ヶ月を表示
 | 
			
		||||
        monthlyTermFrom = subMonths(startOfMonth(new Date()), 11);
 | 
			
		||||
    } else {
 | 
			
		||||
        // 過去のデータを表示する時は、選択年の1〜12月を表示
 | 
			
		||||
        monthlyTermFrom = new Date(e.target.value, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
if (document.getElementById('cal-heatmap')) {
 | 
			
		||||
    new CalHeatMap().init({
 | 
			
		||||
        itemSelector: '#cal-heatmap',
 | 
			
		||||
        domain: 'month',
 | 
			
		||||
        subDomain: 'day',
 | 
			
		||||
        domainLabelFormat: '%Y/%m',
 | 
			
		||||
        weekStartOnMonday: false,
 | 
			
		||||
        start: new Date(getCurrentYear(), 0, 1, 0, 0, 0, 0),
 | 
			
		||||
        range: 12,
 | 
			
		||||
        data: graphData.dailySum,
 | 
			
		||||
        legend: [1, 2, 3, 4]
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    const {keys, values} = createMonthlyGraphData(monthlyTermFrom);
 | 
			
		||||
 | 
			
		||||
    monthlyGraph.data.labels = keys;
 | 
			
		||||
    monthlyGraph.data.datasets[0].data = values;
 | 
			
		||||
    monthlyGraph.update();
 | 
			
		||||
});
 | 
			
		||||
if (document.getElementById('monthly-graph')) {
 | 
			
		||||
    const {keys: monthlyKey, values: monthlySum} = createMonthlyGraphData(new Date(getCurrentYear(), 0, 1, 0, 0, 0, 0));
 | 
			
		||||
    createLineGraph('monthly-graph', monthlyKey, monthlySum);
 | 
			
		||||
}
 | 
			
		||||
if (document.getElementById('yearly-graph')) {
 | 
			
		||||
    createLineGraph('yearly-graph', graphData.yearlyKey, graphData.yearlySum);
 | 
			
		||||
}
 | 
			
		||||
if (document.getElementById('hourly-graph')) {
 | 
			
		||||
    createBarGraph('hourly-graph', graphData.hourlyKey, graphData.hourlySum);
 | 
			
		||||
}
 | 
			
		||||
if (document.getElementById('dow-graph')) {
 | 
			
		||||
    createBarGraph('dow-graph', ['日', '月', '火', '水', '木', '金', '土'], graphData.dowSum);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								resources/views/components/profile-mini.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								resources/views/components/profile-mini.blade.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<div class="d-flex flex-row align-items-end">
 | 
			
		||||
    <img src="{{ $user->getProfileImageUrl(48) }}" srcset="{{ Formatter::profileImageSrcSet($user, 48) }}" class="rounded mr-2">
 | 
			
		||||
    <div class="d-flex flex-column overflow-hidden">
 | 
			
		||||
        <h5 class="card-title text-truncate">
 | 
			
		||||
            <a class="text-dark" href="{{ route('user.profile', ['name' => $user->name]) }}">{{ $user->display_name }}</a>
 | 
			
		||||
        </h5>
 | 
			
		||||
        <h6 class="card-subtitle">
 | 
			
		||||
            <a class="text-muted" href="{{ route('user.profile', ['name' => $user->name]) }}">@{{ $user->name }}</a>
 | 
			
		||||
            @if ($user->is_protected)
 | 
			
		||||
                <span class="oi oi-lock-locked text-muted"></span>
 | 
			
		||||
            @endif
 | 
			
		||||
        </h6>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -4,8 +4,17 @@
 | 
			
		||||
    <div class="container">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-lg-4">
 | 
			
		||||
                @component('components.profile', ['user' => $user])
 | 
			
		||||
                @endcomponent
 | 
			
		||||
                @if (Route::currentRouteName() === 'user.profile')
 | 
			
		||||
                    @component('components.profile', ['user' => $user])
 | 
			
		||||
                    @endcomponent
 | 
			
		||||
                @else
 | 
			
		||||
                    <div class="card mb-4">
 | 
			
		||||
                        <div class="card-body">
 | 
			
		||||
                            @component('components.profile-mini', ['user' => $user])
 | 
			
		||||
                            @endcomponent
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                @endif
 | 
			
		||||
                @section('sidebar')
 | 
			
		||||
                @show
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -15,7 +24,7 @@
 | 
			
		||||
                        <a class="nav-link {{ Route::currentRouteName() === 'user.profile' ? 'active' : '' }}" href="{{ route('user.profile', ['name' => $user->name]) }}">タイムライン</a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    <li class="nav-item">
 | 
			
		||||
                        <a class="nav-link {{ Route::currentRouteName() === 'user.stats' ? 'active' : '' }}" href="{{ route('user.stats', ['name' => $user->name]) }}">グラフ</a>
 | 
			
		||||
                        <a class="nav-link {{ stripos(Route::currentRouteName(), 'user.stats') === 0 ? 'active' : '' }}" href="{{ route('user.stats', ['name' => $user->name]) }}">グラフ</a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    <li class="nav-item">
 | 
			
		||||
                        <a class="nav-link {{ Route::currentRouteName() === 'user.okazu' ? 'active' : '' }}" href="{{ route('user.okazu', ['name' => $user->name]) }}">オカズ</a>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								resources/views/user/stats/all.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								resources/views/user/stats/all.blade.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
@extends('user.stats.base')
 | 
			
		||||
 | 
			
		||||
@section('title', $user->display_name . ' さんのグラフ')
 | 
			
		||||
 | 
			
		||||
@section('stats-content')
 | 
			
		||||
    <h5 class="my-4">年間チェックイン回数</h5>
 | 
			
		||||
    <canvas id="yearly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">時間別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="hourly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">曜日別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="dow-graph" class="w-100"></canvas>
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@push('script')
 | 
			
		||||
<script id="graph-data" type="application/json">@json($graphData)</script>
 | 
			
		||||
<script src="{{ mix('js/vendor/chart.js') }}"></script>
 | 
			
		||||
<script src="{{ mix('js/user/stats.js') }}"></script>
 | 
			
		||||
@endpush
 | 
			
		||||
							
								
								
									
										70
									
								
								resources/views/user/stats/base.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								resources/views/user/stats/base.blade.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
@extends('user.base')
 | 
			
		||||
 | 
			
		||||
@section('sidebar')
 | 
			
		||||
    @if (!$user->is_protected || $user->isMe())
 | 
			
		||||
        <div class="nav d-none d-lg-flex flex-column nav-pills" aria-orientation="vertical">
 | 
			
		||||
            <a class="nav-link {{ Route::currentRouteName() === 'user.stats.all' ? 'active' : '' }}"
 | 
			
		||||
               href="{{ route('user.stats.all', ['name' => $user->name]) }}">全期間</a>
 | 
			
		||||
            @foreach ($availableMonths as $year => $months)
 | 
			
		||||
                <div class="border-top mt-1">
 | 
			
		||||
                    <a class="nav-link mt-1 {{ Route::currentRouteName() === 'user.stats.yearly' && $currentYear === $year ? 'active' : '' }}"
 | 
			
		||||
                       href="{{ route('user.stats.yearly', ['name' => $user->name, 'year' => $year]) }}">{{ $year }}年</a>
 | 
			
		||||
                    @foreach ($months as $month)
 | 
			
		||||
                        <a class="nav-link ml-3 {{ Route::currentRouteName() === 'user.stats.monthly' && $currentYear === $year && $currentMonth === $month ? 'active' : '' }}"
 | 
			
		||||
                           href="{{ route('user.stats.monthly', ['name' => $user->name, 'year' => $year, 'month' => $month]) }}">{{ $month }}月</a>
 | 
			
		||||
                    @endforeach
 | 
			
		||||
                </div>
 | 
			
		||||
            @endforeach
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@section('tab-content')
 | 
			
		||||
    @if ($user->is_protected && !$user->isMe())
 | 
			
		||||
        <p class="mt-4">
 | 
			
		||||
            <span class="oi oi-lock-locked"></span> このユーザはチェックイン履歴を公開していません。
 | 
			
		||||
        </p>
 | 
			
		||||
    @else
 | 
			
		||||
        <div class="row my-2 d-lg-none">
 | 
			
		||||
            <div class="col-12 text-secondary font-weight-bold small">グラフの対象期間</div>
 | 
			
		||||
            <div class="col-6 text-secondary small">年</div>
 | 
			
		||||
            <div class="col-6 text-secondary small">月</div>
 | 
			
		||||
            <div class="col-12">
 | 
			
		||||
                <ul class="nav nav-pills nav-fill">
 | 
			
		||||
                    <li class="nav-item dropdown">
 | 
			
		||||
                        <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
 | 
			
		||||
                            {{ Route::currentRouteName() === 'user.stats.all' ? '全期間' : "{$currentYear}年" }}
 | 
			
		||||
                        </a>
 | 
			
		||||
                        <div class="dropdown-menu">
 | 
			
		||||
                            <a href="{{ route('user.stats.all', ['name' => $user->name]) }}" class="dropdown-item">全期間</a>
 | 
			
		||||
                            @foreach ($availableMonths as $year => $months)
 | 
			
		||||
                                <a href="{{ route('user.stats.yearly', ['name' => $user->name, 'year' => $year]) }}" class="dropdown-item">{{ $year }}年</a>
 | 
			
		||||
                            @endforeach
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    @if (Route::currentRouteName() === 'user.stats.all')
 | 
			
		||||
                        <li class="nav-item dropdown">
 | 
			
		||||
                            <a class="nav-link dropdown-toggle disabled"
 | 
			
		||||
                               href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">全期間</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    @else
 | 
			
		||||
                        <li class="nav-item dropdown">
 | 
			
		||||
                            <a class="nav-link dropdown-toggle"
 | 
			
		||||
                               href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
 | 
			
		||||
                                {{ Route::currentRouteName() === 'user.stats.yearly' ? '全期間' : "{$currentMonth}月" }}
 | 
			
		||||
                            </a>
 | 
			
		||||
                            <div class="dropdown-menu">
 | 
			
		||||
                                <a href="{{ route('user.stats.yearly', ['name' => $user->name, 'year' => $year]) }}" class="dropdown-item">全期間</a>
 | 
			
		||||
                                @foreach ($availableMonths[$currentYear] as $month)
 | 
			
		||||
                                    <a href="{{ route('user.stats.monthly', ['name' => $user->name, 'year' => $year, 'month' => $month]) }}" class="dropdown-item">{{ $month }}月</a>
 | 
			
		||||
                                @endforeach
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    @endif
 | 
			
		||||
                </ul>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row d-lg-none no-gutters border-bottom"></div>
 | 
			
		||||
        @yield('stats-content')
 | 
			
		||||
    @endif
 | 
			
		||||
@endsection
 | 
			
		||||
							
								
								
									
										17
									
								
								resources/views/user/stats/monthly.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								resources/views/user/stats/monthly.blade.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
@extends('user.stats.base')
 | 
			
		||||
 | 
			
		||||
@section('title', $user->display_name . ' さんのグラフ')
 | 
			
		||||
 | 
			
		||||
@section('stats-content')
 | 
			
		||||
    <h5 class="my-4">時間別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="hourly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">曜日別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="dow-graph" class="w-100"></canvas>
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@push('script')
 | 
			
		||||
<script id="graph-data" type="application/json">@json($graphData)</script>
 | 
			
		||||
<script src="{{ mix('js/vendor/chart.js') }}"></script>
 | 
			
		||||
<script src="{{ mix('js/user/stats.js') }}"></script>
 | 
			
		||||
@endpush
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
@extends('user.base')
 | 
			
		||||
@extends('user.stats.base')
 | 
			
		||||
 | 
			
		||||
@section('title', $user->display_name . ' さんのグラフ')
 | 
			
		||||
 | 
			
		||||
@@ -6,34 +6,18 @@
 | 
			
		||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
 | 
			
		||||
@endpush
 | 
			
		||||
 | 
			
		||||
@section('tab-content')
 | 
			
		||||
@if ($user->is_protected && !$user->isMe())
 | 
			
		||||
    <p class="mt-4">
 | 
			
		||||
        <span class="oi oi-lock-locked"></span> このユーザはチェックイン履歴を公開していません。
 | 
			
		||||
    </p>
 | 
			
		||||
@else
 | 
			
		||||
@section('stats-content')
 | 
			
		||||
    <h5 class="my-4">Shikontribution graph</h5>
 | 
			
		||||
    <div id="cal-heatmap" class="tis-contribution-graph"></div>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <div class="row my-4">
 | 
			
		||||
        <div class="col-12 col-lg-6 d-flex align-items-center">
 | 
			
		||||
            <h5 class="my-0">月間チェックイン回数</h5>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-12 col-lg-6 mt-2 mt-lg-0">
 | 
			
		||||
            <select id="monthly-term" class="form-control"></select>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <h5 class="my-4">月間チェックイン回数</h5>
 | 
			
		||||
    <canvas id="monthly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">年間チェックイン回数</h5>
 | 
			
		||||
    <canvas id="yearly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">時間別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="hourly-graph" class="w-100"></canvas>
 | 
			
		||||
    <hr class="my-4">
 | 
			
		||||
    <h5 class="my-4">曜日別チェックイン回数</h5>
 | 
			
		||||
    <canvas id="dow-graph" class="w-100"></canvas>
 | 
			
		||||
@endif
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@push('script')
 | 
			
		||||
@@ -17,7 +17,10 @@ Route::get('/', 'HomeController@index')->name('home');
 | 
			
		||||
 | 
			
		||||
Route::get('/user', 'UserController@redirectMypage')->middleware('auth');
 | 
			
		||||
Route::get('/user/{name?}', 'UserController@profile')->name('user.profile');
 | 
			
		||||
Route::get('/user/{name}/stats', 'UserController@stats')->name('user.stats');
 | 
			
		||||
Route::redirect('/user/{name}/stats', '/user/{name}/stats/all')->name('user.stats');
 | 
			
		||||
Route::get('/user/{name}/stats/all', 'UserController@statsAll')->name('user.stats.all');
 | 
			
		||||
Route::get('/user/{name}/stats/{year}', 'UserController@statsYearly')->name('user.stats.yearly');
 | 
			
		||||
Route::get('/user/{name}/stats/{year}/{month}', 'UserController@statsMonthly')->name('user.stats.monthly');
 | 
			
		||||
Route::get('/user/{name}/okazu', 'UserController@okazu')->name('user.okazu');
 | 
			
		||||
Route::get('/user/{name}/likes', 'UserController@likes')->name('user.likes');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user