235 lines
9.3 KiB
PHP
235 lines
9.3 KiB
PHP
@extends('layouts.app')
|
||
@section('title', '最新ニュース登録')
|
||
|
||
@section('content')
|
||
@php
|
||
$modeLabel = [0=>'非表示', 1=>'公開', 2=>'下書き', 3=>'自動公開'];
|
||
|
||
$curSort = request('sort');
|
||
$curDir = strtolower(request('dir', 'desc'));
|
||
|
||
// DataTables と同一のクラスを付与(未選択: sorting / 昇順: sorting_asc / 降順: sorting_desc)
|
||
$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) {
|
||
$next = ($curSort === $key && $curDir === 'asc') ? 'desc' : 'asc';
|
||
return route('news', array_merge(request()->except('page'), ['sort'=>$key, 'dir'=>$next]));
|
||
};
|
||
@endphp
|
||
|
||
{{-- ▼ コンテンツヘッダー(パンくず) --}}
|
||
<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="{{ route('home') }}">ホーム</a></li>
|
||
<li class="breadcrumb-item active">最新ニュース登録</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<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">×</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">×</span>
|
||
</button>
|
||
</div>
|
||
@endif
|
||
|
||
<div class="card">
|
||
|
||
{{-- ▼ ヘッダー:新規/削除 --}}
|
||
<div class="card-header d-flex align-items-center">
|
||
<a href="{{ route('news_add') }}" class="btn btn-default mr-2">新規</a>
|
||
<button type="button" class="btn btn-default" id="delete_edit">削除</button>
|
||
</div>
|
||
|
||
{{-- ▼ 一覧テーブル --}}
|
||
<div class="card-body p-0">
|
||
<form id="form_delete" method="POST" action="{{ route('news_delete') }}">
|
||
@csrf
|
||
<div class="table-responsive">
|
||
<table class="table table-bordered text-nowrap mb-0 table-news dataTable">
|
||
<thead class="thead-light">
|
||
<tr>
|
||
<th class="col-actions">
|
||
<div class="actions-wrap">
|
||
<input type="checkbox" id="check-all">
|
||
<span class="text-muted" style="font-weight:normal;"></span>
|
||
</div>
|
||
</th>
|
||
|
||
{{-- ▼ 並び替え可能カラム(DataTables と同じクラスを使用) --}}
|
||
<th class="w-id {{ $thClass('id') }}">
|
||
<a href="{{ $urlFor('id') }}" class="header-link">ニュースID</a>
|
||
</th>
|
||
<th class="{{ $thClass('news') }}">
|
||
<a href="{{ $urlFor('news') }}" class="header-link">ニュース内容</a>
|
||
</th>
|
||
<th class="w-datetime {{ $thClass('open_datetime') }}">
|
||
<a href="{{ $urlFor('open_datetime') }}" class="header-link">公開日時</a>
|
||
</th>
|
||
<th class="w-url">リンクURL</th>
|
||
<th class="w-img">画像1URL</th>
|
||
<th class="w-img">画像2URL</th>
|
||
<th class="w-mode {{ $thClass('mode') }}">
|
||
<a href="{{ $urlFor('mode') }}" class="header-link">表示モード</a>
|
||
</th>
|
||
<th class="w-created">登録日時</th>
|
||
<th class="w-updated">更新日時</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@forelse($rows as $r)
|
||
<tr>
|
||
{{-- ▼ 統合セル--}}
|
||
<td style="background: #faebd7;">
|
||
<div class="actions-wrap">
|
||
<input type="checkbox" name="ids[]" value="{{ $r->id }}">
|
||
<a href="{{ route('news_edit', ['id' => $r->id]) }}"
|
||
class="btn btn-sm btn-default ml10">編集</a>
|
||
</div>
|
||
</td>
|
||
|
||
{{-- ▼ データ本体 --}}
|
||
<td class="w-id">{{ $r->id }}</td>
|
||
<td class="one-line" title="{{ $r->news }}">{{ \Illuminate\Support\Str::limit($r->news, 80) }}</td>
|
||
<td class="w-datetime">{{ $r->open_datetime }}</td>
|
||
<td class="w-url one-line" title="{{ $r->link_url }}">{{ $r->link_url }}</td>
|
||
<td class="w-img one-line" title="{{ $r->image1_filename }}">{{ $r->image1_filename }}</td>
|
||
<td class="w-img one-line" title="{{ $r->image2_filename }}">{{ $r->image2_filename }}</td>
|
||
<td class="w-mode">{{ $modeLabel[$r->mode] ?? $r->mode }}</td>
|
||
<td class="w-created">{{ $r->created_at }}</td>
|
||
<td class="w-updated">{{ $r->updated_at }}</td>
|
||
</tr>
|
||
@empty
|
||
<tr>
|
||
<td colspan="10" class="text-center text-muted">データがありません。</td>
|
||
</tr>
|
||
@endforelse
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
{{-- ▼ フッター:ページネーション右寄せ --}}
|
||
<div class="d-flex align-items-center p-3">
|
||
<div class="ml-auto">
|
||
{{ $rows->appends(request()->except('page'))->links('pagination::bootstrap-4') }}
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- jQuery Confirm(存在すれば使用。無ければ下のスクリプトで標準confirmへフォールバック) -->
|
||
<link rel="stylesheet" href="{{ asset('plugins/jquery-confirm/jquery-confirm.min.css') }}">
|
||
<script src="{{ asset('plugins/jquery-confirm/jquery-confirm.min.js') }}"></script>
|
||
|
||
<style>
|
||
/* 見出しの文字色を黒(リンクも黒・下線なし) */
|
||
.table-news thead th .header-link { color:#212529!important;text-decoration:none!important;display:block;white-space:nowrap;padding-right:1.8rem; }
|
||
/* DataTables の矢印位置を統一 */
|
||
.table-news.dataTable thead th.sorting,
|
||
.table-news.dataTable thead th.sorting_asc,
|
||
.table-news.dataTable thead th.sorting_desc { background-repeat:no-repeat;background-position:right .6rem center!important;padding-right:1.8rem; }
|
||
</style>
|
||
|
||
<script>
|
||
(function(){
|
||
// ▼ 全選択チェックボックスの処理
|
||
document.getElementById('check-all')?.addEventListener('change', function(e){
|
||
document.querySelectorAll('input[name="ids[]"]').forEach(function(el){ el.checked = e.target.checked; });
|
||
});
|
||
|
||
// ▼ 共通:削除対象が未選択の場合のアラート表示
|
||
function showNoSelection(){
|
||
if (window.jQuery && window.$ && $.confirm) {
|
||
$.confirm({
|
||
title: '確認ダイアログ。',
|
||
content: '削除対象が選択されていません。',
|
||
buttons: {
|
||
ok: { text: 'はい', btnClass: 'btn-primary' },
|
||
いいえ: function () {}
|
||
}
|
||
});
|
||
} else {
|
||
alert('削除対象が選択されていません。');
|
||
}
|
||
}
|
||
|
||
// ▼ 共通:削除確認ダイアログ表示
|
||
function showDeleteConfirm(onYes){
|
||
if (window.jQuery && window.$ && $.confirm) {
|
||
$.confirm({
|
||
title: '削除確認',
|
||
content: '削除してよろしいですか?',
|
||
buttons: {
|
||
ok: { text: 'はい', btnClass: 'btn-primary', action: function(){ if (typeof onYes==='function') onYes(); } },
|
||
いいえ: function () {}
|
||
}
|
||
});
|
||
} else {
|
||
if (confirm('削除してよろしいですか?')) { if (typeof onYes==='function') onYes(); }
|
||
}
|
||
}
|
||
|
||
// ▼ 削除ボタン(#delete_edit)のクリックイベント処理
|
||
// ①選択チェック → ②確認ダイアログ → ③削除フォーム送信
|
||
const delBtn = document.getElementById('delete_edit');
|
||
if (delBtn && delBtn.dataset.bound !== '1') {
|
||
delBtn.dataset.bound = '1'; // 二重バインド防止
|
||
|
||
// 捕捉段階で処理を実行し、他のリスナーによる重複ダイアログを防止
|
||
delBtn.addEventListener('click', function(e){
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
if (e.stopImmediatePropagation) e.stopImmediatePropagation();
|
||
|
||
const checked = document.querySelectorAll('input[name="ids[]"]:checked').length;
|
||
if (!checked) return showNoSelection();
|
||
|
||
const form = document.getElementById('form_delete');
|
||
if (!form) return;
|
||
|
||
showDeleteConfirm(function(){
|
||
// jQuery 側の submit イベントを回避して、ネイティブでフォーム送信
|
||
form.submit();
|
||
});
|
||
}, true);
|
||
}
|
||
|
||
// ▼ フラッシュメッセージ(成功/エラー)を5秒後に自動で非表示化
|
||
setTimeout(function(){
|
||
document.querySelectorAll('.alert-dismissible')?.forEach(function(el){
|
||
el.classList.remove('show');
|
||
el.style.display='none';
|
||
});
|
||
}, 5000);
|
||
})();
|
||
</script>
|
||
|
||
@endsection
|