Merge branch 'main' of https://git.so-manager-dev.com/so-manager/krgm.so-manager-dev.com
All checks were successful
Deploy main / deploy (push) Successful in 21s

This commit is contained in:
kin.rinzen 2025-10-03 18:27:24 +09:00
commit 6c08ea4599
4 changed files with 628 additions and 24 deletions

View File

@ -6,8 +6,30 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\Support\Facades\Hash;
class UsersController
{
/**
* 利用者分類選択肢を取得
*/
private function buildCategoryOptions(): array
{
return DB::table('usertype')
->orderBy('user_categoryid', 'asc')
->get()
->mapWithKeys(function ($row) {
$label = collect([
$row->usertype_subject1 ?? '',
$row->usertype_subject2 ?? '',
$row->usertype_subject3 ?? '',
])->filter(fn ($v) => $v !== '')->implode('/');
return [$row->user_categoryid => $label !== '' ? $label : (string) $row->user_categoryid];
})
->toArray();
}
/**
* 利用者一覧
* - テーブル名: user
@ -38,13 +60,15 @@ class UsersController
'user_name',
'user_birthdate',
'user_age',
'user_mobile',
'user_homephone',
'user_primemail',
'user_submail',
'user_school',
];
$sort = $request->input('sort', 'user_seq');
$sortType = strtolower($request->input('sort_type', 'desc')) === 'asc' ? 'asc' : 'desc';
$dirParam = strtolower((string) $request->input('dir', $request->input('sort_type', 'asc')));
$sortType = $dirParam === 'asc' ? 'asc' : 'desc';
if (!in_array($sort, $sortable, true)) {
$sort = 'user_seq';
}
@ -56,6 +80,7 @@ class UsersController
$user_phonetic = trim((string) $request->input('user_phonetic', ''));
$phone = trim((string) $request->input('phone', '')); // 携帯/自宅の両方対象
$crime = trim((string) $request->input('crime', '')); // 防犯登録番号(暫定: qr_code
$email = trim((string) $request->input('email', ''));
$user_categoryid = (string) $request->input('user_categoryid', '');
$tag_qr_flag = (string) $request->input('tag_qr_flag', ''); // 0=タグ / 1=QR
$quit_flag = (string) $request->input('quit_flag', ''); // 0=いいえ / 1=はい
@ -63,7 +88,14 @@ class UsersController
$quit_to = (string) $request->input('quit_to', ''); // YYYY-MM-DD
// ▼ ベースクエリ(一覧で使う列が多いので一旦 * を許容)
$query = DB::table('user')->select('user.*');
$query = DB::table('user')
->leftJoin('usertype', 'user.user_categoryid', '=', 'usertype.user_categoryid')
->select(
'user.*',
'usertype.usertype_subject1',
'usertype.usertype_subject2',
'usertype.usertype_subject3'
);
// ▼ テキスト系
if ($user_id !== '')
@ -84,6 +116,8 @@ class UsersController
// ※ dump に防犯登録番号の明確なカラムが無いため暫定的に qr_code を対象
$query->where('user.qr_code', 'like', "%{$crime}%");
}
if ($email !== '')
$query->where('user.user_primemail', 'like', "%{$email}%");
// ▼ セレクト/ラジオ('' 以外なら適用。'0' も通す)
if ($user_categoryid !== '')
@ -107,17 +141,20 @@ class UsersController
'list' => $list,
'sort' => $sort,
'sort_type' => $sortType,
'dir' => $sortType,
'user_id' => $user_id,
'member_id' => $member_id,
'user_tag_serial' => $user_tag_serial,
'user_phonetic' => $user_phonetic,
'phone' => $phone,
'crime' => $crime,
'email' => $email,
'user_categoryid' => $user_categoryid,
'tag_qr_flag' => $tag_qr_flag,
'quit_flag' => $quit_flag,
'quit_from' => $quit_from,
'quit_to' => $quit_to,
'categoryOptions' => $this->buildCategoryOptions(),
]);
}
@ -260,10 +297,9 @@ class UsersController
return view('admin.users.add');
}
// ▼ バリデーションuser_id は半角数字のみ)
$rules = [
'user_id' => ['required', 'regex:/^\d+$/'], // 半角数字のみ許可
'user_id' => ['required', 'regex:/^\d+$/', 'digits_between:1,10'], // 半角数字最大10桁
'user_name' => ['required', 'string', 'max:255'],
// 任意
'user_primemail' => ['nullable', 'email', 'max:255'],
@ -279,6 +315,8 @@ class UsersController
$messages = [
'user_id.required' => '利用者IDは必須です。',
'user_id.regex' => '利用者IDは半角数字のみで入力してください。',
'user_id.digits_between' => '利用者IDは最大10桁以内で入力してください。',
'user_name.required' => '氏名は必須です。',
];
// ▼ 属性名(日本語ラベル)
@ -315,4 +353,111 @@ class UsersController
return redirect()->route('users')->with('success', '利用者を登録しました。');
}
/**
* 利用者編集GET: 表示 / POST: 更新)
*/
public function edit(Request $request, int $seq)
{
$user = DB::table('user')->where('user_seq', $seq)->first();
if (!$user) {
abort(404, '利用者情報が見つかりません。');
}
$operators = DB::table('ope')
->select('ope_id', 'ope_name')
->orderBy('ope_name')
->get();
$categoryOptions = $this->buildCategoryOptions();
if ($request->isMethod('get')) {
return view('admin.users.edit', [
'user' => $user,
'operators' => $operators,
'categoryOptions' => $categoryOptions,
]);
}
$rules = [
'user_id' => ['required', 'regex:/^\d+$/', 'digits_between:1,10'],
'user_name' => ['required', 'string', 'max:255'],
'user_primemail' => ['nullable', 'email', 'max:255'],
'user_gender' => ['nullable', 'in:男性,女性,未入力'],
'member_id' => ['nullable', 'string', 'max:255'],
'user_mobile' => ['nullable', 'string', 'max:255'],
'user_homephone' => ['nullable', 'string', 'max:255'],
'user_birthdate' => ['nullable', 'date'],
'user_categoryid' => ['nullable', 'integer', 'exists:usertype,user_categoryid'],
'user_age' => ['nullable', 'integer', 'min:0'],
'user_chk_day' => ['nullable', 'date'],
'user_quitday' => ['nullable', 'date'],
'ope_id' => ['nullable', 'integer', 'exists:ope,ope_id'],
];
$messages = [
'user_id.required' => '利用者IDは必須です。',
'user_id.regex' => '利用者IDは半角数字のみで入力してください。',
'user_id.digits_between' => '利用者IDは最大10桁以内で入力してください。',
'user_name.required' => '氏名は必須です。',
];
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$data = [
'user_id' => $request->input('user_id'),
'member_id' => $request->input('member_id'),
'user_name' => $request->input('user_name'),
'user_gender' => $request->input('user_gender'),
'user_mobile' => $request->input('user_mobile'),
'user_homephone' => $request->input('user_homephone'),
'user_birthdate' => $request->input('user_birthdate'),
'user_age' => $request->input('user_age'),
'user_categoryid' => $request->input('user_categoryid'),
'user_phonetic' => $request->input('user_phonetic'),
'user_tag_serial' => $request->input('user_tag_serial'),
'user_tag_serial_64' => $request->input('user_tag_serial_64'),
'qr_code' => $request->input('qr_code'),
'tag_qr_flag' => $request->input('tag_qr_flag', '0'),
'user_aid' => $request->input('user_aid'),
'user_place_qrid' => $request->input('user_place_qrid'),
'user_primemail' => $request->input('user_primemail'),
'user_submail' => $request->input('user_submail'),
'ward_residents' => $request->input('ward_residents'),
'user_workplace' => $request->input('user_workplace'),
'user_school' => $request->input('user_school'),
'user_graduate' => $request->input('user_graduate'),
'user_idcard' => $request->input('user_idcard'),
'user_idcard_chk_flag' => $request->input('user_idcard_chk_flag', '0'),
'user_chk_day' => $request->input('user_chk_day'),
'user_chk_opeid' => $request->input('ope_id'),
'ope_id' => $request->input('ope_id'),
'user_regident_zip' => $request->input('user_regident_zip'),
'user_regident_pre' => $request->input('user_regident_pre'),
'user_regident_city' => $request->input('user_regident_city'),
'user_regident_add' => $request->input('user_regident_add'),
'user_relate_zip' => $request->input('user_relate_zip'),
'user_relate_pre' => $request->input('user_relate_pre'),
'user_relate_city' => $request->input('user_relate_city'),
'user_relate_add' => $request->input('user_relate_add'),
'user_tag_issue' => $request->input('user_tag_issue'),
'issue_permission' => $request->input('issue_permission', '1'),
'user_quit_flag' => $request->input('user_quit_flag', '0'),
'user_quitday' => $request->input('user_quitday'),
'user_remarks' => $request->input('user_remarks'),
'updated_at' => now(),
];
if ($request->filled('user_pass')) {
$data['user_pass'] = Hash::make($request->input('user_pass'));
}
DB::table('user')->where('user_seq', $seq)->update($data);
return redirect()
->route('users_edit', ['seq' => $seq])
->with('status', '利用者情報を更新しました。');
}
}

View File

@ -0,0 +1,382 @@
@extends('layouts.app')
@section('title', '利用者マスタ|編集')
@section('content')
@php
/** @var \Illuminate\Support\ViewErrorBag $errors */
$isEdit = isset($user);
$value = static function (string $key, $default = '') use ($isEdit, $user) {
return old($key, $isEdit ? ($user->{$key} ?? $default) : $default);
};
$hasDeleteRoute = Route::has('users_delete_confirm');
$operators = $operators ?? collect();
$categoryOptions = $categoryOptions ?? [];
@endphp
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2 align-items-center">
<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"><a href="{{ route('users') }}">利用者マスタ</a></li>
<li class="breadcrumb-item active">{{ $isEdit ? '編集' : '新規' }}</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
@if (session('status'))
<div class="alert alert-success">{{ session('status') }}</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $e)
<li>{{ $e }}</li>
@endforeach
</ul>
</div>
@endif
<form method="post"
id="user-edit-form"
action="{{ $isEdit ? route('users_edit', ['seq' => $user->user_seq]) : route('users_add') }}"
enctype="multipart/form-data">
@csrf
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h3 class="card-title mb-0 font-weight-bold">基本情報</h3>
<div class="btn-group">
<button type="submit" class="btn btn-success btn-sm px-4">登録</button>
@if ($isEdit && $hasDeleteRoute)
<button type="button" id="btn-quit-top" class="btn btn-outline-danger btn-sm px-4">退会</button>
@endif
</div>
</div>
<div class="card-body p-0">
<table class="table table-form mb-0">
<tbody>
<tr>
<th>利用者連番</th>
<td><input type="text" class="form-control form-control-sm bg-secondary-light" value="{{ $isEdit ? $user->user_seq : '新規' }}" readonly></td>
</tr>
<tr>
<th>利用者ID<span class="text-danger ml-1">*</span></th>
<td><input type="text" name="user_id" class="form-control form-control-sm" value="{{ $value('user_id') }}" required></td>
</tr>
<tr>
<th>会員ID</th>
<td><input type="text" name="member_id" class="form-control form-control-sm" value="{{ $value('member_id') }}"></td>
</tr>
<tr>
<th>氏名<span class="text-danger ml-1">*</span></th>
<td><input type="text" name="user_name" class="form-control form-control-sm" value="{{ $value('user_name') }}" required></td>
</tr>
<tr>
<th>フリガナ</th>
<td><input type="text" name="user_phonetic" class="form-control form-control-sm" value="{{ $value('user_phonetic') }}"></td>
</tr>
<tr>
<th>パスワード</th>
<td>
<input type="password" name="user_pass" class="form-control form-control-sm" autocomplete="new-password">
<small class="form-text text-muted">未入力の場合は変更されません。</small>
</td>
</tr>
<tr>
<th>メインメールアドレス</th>
<td><input type="email" name="user_primemail" class="form-control form-control-sm" value="{{ $value('user_primemail') }}" placeholder="name@example.com"></td>
</tr>
<tr>
<th>予備メールアドレス</th>
<td><input type="email" name="user_submail" class="form-control form-control-sm" value="{{ $value('user_submail') }}" placeholder="name@example.com"></td>
</tr>
<tr>
<th>携帯電話番号</th>
<td><input type="text" name="user_mobile" class="form-control form-control-sm" value="{{ $value('user_mobile') }}" placeholder="080-0000-0000"></td>
</tr>
<tr>
<th>固定電話番号</th>
<td><input type="text" name="user_homephone" class="form-control form-control-sm" value="{{ $value('user_homephone') }}" placeholder="03-0000-0000"></td>
</tr>
<tr>
<th>性別</th>
<td>
@foreach (['男性','女性','未入力'] as $gender)
@php $id = 'user_gender_'.$gender; @endphp
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="{{ $id }}" name="user_gender" value="{{ $gender }}" class="custom-control-input" {{ $value('user_gender') === $gender ? 'checked' : '' }}>
<label class="custom-control-label" for="{{ $id }}">{{ $gender }}</label>
</div>
@endforeach
</td>
</tr>
<tr>
<th>生年月日</th>
<td><input type="date" name="user_birthdate" class="form-control form-control-sm" value="{{ $value('user_birthdate') }}"></td>
</tr>
<tr>
<th>年齢</th>
<td><input type="number" name="user_age" class="form-control form-control-sm" value="{{ $value('user_age') }}"></td>
</tr>
<tr>
<th>学校名</th>
<td><input type="text" name="user_school" class="form-control form-control-sm" value="{{ $value('user_school') }}"></td>
</tr>
<tr>
<th>卒業予定</th>
<td><input type="date" name="user_graduate" class="form-control form-control-sm" value="{{ $value('user_graduate') }}"></td>
</tr>
<tr>
<th>勤務先名</th>
<td><input type="text" name="user_workplace" class="form-control form-control-sm" value="{{ $value('user_workplace') }}"></td>
</tr>
<tr>
<th>区民区分</th>
<td><input type="text" name="ward_residents" class="form-control form-control-sm" value="{{ $value('ward_residents') }}"></td>
</tr>
<tr>
<th>本人確認書類</th>
<td><input type="text" name="user_idcard" class="form-control form-control-sm" value="{{ $value('user_idcard') }}"></td>
</tr>
<tr>
<th>本人確認チェック</th>
<td>
@foreach ([0 => '未チェック', 1 => '手動チェックOK'] as $flag => $label)
@php $id = 'user_idcard_chk_flag_'.$flag; @endphp
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="{{ $id }}" name="user_idcard_chk_flag" value="{{ $flag }}" class="custom-control-input" {{ (string)$value('user_idcard_chk_flag','0') === (string)$flag ? 'checked' : '' }}>
<label class="custom-control-label" for="{{ $id }}">{{ $label }}</label>
</div>
@endforeach
</td>
</tr>
<tr>
<th>本人確認日時</th>
<td><input type="date" name="user_chk_day" class="form-control form-control-sm" value="{{ $value('user_chk_day') }}"></td>
</tr>
<tr>
<th>本人確認オペレータ</th>
<td>
<select name="ope_id" class="form-control form-control-sm">
<option value="">本人確認オペレータID</option>
@foreach ($operators as $operator)
<option value="{{ $operator->ope_id }}" {{ (string) old('ope_id', $isEdit ? (string) ($user->ope_id ?? '') : '') === (string) $operator->ope_id ? 'selected' : '' }}>
{{ $operator->ope_name }}
</option>
@endforeach
</select>
</td>
</tr>
<tr>
<th>タグQRフラグ</th>
<td>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="tag_flag_qr" name="tag_qr_flag" value="1" class="custom-control-input" {{ $value('tag_qr_flag','0') === '1' ? 'checked' : '' }}>
<label class="custom-control-label" for="tag_flag_qr">QR</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="tag_flag_tag" name="tag_qr_flag" value="0" class="custom-control-input" {{ $value('tag_qr_flag','0') === '0' ? 'checked' : '' }}>
<label class="custom-control-label" for="tag_flag_tag">タグ</label>
</div>
</td>
</tr>
<tr>
<th>タグシリアル</th>
<td><input type="text" name="user_tag_serial" class="form-control form-control-sm" value="{{ $value('user_tag_serial') }}"></td>
</tr>
<tr>
<th>タグシリアル64進</th>
<td><input type="text" name="user_tag_serial_64" class="form-control form-control-sm" value="{{ $value('user_tag_serial_64') }}"></td>
</tr>
<tr>
<th>QRコード</th>
<td><input type="text" name="qr_code" class="form-control form-control-sm" value="{{ $value('qr_code') }}"></td>
</tr>
<tr>
<th>AID</th>
<td><input type="text" name="user_aid" class="form-control form-control-sm" value="{{ $value('user_aid') }}"></td>
</tr>
<tr>
<th>設置場所QRID</th>
<td><input type="text" name="user_place_qrid" class="form-control form-control-sm" value="{{ $value('user_place_qrid') }}"></td>
</tr>
<tr>
<th>利用者分類</th>
<td>
<select name="user_categoryid" class="form-control form-control-sm">
<option value="">選択してください</option>
@foreach ($categoryOptions as $id => $label)
<option value="{{ $id }}"
{{ (string) old('user_categoryid', $value('user_categoryid')) === (string) $id ? 'selected' : '' }}>
{{ $label }}
</option>
@endforeach
</select>
</td>
</tr>
<tr>
<th>タグ発行数</th>
<td><input type="number" name="user_tag_issue" class="form-control form-control-sm" value="{{ $value('user_tag_issue') }}"></td>
</tr>
<tr>
<th>タグ発行許可</th>
<td>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="issue_permission_ok" name="issue_permission" value="1" class="custom-control-input" {{ $value('issue_permission','1') === '1' ? 'checked' : '' }}>
<label class="custom-control-label" for="issue_permission_ok">許可</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="issue_permission_ng" name="issue_permission" value="0" class="custom-control-input" {{ $value('issue_permission','1') === '0' ? 'checked' : '' }}>
<label class="custom-control-label" for="issue_permission_ng">発行不可</label>
</div>
</td>
</tr>
<tr>
<th>退会フラグ</th>
<td>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="quit_flag_yes" name="user_quit_flag" value="1" class="custom-control-input" {{ $value('user_quit_flag','0') === '1' ? 'checked' : '' }}>
<label class="custom-control-label" for="quit_flag_yes">退会済</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="quit_flag_no" name="user_quit_flag" value="0" class="custom-control-input" {{ $value('user_quit_flag','0') === '0' ? 'checked' : '' }}>
<label class="custom-control-label" for="quit_flag_no">在籍</label>
</div>
</td>
</tr>
<tr>
<th>退会日</th>
<td><input type="date" name="user_quitday" class="form-control form-control-sm" value="{{ $value('user_quitday') }}"></td>
</tr>
<tr>
<th>現住所 郵便番号</th>
<td><input type="text" name="user_regident_zip" class="form-control form-control-sm" value="{{ $value('user_regident_zip') }}"></td>
</tr>
<tr>
<th>現住所 都道府県</th>
<td><input type="text" name="user_regident_pre" class="form-control form-control-sm" value="{{ $value('user_regident_pre') }}"></td>
</tr>
<tr>
<th>現住所 市区町村</th>
<td><input type="text" name="user_regident_city" class="form-control form-control-sm" value="{{ $value('user_regident_city') }}"></td>
</tr>
<tr>
<th>現住所 番地・建物名</th>
<td><input type="text" name="user_regident_add" class="form-control form-control-sm" value="{{ $value('user_regident_add') }}"></td>
</tr>
<tr>
<th>連絡先 郵便番号</th>
<td><input type="text" name="user_relate_zip" class="form-control form-control-sm" value="{{ $value('user_relate_zip') }}"></td>
</tr>
<tr>
<th>連絡先 都道府県</th>
<td><input type="text" name="user_relate_pre" class="form-control form-control-sm" value="{{ $value('user_relate_pre') }}"></td>
</tr>
<tr>
<th>連絡先 市区町村</th>
<td><input type="text" name="user_relate_city" class="form-control form-control-sm" value="{{ $value('user_relate_city') }}"></td>
</tr>
<tr>
<th>連絡先 番地・建物名</th>
<td><input type="text" name="user_relate_add" class="form-control form-control-sm" value="{{ $value('user_relate_add') }}"></td>
</tr>
<tr>
<th>本人確認書類ファイル1</th>
<td><input type="file" name="id_photo1" class="form-control-file"></td>
</tr>
<tr>
<th>本人確認書類ファイル2</th>
<td><input type="file" name="id_photo2" class="form-control-file"></td>
</tr>
<tr>
<th>備考</th>
<td><textarea name="user_remarks" rows="4" class="form-control form-control-sm">{{ $value('user_remarks') }}</textarea></td>
</tr>
</tbody>
</table>
</div>
<div class="card-footer d-flex justify-content-between align-items-center flex-wrap">
<a href="{{ route('users') }}" class="btn btn-outline-secondary">戻る</a>
<div class="btn-group">
@if ($isEdit && $hasDeleteRoute)
<button type="button" class="btn btn-outline-danger" id="btn-quit-bottom">退会</button>
@endif
<button type="submit" class="btn btn-success">登録</button>
</div>
</div>
</div>
</form>
@if ($isEdit && $hasDeleteRoute)
<form method="post" action="{{ route('users_delete_confirm') }}" id="quitForm" class="d-none">
@csrf
<input type="hidden" name="user_seq" value="{{ $user->user_seq }}">
</form>
@endif
</div>
</section>
@push('scripts')
@if ($isEdit && $hasDeleteRoute)
<script>
(function () {
const confirmQuit = function () {
if (window.confirm('この利用者を退会処理します。よろしいですか?')) {
document.getElementById('quitForm').submit();
}
};
const btnTop = document.getElementById('btn-quit-top');
const btnBottom = document.getElementById('btn-quit-bottom');
if (btnTop) { btnTop.addEventListener('click', confirmQuit); }
if (btnBottom) { btnBottom.addEventListener('click', confirmQuit); }
})();
</script>
@endif
@endpush
<style>
.table-form {
width: 100%;
border-collapse: separate;
border-spacing: 0;
}
.table-form th,
.table-form td {
border-bottom: 1px solid #e2e8f0;
padding: 14px 18px;
vertical-align: middle;
}
.table-form th {
width: 22%;
background: #f1f5f9;
font-weight: 600;
color: #334155;
}
.table-form td {
background: #ffffff;
}
.table-form .form-control-sm,
.table-form textarea.form-control-sm {
background: #ffffff;
}
.bg-secondary-light {
background: #f8fafc !important;
}
.card-footer .btn-group .btn + .btn {
margin-left: .5rem;
}
</style>
@endsection

View File

@ -1,8 +1,42 @@
@extends('layouts.app')
@section('title', '[東京都|〇〇駐輪場]利用者マスタ')
@section('title', '利用者マスタ')
@section('content')
@php
$curSort = $sort ?? request('sort', 'user_seq');
$curDir = strtolower($dir ?? request('dir', $sort_type ?? 'desc'));
if (!in_array($curDir, ['asc', 'desc'], true)) {
$curDir = 'desc';
}
$queryBase = collect([
'user_id' => $user_id ?? null,
'user_categoryid' => $user_categoryid ?? null,
'user_tag_serial' => $user_tag_serial ?? null,
'quit_flag' => $quit_flag ?? null,
'user_phonetic' => $user_phonetic ?? null,
'phone' => $phone ?? null,
'email' => $email ?? null,
'tag_qr_flag' => $tag_qr_flag ?? null,
'quit_from' => $quit_from ?? null,
'quit_to' => $quit_to ?? null,
])->filter(function ($value) {
return !is_null($value) && $value !== '';
})->all();
$thClass = function (string $key) use ($curSort, $curDir) {
if ($curSort !== $key) {
return 'sorting';
}
return $curDir === 'asc' ? 'sorting_asc' : 'sorting_desc';
};
$urlFor = function (string $key) use ($curSort, $curDir, $queryBase) {
$next = ($curSort === $key && $curDir === 'asc') ? 'desc' : 'asc';
return route('users', array_merge($queryBase, ['sort' => $key, 'dir' => $next]));
};
@endphp
{{-- コンテンツヘッダー(パンくず) --}}
<div class="content-header">
<div class="container-fluid">
@ -12,8 +46,7 @@
</div>
<div class="col-lg-6">
<ol class="breadcrumb float-sm-right text-sm">
<li class="breadcrumb-item"><a href="{{ route('home') }}">XX様info(ホーム)</a></li>
<li class="breadcrumb-item"><a href="./index3.html">[東京都|〇〇駐輪場]</a></li>
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
<li class="breadcrumb-item active">利用者マスタ</li>
</ol>
</div>
@ -24,6 +57,23 @@
<section class="content">
<div class="container-fluid">
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
@endif
@if (session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
{{ session('error') }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
@endif
{{-- ===================== 案内文図2 準拠) ===================== --}}
<p class="text-muted small mb-2">
<i class="fa fa-info-circle mr-1"></i>この画面のデータ修正等の必要はありません。
@ -35,11 +85,10 @@
<h3 class="card-title">絞り込みフィルター</h3>
</div>
<div class="card-body">
<form action="{{ route('users') }}" method="post" id="filter-form">
@csrf
<form action="{{ route('users') }}" method="get" id="filter-form">
{{-- ソート保持 --}}
<input type="hidden" name="sort" id="sort" value="{{ $sort }}">
<input type="hidden" name="sort_type" id="sort_type" value="{{ $sort_type }}">
<input type="hidden" name="dir" id="sort_type" value="{{ $curDir }}">
{{-- 1段目左右2カラム --}}
<div class="row">
@ -210,18 +259,26 @@
@csrf
<div id="users-list" class="table-responsive">
<table class="table table-bordered table-hover text-nowrap" style="min-width:1200px;">
<table class="table table-bordered table-hover text-nowrap table-users dataTable" style="min-width:1200px;">
<thead class="thead-light">
<tr>
<th style="width:110px;">利用者ID</th>
<th style="width:110px;" class="{{ $thClass('user_id') }}">
<a href="{{ $urlFor('user_id') }}" class="header-link">利用者ID</a>
</th>
<th style="width:110px;">タグ/QRフラグ</th>
<th style="width:140px;">利用者分類ID</th>
<th style="width:160px;">利用者名</th>
<th style="width:160px;">フリガナ</th>
<th style="width:160px;" class="{{ $thClass('user_phonetic') }}">
<a href="{{ $urlFor('user_phonetic') }}" class="header-link">フリガナ</a>
</th>
<th style="width:120px;">生年月日</th>
<th style="width:80px;">年齢</th>
<th style="width:140px;">携帯電話番号</th>
<th style="width:140px;">自宅電話番号</th>
<th style="width:140px;" class="{{ $thClass('user_mobile') }}">
<a href="{{ $urlFor('user_mobile') }}" class="header-link">携帯電話番号</a>
</th>
<th style="width:140px;" class="{{ $thClass('user_homephone') }}">
<a href="{{ $urlFor('user_homephone') }}" class="header-link">自宅電話番号</a>
</th>
<th style="width:220px;">メールアドレス</th>
<th style="width:140px;">本人確認書類</th>
<th style="width:150px;">本人確認チェック済</th>
@ -233,21 +290,25 @@
<tbody>
@forelse($list as $item)
@php
// ▼ 詳細/編集リンク生成(命名ルート優先)
$userInfoUrl = Route::has('user_info')
? route('user_info', ['seq' => $item->user_seq])
: (Route::has('users_info')
? route('users_info', ['id' => $item->user_seq])
: url('/users/info/' . $item->user_seq));
$userEditUrl = Route::has('users_edit')
? route('users_edit', ['seq' => $item->user_seq])
: (Route::has('user_edit')
? route('user_edit', ['seq' => $item->user_seq])
: url('/users/edit/' . $item->user_seq));
$chk = (string) ($item->user_idcard_chk_flag ?? '0');
@endphp
$categoryDisplay = collect([
$item->usertype_subject1 ?? '',
$item->usertype_subject2 ?? '',
$item->usertype_subject3 ?? '',
])->filter(fn ($v) => $v !== '')->implode('/');
@endphp
<tr>
{{-- 利用者IDリンク --}}
<td class="text-nowrap"><a href="{{ $userInfoUrl }}">{{ $item->user_id }}</a></td>
<td class="text-nowrap"><a href="{{ $userEditUrl }}">{{ $item->user_id }}</a></td>
{{-- タグQR --}}
<td>{{ $item->tag_qr_flag ? '' : 'タグ' }}</td>
{{-- 利用者分類ID氏名フリガナ --}}
<td>{{ $item->user_categoryid }}</td>
<td>{{ $categoryDisplay ?: $item->user_categoryid }}</td>
<td>{{ $item->user_name }}</td>
<td>{{ $item->user_phonetic }}</td>
{{-- 生年月日/年齢 --}}
@ -284,6 +345,20 @@
#users-list tfoot th {
background: #fff !important;
}
.table-users thead th .header-link {
color: #212529 !important;
text-decoration: none !important;
display: block;
white-space: nowrap;
padding-right: 1.8rem;
}
.table-users.dataTable thead th.sorting,
.table-users.dataTable thead th.sorting_asc,
.table-users.dataTable thead th.sorting_desc {
background-repeat: no-repeat;
background-position: right .6rem center !important;
padding-right: 1.8rem;
}
/* 斑馬柄などの行背景も抑止 */
#users-list .table-striped tbody tr:nth-of-type(odd),

View File

@ -218,7 +218,9 @@ Route::middleware('auth')->group(function () {
// 利用者マスタ
Route::match(['get', 'post'], '/users', [UsersController::class, 'list'])->name('users');
Route::match(['get', 'post'], '/users/add', [UsersController::class, 'add'])->name('users_add');
Route::match(['get', 'post'], '/users/edit/{seq}', [UsersController::class, 'edit'])->where(['seq' => '[0-9]+'])->name('users_edit');
Route::match(['get', 'post'], '/users/export', [UsersController::class, 'export'])->name('users_export');
Route::post('/users/delete-confirm', [UsersController::class, 'deleteConfirm'])->name('users_delete_confirm');
// 定期契約マスタ
Route::match(['get', 'post'], '/regularcontracts', [RegularContractController::class, 'list'])->name('regularcontracts');