krgm.so-manager-dev.com/resources/views/admin/contractor/list.blade.php
你的名字 87761805f4
All checks were successful
Deploy main / deploy (push) Successful in 22s
【契約日】Y-M-D形式修正
2025-10-15 18:44:17 +09:00

543 lines
21 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-lg-6">
<h1 class="m-0 text-dark">契約者一覧</h1>
</div>
<div class="col-lg-6">
<ol class="breadcrumb float-sm-right text-sm">
<li class="breadcrumb-item"><a href="{{ url('/home') }}">ホーム</a></li>
<li class="breadcrumb-item active">契約者一覧</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<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="col-lg-12">
<div class="card">
{{-- 絞り込みフィルターcard-header --}}
<div class="card-header" style="font-weight:bold;">
絞り込みフィルター
</div>
{{-- フィルター条件エリアcard-body --}}
<div class="card-body bg-white">
<div class="row">
{{-- 左カラム --}}
<div class="col-md-6">
<div class="form-group row">
<label class="col-sm-3 col-form-label">駐輪場</label>
<div class="col-sm-9">
@isset($parks)
<select name="park_id" class="form-control">
<option value="">全て</option>
@foreach($parks as $p)
<option value="{{ $p->park_id }}" {{ (string) request('park_id') === (string) $p->park_id ? 'selected' : '' }}>
{{ $p->park_name }}
</option>
@endforeach
</select>
@else
<input type="text" name="park_name" value="{{ request('park_name') }}" class="form-control"
placeholder="123456">
@endisset
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">利用者ID</label>
<div class="col-sm-9">
<input type="text" name="user_id" value="{{ request('user_id') }}" class="form-control"
placeholder="123456">
</div>
</div>
{{-- ===== 利用者分類input select に変更 ===== --}}
<div class="form-group row">
<label class="col-sm-3 col-form-label">利用者分類</label>
<div class="col-sm-9">
@isset($categories)
<select name="user_category1" class="form-control">
<option value="">全て</option>
@foreach($categories as $key => $label)
<option value="{{ $key }}"
{{ (string) request('user_category1') === (string) $key ? 'selected' : '' }}>
{{ $label }}
</option>
@endforeach
</select>
@else
<input type="text" name="user_category1" value="{{ request('user_category1') }}" class="form-control"
placeholder="123456">
@endisset
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">タグシリアル64進</label>
<div class="col-sm-9">
<input type="text" name="user_tag_serial_64" value="{{ request('user_tag_serial_64') }}"
class="form-control" placeholder="キーワード...">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">有効期限</label>
<div class="col-sm-9">
<input type="date" name="contract_periode" value="{{ request('contract_periode') }}"
class="form-control">
</div>
</div>
</div>
{{-- 右カラム --}}
<div class="col-md-6">
<div class="form-group row">
<label class="col-sm-3 col-form-label">フリガナ</label>
<div class="col-sm-9">
<input type="text" name="user_phonetic" value="{{ request('user_phonetic') }}" class="form-control"
placeholder="123456">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">電話番号</label>
<div class="col-sm-9">
<input type="text" name="user_mobile" value="{{ request('user_mobile') }}" class="form-control"
placeholder="08011112222">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">メールアドレス</label>
<div class="col-sm-9">
<input type="text" name="user_primemail" value="{{ request('user_primemail') }}" class="form-control"
placeholder="キーワード...">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">勤務先</label>
<div class="col-sm-9">
<input type="text" name="user_workplace" value="{{ request('user_workplace') }}" class="form-control"
placeholder="キーワード...">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">学校</label>
<div class="col-sm-9">
<input type="text" name="user_school" value="{{ request('user_school') }}" class="form-control"
placeholder="キーワード...">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">タグ・QR</label>
<div class="col-sm-9">
<select name="tag_qr_flag" class="form-control">
<option value="" {{ request('tag_qr_flag') === '' ? 'selected' : '' }}>全て</option>
<option value="1" {{ request('tag_qr_flag') === '1' ? 'selected' : '' }}>QR</option>
<option value="0" {{ request('tag_qr_flag') === '0' ? 'selected' : '' }}>タグ</option>
</select>
</div>
</div>
</div>
</div>
{{-- 絞り込みボタン --}}
<div class="mt-2 mb-3 text-start">
<button type="submit" class="btn btn-default px-4">絞り込み</button>
<a href="{{ route('contractor') }}" class="btn btn-default px-4">解除</a>
</div>
</div>
</div>
{{-- ページネーションのラッパーを追加 --}}
<div class="container-fluid mb20 pagination-area">
{{-- ページネーションのビジュアルラッパー --}}
<div class="pagination-wrapper mt-2">
<nav aria-label="ページネーション">
{{-- Bootstrap のリンク出力(元の呼び出しをそのまま利用) --}}
{{ $rows->appends(request()->except('page'))->links('pagination::bootstrap-4') }}
</nav>
</div>
</div>
{{-- 一覧テーブル部:スクロール対応 --}}
<div class="col-lg-12 row sample03-wrapper no_padding_right mb20">
<div class="table-responsive">
<table class="table table-bordered table-hover table-sm rv-table text-nowrap mb-0">
<thead class="thead-light">
<tr>
@php($activeSort = request('sort'))
@php($activeType = request('sort_type'))
<th
class="sorting {{ $activeSort === 'rc.user_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="rc.user_id"
>
<span class="sort-label">
利用者ID
<span class="sort-arrows" aria-hidden="true">
<span class="up"></span>
<span class="down"></span>
</span>
</span>
</th>
<th
class="sorting {{ $activeSort === 'u.user_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="u.user_name"
>
<span class="sort-label">
氏名
<span class="sort-arrows" aria-hidden="true">
<span class="up"></span>
<span class="down"></span>
</span>
</span>
</th>
<th>フリガナ</th>
<th
class="sorting {{ $activeSort === 'rc.contract_id' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="rc.contract_id"
>
<span class="sort-label">
定期契約ID
<span class="sort-arrows" aria-hidden="true">
<span class="up"></span>
<span class="down"></span>
</span>
</span>
</th>
<th
class="sorting {{ $activeSort === 'rc.tag_qr_flag' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="rc.tag_qr_flag"
>
<span class="sort-label">
タグ・QR
<span class="sort-arrows" aria-hidden="true">
<span class="up"></span>
<span class="down"></span>
</span>
</span>
</th>
<th
class="sorting {{ $activeSort === 'p.park_name' ? ($activeType === 'asc' ? 'sorting_asc' : 'sorting_desc') : '' }}"
sort="p.park_name"
>
<span class="sort-label">
駐輪場
<span class="sort-arrows" aria-hidden="true">
<span class="up"></span>
<span class="down"></span>
</span>
</span>
</th>
<th>車種区分</th>
<th>減免措置</th>
<th>利用者分類1</th>
<th>利用者分類2</th>
<th>利用者分類3</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>
<tbody>
@forelse ($rows as $row)
<tr>
<td>
<a href="{{ route('users_edit', ['seq' => $row->user_seq ?? $row->user_id]) }}">
{{ $row->user_id }}
</a>
</td>
<td>{{ $row->user_name }}</td>
<td>{{ $row->user_phonetic }}</td>
<td>
<a href="{{ route('regularcontracts_edit', ['contract_id' => $row->contract_id]) }}">
{{ $row->contract_id }}
</a>
</td>
<td>{{ $row->tag_qr_flag ? 'QR' : 'タグ' }}</td>
<td>{{ $row->park_name }}</td>
<td>{{ $row->vehicle_type ?? '' }}</td>
<td>{{ $row->user_reduction ?? '' }}</td>
<td>{{ $row->user_category1 ?? '' }}</td>
<td>{{ $row->user_category2 ?? '' }}</td>
<td>{{ $row->user_category3 ?? '' }}</td>
<td>{{ $row->user_mobile }}</td>
<td>{{ $row->user_homephone }}</td>
<td>{{ $row->user_birthdate }}</td>
<td>{{ $row->user_gender }}</td>
<td>{{ $row->user_regident_zip }}</td>
<td>{{ $row->user_regident_pre }}</td>
<td>{{ $row->user_regident_city }}</td>
<td>{{ $row->user_regident_add }}</td>
<td>
{{-- 契約日を「yyyymmdd」形式で表示する --}}
{{ $row->contract_created_at
? \Illuminate\Support\Carbon::parse($row->contract_created_at)->format('Y-m-d')
: '' }}
</td>
<td>
<?php
// 直近ラベルを計算(本日と有効期間終了日の月差で判定)
$label = '';
try {
if (!empty($row->contract_periode)) {
$today = \Illuminate\Support\Carbon::now()->startOfDay();
$end = \Illuminate\Support\Carbon::parse($row->contract_periode)->startOfDay();
if ($end->lte($today)) {
$months = $end->diffInMonths($today);
if ($months <= 1) {
$label = '直近1ヶ月';
} elseif ($months <= 3) {
$label = '直近3ヶ月';
} elseif ($months <= 6) {
$label = '直近6ヶ月';
}
}
}
} catch (\Throwable $e) {
$label = '';
}
?>
{{ $label }}
</td>
<td>
{{ \Carbon\Carbon::parse($row->contract_periods)->format('Y-m-d') }}
{{ \Carbon\Carbon::parse($row->contract_periode)->format('Y-m-d') }}
</td>
<td>
@if($row->update_flag == 1)
継続
@elseif($row->update_flag == 2)
それ
@else
{{-- それ以外は空白 --}}
@endif
</td>
<td>{{ $row->user_workplace }}</td>
<td>{{ $row->user_school }}</td>
<td>{{ $row->user_remarks }}</td>
</tr>
@empty
<tr>
<td colspan="25" class="text-center">データがありません。</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</form>
</section>
@push('scripts')
<script>
// ▼ ソート機能(日本語コメント)
// th 要素をクリックすると sort と sort_type を設定してフォーム送信します
document.querySelectorAll('th[sort]').forEach(th => {
th.classList.add('sorting'); // ベースクラスを確実に付ける
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';
}
if (sortInput) sortInput.value = col;
if (typeInput) typeInput.value = nextType;
// 視覚的にソートクラスを切り替え(矢印の色に反映)
document.querySelectorAll('th[sort]').forEach(h => {
h.classList.remove('sorting_asc', 'sorting_desc');
if (!h.classList.contains('sorting')) h.classList.add('sorting');
});
if (nextType === 'asc') {
this.classList.add('sorting_asc');
} else {
this.classList.add('sorting_desc');
}
form.submit();
});
});
</script>
<style>
/* ----------------------------------------
ページネーションの横幅を確保して右寄せ(スクリーンショットは右寄せ)
---------------------------------------- */
.pagination-area .pagination-wrapper {
display: flex;
justify-content: flex-end; /* 右寄せ:必要なら center に変更 */
align-items: center;
width: 100%;
gap: 8px;
}
/* ========================================
ソート矢印の色ルール(日本語コメント)
状態:
未ソート -> 左(上)灰色, 右(下)灰色
昇順(asc) -> 左(上)黒色, 右(下)灰色
降順(desc) -> 左(上)灰色, 右(下)黒色
======================================== */
/* 既存の擬似要素で出る矢印を無効化(保険) */
th.sorting::after,
th.sorting_asc::after,
th.sorting_desc::after {
display: none !important;
content: none !important;
background-image: none !important;
background: none !important;
}
/* 矢印を水平に並べる(左: up, 右: down */
th[sort] .sort-arrows,
th.sorting .sort-arrows,
th.sorting_asc .sort-arrows,
th.sorting_desc .sort-arrows {
display: inline-flex !important;
flex-direction: row !important;
gap: 6px !important;
align-items: center !important;
justify-content: center !important;
line-height: 1 !important;
font-size: 12px !important;
user-select: none !important;
width: auto !important;
box-sizing: border-box;
vertical-align: middle;
color: #bfc9d6 !important; /* デフォルト灰 */
}
th[sort] .sort-arrows .up,
th[sort] .sort-arrows .down,
th.sorting .sort-arrows .up,
th.sorting .sort-arrows .down {
display: inline-block !important;
min-width: 14px;
text-align: center;
line-height: 1;
}
/* 未ソート: 両方灰 */
th.sorting:not(.sorting_asc):not(.sorting_desc) .sort-arrows .up,
th.sorting:not(.sorting_asc):not(.sorting_desc) .sort-arrows .down {
color: #bfc9d6 !important;
}
/* 昇順: 左(上) 黒、右(下) 灰 */
th.sorting_asc .sort-arrows .up,
th[sort].sorting_asc .sort-arrows .up {
color: #000000 !important;
}
th.sorting_asc .sort-arrows .down,
th[sort].sorting_asc .sort-arrows .down {
color: #bfc9d6 !important;
}
/* 降順: 左(上) 灰、右(下) 黒 */
th.sorting_desc .sort-arrows .up,
th[sort].sorting_desc .sort-arrows .up {
color: #bfc9d6 !important;
}
th.sorting_desc .sort-arrows .down,
th[sort].sorting_desc .sort-arrows .down {
color: #000000 !important;
}
/* 矢印間を詰めたい場合(例: 見た目で letter-spacing 相当) */
th[sort] .sort-arrows { gap: 0 !important; }
th[sort] .sort-arrows .down { margin-left: -5px !important; }
/* 矢印の下線を消す(リンク内にある場合の保険) */
th .sort-arrows,
th .sort-label,
th[sort] .sort-arrows,
th.sorting .sort-arrows {
text-decoration: none !important;
}
th .sort-label a,
th .sort-arrows a {
text-decoration: none !important;
border-bottom: none !important;
color: inherit !important;
}
/* SVG 対応(矢印が svg の場合) */
th[sort] .sort-arrows svg path,
th.sorting .sort-arrows svg path {
fill: #bfc9d6 !important;
}
th.sorting_asc .sort-arrows svg path,
th[sort].sorting_asc .sort-arrows svg path {
fill: #000 !important;
}
th.sorting_desc .sort-arrows svg path,
th[sort].sorting_desc .sort-arrows svg path {
fill: #000 !important;
}
/* レスポンシブ:小画面で間隔を狭める */
@media (max-width: 575.98px) {
th[sort] .sort-arrows { gap: 4px !important; font-size: 11px !important; }
}
/* フォーカス時の視認性(アクセシビリティ) */
th.sorting:focus,
th.sorting_asc:focus,
th.sorting_desc:focus {
outline: 2px solid rgba(0,0,0,0.08);
outline-offset: -2px;
}
</style>
@endpush
@endsection