feat(BylawDocument): enhance bylaw document forms with improved validation and file upload support

This commit is contained in:
2026-06-26 15:59:45 +03:30
parent 9cf6957675
commit f242b8936a
3 changed files with 382 additions and 28 deletions

View File

@@ -7,6 +7,7 @@ use App\Models\BylawDocument;
use App\Models\BylawLegalAuthority; use App\Models\BylawLegalAuthority;
use App\Models\BylawSubjectCategory; use App\Models\BylawSubjectCategory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class BylawDocumentController extends Controller class BylawDocumentController extends Controller
{ {
@@ -31,7 +32,29 @@ class BylawDocumentController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$data = $request->validate(['title' => 'required|string|max:1000', 'category_id' => 'nullable|exists:bylaw_subject_categories,id', 'approval_authority_id' => 'nullable|exists:bylaw_legal_authorities,id', 'approval_date' => 'nullable|date', 'promulgation_authority_id' => 'nullable|exists:bylaw_legal_authorities,id', 'promulgation_date' => 'nullable|date', 'promulgation_number' => 'nullable|string|max:100', 'official_gazette_number' => 'nullable|string|max:100', 'official_gazette_date' => 'nullable|date', 'execution_date' => 'nullable|date', 'bylaw_type' => 'required|in:executive,delegated,independent', 'global_status' => 'required|in:valid,explicitly_repealed,implicitly_repealed,annulled,expired,draft', 'pdf_file_path' => 'nullable|string|max:500', 'is_published' => 'nullable|boolean', 'description' => 'nullable|string']); $data = $request->validate([
'title' => 'required|string|max:1000',
'category_id' => 'nullable|exists:bylaw_subject_categories,id',
'approval_authority_id' => 'nullable|exists:bylaw_legal_authorities,id',
'approval_date' => 'nullable|date',
'promulgation_authority_id' => 'nullable|exists:bylaw_legal_authorities,id',
'promulgation_date' => 'nullable|date',
'promulgation_number' => 'nullable|string|max:100',
'official_gazette_number' => 'nullable|string|max:100',
'official_gazette_date' => 'nullable|date',
'execution_date' => 'nullable|date',
'bylaw_type' => 'required|in:executive,delegated,independent',
'global_status' => 'required|in:valid,explicitly_repealed,implicitly_repealed,annulled,expired,draft',
'pdf_file' => 'nullable|file|mimes:pdf|max:20480',
'pdf_file_path' => 'nullable|string|max:500',
'is_published' => 'nullable|boolean',
'description' => 'nullable|string',
]);
if ($request->hasFile('pdf_file')) {
$data['pdf_file_path'] = $request->file('pdf_file')->store('pdfs', 'public');
}
$data['is_published'] = $request->boolean('is_published'); $data['is_published'] = $request->boolean('is_published');
BylawDocument::create($data); BylawDocument::create($data);
@@ -53,7 +76,33 @@ class BylawDocumentController extends Controller
public function update(Request $request, BylawDocument $bylawDocument) public function update(Request $request, BylawDocument $bylawDocument)
{ {
$data = $request->validate(['title' => 'required|string|max:1000', 'category_id' => 'nullable|exists:bylaw_subject_categories,id', 'approval_authority_id' => 'nullable|exists:bylaw_legal_authorities,id', 'approval_date' => 'nullable|date', 'promulgation_authority_id' => 'nullable|exists:bylaw_legal_authorities,id', 'promulgation_date' => 'nullable|date', 'promulgation_number' => 'nullable|string|max:100', 'official_gazette_number' => 'nullable|string|max:100', 'official_gazette_date' => 'nullable|date', 'execution_date' => 'nullable|date', 'bylaw_type' => 'required|in:executive,delegated,independent', 'global_status' => 'required|in:valid,explicitly_repealed,implicitly_repealed,annulled,expired,draft', 'pdf_file_path' => 'nullable|string|max:500', 'is_published' => 'nullable|boolean', 'description' => 'nullable|string']); $data = $request->validate([
'title' => 'required|string|max:1000',
'category_id' => 'nullable|exists:bylaw_subject_categories,id',
'approval_authority_id' => 'nullable|exists:bylaw_legal_authorities,id',
'approval_date' => 'nullable|date',
'promulgation_authority_id' => 'nullable|exists:bylaw_legal_authorities,id',
'promulgation_date' => 'nullable|date',
'promulgation_number' => 'nullable|string|max:100',
'official_gazette_number' => 'nullable|string|max:100',
'official_gazette_date' => 'nullable|date',
'execution_date' => 'nullable|date',
'bylaw_type' => 'required|in:executive,delegated,independent',
'global_status' => 'required|in:valid,explicitly_repealed,implicitly_repealed,annulled,expired,draft',
'pdf_file' => 'nullable|file|mimes:pdf|max:20480',
'pdf_file_path' => 'nullable|string|max:500',
'is_published' => 'nullable|boolean',
'description' => 'nullable|string',
]);
if ($request->hasFile('pdf_file')) {
if ($bylawDocument->pdf_file_path && Storage::disk('public')->exists($bylawDocument->pdf_file_path)) {
Storage::disk('public')->delete($bylawDocument->pdf_file_path);
}
$data['pdf_file_path'] = $request->file('pdf_file')->store('pdfs', 'public');
}
$data['is_published'] = $request->boolean('is_published'); $data['is_published'] = $request->boolean('is_published');
$bylawDocument->update($data); $bylawDocument->update($data);

View File

@@ -1,15 +1,171 @@
@extends('admin.layouts.app') @extends('admin.layouts.app')
@section('content') @section('content')
<form method="post" action="{{ route('bylaw-document.store') }}">@csrf <div class="row">
<input class="form-control mb-2" name="title" placeholder="عنوان"> @include('admin.layouts.errors')
<select class="form-control mb-2" name="category_id"><option value="">دسته</option>@foreach($categories as $item)<option value="{{ $item->id }}">{{ $item->name }}</option>@endforeach</select>
<select class="form-control mb-2" name="approval_authority_id"><option value="">مرجع تصویب</option>@foreach($authorities as $item)<option value="{{ $item->id }}">{{ $item->name }}</option>@endforeach</select> <div class="col-lg-12">
<select class="form-control mb-2" name="promulgation_authority_id"><option value="">مرجع ابلاغ</option>@foreach($authorities as $item)<option value="{{ $item->id }}">{{ $item->name }}</option>@endforeach</select> <div class="card">
<input class="form-control mb-2" name="approval_date" type="date"><input class="form-control mb-2" name="promulgation_date" type="date"><input class="form-control mb-2" name="execution_date" type="date"> <div class="card-body">
<input class="form-control mb-2" name="promulgation_number" placeholder="شماره ابلاغیه"><input class="form-control mb-2" name="official_gazette_number" placeholder="شماره روزنامه رسمی"> <div class="d-flex align-items-start justify-content-between mb-4">
<select class="form-control mb-2" name="bylaw_type"><option value="executive">executive</option><option value="delegated">delegated</option><option value="independent">independent</option></select> <div>
<select class="form-control mb-2" name="global_status"><option value="valid">valid</option><option value="explicitly_repealed">explicitly_repealed</option><option value="implicitly_repealed">implicitly_repealed</option><option value="annulled">annulled</option><option value="expired">expired</option><option value="draft">draft</option></select> <h4 class="card-title mb-1">افزودن سند آیین‌نامه</h4>
<input class="form-control mb-2" name="pdf_file_path" placeholder="pdf path"> <p class="text-muted mb-0">اطلاعات سند را وارد کنید و در صورت نیاز فایل PDF را آپلود کنید.</p>
<textarea class="form-control mb-2" name="description"></textarea> </div>
<label><input type="checkbox" name="is_published" value="1" checked> منتشر شده</label> <a href="{{ route('bylaw-document.index') }}" class="btn btn-light">بازگشت به لیست</a>
<button class="btn btn-primary">ذخیره</button></form>@endsection </div>
<form method="post" action="{{ route('bylaw-document.store') }}" enctype="multipart/form-data">
@csrf
<div class="row">
<div class="col-md-8">
<div class="mb-3">
<label class="form-label" for="title">عنوان سند</label>
<input class="form-control" name="title" id="title" value="{{ old('title') }}" placeholder="عنوان رسمی و کامل سند">
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label" for="bylaw_type">نوع آیین‌نامه</label>
<select class="form-control" name="bylaw_type" id="bylaw_type">
<option value="executive" @selected(old('bylaw_type') === 'executive')>اجرایی</option>
<option value="delegated" @selected(old('bylaw_type') === 'delegated')>تفویضی</option>
<option value="independent" @selected(old('bylaw_type') === 'independent')>مستقل</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="category_id">دسته موضوعی</label>
<select class="form-control" name="category_id" id="category_id">
<option value="">بدون دسته</option>
@foreach($categories as $item)
<option value="{{ $item->id }}" @selected(old('category_id') == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="global_status">وضعیت کلی</label>
<select class="form-control" name="global_status" id="global_status">
<option value="valid" @selected(old('global_status', 'valid') === 'valid')>معتبر</option>
<option value="explicitly_repealed" @selected(old('global_status') === 'explicitly_repealed')>نسخ صریح</option>
<option value="implicitly_repealed" @selected(old('global_status') === 'implicitly_repealed')>نسخ ضمنی</option>
<option value="annulled" @selected(old('global_status') === 'annulled')>ابطال شده</option>
<option value="expired" @selected(old('global_status') === 'expired')>منقضی</option>
<option value="draft" @selected(old('global_status') === 'draft')>پیش‌نویس</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card border shadow-none">
<div class="card-body">
<h5 class="card-title mb-3">مرجع تصویب و ابلاغ</h5>
<div class="mb-3">
<label class="form-label" for="approval_authority_id">مرجع تصویب</label>
<select class="form-control" name="approval_authority_id" id="approval_authority_id">
<option value="">انتخاب مرجع</option>
@foreach($authorities as $item)
<option value="{{ $item->id }}" @selected(old('approval_authority_id') == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label" for="approval_date">تاریخ تصویب</label>
<input class="form-control" name="approval_date" id="approval_date" type="date" value="{{ old('approval_date') }}">
</div>
<div class="mb-3">
<label class="form-label" for="promulgation_authority_id">مرجع ابلاغ</label>
<select class="form-control" name="promulgation_authority_id" id="promulgation_authority_id">
<option value="">انتخاب مرجع</option>
@foreach($authorities as $item)
<option value="{{ $item->id }}" @selected(old('promulgation_authority_id') == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label class="form-label" for="promulgation_date">تاریخ ابلاغ</label>
<input class="form-control" name="promulgation_date" id="promulgation_date" type="date" value="{{ old('promulgation_date') }}">
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card border shadow-none">
<div class="card-body">
<h5 class="card-title mb-3">انتشار و اجرا</h5>
<div class="mb-3">
<label class="form-label" for="official_gazette_number">شماره روزنامه رسمی</label>
<input class="form-control" name="official_gazette_number" id="official_gazette_number" value="{{ old('official_gazette_number') }}" placeholder="مثلا 12345">
</div>
<div class="mb-3">
<label class="form-label" for="official_gazette_date">تاریخ انتشار در روزنامه رسمی</label>
<input class="form-control" name="official_gazette_date" id="official_gazette_date" type="date" value="{{ old('official_gazette_date') }}">
</div>
<div class="mb-3">
<label class="form-label" for="promulgation_number">شماره ابلاغیه</label>
<input class="form-control" name="promulgation_number" id="promulgation_number" value="{{ old('promulgation_number') }}" placeholder="شماره نامه یا ابلاغیه">
</div>
<div class="mb-0">
<label class="form-label" for="execution_date">تاریخ لازم‌الاجرا شدن</label>
<input class="form-control" name="execution_date" id="execution_date" type="date" value="{{ old('execution_date') }}">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="pdf_file">فایل PDF</label>
<input class="form-control" name="pdf_file" id="pdf_file" type="file" accept="application/pdf">
<small class="text-muted">اگر فایل PDF انتخاب شود، در مسیر `storage/app/public/pdfs` ذخیره می‌شود.</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="pdf_file_path">مسیر فایل PDF</label>
<input class="form-control" name="pdf_file_path" id="pdf_file_path" value="{{ old('pdf_file_path') }}" placeholder="در صورت وارد کردن دستی مسیر">
</div>
</div>
</div>
<div class="mb-4">
<label class="form-label" for="description">توضیحات</label>
<textarea class="form-control" name="description" id="description" rows="6" placeholder="یادداشت، تاریخچه یا توضیحات تکمیلی">{{ old('description') }}</textarea>
</div>
<div class="mb-4">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" name="is_published" id="is_published" value="1" @checked(old('is_published', true))>
<label class="form-check-label" for="is_published">سند منتشر شده باشد</label>
</div>
</div>
<div class="d-flex gap-2">
<button class="btn btn-primary px-4" type="submit">ذخیره</button>
<a href="{{ route('bylaw-document.index') }}" class="btn btn-secondary">انصراف</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -1,15 +1,164 @@
@extends('admin.layouts.app') @extends('admin.layouts.app')
@section('content') @section('content')
<form method="post" action="{{ route('bylaw-document.update', $bylawDocument) }}">@csrf @method('PUT') <div class="row">
<input class="form-control mb-2" name="title" value="{{ $bylawDocument->title }}"> @include('admin.layouts.errors')
<select class="form-control mb-2" name="category_id"><option value="">دسته</option>@foreach($categories as $item)<option value="{{ $item->id }}" @selected($bylawDocument->category_id===$item->id)>{{ $item->name }}</option>@endforeach</select>
<select class="form-control mb-2" name="approval_authority_id"><option value="">مرجع تصویب</option>@foreach($authorities as $item)<option value="{{ $item->id }}" @selected($bylawDocument->approval_authority_id===$item->id)>{{ $item->name }}</option>@endforeach</select> <div class="col-lg-12">
<select class="form-control mb-2" name="promulgation_authority_id"><option value="">مرجع ابلاغ</option>@foreach($authorities as $item)<option value="{{ $item->id }}" @selected($bylawDocument->promulgation_authority_id===$item->id)>{{ $item->name }}</option>@endforeach</select> <div class="card">
<input class="form-control mb-2" name="approval_date" type="date" value="{{ $bylawDocument->approval_date }}"><input class="form-control mb-2" name="promulgation_date" type="date" value="{{ $bylawDocument->promulgation_date }}"><input class="form-control mb-2" name="execution_date" type="date" value="{{ $bylawDocument->execution_date }}"> <div class="card-body">
<input class="form-control mb-2" name="promulgation_number" value="{{ $bylawDocument->promulgation_number }}"><input class="form-control mb-2" name="official_gazette_number" value="{{ $bylawDocument->official_gazette_number }}"> <div class="d-flex align-items-start justify-content-between mb-4">
<select class="form-control mb-2" name="bylaw_type">@foreach(['executive','delegated','independent'] as $type)<option value="{{ $type }}" @selected($bylawDocument->bylaw_type===$type)>{{ $type }}</option>@endforeach</select> <div>
<select class="form-control mb-2" name="global_status">@foreach(['valid','explicitly_repealed','implicitly_repealed','annulled','expired','draft'] as $status)<option value="{{ $status }}" @selected($bylawDocument->global_status===$status)>{{ $status }}</option>@endforeach</select> <h4 class="card-title mb-1">ویرایش سند آیین‌نامه</h4>
<input class="form-control mb-2" name="pdf_file_path" value="{{ $bylawDocument->pdf_file_path }}"> <p class="text-muted mb-0">اطلاعات شناسنامه‌ای، مرجع تصویب و وضعیت انتشار را در این بخش ویرایش کنید.</p>
<textarea class="form-control mb-2" name="description">{{ $bylawDocument->description }}</textarea> </div>
<label><input type="checkbox" name="is_published" value="1" @checked($bylawDocument->is_published)> منتشر شده</label> <a href="{{ route('bylaw-document.index') }}" class="btn btn-light">بازگشت به لیست</a>
<button class="btn btn-primary">بروزرسانی</button></form>@endsection </div>
<form method="post" action="{{ route('bylaw-document.update', $bylawDocument) }}">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-8">
<div class="mb-3">
<label class="form-label" for="title">عنوان سند</label>
<input class="form-control" name="title" id="title" value="{{ old('title', $bylawDocument->title) }}" placeholder="عنوان رسمی و کامل سند">
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label" for="bylaw_type">نوع آیین‌نامه</label>
<select class="form-control" name="bylaw_type" id="bylaw_type">
@foreach(['executive' => 'اجرایی', 'delegated' => 'تفویضی', 'independent' => 'مستقل'] as $value => $label)
<option value="{{ $value }}" @selected(old('bylaw_type', $bylawDocument->bylaw_type) === $value)>{{ $label }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="category_id">دسته موضوعی</label>
<select class="form-control" name="category_id" id="category_id">
<option value="">بدون دسته</option>
@foreach($categories as $item)
<option value="{{ $item->id }}" @selected(old('category_id', $bylawDocument->category_id) == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="global_status">وضعیت کلی</label>
<select class="form-control" name="global_status" id="global_status">
@foreach(['valid' => 'معتبر', 'explicitly_repealed' => 'نسخ صریح', 'implicitly_repealed' => 'نسخ ضمنی', 'annulled' => 'ابطال شده', 'expired' => 'منقضی', 'draft' => 'پیش‌نویس'] as $value => $label)
<option value="{{ $value }}" @selected(old('global_status', $bylawDocument->global_status) === $value)>{{ $label }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card border shadow-none">
<div class="card-body">
<h5 class="card-title mb-3">مرجع تصویب و ابلاغ</h5>
<div class="mb-3">
<label class="form-label" for="approval_authority_id">مرجع تصویب</label>
<select class="form-control" name="approval_authority_id" id="approval_authority_id">
<option value="">انتخاب مرجع</option>
@foreach($authorities as $item)
<option value="{{ $item->id }}" @selected(old('approval_authority_id', $bylawDocument->approval_authority_id) == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label" for="approval_date">تاریخ تصویب</label>
<input class="form-control" name="approval_date" id="approval_date" type="date" value="{{ old('approval_date', $bylawDocument->approval_date) }}">
</div>
<div class="mb-3">
<label class="form-label" for="promulgation_authority_id">مرجع ابلاغ</label>
<select class="form-control" name="promulgation_authority_id" id="promulgation_authority_id">
<option value="">انتخاب مرجع</option>
@foreach($authorities as $item)
<option value="{{ $item->id }}" @selected(old('promulgation_authority_id', $bylawDocument->promulgation_authority_id) == $item->id)>{{ $item->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label class="form-label" for="promulgation_date">تاریخ ابلاغ</label>
<input class="form-control" name="promulgation_date" id="promulgation_date" type="date" value="{{ old('promulgation_date', $bylawDocument->promulgation_date) }}">
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card border shadow-none">
<div class="card-body">
<h5 class="card-title mb-3">انتشار و اجرا</h5>
<div class="mb-3">
<label class="form-label" for="official_gazette_number">شماره روزنامه رسمی</label>
<input class="form-control" name="official_gazette_number" id="official_gazette_number" value="{{ old('official_gazette_number', $bylawDocument->official_gazette_number) }}" placeholder="مثلا 12345">
</div>
<div class="mb-3">
<label class="form-label" for="official_gazette_date">تاریخ انتشار در روزنامه رسمی</label>
<input class="form-control" name="official_gazette_date" id="official_gazette_date" type="date" value="{{ old('official_gazette_date', $bylawDocument->official_gazette_date) }}">
</div>
<div class="mb-3">
<label class="form-label" for="promulgation_number">شماره ابلاغیه</label>
<input class="form-control" name="promulgation_number" id="promulgation_number" value="{{ old('promulgation_number', $bylawDocument->promulgation_number) }}" placeholder="شماره نامه یا ابلاغیه">
</div>
<div class="mb-0">
<label class="form-label" for="execution_date">تاریخ لازم‌الاجرا شدن</label>
<input class="form-control" name="execution_date" id="execution_date" type="date" value="{{ old('execution_date', $bylawDocument->execution_date) }}">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="pdf_file_path">مسیر فایل PDF</label>
<input class="form-control" name="pdf_file_path" id="pdf_file_path" value="{{ old('pdf_file_path', $bylawDocument->pdf_file_path) }}" placeholder="/storage/...">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label d-block">وضعیت نمایش</label>
<div class="form-check form-switch mt-2">
<input class="form-check-input" type="checkbox" role="switch" name="is_published" id="is_published" value="1" @checked(old('is_published', $bylawDocument->is_published))>
<label class="form-check-label" for="is_published">این سند در سایت/اپلیکیشن نمایش داده شود</label>
</div>
</div>
</div>
</div>
<div class="mb-4">
<label class="form-label" for="description">توضیحات</label>
<textarea class="form-control" name="description" id="description" rows="6" placeholder="یادداشت، تاریخچه یا توضیحات تکمیلی">{{ old('description', $bylawDocument->description) }}</textarea>
</div>
<div class="d-flex gap-2">
<button class="btn btn-primary px-4" type="submit">بروزرسانی</button>
<a href="{{ route('bylaw-document.index') }}" class="btn btn-secondary">انصراف</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection