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

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Customer;
use App\Services\GeneralService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
@ -17,7 +18,7 @@ class CustomerController extends Controller
}
$query->orderBy('created_at', 'desc');
return inertia('Customer/Index', [
'query' => $query->paginate(10),
]);
@ -32,7 +33,7 @@ class CustomerController extends Controller
]);
Customer::create([
'code' => Str::upper(Str::random(6)),
'code' => 'PE-' . GeneralService::formatNum(Customer::count() + 1),
'name' => $request->name,
'phone' => $request->phone,
'address' => $request->address,

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Product;
use App\Services\GeneralService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
@ -17,7 +18,7 @@ class ProductController extends Controller
}
$query->orderBy('created_at', 'desc');
return inertia('Product/Index', [
'query' => $query->paginate(10),
]);
@ -31,15 +32,17 @@ class ProductController extends Controller
'cost' => 'required|numeric|min:1',
'stock' => 'required|numeric|min:1',
'category_id' => 'required|exists:categories,id',
'is_active' => 'required|in:0,1',
]);
Product::create([
'code' => Str::upper(Str::random(6)),
'code' => 'PO-' . GeneralService::formatNum(Product::count() + 1),
'name' => $request->name,
'price' => $request->price,
'cost' => $request->cost,
'stock' => $request->stock,
'category_id' => $request->category_id,
'is_active' => $request->is_active,
]);
return redirect()->route('product.index')
@ -54,6 +57,7 @@ class ProductController extends Controller
'cost' => 'required|numeric|min:1',
'stock' => 'required|numeric|min:1',
'category_id' => 'required|exists:categories,id',
'is_active' => 'required|in:0,1',
]);
$product->update([
@ -62,6 +66,7 @@ class ProductController extends Controller
'cost' => $request->cost,
'stock' => $request->stock,
'category_id' => $request->category_id,
'is_active' => $request->is_active,
]);
return redirect()->route('product.index')

@ -4,6 +4,10 @@ namespace App\Models;
class Product extends Model
{
const ACTIVE = 0;
const INACTIVE = 1;
protected $fillable = [
'code',
'name',
@ -11,6 +15,7 @@ class Product extends Model
'cost',
'stock',
'category_id',
'is_active'
];
public function category()

@ -0,0 +1,24 @@
<?php
namespace App\Services;
class GeneralService
{
public static function formatNum($num)
{
// 0001
if ($num < 10) {
return '000' . $num;
}
if ($num < 100) {
return '00' . $num;
}
if ($num < 1000) {
return '0' . $num;
}
return $num;
}
}

@ -19,6 +19,7 @@ return new class extends Migration
$table->decimal('cost', 14, 2)->default(0);
$table->decimal('stock', 14, 2)->default(0);
$table->uuid('category_id')->nullable();
$table->smallInteger('is_active')->default(0);
$table->timestamps();
$table->softDeletes();
$table->uuid('created_by')->nullable();

@ -5,6 +5,7 @@ namespace Database\Seeders;
use App\Models\Category;
use App\Models\Customer;
use App\Models\Product;
use App\Services\GeneralService;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
@ -48,9 +49,9 @@ class DummySeeder extends Seeder
'Sepatu',
'Obat Nyamuk'
];
foreach ($products as $prod) {
foreach ($products as $index => $prod) {
Product::create([
'code' => Str::upper(Str::random(6)),
'code' => 'PO-' . GeneralService::formatNum($index + 1),
'name' => $prod,
'price' => rand(1000, 10000),
'cost' => rand(1000, 10000),
@ -59,9 +60,9 @@ class DummySeeder extends Seeder
]);
}
foreach (['Customer A', 'Customer B'] as $cust) {
foreach (['Customer A', 'Customer B'] as $index => $cust) {
Customer::create([
'code' => Str::upper(Str::random(6)),
'code' => 'PE-' . GeneralService::formatNum($index + 1),
'name' => $cust,
]);
}

@ -1,43 +1,52 @@
import React, { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/Defaults/InputError';
import { Head, Link, useForm } from '@inertiajs/react';
import { Button, TextInput,Label, Checkbox, Spinner } from 'flowbite-react';
import React, { useEffect } from 'react'
import GuestLayout from '@/Layouts/GuestLayout'
import InputError from '@/Components/Defaults/InputError'
import { Head, Link, useForm } from '@inertiajs/react'
import { Button, TextInput, Label, Checkbox, Spinner } from 'flowbite-react'
export default function Login({ status }) {
const { data, setData, post, processing, errors, reset } = useForm({
email: '',
password: '',
remember: '',
});
})
useEffect(() => {
return () => {
reset('password');
};
}, []);
reset('password')
}
}, [])
const onHandleChange = (event) => {
setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value);
};
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
: event.target.value
)
}
const handleKeyDown = e => {
if(e.code === 'Enter') {
const handleKeyDown = (e) => {
if (e.code === 'Enter') {
post(route('login'))
}
}
const submit = (e) => {
e.preventDefault();
e.preventDefault()
post(route('login'));
};
post(route('login'))
}
return (
<GuestLayout>
<Head title="Log in" />
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
{status && (
<div className="mb-4 font-medium text-sm text-green-600">
{status}
</div>
)}
<form onSubmit={submit}>
<div>
@ -66,29 +75,37 @@ export default function Login({ status }) {
className="mt-1 block w-full"
autoComplete="current-password"
onChange={onHandleChange}
onKeyDownCapture={e => handleKeyDown(e)}
onKeyDownCapture={(e) => handleKeyDown(e)}
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="block mt-4">
<label className="flex items-center space-x-2">
<Checkbox id="remember" value={data.remember} onChange={onHandleChange}/>
<Label htmlFor="remember">
Remember me
</Label>
</label>
<div className="flex flex-row justify-between items-center mt-4">
<div className="block ">
<label className="flex items-center space-x-2">
<Checkbox
id="remember"
value={data.remember}
onChange={onHandleChange}
/>
<Label htmlFor="remember">Remember me</Label>
</label>
</div>
<Link
href={route('password.request')}
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Forgot password
</Link>
</div>
<div className="flex items-center justify-end mt-4">
<Button onClick={submit} disabled={processing}>
{processing ? (
<Spinner/>
) : ('Log in')}
{processing ? <Spinner /> : 'Log in'}
</Button>
</div>
</form>
</GuestLayout>
);
)
}

@ -16,6 +16,7 @@ export default function FormModal(props) {
cost: 0,
stock: 0,
category_id: null,
is_active: 0,
})
const handleOnChange = (event) => {
@ -62,6 +63,7 @@ export default function FormModal(props) {
cost: product.cost,
stock: product.stock,
category_id: product.category_id,
is_active: product.is_active,
})
return
}
@ -106,6 +108,23 @@ export default function FormModal(props) {
onItemSelected={(id) => setData('category_id', id)}
error={errors.category_id}
/>
<div className="mt-4">
<div className="mb-1 text-sm">Status</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 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
onChange={handleOnChange}
value={data.is_active}
name="is_active"
>
<option value="0">Aktif</option>
<option value="1">Tidak Aktif</option>
</select>
{errors.is_active && (
<p className="mb-2 text-sm text-red-600 dark:text-red-500">
{errors.is_active}
</p>
)}
</div>
<div className="flex items-center">
<Button onClick={handleSubmit} processing={processing}>
Simpan

@ -105,6 +105,12 @@ export default function Product(props) {
>
Nama
</th>
<th
scope="col"
className="py-3 px-6"
>
Status
</th>
<th
scope="col"
className="py-3 px-6"
@ -150,6 +156,16 @@ export default function Product(props) {
<td className="py-4 px-6">
{product.name}
</td>
<td className="py-4 px-6">
<div
className={`w-5 h-5 rounded-full mx-auto ${
+product.is_active ===
0
? 'bg-green-500'
: 'bg-red-500'
}`}
></div>
</td>
<td className="py-4 px-6">
{product.category.name}
</td>

@ -105,8 +105,8 @@ export default function Sale(props) {
<Head title="Penjualan" />
<div className="mx-auto sm:px-6 lg:px-8 w-full">
<div className="flex flex-row p-6 shadow-sm sm:rounded-lg bg-white w-full space-x-2">
<div className="w-full md:w-7/12">
<div className="flex flex-col lg:flex-row p-6 shadow-sm sm:rounded-lg bg-white w-full gap-2">
<div className="w-full lg:w-7/12">
<div className="mb-4">
<SearchInput
onChange={(e) => setSearch(e.target.value)}
@ -118,16 +118,19 @@ export default function Sale(props) {
<Spinner size="xl" />
</div>
) : (
<div className="grid grid-cols-4 gap-2 text-center h-[320px]">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-2 text-center min-h-[320px]">
{products.map((item) => (
<div
className="rounded bg-gray-300 hover:bg-gray-200 shadow-lg px-4 py-2 flex flex-col justify-between"
className="rounded bg-gray-200 hover:bg-gray-300 shadow-lg px-4 py-2 flex flex-col gap-1 justify-between"
key={item.id}
onClick={() => addItem(item)}
>
<div className="font-bold">
<div className="text-base">
{item.name}
</div>
<div className="font-bold">
({item.code})
</div>
<div className="rounded-md bg-gray-800 p-0.5 text-white">
Rp. {formatIDR(item.price)}
</div>
@ -151,7 +154,7 @@ export default function Sale(props) {
/>
</div>
</div>
<div className="w-full md:w-5/12 flex flex-col">
<div className="w-full lg:w-5/12 flex flex-col">
<CustomerSelectionInput
placeholder="Pelanggan"
itemSelected={data.customer_id}

Loading…
Cancel
Save