krgm.so-manager-dev.com/resources/views/admin/periodical/list.blade.php
你的名字 75bbec6f5a
All checks were successful
Deploy main / deploy (push) Successful in 22s
【定期利用・契約状況】データ不表示を修正
2025-09-30 16:01:53 +09:00

247 lines
8.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.app')
@section('title', '定期利用・契約状況')
@section('content')
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6"><h1 class="m-0 text-dark">定期利用・契約状況</h1></div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right text-sm">
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
<li class="breadcrumb-item active">定期利用・契約状況</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
<div class="card card-body mb-3">
<form class="form-inline" onsubmit="return false;">
<label class="mr-2 mb-0">駐輪場:</label>
<select name="park_id" id="park_id" class="form-control mr-3">
<option value="">全て</option>
@foreach ($parks as $p)
<option value="{{ $p->park_id }}" {{ (string)$selectedParkId === (string)$p->park_id ? 'selected' : '' }}>
{{ $p->park_name }}
</option>
@endforeach
</select>
</form>
<small class="text-muted d-block mt-2">
以下に記載以外の期間情報を参照したい場合は、マスタ管理定期期間マスタのCSV出力を利用してください。
</small>
</div>
<div id="stats-sections" style="display:none;">
<div class="card mb-3">
<div class="card-header p-2">契約状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">契約状況</th>
<th rowspan="2" class="align-middle">一般</th>
<th rowspan="2" class="align-middle">学生</th>
<th rowspan="2" class="align-middle">利用計</th>
<th rowspan="2" class="align-middle">空き</th>
<th rowspan="2" class="align-middle">合計</th>
<th colspan="2">直近契約</th>
</tr>
<tr>
<th>予約日</th>
<th>契約日</th>
</tr>
</thead>
<tbody id="tbl-contract-summary"></tbody>
</table>
</div>
</div>
<div class="card mb-3">
<div class="card-header p-2">空き待ち状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">空き待ち状況</th>
<th colspan="2">一般</th>
<th colspan="2">学生</th>
<th rowspan="2" class="align-middle">合計</th>
</tr>
<tr>
<th>件数</th>
<th>先頭日</th>
<th>件数</th>
<th>先頭日</th>
</tr>
</thead>
<tbody id="tbl-waiting-summary"></tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-header p-2">更新状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle" style="min-width:70px"></th>
<th rowspan="2" class="align-middle" style="min-width:60px">更新状況</th>
<th colspan="3">自転車</th>
<th colspan="3">原付</th>
<th colspan="3">その他</th>
</tr>
<tr>
<th>一般</th><th>学生</th><th></th>
<th>一般</th><th>学生</th><th></th>
<th>一般</th><th>学生</th><th></th>
</tr>
</thead>
<tbody id="tbl-renewal-summary"></tbody>
</table>
</div>
</div>
</div>
</div>
</section>
@endsection
@push('scripts')
<script>
(function() {
function $(sel){return document.querySelector(sel)}
function $tb(id){return document.getElementById(id)}
function escapeHtml(s){const d=document.createElement('div');d.textContent=(s??'');return d.innerHTML}
function numberOrDash(v){const n=Number(v);return Number.isFinite(n)?n.toString():'-'}
function formatDate(d){return d && d !== 'null' ? d : '-'}
function formatMonth(m){
if(!m || m === 'null') return '-';
// YYYY-MM 形式を MM月 形式に変換
const parts = m.split('-');
if(parts.length === 2) {
const monthNum = parseInt(parts[1], 10);
return `${monthNum}月`;
}
return m.replace('-', '/');
}
const park = $('#park_id');
const stats = $('#stats-sections');
park.addEventListener('change', loadStats);
loadStats();
function loadStats(){
const id = park.value;
if(!id){ stats.style.display='none'; clearTables(); return; }
fetch("{{ route('periodical.listData') }}?park_id="+encodeURIComponent(id), {headers:{'Accept':'application/json'}})
.then(r => r.ok ? r.json() : Promise.reject(r))
.then(res => {
stats.style.display='block';
// デバッグ情報があれば表示
if(res.debug_info) {
console.log('Debug info:', res.debug_info);
}
renderContractSummary(res.contract_summary||[]);
renderWaitingSummary(res.waiting_summary||[]);
renderRenewalSummary(res.renewal_summary||[]);
})
.catch(err => {
stats.style.display='none';
clearTables();
});
}
function clearTables(){
['tbl-contract-summary','tbl-waiting-summary','tbl-renewal-summary'].forEach(id => $tb(id).innerHTML='');
}
// 契約状況
function renderContractSummary(list){
const tb = $tb('tbl-contract-summary'); tb.innerHTML='';
if(!Array.isArray(list)||!list.length){
tb.innerHTML = noDataRow(8);
return;
}
list.forEach(row=>{
const rowClass = row.type === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
<td>${escapeHtml(row.type)}</td>
<td>${formatPair(row.general_count, row.general_extra)}</td>
<td>${formatPair(row.student_count, row.student_extra)}</td>
<td>${numberOrDash(row.use_total)}</td>
<td>${numberOrDash(row.vacancy)}</td>
<td>${numberOrDash(row.total)}</td>
<td>${formatDate(row?.last?.reserve_date)}</td>
<td>${formatDate(row?.last?.contract_date)}</td>
</tr>`);
});
}
function formatPair(c,e){
const n = Number.isFinite(Number(c))?Number(c):0;
const m = Number.isFinite(Number(e))?Number(e):0;
return `${n}${m}`;
}
// 空き待ち
function renderWaitingSummary(list){
const tb = $tb('tbl-waiting-summary'); tb.innerHTML='';
if(!Array.isArray(list)||!list.length){ tb.innerHTML = noDataRow(6); return; }
list.forEach(r=>{
const rowClass = r.type === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
<td>${escapeHtml(r.type)}</td>
<td>${numberOrDash(r.general_count)}</td>
<td>${formatDate(r.general_first)}</td>
<td>${numberOrDash(r.student_count)}</td>
<td>${formatDate(r.student_first)}</td>
<td>${numberOrDash(r.total)}</td>
</tr>`);
});
}
// 更新状況(月ブロック形式)
function renderRenewalSummary(blocks){
const tb = $tb('tbl-renewal-summary'); tb.innerHTML='';
if(!Array.isArray(blocks)||!blocks.length){ tb.innerHTML = noDataRow(11); return; }
// 新形式: [{month:'YYYY-MM', rows:[{label,...}]}]
blocks.forEach(b=>{
const rows = Array.isArray(b.rows)?b.rows:[];
if(rows.length === 0) return;
rows.forEach((r,idx)=>{
const monthCell = idx===0 ? `<td rowspan="${rows.length}" class="align-middle">${formatMonth(b.month)}</td>` : '';
const rowClass = r.label === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
${monthCell}
<td>${escapeHtml(r.label)}</td>
<td>${numberOrDash(r.bicycle_general)}</td>
<td>${numberOrDash(r.bicycle_student)}</td>
<td>${numberOrDash(r.bicycle_total)}</td>
<td>${numberOrDash(r.moped_general)}</td>
<td>${numberOrDash(r.moped_student)}</td>
<td>${numberOrDash(r.moped_total)}</td>
<td>${numberOrDash(r.other_general)}</td>
<td>${numberOrDash(r.other_student)}</td>
<td>${numberOrDash(r.other_total)}</td>
</tr>`);
});
});
}
function noDataRow(colspan){ return `<tr><td colspan="${colspan}">データがありません</td></tr>`; }
})();
</script>
@endpush