lokasi done

dev
Aji Kamaludin 1 year ago
parent d9a40b1895
commit b709a716e4
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -6,7 +6,7 @@
- [x] CRUD Banner - [x] CRUD Banner
- [x] CRUD Rekening / Account - [x] CRUD Rekening / Account
- [x] CRUD Customer - [x] CRUD Customer
- [ ] CRUD Lokasi - [x] CRUD Lokasi
- [ ] CRUD Voucher - [ ] CRUD Voucher
- [ ] Import Voucher - [ ] Import Voucher
- [ ] Deposit Menu (view daftar histori deposit) - [ ] Deposit Menu (view daftar histori deposit)

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Customer;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Banner; use App\Models\Banner;
use App\Models\Info; use App\Models\Info;
use App\Models\Location;
class HomeController extends Controller class HomeController extends Controller
{ {
@ -12,10 +13,12 @@ class HomeController extends Controller
{ {
$infos = Info::where('is_publish', 1)->orderBy('updated_at', 'desc')->get(); $infos = Info::where('is_publish', 1)->orderBy('updated_at', 'desc')->get();
$banners = Banner::orderBy('updated_at', 'desc')->get(); $banners = Banner::orderBy('updated_at', 'desc')->get();
$locations = Location::get();
return inertia('Home/Index/Index', [ return inertia('Home/Index/Index', [
'infos' => $infos, 'infos' => $infos,
'banners' => $banners 'banners' => $banners,
'locations' => $locations
]); ]);
} }

@ -2,9 +2,71 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Location;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class LocationController extends Controller class LocationController extends Controller
{ {
// public function index()
{
$query = Location::paginate();
return inertia('Location/Index', [
'query' => $query,
]);
}
public function store(Request $request)
{
$request->validate([
'name' => 'required|string',
'description' => 'nullable|string',
'logo' => 'nullable|image',
]);
$logo = null;
if ($request->hasFile('midtrans_logo_file')) {
$file = $request->file('midtrans_logo_file');
$file->store('uploads', 'public');
$logo = $file->hashName('uploads');
}
Location::create([
'name' => $request->name,
'description' => $request->description,
'logo' => $logo,
]);
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed saved']);
}
public function update(Request $request, Location $location)
{
$request->validate([
'name' => 'required|string',
'description' => 'nullable|string',
'logo' => 'nullable|image',
]);
if ($request->hasFile('midtrans_logo_file')) {
$file = $request->file('midtrans_logo_file');
$file->store('uploads', 'public');
$location->logo = $file->hashName('uploads');
}
$location->update([
'name' => $request->name,
'description' => $request->description,
'logo' => $location->logo,
]);
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed updated']);
}
public function destroy(Location $location)
{
$location->delete();
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed deleted']);
}
} }

@ -5,6 +5,7 @@ namespace Database\Seeders;
use App\Models\Account; use App\Models\Account;
use App\Models\Banner; use App\Models\Banner;
use App\Models\Info; use App\Models\Info;
use App\Models\Location;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
class DummySeeder extends Seeder class DummySeeder extends Seeder
@ -19,6 +20,7 @@ class DummySeeder extends Seeder
$this->info(); $this->info();
$this->banner(); $this->banner();
$this->account(); $this->account();
$this->location();
} }
public function info() public function info()
@ -57,4 +59,16 @@ class DummySeeder extends Seeder
]); ]);
} }
} }
public function location()
{
$locations = ['Jarbriel.id', 'Shaff.net', 'Weslycamp.net', 'Glory.net', 'Salgo.id', 'Terna.id', 'Kanza.id'];
foreach ($locations as $location) {
Location::create([
'name' => $location,
'description' => '-'
]);
}
}
} }

@ -8,6 +8,7 @@ import {
} from 'react-icons/hi' } from 'react-icons/hi'
import { import {
HiBanknotes, HiBanknotes,
HiMap,
HiOutlineGlobeAlt, HiOutlineGlobeAlt,
HiQuestionMarkCircle, HiQuestionMarkCircle,
HiUserCircle, HiUserCircle,
@ -46,6 +47,14 @@ export default [
active: 'setting.*', active: 'setting.*',
permission: 'view-setting', permission: 'view-setting',
}, },
{
name: 'Lokasi',
show: true,
icon: HiMap,
route: route('location.index'),
active: 'location.*',
permission: 'view-location',
},
{ {
name: 'Front Home', name: 'Front Home',
show: true, show: true,

@ -29,7 +29,7 @@ const GuestBanner = () => {
) )
} }
export default function Index({ auth: { user }, infos, banners }) { export default function Index({ auth: { user }, infos, banners, locations }) {
const handleBanner = (banner) => { const handleBanner = (banner) => {
router.get(route('home.banner', banner)) router.get(route('home.banner', banner))
} }
@ -73,27 +73,15 @@ export default function Index({ auth: { user }, infos, banners }) {
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
{/* chips */} {/* chips */}
<div className="w-full flex flex-row overflow-y-scroll space-x-2 px-2"> <div className="w-full flex flex-row overflow-y-scroll space-x-2 px-2">
<div className="px-2 py-1 rounded-2xl text-white bg-blue-600 border border-blue-800"> {locations.map((location) => (
Jarbriel.id <div
</div> key={location.id}
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200"> // selected: px-2 py-1 rounded-2xl text-white bg-blue-600 border border-blue-800
Shaff.net className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200"
</div> >
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200"> {location.name}
Weslycamp.net </div>
</div> ))}
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200">
Glory.net
</div>
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200">
Salgo.id
</div>
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200">
Terna.id
</div>
<div className="px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200">
Kanza.id
</div>
</div> </div>
{/* voucher */} {/* voucher */}

@ -0,0 +1,91 @@
import React, { useEffect } from 'react'
import Modal from '@/Components/Modal'
import { useForm } from '@inertiajs/react'
import Button from '@/Components/Button'
import FormInput from '@/Components/FormInput'
import RoleSelectionInput from '../Role/SelectionInput'
import { isEmpty } from 'lodash'
export default function FormModal(props) {
const { modalState } = props
const { data, setData, post, put, processing, errors, reset, clearErrors } =
useForm({
name: '',
description: '',
})
const handleOnChange = (event) => {
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
? 1
: 0
: event.target.value
)
}
const handleReset = () => {
modalState.setData(null)
reset()
clearErrors()
}
const handleClose = () => {
handleReset()
modalState.toggle()
}
const handleSubmit = () => {
const location = modalState.data
if (location !== null) {
put(route('location.update', location), {
onSuccess: () => handleClose(),
})
return
}
post(route('location.store'), {
onSuccess: () => handleClose(),
})
}
useEffect(() => {
const location = modalState.data
if (isEmpty(location) === false) {
setData({
name: location.name,
description: location.description,
})
return
}
}, [modalState])
return (
<Modal isOpen={modalState.isOpen} toggle={handleClose} title={'Lokasi'}>
<FormInput
name="name"
value={data.name}
onChange={handleOnChange}
label="name"
error={errors.name}
/>
<FormInput
name="description"
value={data.description}
onChange={handleOnChange}
label="description"
error={errors.description}
/>
<div className="flex items-center">
<Button onClick={handleSubmit} processing={processing}>
Simpan
</Button>
<Button onClick={handleClose} type="secondary">
Batal
</Button>
</div>
</Modal>
)
}

@ -0,0 +1,164 @@
import React, { useEffect, useState } from 'react'
import { router } from '@inertiajs/react'
import { usePrevious } from 'react-use'
import { Head } from '@inertiajs/react'
import { Button, Dropdown } from 'flowbite-react'
import { HiPencil, HiTrash } from 'react-icons/hi'
import { useModalState } from '@/hooks'
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import Pagination from '@/Components/Pagination'
import ModalConfirm from '@/Components/ModalConfirm'
import FormModal from './FormModal'
import SearchInput from '@/Components/SearchInput'
import { hasPermission } from '@/utils'
export default function Index(props) {
const {
query: { links, data },
auth,
} = props
const confirmModal = useModalState()
const formModal = useModalState()
const toggleFormModal = (location = null) => {
formModal.setData(location)
formModal.toggle()
}
const handleDeleteClick = (location) => {
confirmModal.setData(location)
confirmModal.toggle()
}
const onDelete = () => {
if (confirmModal.data !== null) {
router.delete(route('location.destroy', confirmModal.data.id))
}
}
const canCreate = hasPermission(auth, 'create-location')
const canUpdate = hasPermission(auth, 'update-location')
const canDelete = hasPermission(auth, 'delete-location')
return (
<AuthenticatedLayout
auth={props.auth}
errors={props.errors}
flash={props.flash}
page={'Location'}
action={''}
>
<Head title="Location" />
<div>
<div className="mx-auto sm:px-6 lg:px-8 ">
<div className="p-6 overflow-hidden shadow-sm sm:rounded-lg bg-gray-200 dark:bg-gray-800 space-y-4">
<div className="flex justify-between">
{canCreate && (
<Button
size="sm"
onClick={() => toggleFormModal()}
>
Tambah
</Button>
)}
</div>
<div className="overflow-auto">
<div>
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 mb-4">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th
scope="col"
className="py-3 px-6"
>
Name
</th>
<th
scope="col"
className="py-3 px-6"
>
Description
</th>
<th
scope="col"
className="py-3 px-6"
/>
</tr>
</thead>
<tbody>
{data.map((location) => (
<tr
className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
key={location.id}
>
<td
scope="row"
className="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
{location.name}
</td>
<td className="py-4 px-6">
{location.description}
</td>
<td className="py-4 px-6 flex justify-end">
<Dropdown
label={'Opsi'}
floatingArrow={true}
arrowIcon={true}
dismissOnClick={true}
size={'sm'}
>
{canUpdate && (
<Dropdown.Item
onClick={() =>
toggleFormModal(
location
)
}
>
<div className="flex space-x-1 items-center">
<HiPencil />
<div>
Ubah
</div>
</div>
</Dropdown.Item>
)}
{canDelete && (
<Dropdown.Item
onClick={() =>
handleDeleteClick(
location
)
}
>
<div className="flex space-x-1 items-center">
<HiTrash />
<div>
Hapus
</div>
</div>
</Dropdown.Item>
)}
</Dropdown>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="w-full flex items-center justify-center">
<Pagination links={links} />
</div>
</div>
</div>
</div>
</div>
<ModalConfirm modalState={confirmModal} onConfirm={onDelete} />
<FormModal modalState={formModal} />
</AuthenticatedLayout>
)
}

@ -6,6 +6,7 @@ use App\Http\Controllers\BannerController;
use App\Http\Controllers\CustomerController; use App\Http\Controllers\CustomerController;
use App\Http\Controllers\GeneralController; use App\Http\Controllers\GeneralController;
use App\Http\Controllers\InfoController; use App\Http\Controllers\InfoController;
use App\Http\Controllers\LocationController;
use App\Http\Controllers\ProfileController; use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RoleController; use App\Http\Controllers\RoleController;
use App\Http\Controllers\SettingController; use App\Http\Controllers\SettingController;
@ -52,6 +53,12 @@ Route::middleware(['http_secure_aware', 'inertia.admin'])
Route::put('/infos/{info}', [InfoController::class, 'update'])->name('info.update'); Route::put('/infos/{info}', [InfoController::class, 'update'])->name('info.update');
Route::delete('/infos/{info}', [InfoController::class, 'destroy'])->name('info.destroy'); Route::delete('/infos/{info}', [InfoController::class, 'destroy'])->name('info.destroy');
// Location
Route::get('/locations', [LocationController::class, 'index'])->name('location.index');
Route::post('/locations', [LocationController::class, 'store'])->name('location.store');
Route::put('/locations/{location}', [LocationController::class, 'update'])->name('location.update');
Route::delete('/locations/{location}', [LocationController::class, 'destroy'])->name('location.destroy');
// Account // Account
Route::get('/accounts', [AccountController::class, 'index'])->name('account.index'); Route::get('/accounts', [AccountController::class, 'index'])->name('account.index');
Route::post('/accounts', [AccountController::class, 'store'])->name('account.store'); Route::post('/accounts', [AccountController::class, 'store'])->name('account.store');

Loading…
Cancel
Save