refact info

dev
Aji Kamaludin 1 year ago
parent 59aff206e5
commit 5a64b99860
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -9,47 +9,66 @@ class InfoController extends Controller
{
public function index()
{
$query = Info::paginate();
$query = Info::orderBy('updated_at', 'desc')->paginate();
return inertia('Info/Index', [
'query' => $query,
]);
}
public function create()
{
return inertia('Info/Form');
}
public function store(Request $request)
{
$request->validate([
'info' => 'required|string',
'title' => 'required|string',
'description' => 'required|string',
'is_publish' => 'required|in:0,1',
]);
Info::create([
'title' => $request->info,
'title' => $request->title,
'description' => $request->description,
'is_publish' => $request->is_publish,
]);
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed saved']);
return redirect()->route('info.index')
->with('message', ['type' => 'success', 'message' => 'Item has beed saved']);
}
public function edit(Info $info)
{
return inertia('Info/Form', [
'info' => $info
]);
}
public function update(Request $request, Info $info)
{
$request->validate([
'info' => 'required|string',
'title' => 'required|string',
'description' => 'required|string',
'is_publish' => 'required|in:0,1',
]);
$info->update([
'title' => $request->info,
'title' => $request->title,
'description' => $request->description,
'is_publish' => $request->is_publish,
]);
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed updated']);
return redirect()->route('info.index')
->with('message', ['type' => 'success', 'message' => 'Item has beed updated']);
}
public function destroy(Info $info)
{
$info->delete();
session()->flash('message', ['type' => 'success', 'message' => 'Item has beed deleted']);
return redirect()->route('info.index')
->with('message', ['type' => 'success', 'message' => 'Item has beed deleted']);
}
}

@ -8,6 +8,7 @@ class Info extends Model
protected $fillable = [
'title',
'description',
'destination',
'type',
'is_publish',

@ -14,7 +14,8 @@ return new class extends Migration
Schema::create('infos', function (Blueprint $table) {
$table->ulid('id')->primary();
$table->text('title');
$table->string('title')->nullable();
$table->text('description')->nullable();
$table->string('destination')->nullable();
$table->string('type')->nullable();
$table->smallInteger('is_publish')->nullable();

@ -35,6 +35,14 @@ class DummySeeder extends Seeder
{
Info::create([
'title' => 'Welcome to our new site',
'description' => '
<div
class="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50"
role="alert"
>
Info: Welcome to new WBB site
</div>
',
'is_publish' => 1,
]);
}

@ -87,12 +87,13 @@ const Content = ({
)
}
const DropdownLink = ({ href, method, as, children }) => {
const DropdownLink = ({ href, method, as, children, target = 'self' }) => {
return (
<Link
href={href}
method={method}
as={as}
target={target}
className="block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none transition duration-150 ease-in-out dark:text-white hover:dark:bg-gray-500"
>
{children}

@ -84,12 +84,9 @@ export default function Index(props) {
<div className="w-full px-3">
{infos.map((info) => (
<div
className="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50"
role="alert"
dangerouslySetInnerHTML={{__html: info.description}}
key={info.id}
>
{info.title}
</div>
/>
))}
</div>

@ -122,6 +122,13 @@ export default function Authenticated({
</Dropdown.Trigger>
<Dropdown.Content>
<a
href={route('home.index')}
target='_blank'
className="block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none transition duration-150 ease-in-out dark:text-white hover:dark:bg-gray-500"
>
Visit Site
</a>
<Dropdown.Link
href={route('profile.edit')}
>

@ -96,7 +96,7 @@ export default [
show: true,
icon: HiQuestionMarkCircle,
route: route('info.index'),
active: 'info.index',
active: 'info.*',
permission: 'view-info',
},
],

@ -0,0 +1,112 @@
import React, { useEffect, Suspense } from 'react'
import { isEmpty } from 'lodash'
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import FormInput from '@/Components/FormInput'
import Button from '@/Components/Button'
import { Head, useForm } from '@inertiajs/react'
const TinyEditor = React.lazy(() => import('@/Components/TinyMCE'))
export default function Form(props) {
const { info } = props
const { data, setData, post, put, processing, errors } = useForm({
title: '',
description: '',
is_publish: 1,
})
const handleOnChange = (event) => {
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
? 1
: 0
: event.target.value
)
}
const handleSubmit = () => {
if (isEmpty(info) === false) {
put(route('info.update', info))
return
}
post(route('info.store'))
}
useEffect(() => {
if (isEmpty(info) === false) {
setData({
title: info.title,
description: info.description,
is_publish: info.is_publish,
})
}
}, [info])
return (
<AuthenticatedLayout page={'Info'} action={'Form'}>
<Head title="Info" />
<div>
<div className="mx-auto sm:px-6 lg:px-8">
<div className="overflow-hidden p-4 shadow-sm sm:rounded-lg bg-white dark:bg-gray-800 flex flex-col ">
<div className="text-xl font-bold mb-4">Info</div>
<FormInput
name="title"
value={data.title}
onChange={handleOnChange}
label="Title"
error={errors.title}
/>
<div className="py-4">
<Suspense fallback={<div>Loading...</div>}>
<TinyEditor
value={data.description}
init={{
height: 500,
// menubar: false,
menubar:
'file edit view insert format tools table help',
plugins:
'preview importcss searchreplace autolink directionality code visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap emoticons',
toolbar_mode: 'scrolling',
toolbar:
'undo redo | insertfile image media link | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | charmap emoticons | fullscreen preview save print | ltr rtl | anchor codesample',
}}
onEditorChange={(newValue, editor) => {
setData(
'description',
editor.getContent()
)
}}
/>
</Suspense>
</div>
<div className="my-4">
<div className="mb-1 text-sm">Publish </div>
<select
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
onChange={handleOnChange}
value={+data.is_publish}
name="is_publish"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
<div className="mt-8">
<Button
onClick={handleSubmit}
processing={processing}
>
Simpan
</Button>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
)
}

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'
import { router } from '@inertiajs/react'
import { Link, router } from '@inertiajs/react'
import { usePrevious } from 'react-use'
import { Head } from '@inertiajs/react'
import { Button, Dropdown } from 'flowbite-react'
@ -20,12 +20,6 @@ export default function Info(props) {
} = props
const confirmModal = useModalState()
const formModal = useModalState()
const toggleFormModal = (info = null) => {
formModal.setData(info)
formModal.toggle()
}
const handleDeleteClick = (info) => {
confirmModal.setData(info)
@ -51,12 +45,9 @@ export default function Info(props) {
<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>
<Link href={route('info.create')}>
<Button size="sm">Tambah</Button>
</Link>
)}
</div>
<div className="overflow-auto">
@ -108,19 +99,13 @@ export default function Info(props) {
size={'sm'}
>
{canUpdate && (
<Dropdown.Item
onClick={() =>
toggleFormModal(
info
)
}
>
<div className="flex space-x-1 items-center">
<Dropdown.Item>
<Link href={route('info.edit', info)} className="flex space-x-1 items-center">
<HiPencil />
<div>
Ubah
</div>
</div>
</Link>
</Dropdown.Item>
)}
{canDelete && (
@ -154,7 +139,6 @@ export default function Info(props) {
</div>
</div>
<ModalConfirm modalState={confirmModal} onConfirm={onDelete} />
<FormModal modalState={formModal} />
</AuthenticatedLayout>
)
}

@ -57,7 +57,9 @@ Route::middleware(['http_secure_aware', 'inertia.admin'])
// Info
Route::get('/infos', [InfoController::class, 'index'])->name('info.index');
Route::get('/infos/create', [InfoController::class, 'create'])->name('info.create');
Route::post('/infos', [InfoController::class, 'store'])->name('info.store');
Route::get('/infos/{info}', [InfoController::class, 'edit'])->name('info.edit');
Route::put('/infos/{info}', [InfoController::class, 'update'])->name('info.update');
Route::delete('/infos/{info}', [InfoController::class, 'destroy'])->name('info.destroy');

@ -28,7 +28,7 @@ module.exports = {
600: '#0867ff',
700: '#024ff3',
800: '#0940c4',
900: '#0e3995',
900: '#0e3995', // default
950: '#0e255d',
},
secondary: {
@ -37,7 +37,7 @@ module.exports = {
200: '#fbe88c',
300: '#f9d650',
400: '#f7c328',
500: '#f1a410',
500: '#f1a410', //default
600: '#d57d0a',
700: '#b1580c',
800: '#904510',

Loading…
Cancel
Save