feat(custom-field): tambahkan kolom label dan urutan prioritas

- Menambahkan kolom 'label' pada tabel custom_fields.
- Menambahkan kolom 'urutan_prioritas' pada tabel custom_fields.
- Memperbarui model CustomField untuk menyertakan kolom baru.
- Memperbarui form input untuk label dan urutan prioritas di tampilan create dan index.
- Menambahkan validasi untuk label dan urutan prioritas di CustomFieldRequest.
This commit is contained in:
Daeng Deni Mardaeni
2025-01-30 16:14:48 +07:00
parent b8a84bb7e1
commit 18cbb0bbc5
7 changed files with 251 additions and 136 deletions

View File

@@ -1,150 +1,153 @@
<?php <?php
namespace Modules\Lpj\Http\Controllers; namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel; use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\CustomFieldExport; use Modules\Lpj\Exports\CustomFieldExport;
use Modules\Lpj\Http\Requests\CustomFieldRequest; use Modules\Lpj\Http\Requests\CustomFieldRequest;
use Modules\Lpj\Models\CustomField; use Modules\Lpj\Models\CustomField;
class CustomFieldController extends Controller class CustomFieldController extends Controller
{
public $user;
public function index()
{ {
return view('lpj::custom_fields.index'); public $user;
}
public function store(CustomFieldRequest $request) public function index()
{ {
$validate = $request->validated(); return view('lpj::custom_fields.index');
}
if ($validate) { public function store(CustomFieldRequest $request)
try { {
// Save to database $validate = $request->validated();
CustomField::create($validate);
return redirect() if ($validate) {
->route('basicdata.custom-field.index') try {
->with('success', 'Custom Field created successfully'); // Save to database
} catch (Exception $e) { CustomField::create($validate);
return redirect() return redirect()
->route('basicdata.custom-field.create') ->route('basicdata.custom-field.index')
->with('error', $e->getMessage()); ->with('success', 'Custom Field created successfully');
} catch (Exception $e) {
return redirect()
->route('basicdata.custom-field.create')
->with('error', $e->getMessage());
}
} }
} }
}
public function create() public function create()
{ {
return view('lpj::custom_fields.create'); $urutan_prioritas = CustomField::max('urutan_prioritas')+1;
} return view('lpj::custom_fields.create', compact('urutan_prioritas'));
public function edit($id)
{
$customField = CustomField::find($id);
return view('lpj::custom_fields.create', compact('customField'));
}
public function update(CustomFieldRequest $request, $id)
{
$validate = $request->validated();
if ($validate) {
try {
// Update in database
$customField = CustomField::find($id);
$customField->update($validate);
return redirect()
->route('basicdata.custom-field.index')
->with('success', 'Custom Field updated successfully');
} catch (Exception $e) {
return redirect()
->route('basicdata.custom-field.edit', $id)
->with('error', 'Failed to update custom field');
}
} }
}
public function destroy($id) public function edit($id)
{ {
try {
// Delete from database
$customField = CustomField::find($id); $customField = CustomField::find($id);
$customField->delete(); $urutan_prioritas = $customField->urutan_prioritas ?? CustomField::max('urutan_prioritas')+1;
return view('lpj::custom_fields.create', compact('customField', 'urutan_prioritas' ));
}
echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']); public function update(CustomFieldRequest $request, $id)
} catch (Exception $e) { {
echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']); $validate = $request->validated();
if ($validate) {
try {
// Update in database
$customField = CustomField::find($id);
$customField->update($validate);
return redirect()
->route('basicdata.custom-field.index')
->with('success', 'Custom Field updated successfully');
} catch (Exception $e) {
return redirect()
->route('basicdata.custom-field.edit', $id)
->with('error', 'Failed to update custom field');
}
}
}
public function destroy($id)
{
try {
// Delete from database
$customField = CustomField::find($id);
$customField->delete();
echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']);
}
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('custom_fields.view')) {
//abort(403, 'Sorry! You are not allowed to view custom fields.');
}
// Retrieve data from the database
$query = CustomField::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%");
$q->orWhere('label', 'LIKE', "%$search%");
$q->orWhere('type', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
return Excel::download(new CustomFieldExport, 'custom_fields.xlsx');
} }
} }
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('custom_fields.view')) {
//abort(403, 'Sorry! You are not allowed to view custom fields.');
}
// Retrieve data from the database
$query = CustomField::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%");
$q->orWhere('type', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
return Excel::download(new CustomFieldExport, 'custom_fields.xlsx');
}
}

View File

@@ -3,6 +3,8 @@
namespace Modules\Lpj\Http\Requests; namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Modules\Lpj\Models\customField;
use Illuminate\Validation\Rule;
class CustomFieldRequest extends FormRequest class CustomFieldRequest extends FormRequest
{ {
@@ -14,6 +16,12 @@ class CustomFieldRequest extends FormRequest
return [ return [
'name' => 'required|max:255', 'name' => 'required|max:255',
'type' => 'required|in:text,select,radio,checkbox', 'type' => 'required|in:text,select,radio,checkbox',
'label' => 'nullable|max:255',
'urutan_prioritas' => [
'nullable',
'integer',
Rule::unique('custom_fields')->ignore($this->route('custom_field')),
],
]; ];
} }
@@ -29,5 +37,22 @@ class CustomFieldRequest extends FormRequest
if(!$this->type){ if(!$this->type){
$this->merge(['type' => 'text']); $this->merge(['type' => 'text']);
} }
if (!$this->urutan_prioritas) {
$maxPrioritas = CustomField::max('urutan_prioritas') ?? 0;
$this->merge(['urutan_prioritas' => $maxPrioritas + 1]);
}
}
/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [
'urutan_prioritas.unique' => 'Urutan prioritas sudah digunakan. Silakan pilih nomor lain.',
];
} }
} }

View File

@@ -14,7 +14,9 @@ class customField extends Base
*/ */
protected $fillable = [ protected $fillable = [
'name', 'name',
'type' 'type',
'urutan_prioritas',
'label'
]; ];
// protected static function newFactory(): CustomFieldFactory // protected static function newFactory(): CustomFieldFactory

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->integer('urutan_prioritas')->nullable()->after('type');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->dropColumn('urutan_prioritas');
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->string('label')->nullable()->after('name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->dropColumn('label');
});
}
};

View File

@@ -39,6 +39,17 @@
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Label
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('label') border-danger bg-danger-light @enderror" type="text" name="label" value="{{ $customField->label ?? '' }}">
@error('label')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Type Type
@@ -55,6 +66,17 @@
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Urutan Prioritas
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('urutan_prioritas') border-danger bg-danger-light @enderror" type="number" name="urutan_prioritas" value="{{ $customField->urutan_prioritas ?? $urutan_prioritas }}">
@error('urutan_prioritas')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex justify-end"> <div class="flex justify-end">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
Save Save

View File

@@ -40,6 +40,10 @@
<span class="sort"> <span class="sort-label"> Type </span> <span class="sort"> <span class="sort-label"> Type </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[250px]" data-datatable-column="urutan_prioritas">
<span class="sort"> <span class="sort-label"> Urutan Prioritas </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th> <th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr> </tr>
</thead> </thead>
@@ -113,12 +117,15 @@
return checkbox.outerHTML.trim(); return checkbox.outerHTML.trim();
}, },
}, },
name: { label: {
title: 'Custom Field', title: 'Custom Field',
}, },
type: { type: {
title: 'Type', title: 'Type',
}, },
urutan_prioritas: {
title: 'Urutan Prioritas',
},
actions: { actions: {
title: 'Status', title: 'Status',
render: (item, data) => { render: (item, data) => {