From f633cf9f7f496cba31f0c5fbafe22aac6af16fbc Mon Sep 17 00:00:00 2001 From: ajikamaludin Date: Mon, 30 Jan 2023 14:52:34 +0700 Subject: [PATCH] add feature to group region company --- app/Http/Controllers/GroupController.php | 70 +++++++++ app/Http/Controllers/RegionController.php | 78 ++++++++++ app/Models/Company.php | 22 +++ app/Models/Group.php | 20 +++ app/Models/Region.php | 26 ++++ .../2014_10_12_000000_create_users_table.php | 5 +- .../2022_01_30_141034_create_groups_table.php | 32 ++++ ...2022_01_30_141046_create_regions_table.php | 33 +++++ ...22_01_30_141103_create_companies_table.php | 34 +++++ database/seeders/DatabaseSeeder.php | 12 ++ resources/js/Layouts/AuthenticatedLayout.jsx | 7 +- resources/js/Pages/Group/FormModal.jsx | 112 ++++++++++++++ resources/js/Pages/Group/Index.jsx | 118 +++++++++++++++ resources/js/Pages/Region/FormModal.jsx | 138 ++++++++++++++++++ resources/js/Pages/Region/Index.jsx | 120 +++++++++++++++ routes/web.php | 12 ++ 16 files changed, 836 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/GroupController.php create mode 100644 app/Http/Controllers/RegionController.php create mode 100644 app/Models/Company.php create mode 100644 app/Models/Group.php create mode 100644 app/Models/Region.php create mode 100644 database/migrations/2022_01_30_141034_create_groups_table.php create mode 100644 database/migrations/2022_01_30_141046_create_regions_table.php create mode 100644 database/migrations/2022_01_30_141103_create_companies_table.php create mode 100644 resources/js/Pages/Group/FormModal.jsx create mode 100644 resources/js/Pages/Group/Index.jsx create mode 100644 resources/js/Pages/Region/FormModal.jsx create mode 100644 resources/js/Pages/Region/Index.jsx diff --git a/app/Http/Controllers/GroupController.php b/app/Http/Controllers/GroupController.php new file mode 100644 index 0000000..dc95014 --- /dev/null +++ b/app/Http/Controllers/GroupController.php @@ -0,0 +1,70 @@ + Group::paginate(), + ]); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:255' + ]); + + Group::create(['name' => $request->name]); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, Group $group) + { + $request->validate([ + 'name' => 'required|string|max:255' + ]); + + $group->update(['name' => $request->name]); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy(Group $group) + { + $group->regions()->each(function ($region) { + $region->companies()->each(function($company) { + $company->users()->delete(); + }); + $region->companies()->delete(); + }); + $group->regions()->delete(); + $group->delete(); + } +} diff --git a/app/Http/Controllers/RegionController.php b/app/Http/Controllers/RegionController.php new file mode 100644 index 0000000..967780a --- /dev/null +++ b/app/Http/Controllers/RegionController.php @@ -0,0 +1,78 @@ + Region::with(['group'])->paginate(), + 'groups' => Group::all(), + ]); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:255', + 'group_id' => 'required|exists:groups,id' + ]); + + Region::create([ + 'group_id' => $request->group_id, + 'name' => $request->name + ]); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, Region $region) + { + $request->validate([ + 'name' => 'required|string|max:255', + 'group_id' => 'required|exists:groups,id' + ]); + + $region->update([ + 'group_id' => $request->group_id, + 'name' => $request->name + ]); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy(Region $region) + { + $region->companies()->each(function($company) { + $company->users()->delete(); + }); + $region->companies()->delete(); + + $region->delete(); + } +} diff --git a/app/Models/Company.php b/app/Models/Company.php new file mode 100644 index 0000000..75d51d7 --- /dev/null +++ b/app/Models/Company.php @@ -0,0 +1,22 @@ +hasMany(User::class); + } +} diff --git a/app/Models/Group.php b/app/Models/Group.php new file mode 100644 index 0000000..ac947f1 --- /dev/null +++ b/app/Models/Group.php @@ -0,0 +1,20 @@ +hasMany(Region::class); + } +} diff --git a/app/Models/Region.php b/app/Models/Region.php new file mode 100644 index 0000000..23e1990 --- /dev/null +++ b/app/Models/Region.php @@ -0,0 +1,26 @@ +belongsTo(Group::class); + } + + public function companies() + { + return $this->hasMany(Company::class); + } +} diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index ec17533..69fcd21 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -20,8 +20,9 @@ return new class extends Migration { $table->string('password'); $table->smallInteger('is_admin')->default(0); $table->bigInteger('role_id')->nullable(); - $table->string('group')->nullable(); - $table->string('region')->nullable(); + // $table->string('group')->nullable(); + // $table->string('region')->nullable(); + $table->bigInteger("company_id")->nullable(); $table->rememberToken(); $table->timestamps(); }); diff --git a/database/migrations/2022_01_30_141034_create_groups_table.php b/database/migrations/2022_01_30_141034_create_groups_table.php new file mode 100644 index 0000000..8157c27 --- /dev/null +++ b/database/migrations/2022_01_30_141034_create_groups_table.php @@ -0,0 +1,32 @@ +id(); + $table->string("name"); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('groups'); + } +}; diff --git a/database/migrations/2022_01_30_141046_create_regions_table.php b/database/migrations/2022_01_30_141046_create_regions_table.php new file mode 100644 index 0000000..ecf0e6a --- /dev/null +++ b/database/migrations/2022_01_30_141046_create_regions_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignId("group_id")->constrained(); + $table->string("name"); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('regions'); + } +}; diff --git a/database/migrations/2022_01_30_141103_create_companies_table.php b/database/migrations/2022_01_30_141103_create_companies_table.php new file mode 100644 index 0000000..faa7fa7 --- /dev/null +++ b/database/migrations/2022_01_30_141103_create_companies_table.php @@ -0,0 +1,34 @@ +id(); + $table->foreignId("region_id")->constrained(); + $table->string("name"); + $table->string("short"); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('companies'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 2fa9e9e..bd8ddea 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -57,6 +57,18 @@ class DatabaseSeeder extends Seeder ['name' => 'update-user', 'label' => 'Edit User'], ['name' => 'create-user', 'label' => 'Buat User'], ['name' => 'delete-user', 'label' => 'Hapus User'], + ['name' => 'view-group', 'label' => 'Lihat Group'], + ['name' => 'update-group', 'label' => 'Edit Group'], + ['name' => 'create-group', 'label' => 'Buat Group'], + ['name' => 'delete-group', 'label' => 'Hapus Group'], + ['name' => 'view-region', 'label' => 'Lihat Region'], + ['name' => 'update-region', 'label' => 'Edit Region'], + ['name' => 'create-region', 'label' => 'Buat Region'], + ['name' => 'delete-region', 'label' => 'Hapus Region'], + ['name' => 'view-company', 'label' => 'Lihat Perusahaan'], + ['name' => 'update-company', 'label' => 'Edit Perusahaan'], + ['name' => 'create-company', 'label' => 'Buat Perusahaan'], + ['name' => 'delete-company', 'label' => 'Hapus Perusahaan'], ['name' => 'view-setting', 'label' => 'Setting'], ]; diff --git a/resources/js/Layouts/AuthenticatedLayout.jsx b/resources/js/Layouts/AuthenticatedLayout.jsx index 1e9702d..d4e0b5f 100644 --- a/resources/js/Layouts/AuthenticatedLayout.jsx +++ b/resources/js/Layouts/AuthenticatedLayout.jsx @@ -13,6 +13,11 @@ const rs = [ {name: "Ketegori", route: 'categories.index', show: true, permission: 'view-category'}, {name: "Jenis", route: 'types.index', show: true, permission: 'view-type'}, ]}, + {name: "Perusahaan", show: true, items: [ + {name:"Group", route: "groups.index", show: true, permission: 'view-group'}, + {name:"Region", route: "regions.index", show: true, permission: 'view-region'}, + {name:"Perusahaan", route: "groups.index", show: true, permission: 'view-company'}, + ]}, {name: "User", show: true, items: [ {name:"User", route: "users.index", show: true, permission: 'view-user'}, {name:"Role", route: "roles.index", show: true, permission: 'view-role'}, @@ -54,7 +59,7 @@ export default function Authenticated({ auth, children, flash, notify }) {
Monitor Doc
-
+
{routes.filter(r => r.show).map((item, index) => (
diff --git a/resources/js/Pages/Group/FormModal.jsx b/resources/js/Pages/Group/FormModal.jsx new file mode 100644 index 0000000..7ba422e --- /dev/null +++ b/resources/js/Pages/Group/FormModal.jsx @@ -0,0 +1,112 @@ +import React, { useEffect } from 'react' +import { useForm, usePage } from '@inertiajs/react' +import { toast } from 'react-toastify' + +export default function FormModal(props) { + const { modalState } = props + + const { data, setData, post, put, processing, errors, reset, clearErrors } = useForm({ + name: '', + }) + + const handleOnChange = (event) => { + setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value); + } + + const handleReset = () => { + reset() + clearErrors() + modalState.setData(null) + } + + const handleCancel = () => { + handleReset() + modalState.toggle() + } + + const handleSubmit = () => { + const group = modalState.data + if(group !== null) { + put(route('groups.update', group), { + onSuccess: () => + Promise.all([ + handleReset(), + modalState.toggle(), + toast.success('The Data has been changed'), + ]), + }) + return + } + post(route('groups.store'), { + onSuccess: () => + Promise.all([ + handleReset(), + modalState.toggle(), + toast.success('The Data has been saved'), + ]), + }) + } + + useEffect(() => { + const group = modalState.data + if (group !== null) { + setData({ + name: group?.name, + }) + } + }, [modalState]) + + return ( +
+
+

Group

+
+ + + +
+
+
+ Simpan +
+
+ Batal +
+
+
+
+ ) +} \ No newline at end of file diff --git a/resources/js/Pages/Group/Index.jsx b/resources/js/Pages/Group/Index.jsx new file mode 100644 index 0000000..f561c6a --- /dev/null +++ b/resources/js/Pages/Group/Index.jsx @@ -0,0 +1,118 @@ +import React from 'react' +import { Head } from '@inertiajs/react' +import { router } from '@inertiajs/react' +import { toast } from 'react-toastify' + +import { useModalState } from '@/Hooks' +import { hasPermission } from '@/utils' +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import ModalConfirm from '@/Components/ModalConfirm' +import FormModal from './FormModal' + +export default function Types(props) { + const { data: groups, links } = props.groups + + const formModal = useModalState(false) + const toggle = (group = null) => { + formModal.setData(group) + formModal.toggle() + } + + const confirmModal = useModalState(false) + const handleDelete = (group) => { + confirmModal.setData(group) + confirmModal.toggle() + } + + const onDelete = () => { + const group = confirmModal.data + if(group != null) { + router.delete(route('groups.destroy', group), { + onSuccess: () => toast.success('The Data has been deleted'), + }) + } + } + + const canCreate = hasPermission('create-group', props.auth.user) + const canUpdate = hasPermission('update-group', props.auth.user) + const canDelete = hasPermission('delete-group', props.auth.user) + + return ( + + +
+
+
+
+ {canCreate && ( +
toggle()} + > + Tambah +
+ )} +
+
+ + + + + + + + + + {groups?.map((group) => ( + + + + + + ))} + +
IdNama
{group.id}{group.name} + {canUpdate && ( +
+ toggle(group) + } + > + Edit +
+ )} + {canDelete && ( +
+ handleDelete(group) + } + > + Delete +
+ )} +
+
+ +
+
+
+ + + +
+ ) +} \ No newline at end of file diff --git a/resources/js/Pages/Region/FormModal.jsx b/resources/js/Pages/Region/FormModal.jsx new file mode 100644 index 0000000..0c52452 --- /dev/null +++ b/resources/js/Pages/Region/FormModal.jsx @@ -0,0 +1,138 @@ +import React, { useEffect } from 'react' +import { useForm, usePage } from '@inertiajs/react' +import { toast } from 'react-toastify' + +export default function FormModal(props) { + const { modalState } = props + const { props: { groups } } = usePage() + + const { data, setData, post, put, processing, errors, reset, clearErrors } = useForm({ + name: '', + group_id: '' + }) + + const handleOnChange = (event) => { + setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value); + } + + const handleReset = () => { + reset() + clearErrors() + modalState.setData(null) + } + + const handleCancel = () => { + handleReset() + modalState.toggle() + } + + const handleSubmit = () => { + const region = modalState.data + if(region !== null) { + put(route('regions.update', region), { + onSuccess: () => + Promise.all([ + handleReset(), + modalState.toggle(), + toast.success('The Data has been changed'), + ]), + }) + return + } + post(route('regions.store'), { + onSuccess: () => + Promise.all([ + handleReset(), + modalState.toggle(), + toast.success('The Data has been saved'), + ]), + }) + } + + useEffect(() => { + const region = modalState.data + if (region !== null) { + setData({ + name: region?.name, + group_id: region?.group_id + }) + } + }, [modalState]) + + return ( +
+
+

Region

+
+ + + +
+
+ + + +
+
+
+ Simpan +
+
+ Batal +
+
+
+
+ ) +} \ No newline at end of file diff --git a/resources/js/Pages/Region/Index.jsx b/resources/js/Pages/Region/Index.jsx new file mode 100644 index 0000000..797fc1e --- /dev/null +++ b/resources/js/Pages/Region/Index.jsx @@ -0,0 +1,120 @@ +import React from 'react' +import { Head } from '@inertiajs/react' +import { router } from '@inertiajs/react' +import { toast } from 'react-toastify' + +import { useModalState } from '@/Hooks' +import { hasPermission } from '@/utils' +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import ModalConfirm from '@/Components/ModalConfirm' +import FormModal from './FormModal' + +export default function Types(props) { + const { data: regions, links } = props.regions + + const formModal = useModalState(false) + const toggle = (region = null) => { + formModal.setData(region) + formModal.toggle() + } + + const confirmModal = useModalState(false) + const handleDelete = (region) => { + confirmModal.setData(region) + confirmModal.toggle() + } + + const onDelete = () => { + const region = confirmModal.data + if(region != null) { + router.delete(route('regions.destroy', region), { + onSuccess: () => toast.success('The Data has been deleted'), + }) + } + } + + const canCreate = hasPermission('create-region', props.auth.user) + const canUpdate = hasPermission('update-region', props.auth.user) + const canDelete = hasPermission('delete-region', props.auth.user) + + return ( + + +
+
+
+
+ {canCreate && ( +
toggle()} + > + Tambah +
+ )} +
+
+ + + + + + + + + + + {regions?.map((region) => ( + + + + + + + ))} + +
IdNamaGroup
{region.id}{region.name}{region.group.name} + {canUpdate && ( +
+ toggle(region) + } + > + Edit +
+ )} + {canDelete && ( +
+ handleDelete(region) + } + > + Delete +
+ )} +
+
+ +
+
+
+ + + +
+ ) +} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 6e8f297..0accbad 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,7 +3,9 @@ use App\Http\Controllers\CategoryController; use App\Http\Controllers\DocumentController; use App\Http\Controllers\GeneralController; +use App\Http\Controllers\GroupController; use App\Http\Controllers\NotificationController; +use App\Http\Controllers\RegionController; use App\Http\Controllers\RoleController; use App\Http\Controllers\SettingController; use App\Http\Controllers\TypeController; @@ -40,6 +42,16 @@ Route::middleware(['auth'])->group(function () { Route::put('/roles/{role}', [RoleController::class, 'update'])->name('roles.update'); Route::delete('/roles/{role}', [RoleController::class, 'destroy'])->name('roles.destroy'); + Route::get('/groups', [GroupController::class, 'index'])->name('groups.index'); + Route::post('/groups', [GroupController::class, 'store'])->name('groups.store'); + Route::put('/groups/{group}', [GroupController::class, 'update'])->name('groups.update'); + Route::delete('/groups/{group}', [GroupController::class, 'destroy'])->name('groups.destroy'); + + Route::get('/regions', [RegionController::class, 'index'])->name('regions.index'); + Route::post('/regions', [RegionController::class, 'store'])->name('regions.store'); + Route::put('/regions/{region}', [RegionController::class, 'update'])->name('regions.update'); + Route::delete('/regions/{region}', [RegionController::class, 'destroy'])->name('regions.destroy'); + Route::get('/types', [TypeController::class, 'index'])->name('types.index'); Route::post('/types', [TypeController::class, 'store'])->name('types.store'); Route::put('/types/{type}', [TypeController::class, 'update'])->name('types.update');