add feature to group region company

twopenny
ajikamaludin 2 years ago
parent b377d4fbb6
commit f633cf9f7f

@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers;
use App\Models\Group;
use Illuminate\Http\Request;
class GroupController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return inertia('Group/Index', [
'groups' => 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();
}
}

@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers;
use App\Models\Group;
use App\Models\Region;
use Illuminate\Http\Request;
class RegionController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return inertia('Region/Index', [
'regions' => 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();
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Company extends Model
{
use HasFactory;
protected $fillable = [
"region_id",
"name",
"short"
];
public function users()
{
return $this->hasMany(User::class);
}
}

@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Group extends Model
{
use HasFactory;
protected $fillable = [
"name"
];
public function regions()
{
return $this->hasMany(Region::class);
}
}

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Region extends Model
{
use HasFactory;
protected $fillable = [
"name",
"group_id",
];
public function group()
{
return $this->belongsTo(Group::class);
}
public function companies()
{
return $this->hasMany(Company::class);
}
}

@ -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();
});

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('groups', function (Blueprint $table) {
$table->id();
$table->string("name");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('groups');
}
};

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('regions', function (Blueprint $table) {
$table->id();
$table->foreignId("group_id")->constrained();
$table->string("name");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('regions');
}
};

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->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');
}
};

@ -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'],
];

@ -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 }) {
<div className="px-2">
<a className="text-xl font-bold">Monitor Doc</a>
</div>
<div className="sm:flex flex-1 px-6 hidden">
<div className="sm:flex px-6 hidden">
<div className="flex items-stretch gap-2">
{routes.filter(r => r.show).map((item, index) => (
<div key={index}>

@ -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 (
<div
className="modal modal-bottom sm:modal-middle pb-10"
style={
modalState.isOpen
? {
opacity: 1,
pointerEvents: 'auto',
visibility: 'visible',
overflowY: 'initial',
}
: {}
}
>
<div className="modal-box overflow-y-auto max-h-screen">
<h1 className="font-bold text-2xl pb-8">Group</h1>
<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Nama</span>
</label>
<input
type="text"
placeholder="nama"
className={`input input-bordered ${
errors.name && 'input-error'
}`}
name="name"
value={data.name}
onChange={handleOnChange}
/>
<label className="label">
<span className="label-text-alt text-red-600">{errors.name}</span>
</label>
</div>
<div className="modal-action">
<div
onClick={handleSubmit}
className="btn btn-primary"
disabled={processing}
>
Simpan
</div>
<div
onClick={handleCancel}
className="btn btn-secondary"
disabled={processing}
>
Batal
</div>
</div>
</div>
</div>
)
}

@ -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 (
<AuthenticatedLayout
auth={props.auth}
errors={props.errors}
flash={props.flash}
notify={props.notify}
>
<Head title="Roles" />
<div className="flex flex-col w-full sm:px-6 lg:px-8 space-y-2">
<div className="card bg-base-100 w-full">
<div className="card-body">
<div className="flex w-full mb-4 justify-between">
{canCreate && (
<div
className="btn btn-neutral"
onClick={() => toggle()}
>
Tambah
</div>
)}
</div>
<div className="overflow-x-auto">
<table className="table w-full table-zebra">
<thead>
<tr>
<th>Id</th>
<th>Nama</th>
<th></th>
</tr>
</thead>
<tbody>
{groups?.map((group) => (
<tr key={group.id}>
<th>{group.id}</th>
<td>{group.name}</td>
<td className="text-right">
{canUpdate && (
<div
className="btn btn-primary mx-1"
onClick={() =>
toggle(group)
}
>
Edit
</div>
)}
{canDelete && (
<div
className="btn btn-secondary mx-1"
onClick={() =>
handleDelete(group)
}
>
Delete
</div>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
<Pagination links={links} />
</div>
</div>
</div>
<FormModal
modalState={formModal}
/>
<ModalConfirm
isOpen={confirmModal.isOpen}
toggle={confirmModal.toggle}
onConfirm={onDelete}
/>
</AuthenticatedLayout>
)
}

@ -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 (
<div
className="modal modal-bottom sm:modal-middle pb-10"
style={
modalState.isOpen
? {
opacity: 1,
pointerEvents: 'auto',
visibility: 'visible',
overflowY: 'initial',
}
: {}
}
>
<div className="modal-box overflow-y-auto max-h-screen">
<h1 className="font-bold text-2xl pb-8">Region</h1>
<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Nama</span>
</label>
<input
type="text"
placeholder="nama"
className={`input input-bordered ${
errors.name && 'input-error'
}`}
name="name"
value={data.name}
onChange={handleOnChange}
/>
<label className="label">
<span className="label-text-alt text-red-600">{errors.name}</span>
</label>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Group</span>
</label>
<select
className={`select select-bordered w-full ${
errors.group_id && 'select-error'
}`}
name='group_id'
value={data.group_id}
onChange={handleOnChange}
>
<option disabled value=""></option>
{groups.map(group => (
<option key={group.id} value={group.id}>{group.name}</option>
))}
</select>
<label className="label">
<span className="label-text-alt">
{errors.group_id}
</span>
</label>
</div>
<div className="modal-action">
<div
onClick={handleSubmit}
className="btn btn-primary"
disabled={processing}
>
Simpan
</div>
<div
onClick={handleCancel}
className="btn btn-secondary"
disabled={processing}
>
Batal
</div>
</div>
</div>
</div>
)
}

@ -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 (
<AuthenticatedLayout
auth={props.auth}
errors={props.errors}
flash={props.flash}
notify={props.notify}
>
<Head title="Roles" />
<div className="flex flex-col w-full sm:px-6 lg:px-8 space-y-2">
<div className="card bg-base-100 w-full">
<div className="card-body">
<div className="flex w-full mb-4 justify-between">
{canCreate && (
<div
className="btn btn-neutral"
onClick={() => toggle()}
>
Tambah
</div>
)}
</div>
<div className="overflow-x-auto">
<table className="table w-full table-zebra">
<thead>
<tr>
<th>Id</th>
<th>Nama</th>
<th>Group</th>
<th></th>
</tr>
</thead>
<tbody>
{regions?.map((region) => (
<tr key={region.id}>
<th>{region.id}</th>
<td>{region.name}</td>
<td>{region.group.name}</td>
<td className="text-right">
{canUpdate && (
<div
className="btn btn-primary mx-1"
onClick={() =>
toggle(region)
}
>
Edit
</div>
)}
{canDelete && (
<div
className="btn btn-secondary mx-1"
onClick={() =>
handleDelete(region)
}
>
Delete
</div>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
<Pagination links={links} />
</div>
</div>
</div>
<FormModal
modalState={formModal}
/>
<ModalConfirm
isOpen={confirmModal.isOpen}
toggle={confirmModal.toggle}
onConfirm={onDelete}
/>
</AuthenticatedLayout>
)
}

@ -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');

Loading…
Cancel
Save