sale partial

dev
Aji Kamaludin 1 year ago
parent 140343d091
commit 8bea9fd9ea
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -0,0 +1,26 @@
<?php
namespace App\Http\Controllers;
use App\Models\Sale;
use Illuminate\Http\Request;
class SaleController extends Controller
{
public function index()
{
$query = Sale::with(['items.voucher', 'customer.level'])
->withCount(['items']);
return inertia('Sale/Index', [
'query' => $query->paginate(),
]);
}
public function show(Sale $sale)
{
return inertia('Sale/Detail', [
'sale' => $sale->load(['items.voucher', 'customer.level']),
]);
}
}

@ -42,6 +42,11 @@ class Sale extends Model
return $this->hasMany(SaleItem::class);
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function formatHumanCreatedAt(): Attribute
{
return Attribute::make(get: function () {

@ -64,10 +64,10 @@ class PermissionSeeder extends Seeder
['id' => Str::ulid(), 'label' => 'View Coin', 'name' => 'view-coin'],
['id' => Str::ulid(), 'label' => 'Update Coin', 'name' => 'update-coin'],
['id' => Str::ulid(), 'label' => 'Create Sale', 'name' => 'create-sale'],
['id' => Str::ulid(), 'label' => 'Update Sale', 'name' => 'update-sale'],
// ['id' => Str::ulid(), 'label' => 'Create Sale', 'name' => 'create-sale'],
// ['id' => Str::ulid(), 'label' => 'Update Sale', 'name' => 'update-sale'],
['id' => Str::ulid(), 'label' => 'View Sale', 'name' => 'view-sale'],
['id' => Str::ulid(), 'label' => 'Delete Sale', 'name' => 'delete-sale'],
// ['id' => Str::ulid(), 'label' => 'Delete Sale', 'name' => 'delete-sale'],
['id' => Str::ulid(), 'label' => 'Create Coin Reward', 'name' => 'create-coin-reward'],
['id' => Str::ulid(), 'label' => 'Update Coin Reward', 'name' => 'update-coin-reward'],

@ -45,12 +45,12 @@ export default [
permission: 'view-voucher',
},
{
name: 'Sale', //TODO
name: 'Sale',
show: true,
icon: HiCreditCard,
route: route('deposit.index'),
active: 'deposit.*',
permission: 'view-deposit',
route: route('sale.index'),
active: 'sale.*',
permission: 'view-sale',
},
{
name: 'Deposit',

@ -111,7 +111,7 @@ export default function Customer(props) {
scope="col"
className="py-3 px-6"
>
Referal Code
Referral Code
</th>
<th
scope="col"

@ -0,0 +1,125 @@
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'
import FormFile from '@/Components/FormFile'
const TinyEditor = React.lazy(() => import('@/Components/TinyMCE'))
export default function Form(props) {
const { banner } = props
const { data, setData, post, processing, errors } = useForm({
title: '',
description: '',
image: '',
image_url: '',
})
const handleOnChange = (event) => {
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
? 1
: 0
: event.target.value
)
}
const handleSubmit = () => {
if (isEmpty(banner) === false) {
post(route('banner.update', banner))
return
}
post(route('banner.store'))
}
useEffect(() => {
if (isEmpty(banner) === false) {
setData({
title: banner.title,
description: banner.description,
image_url: banner.image_url,
})
}
}, [banner])
return (
<AuthenticatedLayout
auth={props.auth}
errors={props.errors}
flash={props.flash}
page={'Banner'}
action={'Form'}
>
<Head title="Banner" />
<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">Banner</div>
<FormInput
name="title"
value={data.title}
onChange={handleOnChange}
label="Title"
error={errors.title}
/>
<FormFile
label={'Image'}
onChange={(e) =>
setData('image', e.target.files[0])
}
error={errors.image}
preview={
isEmpty(data.image_url) === false && (
<img
src={data.image_url}
className="mb-1 h-24 w-full object-cover"
alt="preview"
/>
)
}
/>
<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="mt-8">
<Button
onClick={handleSubmit}
processing={processing}
>
Simpan
</Button>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
)
}

@ -0,0 +1,129 @@
import React from 'react'
import { Head, router } from '@inertiajs/react'
import { HiEye } from 'react-icons/hi'
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import Pagination from '@/Components/Pagination'
import { formatIDR } from '@/utils'
export default function Info(props) {
const {
query: { links, data },
} = props
return (
<AuthenticatedLayout
auth={props.auth}
errors={props.errors}
flash={props.flash}
page={'Sale'}
action={''}
>
<Head title="Sale" />
<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 && (
<Link href={route('banner.create')}>
<Button size="sm">Tambah</Button>
</Link>
)} */}
</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"
>
#
</th>
<th
scope="col"
className="py-3 px-6"
>
Customer
</th>
<th
scope="col"
className="py-3 px-6"
>
Tanggal
</th>
<th
scope="col"
className="py-3 px-6"
>
Voucher
</th>
<th
scope="col"
className="py-3 px-6"
>
Total
</th>
<th
scope="col"
className="py-3 px-6 w-1/8"
/>
</tr>
</thead>
<tbody>
{data.map((sale) => (
<tr
className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
key={sale.id}
>
<td
scope="row"
className="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
{sale.code}
</td>
<td className="py-4 px-6">
{sale.customer.name}
</td>
<td className="py-4 px-6">
{sale.format_created_at}
</td>
<td className="py-4 px-6">
{formatIDR(
sale.items_count
)}
</td>
<td className="py-4 px-6">
{formatIDR(sale.amount)}
</td>
<td
className="py-4 px-6 flex justify-center items-center space-x-1 hover:underline"
onClick={() =>
router.get(
route(
'sale.show',
sale
)
)
}
>
<HiEye />
<div>Lihat</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="w-full flex items-center justify-center">
<Pagination links={links} />
</div>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
)
}

@ -13,6 +13,7 @@ use App\Http\Controllers\InfoController;
use App\Http\Controllers\LocationController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RoleController;
use App\Http\Controllers\SaleController;
use App\Http\Controllers\SettingController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\VoucherController;
@ -122,5 +123,9 @@ Route::middleware(['http_secure_aware', 'inertia.admin'])
Route::post('/bonus-coin', [CoinRewardController::class, 'store'])->name('coin-reward.store');
Route::put('/bonus-coin/{reward}', [CoinRewardController::class, 'update'])->name('coin-reward.update');
Route::delete('/bonus-coin/{reward}', [CoinRewardController::class, 'destroy'])->name('coin-reward.destroy');
// sale
Route::get('/sales', [SaleController::class, 'index'])->name('sale.index');
Route::get('/sales/{sale}', [SaleController::class, 'show'])->name('sale.show');
});
});

Loading…
Cancel
Save