[契約者一覧][未更新者一覧]絞り込み条件修正
All checks were successful
Deploy main / deploy (push) Successful in 23s

This commit is contained in:
你的名字 2025-09-24 10:27:25 +09:00
parent 7fc3c33bed
commit c7db94973b
4 changed files with 554 additions and 280 deletions

View File

@ -14,6 +14,7 @@ class ContractorController extends Controller
public function list(Request $request) public function list(Request $request)
{ {
$q = DB::table('regular_contract as rc') $q = DB::table('regular_contract as rc')
->leftJoin('user as u','rc.user_id','=','u.user_id')
->select([ ->select([
'rc.contract_id', 'rc.contract_id',
'rc.contract_qr_id', 'rc.contract_qr_id',
@ -52,37 +53,110 @@ class ContractorController extends Controller
'u.user_workplace', 'u.user_workplace',
'u.user_school', 'u.user_school',
'u.user_remarks', 'u.user_remarks',
// 他に必要なカラムもここに追加 'u.user_tag_serial_64',
'u.user_reduction',
DB::raw('rc.user_securitynum as crime_prevention'),
DB::raw('rc.contract_seal_issue as seal_issue_count'),
DB::raw("CASE rc.enable_months
WHEN 1 THEN '月極(1ヶ月)'
WHEN 3 THEN '3ヶ月'
WHEN 6 THEN '6ヶ月'
WHEN 12 THEN '年'
ELSE CONCAT(rc.enable_months, 'ヶ月') END as ticket_type"),
DB::raw('ps.psection_subject as vehicle_type'),
// 利用者分類名usertype テーブル)
DB::raw('ut.usertype_subject1 as user_category1'),
DB::raw('ut.usertype_subject2 as user_category2'),
DB::raw('ut.usertype_subject3 as user_category3'),
]) ])
->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id') ->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id')
->leftJoin('user as u', 'rc.user_id', '=', 'u.user_id'); ->leftJoin('psection as ps', 'rc.psection_id', '=', 'ps.psection_id')
->leftJoin('usertype as ut', 'u.user_categoryid', '=', 'ut.user_categoryid');
// 検索条件例 // ===== 絞り込み条件 =====
if ($request->filled('contract_id')) { // 駐輪場
$q->where('rc.contract_id', $request->input('contract_id')); if ($request->filled('park_id')) {
$q->where('rc.park_id', $request->park_id);
} }
if ($request->filled('name')) { // 利用者ID完全一致
$q->where('u.user_name', 'like', '%' . $request->input('name') . '%'); if ($request->filled('user_id')) {
$q->where('rc.user_id', $request->user_id);
} }
// タグ・QR完全一致、空白なら絞り込まない // 分類名1完全一致: ut.usertype_subject1 = 入力値
if ($request->filled('tag_qr_flag') && $request->input('tag_qr_flag') !== '') { if ($request->filled('user_category1')) {
$q->where('rc.tag_qr_flag', $request->input('tag_qr_flag')); $q->where('ut.usertype_subject1', $request->user_category1);
}
// タグシリアル64進部分一致
if ($request->filled('user_tag_serial_64')) {
$val = $request->user_tag_serial_64;
$q->where('u.user_tag_serial_64','like','%'.$val.'%');
}
// 有効期限(契約有効期間 終了日:指定日以前を抽出)
if ($request->filled('contract_periode')) {
$raw = trim($request->contract_periode);
$norm = str_replace('/', '-', $raw); // スラッシュ入力許容
try {
$target = \Carbon\Carbon::parse($norm)->format('Y-m-d');
// 指定日 “以前” を含む (以前のみなら '<' に変更)
$q->whereDate('rc.contract_periode', '>=', $target);
} catch (\Exception $e) {
// 不正日付は無視
}
}
// フリガナ(部分一致)
if ($request->filled('user_phonetic')) {
$q->where('u.user_phonetic', 'like', '%' . $request->user_phonetic . '%');
}
// 携帯電話(部分一致)
if ($request->filled('user_mobile')) {
$q->where('u.user_mobile', 'like', '%' . $request->user_mobile . '%');
}
// メール(部分一致)
if ($request->filled('user_primemail')) {
$q->where('u.user_primemail', 'like', '%' . $request->user_primemail . '%');
}
// 勤務先(部分一致)
if ($request->filled('user_workplace')) {
$q->where('u.user_workplace', 'like', '%' . $request->user_workplace . '%');
}
// 学校(部分一致)
if ($request->filled('user_school')) {
$q->where('u.user_school', 'like', '%' . $request->user_school . '%');
}
// タグ・QR完全一致
if ($request->filled('tag_qr_flag') && $request->tag_qr_flag !== '') {
$q->where('rc.tag_qr_flag', $request->tag_qr_flag);
} }
// ソート処理 // ソート処理
$sort = $request->input('sort', 'rc.contract_id'); // パラメータが来た時だけ適用。未指定なら主キー昇順
$sortType = $request->input('sort_type', 'desc'); $sort = $request->input('sort'); // null 許容
// カラム名のバリデーション(必要に応じて拡張) $sortType = $request->input('sort_type','asc');
$allowSorts = ['rc.contract_id'];
if (!in_array($sort, $allowSorts)) { $allowSorts = [
$sort = 'rc.contract_id'; 'rc.contract_id',
'rc.user_id',
'u.user_name',
'rc.tag_qr_flag',
'p.park_name',
];
if ($sort && in_array($sort, $allowSorts)) {
$sortType = $sortType === 'desc' ? 'desc' : 'asc';
$q->orderBy($sort, $sortType);
} else {
// 初期表示は契約ID昇順 (物理順に近い)
$sort = null;
$sortType = null;
$q->orderBy('rc.contract_id','asc');
} }
$sortType = ($sortType === 'asc') ? 'asc' : 'desc';
$rows = $q->orderBy($sort, $sortType)->paginate(20)->withQueryString(); $rows = $q->paginate(20)->appends($request->query());
return view('admin.contractor.list', compact('rows', 'sort', 'sortType')); // 駐輪場セレクト用
$parks = DB::table('park')->select('park_id', 'park_name')->orderBy('park_name')->get();
return view('admin.contractor.list', compact('rows', 'sort', 'sortType', 'parks'));
} }
/** /**

View File

@ -9,11 +9,12 @@ use Illuminate\Support\Facades\DB;
class ContractorListController extends Controller class ContractorListController extends Controller
{ {
/** /**
* 一覧表示GET/POST * 未更新者一覧 (contract_renewal IS NULL)
*/ */
public function list(Request $request) public function list(Request $request)
{ {
$q = DB::table('regular_contract as rc') $q = DB::table('regular_contract as rc')
->leftJoin('user as u','rc.user_id','=','u.user_id')
->select([ ->select([
'rc.contract_id', 'rc.contract_id',
'rc.contract_qr_id', 'rc.contract_qr_id',
@ -33,7 +34,6 @@ class ContractorListController extends Controller
'rc.contract_manual', 'rc.contract_manual',
'rc.contract_notice', 'rc.contract_notice',
'p.park_name', 'p.park_name',
// userテーブルの正しいカラム名
'u.user_name', 'u.user_name',
'u.user_phonetic', 'u.user_phonetic',
'u.user_mobile', 'u.user_mobile',
@ -53,64 +53,110 @@ class ContractorListController extends Controller
'u.user_workplace', 'u.user_workplace',
'u.user_school', 'u.user_school',
'u.user_remarks', 'u.user_remarks',
// 他に必要なカラムもここに追加 'u.user_tag_serial_64',
'u.user_reduction',
DB::raw('rc.user_securitynum as crime_prevention'),
DB::raw('rc.contract_seal_issue as seal_issue_count'),
DB::raw("CASE rc.enable_months
WHEN 1 THEN '月極(1ヶ月)'
WHEN 3 THEN '3ヶ月'
WHEN 6 THEN '6ヶ月'
WHEN 12 THEN '年'
ELSE CONCAT(rc.enable_months, 'ヶ月') END as ticket_type"),
DB::raw('ps.psection_subject as vehicle_type'),
// 利用者分類名usertype テーブル)
DB::raw('ut.usertype_subject1 as user_category1'),
DB::raw('ut.usertype_subject2 as user_category2'),
DB::raw('ut.usertype_subject3 as user_category3'),
]) ])
->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id') ->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id')
->leftJoin('user as u', 'rc.user_id', '=', 'u.user_id'); ->leftJoin('psection as ps', 'rc.psection_id', '=', 'ps.psection_id')
->leftJoin('usertype as ut', 'u.user_categoryid', '=', 'ut.user_categoryid');
// 検索条件例 // ===== 絞り込み条件 =====
if ($request->filled('contract_id')) { // 駐輪場
$q->where('rc.contract_id', $request->input('contract_id')); if ($request->filled('park_id')) {
$q->where('rc.park_id', $request->park_id);
} }
if ($request->filled('name')) { // 利用者ID完全一致
$q->where('u.user_name', 'like', '%' . $request->input('name') . '%'); if ($request->filled('user_id')) {
$q->where('rc.user_id', $request->user_id);
}
// 分類名1完全一致
if ($request->filled('user_category1')) {
$q->where('ut.usertype_subject1', $request->user_category1);
}
// タグシリアル64進部分一致
if ($request->filled('user_tag_serial_64')) {
$val = $request->user_tag_serial_64;
$q->where('u.user_tag_serial_64','like','%'.$val.'%');
}
// 有効期限(契約有効期間 終了日:指定日以前を抽出)
if ($request->filled('contract_periode')) {
$raw = trim($request->contract_periode);
$norm = str_replace('/', '-', $raw); // スラッシュ入力許容
try {
$target = \Carbon\Carbon::parse($norm)->format('Y-m-d');
// 指定日 “以前” を含む (以前のみなら '<' に変更)
$q->whereDate('rc.contract_periode', '>=', $target);
} catch (\Exception $e) {
// 不正日付は無視
}
}
// フリガナ(部分一致)
if ($request->filled('user_phonetic')) {
$q->where('u.user_phonetic', 'like', '%' . $request->user_phonetic . '%');
}
// 携帯電話(部分一致)
if ($request->filled('user_mobile')) {
$q->where('u.user_mobile', 'like', '%' . $request->user_mobile . '%');
}
// メール(部分一致)
if ($request->filled('user_primemail')) {
$q->where('u.user_primemail', 'like', '%' . $request->user_primemail . '%');
}
// 勤務先(部分一致)
if ($request->filled('user_workplace')) {
$q->where('u.user_workplace', 'like', '%' . $request->user_workplace . '%');
}
// 学校(部分一致)
if ($request->filled('user_school')) {
$q->where('u.user_school', 'like', '%' . $request->user_school . '%');
}
// タグ・QR完全一致
if ($request->filled('tag_qr_flag') && $request->tag_qr_flag !== '') {
$q->where('rc.tag_qr_flag', $request->tag_qr_flag);
} }
// タグ・QR完全一致、空白なら絞り込まない // ---- ソート ----
if ($request->filled('tag_qr_flag') && $request->input('tag_qr_flag') !== '') { $sort = $request->input('sort',''); // 初期は未指定
$q->where('rc.tag_qr_flag', $request->input('tag_qr_flag')); $sortType = $request->input('sort_type','asc');
$allowSorts = [
'user_id' => 'rc.user_id',
'user_name' => 'u.user_name',
'contract_id' => 'rc.contract_id',
'tag_qr_flag' => 'rc.tag_qr_flag',
'park_name' => 'p.park_name',
];
if($sort !== '' && isset($allowSorts[$sort])){
$sortType = $sortType === 'desc' ? 'desc' : 'asc';
$q->orderBy($allowSorts[$sort], $sortType)
->orderBy('rc.contract_id','asc'); // セカンダリ安定
} else {
// 初期表示: DB登録順の近似PK昇順
$sort = ''; // Blade 側で未ソート状態
$q->orderBy('rc.contract_id','asc');
} }
// ソート処理 // 駐輪場選択
$sort = $request->input('sort', 'rc.contract_id'); $parks = DB::table('park')
$sortType = $request->input('sort_type', 'desc'); ->select('park_id','park_name')
// カラム名のバリデーション(必要に応じて拡張) ->orderBy('park_name')
$allowSorts = ['rc.contract_id']; ->orderBy('park_id')
if (!in_array($sort, $allowSorts)) { ->get();
$sort = 'rc.contract_id';
}
$sortType = ($sortType === 'asc') ? 'asc' : 'desc';
$rows = $q->orderBy($sort, $sortType)->paginate(20)->withQueryString(); $rows = $q->paginate(20)->appends($request->query());
return view('admin.contractor_list.list', compact('rows', 'sort', 'sortType')); return view('admin.contractor_list.list', compact('rows','sort','sortType','parks'));
}
/**
* 詳細表示
*/
public function info($id)
{
$contract = DB::table('regular_contract as rc')
->select([
'rc.*',
'p.park_name',
'u.user_name',
'u.user_phonetic',
'u.user_mobile',
'u.user_homephone',
'u.user_primemail',
'u.user_gender',
'u.user_birthdate',
'u.user_regident_city',
])
->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id')
->leftJoin('user as u', 'rc.user_id', '=', 'u.user_id')
->where('rc.contract_id', $id)
->first();
if (!$contract) { abort(404); }
return view('admin.contractor.info', compact('contract'));
} }
} }

View File

@ -23,7 +23,9 @@
<div class="container-fluid"> <div class="container-fluid">
{{-- 絞り込みフィルター --}} {{-- 絞り込みフィルター --}}
<form method="GET" action="{{ route('contractor') }}" class="mb-3" id="filter-form"> <form method="GET" action="{{ route('contractor') }}" class="mb-3" id="list-form">
<input type="hidden" name="sort" value="{{ $sort ?? request('sort') }}">
<input type="hidden" name="sort_type" value="{{ $sortType ?? request('sort_type') }}">
<div class="card p-3"> <div class="card p-3">
<h6 class="mb-3">絞り込みフィルター</h6> <h6 class="mb-3">絞り込みフィルター</h6>
<div class="row"> <div class="row">
@ -36,8 +38,7 @@
<select name="park_id" class="form-control"> <select name="park_id" class="form-control">
<option value="">全て</option> <option value="">全て</option>
@foreach($parks as $p) @foreach($parks as $p)
<option value="{{ $p->park_id }}" <option value="{{ $p->park_id }}" {{ (string) request('park_id') === (string) $p->park_id ? 'selected' : '' }}>
{{ (string)request('park_id')===(string)$p->park_id ? 'selected' : '' }}>
{{ $p->park_name }} {{ $p->park_name }}
</option> </option>
@endforeach @endforeach
@ -58,21 +59,23 @@
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">利用者分類</label> <label class="col-sm-3 col-form-label">利用者分類</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" name="user_categoryid" value="{{ request('user_categoryid') }}" class="form-control"> <input type="text" name="user_category1" value="{{ request('user_category1') }}" class="form-control" placeholder="分類名1">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">タグシリアル64進</label> <label class="col-sm-3 col-form-label">タグシリアル64進</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" name="user_tag_serial_64" value="{{ request('user_tag_serial_64') }}" class="form-control"> <input type="text" name="user_tag_serial_64" value="{{ request('user_tag_serial_64') }}"
class="form-control">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">有効期限</label> <label class="col-sm-3 col-form-label">有効期限</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="date" name="contract_periode" value="{{ request('contract_periode') }}" class="form-control"> <input type="date" name="contract_periode" value="{{ request('contract_periode') }}"
class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -118,9 +121,9 @@
<label class="col-sm-3 col-form-label">タグ・QR</label> <label class="col-sm-3 col-form-label">タグ・QR</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select name="tag_qr_flag" class="form-control"> <select name="tag_qr_flag" class="form-control">
<option value="" {{ request('tag_qr_flag')==='' ? 'selected' : '' }}>全て</option> <option value="" {{ request('tag_qr_flag') === '' ? 'selected' : '' }}>全て</option>
<option value="1" {{ request('tag_qr_flag')==='1' ? 'selected' : '' }}>QR</option> <option value="1" {{ request('tag_qr_flag') === '1' ? 'selected' : '' }}>QR</option>
<option value="0" {{ request('tag_qr_flag')==='0' ? 'selected' : '' }}>タグ</option> <option value="0" {{ request('tag_qr_flag') === '0' ? 'selected' : '' }}>タグ</option>
</select> </select>
</div> </div>
</div> </div>
@ -138,98 +141,116 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-hover table-sm rv-table text-nowrap"> <table class="table table-bordered table-hover table-sm rv-table text-nowrap">
<thead> <thead>
<tr> <tr>
<th>利用者ID</th> @php($activeSort = request('sort'))
<th>氏名</th> @php($activeType = request('sort_type'))
<th>フリガナ</th> <th
<th> class="sorting {{ $activeSort === 'rc.user_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<a href="{{ request()->fullUrlWithQuery([ sort="rc.user_id"
'sort' => 'rc.contract_id', aria-sort="{{ $activeSort === 'rc.user_id' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
'sort_type' => (request('sort') === 'rc.contract_id' && request('sort_type') === 'asc') ? 'desc' : 'asc' <span class="th-inner"><span class="th-label">利用者ID</span><span class="th-arrows"><span
]) }}"> class="up"></span><span class="down"></span></span></span>
定期契約ID </th>
@if(request('sort') === 'rc.contract_id') <th
@if(request('sort_type') === 'asc') class="sorting {{ $activeSort === 'u.user_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="u.user_name"
@else aria-sort="{{ $activeSort === 'u.user_name' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<span class="th-inner"><span class="th-label">氏名</span><span class="th-arrows"><span
@endif class="up"></span><span class="down"></span></span></span>
@endif </th>
</a> <th>フリガナ</th>
</th> <th
<th>タグ・QR</th> class="sorting {{ $activeSort === 'rc.contract_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>駐輪場</th> sort="rc.contract_id"
<th>車種区分</th> aria-sort="{{ $activeSort === 'rc.contract_id' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>減免措置</th> <span class="th-inner"><span class="th-label">定期契約ID</span><span class="th-arrows"><span
<th>利用者分類1</th> class="up"></span><span class="down"></span></span></span>
<th>利用者分類2</th> </th>
<th>利用者分類3</th> <th
<th>携帯電話番号</th> class="sorting {{ $activeSort === 'rc.tag_qr_flag' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>自宅電話番号</th> sort="rc.tag_qr_flag"
<th>生年月日</th> aria-sort="{{ $activeSort === 'rc.tag_qr_flag' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>性別</th> <span class="th-inner"><span class="th-label">タグ・QR</span><span class="th-arrows"><span
<th>居住所:郵便番号</th> class="up"></span><span class="down"></span></span></span>
<th>居住所:都道府県</th> </th>
<th>居住所:市区群</th> <th
<th>居住所:住所</th> class="sorting {{ $activeSort === 'p.park_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>関連住所:郵便番号</th> sort="p.park_name"
<th>関連住所:都道府県</th> aria-sort="{{ $activeSort === 'p.park_name' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>関連住所:市区群</th> <span class="th-inner"><span class="th-label">駐輪場</span><span class="th-arrows"><span
<th>関連住所:住所</th> class="up"></span><span class="down"></span></span></span>
<th>契約日</th> </th>
<th>利用期間</th> <th>車種区分</th>
<th>有効期間</th> <th>減免措置</th>
<th>定期券区分</th> <th>利用者分類1</th>
<th>勤務先名</th> <th>利用者分類2</th>
<th>学校</th> <th>利用者分類3</th>
<th>卒業予定</th> <th>携帯電話番号</th>
<th>シール発行回数</th> <th>自宅電話番号</th>
<th>防犯登録</th> <th>生年月日</th>
<th>備考</th> <th>性別</th>
</tr> <th>居住所:郵便番号</th>
<th>居住所:都道府県</th>
<th>居住所:市区群</th>
<th>居住所:住所</th>
<th>関連住所:郵便番号</th>
<th>関連住所:都道府県</th>
<th>関連住所:市区群</th>
<th>関連住所:住所</th>
<th>契約日</th>
<th>利用期間</th>
<th>有効期間</th>
<th>定期券区分</th>
<th>勤務先名</th>
<th>学校</th>
<th>卒業予定</th>
<th>シール発行回数</th>
<th>防犯登録</th>
<th>備考</th>
</tr>
</thead> </thead>
<tbody> <tbody>
@forelse ($rows as $row) @forelse ($rows as $row)
<tr> <tr>
<td>{{ $row->user_id }}</td> <td>{{ $row->user_id }}</td>
<td>{{ $row->user_name }}</td> <td>{{ $row->user_name }}</td>
<td>{{ $row->user_phonetic }}</td> <td>{{ $row->user_phonetic }}</td>
<td>{{ $row->contract_id }}</td> <td>{{ $row->contract_id }}</td>
<td>{{ $row->tag_qr_flag ? 'QR' : 'タグ' }}</td> <td>{{ $row->tag_qr_flag ? 'QR' : 'タグ' }}</td>
<td>{{ $row->park_name }}</td> <td>{{ $row->park_name }}</td>
<td>{{ $row->vehicle_type ?? '' }}</td> <td>{{ $row->vehicle_type ?? '' }}</td>
<td>{{ $row->user_reduction ?? '' }}</td> <td>{{ $row->user_reduction ?? '' }}</td>
<td>{{ $row->user_category1 ?? '' }}</td> <td>{{ $row->user_category1 ?? '' }}</td>
<td>{{ $row->user_category2 ?? '' }}</td> <td>{{ $row->user_category2 ?? '' }}</td>
<td>{{ $row->user_category3 ?? '' }}</td> <td>{{ $row->user_category3 ?? '' }}</td>
<td>{{ $row->user_mobile }}</td> <td>{{ $row->user_mobile }}</td>
<td>{{ $row->user_homephone }}</td> <td>{{ $row->user_homephone }}</td>
<td>{{ $row->user_birthdate }}</td> <td>{{ $row->user_birthdate }}</td>
<td>{{ $row->user_gender }}</td> <td>{{ $row->user_gender }}</td>
<td>{{ $row->user_regident_zip }}</td> <td>{{ $row->user_regident_zip }}</td>
<td>{{ $row->user_regident_pre }}</td> <td>{{ $row->user_regident_pre }}</td>
<td>{{ $row->user_regident_city }}</td> <td>{{ $row->user_regident_city }}</td>
<td>{{ $row->user_regident_add }}</td> <td>{{ $row->user_regident_add }}</td>
<td>{{ $row->user_relate_zip }}</td> <td>{{ $row->user_relate_zip }}</td>
<td>{{ $row->user_relate_pre }}</td> <td>{{ $row->user_relate_pre }}</td>
<td>{{ $row->user_relate_city }}</td> <td>{{ $row->user_relate_city }}</td>
<td>{{ $row->user_relate_add }}</td> <td>{{ $row->user_relate_add }}</td>
<td>{{ $row->contract_created_at }}</td> <td>{{ $row->contract_created_at }}</td>
<td>{{ $row->contract_periods }}</td> <td>{{ $row->contract_periods }}</td>
<td>{{ $row->contract_periode }}</td> <td>{{ $row->contract_periode }}</td>
<td>{{ $row->ticket_type ?? '' }}</td> <td>{{ $row->ticket_type ?? '' }}</td>
<td>{{ $row->user_workplace }}</td> <td>{{ $row->user_workplace }}</td>
<td>{{ $row->user_school }}</td> <td>{{ $row->user_school }}</td>
<td>{{ $row->user_graduate }}</td> <td>{{ $row->user_graduate }}</td>
<td>{{ $row->seal_issue_count ?? '' }}</td> <td>{{ $row->seal_issue_count ?? '' }}</td>
<td>{{ $row->crime_prevention ?? '' }}</td> <td>{{ $row->crime_prevention ?? '' }}</td>
<td>{{ $row->user_remarks }}</td> <td>{{ $row->user_remarks }}</td>
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="33" class="text-center">データがありません。</td> <td colspan="33" class="text-center">データがありません。</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
</table> </table>
</div> </div>
@ -242,13 +263,68 @@
{{-- 画面用スタイル(表頭をグレー、データ部分を白) --}} {{-- 画面用スタイル(表頭をグレー、データ部分を白) --}}
<style> <style>
.rv-table thead th{ .rv-table thead th {
background:#eeeeee; background: #eeeeee;
white-space:nowrap; /* settlement_transactions も薄グレー系 */
vertical-align:middle; white-space: nowrap;
vertical-align: middle;
padding: 8px 10px;
/* settlement_transactions のデフォルトに近い余白 */
font-size: 0.875rem;
/* 視認性と行高を近づける */
} }
.rv-table tbody tr { .rv-table tbody tr {
background: #fff; background: #fff;
} }
/* 矢印色制御:デフォルトはグレー、アクティブ方向のみ黒 */
th.sorting .th-arrows .up,
th.sorting .th-arrows .down {
color: #999;
}
th.sorting_asc .th-arrows .up {
color: #000;
}
th.sorting_desc .th-arrows .down {
color: #000;
}
/* アクセシビリティ向上:フォーカス時の視認性 */
th.sorting:focus,
th.sorting_asc:focus,
th.sorting_desc:focus {
outline: 2px solid #999;
outline-offset: -2px;
}
th[aria-sort] {
cursor: pointer;
}
</style> </style>
@endsection @push('scripts')
<script>
// 契約者一覧:決済トランザクション方式のクリックソート
document.querySelectorAll('th.sorting, th.sorting_asc, th.sorting_desc').forEach(th => {
th.addEventListener('click', function () {
const col = this.getAttribute('sort');
if (!col) return;
const form = document.getElementById('list-form');
const sortInput = form.querySelector('input[name="sort"]');
const typeInput = form.querySelector('input[name="sort_type"]');
const current = sortInput.value;
const currentType = typeInput.value;
let nextType = 'asc';
if (current === col) {
nextType = (currentType === 'asc') ? 'desc' : 'asc';
}
sortInput.value = col;
typeInput.value = nextType;
form.submit();
});
});
</script>
@endpush
@endsection

View File

@ -23,7 +23,9 @@
<div class="container-fluid"> <div class="container-fluid">
{{-- 絞り込みフィルター --}} {{-- 絞り込みフィルター --}}
<form method="GET" action="{{ route('contractor') }}" class="mb-3" id="filter-form"> <form method="GET" action="{{ route('contractor_List') }}" class="mb-3" id="list-form">
<input type="hidden" name="sort" value="{{ $sort ?? request('sort','rc.contract_id') }}">
<input type="hidden" name="sort_type" value="{{ $sortType ?? request('sort_type','desc') }}">
<div class="card p-3"> <div class="card p-3">
<h6 class="mb-3">絞り込みフィルター</h6> <h6 class="mb-3">絞り込みフィルター</h6>
<div class="row"> <div class="row">
@ -36,8 +38,7 @@
<select name="park_id" class="form-control"> <select name="park_id" class="form-control">
<option value="">全て</option> <option value="">全て</option>
@foreach($parks as $p) @foreach($parks as $p)
<option value="{{ $p->park_id }}" <option value="{{ $p->park_id }}" {{ (string) request('park_id') === (string) $p->park_id ? 'selected' : '' }}>
{{ (string)request('park_id')===(string)$p->park_id ? 'selected' : '' }}>
{{ $p->park_name }} {{ $p->park_name }}
</option> </option>
@endforeach @endforeach
@ -58,21 +59,25 @@
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">利用者分類</label> <label class="col-sm-3 col-form-label">利用者分類</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" name="user_categoryid" value="{{ request('user_categoryid') }}" class="form-control"> <input type="text" name="user_category1"
value="{{ request('user_category1') }}"
class="form-control" placeholder="分類名1">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">タグシリアル64進</label> <label class="col-sm-3 col-form-label">タグシリアル64進</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" name="user_tag_serial_64" value="{{ request('user_tag_serial_64') }}" class="form-control"> <input type="text" name="user_tag_serial_64" value="{{ request('user_tag_serial_64') }}"
class="form-control">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">有効期限</label> <label class="col-sm-3 col-form-label">有効期限</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="date" name="contract_periode" value="{{ request('contract_periode') }}" class="form-control"> <input type="date" name="contract_periode" value="{{ request('contract_periode') }}"
class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -118,9 +123,9 @@
<label class="col-sm-3 col-form-label">タグ・QR</label> <label class="col-sm-3 col-form-label">タグ・QR</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select name="tag_qr_flag" class="form-control"> <select name="tag_qr_flag" class="form-control">
<option value="" {{ request('tag_qr_flag')==='' ? 'selected' : '' }}>全て</option> <option value="" {{ request('tag_qr_flag') === '' ? 'selected' : '' }}>全て</option>
<option value="1" {{ request('tag_qr_flag')==='1' ? 'selected' : '' }}>QR</option> <option value="1" {{ request('tag_qr_flag') === '1' ? 'selected' : '' }}>QR</option>
<option value="0" {{ request('tag_qr_flag')==='0' ? 'selected' : '' }}>タグ</option> <option value="0" {{ request('tag_qr_flag') === '0' ? 'selected' : '' }}>タグ</option>
</select> </select>
</div> </div>
</div> </div>
@ -128,8 +133,8 @@
</div> </div>
<div class="mt-2"> <div class="mt-2">
<button type="submit" class="btn btn-default">絞り込み</button> <button type="submit" class="btn btn-default">絞り込み</button>
<a href="{{ route('contractor') }}" class="btn btn-default">解除</a> <a href="{{ route('contractor_List') }}" class="btn btn-default">解除</a>
</div> </div>
</div> </div>
</form> </form>
@ -138,98 +143,116 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-hover table-sm rv-table text-nowrap"> <table class="table table-bordered table-hover table-sm rv-table text-nowrap">
<thead> <thead>
<tr> <tr>
<th>利用者ID</th> @php($activeSort = request('sort'))
<th>氏名</th> @php($activeType = request('sort_type'))
<th>フリガナ</th> <th
<th> class="sorting {{ $activeSort === 'rc.user_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<a href="{{ request()->fullUrlWithQuery([ sort="rc.user_id"
'sort' => 'contract_id', aria-sort="{{ $activeSort === 'rc.user_id' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
'sort_type' => (request('sort') === 'contract_id' && request('sort_type') === 'asc') ? 'desc' : 'asc' <span class="th-inner"><span class="th-label">利用者ID</span><span class="th-arrows"><span
]) }}"> class="up"></span><span class="down"></span></span></span>
定期契約ID </th>
@if(request('sort') === 'contract_id') <th
@if(request('sort_type') === 'asc') class="sorting {{ $activeSort === 'u.user_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="u.user_name"
@else aria-sort="{{ $activeSort === 'u.user_name' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<span class="th-inner"><span class="th-label">氏名</span><span class="th-arrows"><span
@endif class="up"></span><span class="down"></span></span></span>
@endif </th>
</a> <th>フリガナ</th>
</th> <th
<th>タグ・QR</th> class="sorting {{ $activeSort === 'rc.contract_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>駐輪場</th> sort="rc.contract_id"
<th>車種区分</th> aria-sort="{{ $activeSort === 'rc.contract_id' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>減免措置</th> <span class="th-inner"><span class="th-label">定期契約ID</span><span class="th-arrows"><span
<th>利用者分類1</th> class="up"></span><span class="down"></span></span></span>
<th>利用者分類2</th> </th>
<th>利用者分類3</th> <th
<th>携帯電話番号</th> class="sorting {{ $activeSort === 'rc.tag_qr_flag' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>自宅電話番号</th> sort="rc.tag_qr_flag"
<th>生年月日</th> aria-sort="{{ $activeSort === 'rc.tag_qr_flag' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>性別</th> <span class="th-inner"><span class="th-label">タグ・QR</span><span class="th-arrows"><span
<th>居住所:郵便番号</th> class="up"></span><span class="down"></span></span></span>
<th>居住所:都道府県</th> </th>
<th>居住所:市区群</th> <th
<th>居住所:住所</th> class="sorting {{ $activeSort === 'p.park_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
<th>関連住所:郵便番号</th> sort="p.park_name"
<th>関連住所:都道府県</th> aria-sort="{{ $activeSort === 'p.park_name' ? ($activeType === 'asc' ? 'ascending' : 'descending') : 'none' }}">
<th>関連住所:市区群</th> <span class="th-inner"><span class="th-label">駐輪場</span><span class="th-arrows"><span
<th>関連住所:住所</th> class="up"></span><span class="down"></span></span></span>
<th>契約日</th> </th>
<th>利用期間</th> <th>車種区分</th>
<th>有効期間</th> <th>減免措置</th>
<th>定期券区分</th> <th>利用者分類1</th>
<th>勤務先名</th> <th>利用者分類2</th>
<th>学校</th> <th>利用者分類3</th>
<th>卒業予定</th> <th>携帯電話番号</th>
<th>シール発行回数</th> <th>自宅電話番号</th>
<th>防犯登録</th> <th>生年月日</th>
<th>備考</th> <th>性別</th>
</tr> <th>居住所:郵便番号</th>
<th>居住所:都道府県</th>
<th>居住所:市区群</th>
<th>居住所:住所</th>
<th>関連住所:郵便番号</th>
<th>関連住所:都道府県</th>
<th>関連住所:市区群</th>
<th>関連住所:住所</th>
<th>契約日</th>
<th>利用期間</th>
<th>有効期間</th>
<th>定期券区分</th>
<th>勤務先名</th>
<th>学校</th>
<th>卒業予定</th>
<th>シール発行回数</th>
<th>防犯登録</th>
<th>備考</th>
</tr>
</thead> </thead>
<tbody> <tbody>
@forelse ($rows as $row) @forelse ($rows as $row)
<tr> <tr>
<td>{{ $row->user_id }}</td> <td>{{ $row->user_id }}</td>
<td>{{ $row->user_name }}</td> <td>{{ $row->user_name }}</td>
<td>{{ $row->user_phonetic }}</td> <td>{{ $row->user_phonetic }}</td>
<td>{{ $row->contract_id }}</td> <td>{{ $row->contract_id }}</td>
<td>{{ $row->tag_qr_flag ? 'QR' : 'タグ' }}</td> <td>{{ $row->tag_qr_flag ? 'QR' : 'タグ' }}</td>
<td>{{ $row->park_name }}</td> <td>{{ $row->park_name }}</td>
<td>{{ $row->vehicle_type ?? '' }}</td> <td>{{ $row->vehicle_type ?? '' }}</td>
<td>{{ $row->user_reduction ?? '' }}</td> <td>{{ $row->user_reduction ?? '' }}</td>
<td>{{ $row->user_category1 ?? '' }}</td> <td>{{ $row->user_category1 ?? '' }}</td>
<td>{{ $row->user_category2 ?? '' }}</td> <td>{{ $row->user_category2 ?? '' }}</td>
<td>{{ $row->user_category3 ?? '' }}</td> <td>{{ $row->user_category3 ?? '' }}</td>
<td>{{ $row->user_mobile }}</td> <td>{{ $row->user_mobile }}</td>
<td>{{ $row->user_homephone }}</td> <td>{{ $row->user_homephone }}</td>
<td>{{ $row->user_birthdate }}</td> <td>{{ $row->user_birthdate }}</td>
<td>{{ $row->user_gender }}</td> <td>{{ $row->user_gender }}</td>
<td>{{ $row->user_regident_zip }}</td> <td>{{ $row->user_regident_zip }}</td>
<td>{{ $row->user_regident_pre }}</td> <td>{{ $row->user_regident_pre }}</td>
<td>{{ $row->user_regident_city }}</td> <td>{{ $row->user_regident_city }}</td>
<td>{{ $row->user_regident_add }}</td> <td>{{ $row->user_regident_add }}</td>
<td>{{ $row->user_relate_zip }}</td> <td>{{ $row->user_relate_zip }}</td>
<td>{{ $row->user_relate_pre }}</td> <td>{{ $row->user_relate_pre }}</td>
<td>{{ $row->user_relate_city }}</td> <td>{{ $row->user_relate_city }}</td>
<td>{{ $row->user_relate_add }}</td> <td>{{ $row->user_relate_add }}</td>
<td>{{ $row->contract_created_at }}</td> <td>{{ $row->contract_created_at }}</td>
<td>{{ $row->contract_periods }}</td> <td>{{ $row->contract_periods }}</td>
<td>{{ $row->contract_periode }}</td> <td>{{ $row->contract_periode }}</td>
<td>{{ $row->ticket_type ?? '' }}</td> <td>{{ $row->ticket_type ?? '' }}</td>
<td>{{ $row->user_workplace }}</td> <td>{{ $row->user_workplace }}</td>
<td>{{ $row->user_school }}</td> <td>{{ $row->user_school }}</td>
<td>{{ $row->user_graduate }}</td> <td>{{ $row->user_graduate }}</td>
<td>{{ $row->seal_issue_count ?? '' }}</td> <td>{{ $row->seal_issue_count ?? '' }}</td>
<td>{{ $row->crime_prevention ?? '' }}</td> <td>{{ $row->crime_prevention ?? '' }}</td>
<td>{{ $row->user_remarks }}</td> <td>{{ $row->user_remarks }}</td>
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="33" class="text-center">データがありません。</td> <td colspan="33" class="text-center">データがありません。</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
</table> </table>
</div> </div>
@ -242,13 +265,68 @@
{{-- 画面用スタイル(表頭をグレー、データ部分を白) --}} {{-- 画面用スタイル(表頭をグレー、データ部分を白) --}}
<style> <style>
.rv-table thead th{ .rv-table thead th {
background:#eeeeee; background: #eeeeee;
white-space:nowrap; /* settlement_transactions も薄グレー系 */
vertical-align:middle; white-space: nowrap;
vertical-align: middle;
padding: 8px 10px;
/* settlement_transactions のデフォルトに近い余白 */
font-size: 0.875rem;
/* 視認性と行高を近づける */
} }
.rv-table tbody tr { .rv-table tbody tr {
background: #fff; background: #fff;
} }
/* 矢印色制御:デフォルトはグレー、アクティブ方向のみ黒 */
th.sorting .th-arrows .up,
th.sorting .th-arrows .down {
color: #999;
}
th.sorting_asc .th-arrows .up {
color: #000;
}
th.sorting_desc .th-arrows .down {
color: #000;
}
/* アクセシビリティ向上:フォーカス時の視認性 */
th.sorting:focus,
th.sorting_asc:focus,
th.sorting_desc:focus {
outline: 2px solid #999;
outline-offset: -2px;
}
th[aria-sort] {
cursor: pointer;
}
</style> </style>
@endsection @push('scripts')
<script>
// 未更新者一覧:決済トランザクション方式のクリックソート
document.querySelectorAll('th.sorting, th.sorting_asc, th.sorting_desc').forEach(th => {
th.addEventListener('click', function () {
const col = this.getAttribute('sort');
if (!col) return;
const form = document.getElementById('list-form');
const sortInput = form.querySelector('input[name="sort"]');
const typeInput = form.querySelector('input[name="sort_type"]');
const current = sortInput.value;
const currentType = typeInput.value;
let nextType = 'asc';
if (current === col) {
nextType = (currentType === 'asc') ? 'desc' : 'asc';
}
sortInput.value = col;
typeInput.value = nextType;
form.submit();
});
});
</script>
@endpush
@endsection