diff --git a/app/Http/Controllers/Api/CustomerController.php b/app/Http/Controllers/Api/CustomerController.php
new file mode 100644
index 0000000..8b866e5
--- /dev/null
+++ b/app/Http/Controllers/Api/CustomerController.php
@@ -0,0 +1,29 @@
+q) {
+ $query->where('name', 'like', "%{$request->q}%");
+ }
+
+ if ($request->except_id) {
+ $query->where('id', '!=', $request->except_id);
+ }
+
+ if ($request->all == 1) {
+ return $query->get();
+ }
+
+ return $query->get();
+ }
+}
diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php
new file mode 100644
index 0000000..7b98f8e
--- /dev/null
+++ b/app/Http/Controllers/CustomerController.php
@@ -0,0 +1,74 @@
+q) {
+ $query->where('name', 'like', "%{$request->q}%")
+ ->orWhere('code', 'like', "%{$request->q}%");
+ }
+
+ $query->orderBy('created_at', 'desc');
+
+ return inertia('Customer/Index', [
+ 'query' => $query->paginate(),
+ ]);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'code' => 'required|string|max:255',
+ 'name' => 'required|string|max:255',
+ 'point' => 'required|numeric',
+ ]);
+
+ Customer::create([
+ 'code' => $request->code,
+ 'name' => $request->name,
+ 'start_point' => $request->point,
+ 'last_point' => $request->point,
+ ]);
+
+ return redirect()->route('customer.index')
+ ->with('message', ['type' => 'success', 'message' => 'Item has beed saved']);
+ }
+
+ public function update(Request $request, Customer $customer)
+ {
+ $request->validate([
+ 'code' => 'required|string|max:255',
+ 'name' => 'required|string|max:255',
+ 'point' => 'required|numeric',
+ ]);
+
+ $customer->update([
+ 'code' => $request->code,
+ 'name' => $request->name,
+ 'last_point' => $request->point,
+ ]);
+
+ return redirect()->route('customer.index')
+ ->with('message', ['type' => 'success', 'message' => 'Item has beed updated']);
+ }
+
+ public function destroy(Customer $customer)
+ {
+ $customer->delete();
+
+ return redirect()->route('customer.index')
+ ->with('message', ['type' => 'success', 'message' => 'Item has beed deleted']);
+ }
+
+ public function import()
+ {
+ }
+}
diff --git a/app/Http/Controllers/CustomerPointController.php b/app/Http/Controllers/CustomerPointController.php
new file mode 100644
index 0000000..00961fd
--- /dev/null
+++ b/app/Http/Controllers/CustomerPointController.php
@@ -0,0 +1,24 @@
+ Setting::where('key', 'app_name')->value('value'),
+ ]);
+ }
+
+ public function check(Request $request)
+ {
+ $request->validate([
+ 'customer_code' => 'required|string|exists:customers,code'
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php
new file mode 100644
index 0000000..322f58e
--- /dev/null
+++ b/app/Http/Controllers/SettingController.php
@@ -0,0 +1,41 @@
+ Setting::all(),
+ ]);
+ }
+
+ public function update(Request $request)
+ {
+ $request->validate([
+ 'app_name' => 'required|string',
+ ]);
+
+ DB::beginTransaction();
+
+ foreach ($request->input() as $key => $value) {
+ Setting::updateOrCreate(
+ ['key' => $key],
+ [
+ 'value' => $value,
+ 'type' => 'text'
+ ]
+ );
+ }
+
+ DB::commit();
+
+ return redirect()->route('setting.index')
+ ->with('message', ['type' => 'success', 'message' => 'Setting saved']);
+ }
+}
diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php
index 9dc5ef9..530351f 100644
--- a/app/Http/Middleware/HandleInertiaRequests.php
+++ b/app/Http/Middleware/HandleInertiaRequests.php
@@ -36,6 +36,7 @@ class HandleInertiaRequests extends Middleware
'flash' => [
'message' => fn () => $request->session()->get('message'),
],
+ 'app_name' => env('APP_NAME', 'App Name')
]);
}
}
diff --git a/app/Models/Customer.php b/app/Models/Customer.php
index bd96440..c48a7cb 100644
--- a/app/Models/Customer.php
+++ b/app/Models/Customer.php
@@ -2,10 +2,13 @@
namespace App\Models;
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
- use HasFactory;
+ protected $fillable = [
+ 'name',
+ 'code',
+ 'start_point',
+ 'last_point',
+ ];
}
diff --git a/app/Models/CustomerPoint.php b/app/Models/CustomerPoint.php
index 9a20435..adaeb9b 100644
--- a/app/Models/CustomerPoint.php
+++ b/app/Models/CustomerPoint.php
@@ -2,10 +2,11 @@
namespace App\Models;
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
-
class CustomerPoint extends Model
{
- use HasFactory;
+ protected $fillable = [
+ 'customer_id',
+ 'description',
+ 'point',
+ ];
}
diff --git a/database/migrations/2023_06_14_022155_create_customers_table.php b/database/migrations/2023_06_14_022155_create_customers_table.php
index 5e1f0d5..f3c382b 100644
--- a/database/migrations/2023_06_14_022155_create_customers_table.php
+++ b/database/migrations/2023_06_14_022155_create_customers_table.php
@@ -12,8 +12,16 @@ return new class extends Migration
public function up(): void
{
Schema::create('customers', function (Blueprint $table) {
- $table->id();
+ $table->ulid('id')->primary();
+ $table->string('name');
+ $table->string('code');
+ $table->decimal('start_point', 20, 2);
+ $table->decimal('last_point', 20, 2);
$table->timestamps();
+ $table->softDeletes();
+ $table->ulid('created_by')->nullable();
+ $table->ulid('updated_by')->nullable();
+ $table->ulid('deleted_by')->nullable();
});
}
diff --git a/database/migrations/2023_06_14_022203_create_customer_points_table.php b/database/migrations/2023_06_14_022203_create_customer_points_table.php
index 253fcda..04060c7 100644
--- a/database/migrations/2023_06_14_022203_create_customer_points_table.php
+++ b/database/migrations/2023_06_14_022203_create_customer_points_table.php
@@ -12,8 +12,15 @@ return new class extends Migration
public function up(): void
{
Schema::create('customer_points', function (Blueprint $table) {
- $table->id();
+ $table->ulid('id')->primary();
+ $table->ulid('customer_id');
+ $table->string('description', 1000);
+ $table->decimal('point', 20, 2);
$table->timestamps();
+ $table->softDeletes();
+ $table->ulid('created_by')->nullable();
+ $table->ulid('updated_by')->nullable();
+ $table->ulid('deleted_by')->nullable();
});
}
diff --git a/database/seeders/DummySeeder.php b/database/seeders/DummySeeder.php
index e237efc..61b839b 100644
--- a/database/seeders/DummySeeder.php
+++ b/database/seeders/DummySeeder.php
@@ -2,7 +2,9 @@
namespace Database\Seeders;
+use App\Models\Setting;
use Illuminate\Database\Seeder;
+use Illuminate\Support\Str;
class DummySeeder extends Seeder
{
@@ -13,6 +15,10 @@ class DummySeeder extends Seeder
*/
public function run()
{
- //
+ $settings = [
+ ['id' => Str::ulid(), 'key' => 'app_name', 'value' => 'Customer Point', 'type' => 'text']
+ ];
+
+ Setting::insert($settings);
}
}
diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php
index 50d22e9..82f3e2c 100644
--- a/database/seeders/PermissionSeeder.php
+++ b/database/seeders/PermissionSeeder.php
@@ -30,6 +30,18 @@ class PermissionSeeder extends Seeder
['id' => Str::ulid(), 'label' => 'Update Role', 'name' => 'update-role'],
['id' => Str::ulid(), 'label' => 'View Role', 'name' => 'view-role'],
['id' => Str::ulid(), 'label' => 'Delete Role', 'name' => 'delete-role'],
+
+ ['id' => Str::ulid(), 'label' => 'View Setting', 'name' => 'view-setting'],
+
+ ['id' => Str::ulid(), 'label' => 'Create Customer', 'name' => 'create-customer'],
+ ['id' => Str::ulid(), 'label' => 'Update Customer', 'name' => 'update-customer'],
+ ['id' => Str::ulid(), 'label' => 'View Customer', 'name' => 'view-customer'],
+ ['id' => Str::ulid(), 'label' => 'Delete Customer', 'name' => 'delete-customer'],
+
+ ['id' => Str::ulid(), 'label' => 'Create Customer Point', 'name' => 'create-customer-point'],
+ ['id' => Str::ulid(), 'label' => 'Update Customer Point', 'name' => 'update-customer-point'],
+ ['id' => Str::ulid(), 'label' => 'View Customer Point', 'name' => 'view-customer-point'],
+ ['id' => Str::ulid(), 'label' => 'Delete Customer Point', 'name' => 'delete-customer-point'],
];
foreach ($permissions as $permission) {
diff --git a/resources/js/Components/Defaults/ApplicationLogo.jsx b/resources/js/Components/Defaults/ApplicationLogo.jsx
index 08b4984..092d6da 100644
--- a/resources/js/Components/Defaults/ApplicationLogo.jsx
+++ b/resources/js/Components/Defaults/ApplicationLogo.jsx
@@ -1,7 +1,10 @@
-import React from 'react';
+import { usePage } from '@inertiajs/react'
+import React from 'react'
export default function ApplicationLogo({ className }) {
- return (
-
App Name
- );
+ const {
+ props: { app_name },
+ } = usePage()
+
+ return {app_name}
}
diff --git a/resources/js/Components/FormInput.jsx b/resources/js/Components/FormInput.jsx
index 41073e8..483b005 100644
--- a/resources/js/Components/FormInput.jsx
+++ b/resources/js/Components/FormInput.jsx
@@ -1,11 +1,31 @@
-import React from "react";
-import Input from "./Input";
+import React from 'react'
+import Input from './Input'
-export default function FormInput({ type, name, onChange, value, label, className, error, autoComplete, autoFocus, placeholder, disabled, readOnly}) {
+export default function FormInput({
+ type,
+ name,
+ onChange,
+ value,
+ label,
+ className,
+ error,
+ autoComplete,
+ autoFocus,
+ placeholder,
+ disabled,
+ readOnly,
+}) {
+ const id = `${name}-${label}`
return (
-
+
)
-}
\ No newline at end of file
+}
diff --git a/resources/js/Components/Input.jsx b/resources/js/Components/Input.jsx
index 1e64a6a..4ae2795 100644
--- a/resources/js/Components/Input.jsx
+++ b/resources/js/Components/Input.jsx
@@ -1,24 +1,43 @@
import React from 'react'
-export default function Input({ type = 'text', name, onChange, value, error = "", autoComplete = false, autoFocus = false, placeholder , className ,disabled, readOnly}) {
+export default function Input({
+ type = 'text',
+ name,
+ onChange,
+ value,
+ error = '',
+ autoComplete = false,
+ autoFocus = false,
+ placeholder,
+ className,
+ disabled,
+ readOnly,
+ id,
+}) {
return (
<>
-
{error && (
- {error}
+
+ {error}
+
)}
>
-
)
-}
\ No newline at end of file
+}
diff --git a/resources/js/Layouts/Partials/SidebarNav.jsx b/resources/js/Layouts/Partials/SidebarNav.jsx
index c7fb390..06ca174 100644
--- a/resources/js/Layouts/Partials/SidebarNav.jsx
+++ b/resources/js/Layouts/Partials/SidebarNav.jsx
@@ -1,21 +1,24 @@
-import React from 'react';
-import { router } from '@inertiajs/react';
-import { Sidebar } from 'flowbite-react';
-import { HiLogout } from 'react-icons/hi';
-import { filterOpenMenu } from './helpers';
-import routes from './routes';
-import { formatDate } from '@/utils';
+import React from 'react'
+import { Link, router, usePage } from '@inertiajs/react'
+import { Sidebar } from 'flowbite-react'
+import { HiLogout } from 'react-icons/hi'
+import { filterOpenMenu } from './helpers'
+import routes from './routes'
export default function SidebarNav({ user }) {
- const menus = routes.filter(item => {
+ const {
+ props: { app_name },
+ } = usePage()
+
+ const menus = routes.filter((item) => {
item.open = false
if (!item.show) {
return null
}
- if (+user.is_superadmin === 1) {
+ if (user.role === null) {
return filterOpenMenu(user, item)
}
- if(user.role.permissions.find(p => p.name === item.permission)) {
+ if (user.role.permissions.find((p) => p.name === item.permission)) {
return item
}
@@ -26,33 +29,36 @@ export default function SidebarNav({ user }) {
- {menus.map(item => (
+ {menus.map((item) => (
{item.items === undefined ? (
- router.visit(item.route)}
- icon={item.icon}
- active={route().current(item.active)}
- >
- {item.name}
-
+ router.visit(item.route)}
+ icon={item.icon}
+ active={route().current(item.active)}
+ >
+ {item.name}
+
) : (
- {item.items.map(item => (
- (
+ router.visit(item.route)}
icon={item.icon}
- active={route().current(item.active)}
+ active={route().current(
+ item.active
+ )}
+ onClick={() =>
+ router.visit(item.route)
+ }
>
{item.name}
))}
-
)}
@@ -64,10 +70,10 @@ export default function SidebarNav({ user }) {
Logout
-
- App Name © {(new Date()).getFullYear()}
+
+ {app_name} © {new Date().getFullYear()}
)
-}
\ No newline at end of file
+}
diff --git a/resources/js/Layouts/Partials/helpers.js b/resources/js/Layouts/Partials/helpers.js
index 4450946..7a6fa74 100644
--- a/resources/js/Layouts/Partials/helpers.js
+++ b/resources/js/Layouts/Partials/helpers.js
@@ -1,21 +1,25 @@
export const filterOpenMenu = (user, item) => {
- const isAdmin = +user.is_superadmin === 1
+ const isAdmin = user.role === null
if ('items' in item) {
let items = []
if (isAdmin) {
items = item.items
} else {
- items = item.items.filter(item => user.role.permissions.find(p => p.name === item.permission) ? item : null)
+ items = item.items.filter((item) =>
+ user.role.permissions.find((p) => p.name === item.permission)
+ ? item
+ : null
+ )
}
if (items.length > 0) {
- let activeItem = items.map(item => route().current(item.active))
+ let activeItem = items.map((item) => route().current(item.active))
item.open = activeItem.includes(true)
- item.items = items.filter(item => item.show ? item : null)
+ item.items = items.filter((item) => (item.show ? item : null))
return item
}
}
if (isAdmin) {
return item
}
-}
\ No newline at end of file
+}
diff --git a/resources/js/Layouts/Partials/routes.js b/resources/js/Layouts/Partials/routes.js
index c4b349e..17125f1 100644
--- a/resources/js/Layouts/Partials/routes.js
+++ b/resources/js/Layouts/Partials/routes.js
@@ -1,56 +1,67 @@
import {
HiChartPie,
HiUser,
- HiCollection,
- HiAdjustments,
- HiPlusCircle,
- HiCurrencyDollar,
- HiCash,
- HiClipboardList,
- HiHashtag,
HiUsers,
HiUserGroup,
HiUserCircle,
- HiOutlineTruck,
- HiDatabase,
- HiShoppingBag,
- HiReceiptTax,
- HiHome,
- HiInboxIn,
- HiOutlineCash,
- HiOutlineTable
-} from "react-icons/hi";
+ HiCog,
+} from 'react-icons/hi'
+import { HiTrophy } from 'react-icons/hi2'
export default [
{
- name: "Dashboard",
+ name: 'Dashboard',
show: true,
icon: HiChartPie,
- route: route("dashboard"),
- active: "dashboard",
- permission: "view-dashboard",
+ route: route('dashboard'),
+ active: 'dashboard',
+ permission: 'view-dashboard',
},
{
- name: "User",
+ name: 'Customers',
+ show: true,
+ icon: HiUserCircle,
+ route: route('customer.index'),
+ active: 'customer.index',
+ permission: 'view-customer',
+ },
+ {
+ name: 'Point',
+ show: true,
+ icon: HiTrophy,
+ route: route('customer-point.index'),
+ active: 'customer-point.index',
+ permission: 'view-customer-point',
+ },
+ {
+ name: 'Admin',
show: true,
icon: HiUser,
items: [
{
- name: "Roles",
+ name: 'Roles',
show: true,
icon: HiUserGroup,
- route: route("roles.index"),
- active: "roles.*",
- permission: "view-role",
+ route: route('roles.index'),
+ active: 'roles.*',
+ permission: 'view-role',
},
{
- name: "Users",
+ name: 'Users',
show: true,
icon: HiUsers,
- route: route("user.index"),
- active: "user.index",
- permission: "view-user",
+ route: route('user.index'),
+ active: 'user.index',
+ permission: 'view-user',
},
],
},
-];
+ {
+ name: 'Setting',
+ show: true,
+ icon: HiCog,
+ route: route('setting.index'),
+ active: 'setting.index',
+ permission: 'view-setting',
+ },
+]
diff --git a/resources/js/Pages/Customer/FormModal.jsx b/resources/js/Pages/Customer/FormModal.jsx
new file mode 100644
index 0000000..f9851e6
--- /dev/null
+++ b/resources/js/Pages/Customer/FormModal.jsx
@@ -0,0 +1,102 @@
+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 { isEmpty } from 'lodash'
+
+export default function FormModal(props) {
+ const { modalState } = props
+ const { data, setData, post, put, processing, errors, reset, clearErrors } =
+ useForm({
+ code: '',
+ name: '',
+ point: 0,
+ })
+
+ 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 customer = modalState.data
+ if (customer !== null) {
+ put(route('customer.update', customer), {
+ onSuccess: () => handleClose(),
+ })
+ return
+ }
+ post(route('customer.store'), {
+ onSuccess: () => handleClose(),
+ })
+ }
+
+ useEffect(() => {
+ const customer = modalState.data
+ if (isEmpty(customer) === false) {
+ setData({
+ name: customer.name,
+ code: customer.code,
+ point: customer.last_point,
+ })
+ return
+ }
+ }, [modalState])
+
+ return (
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/resources/js/Pages/Customer/Index.jsx b/resources/js/Pages/Customer/Index.jsx
new file mode 100644
index 0000000..7231423
--- /dev/null
+++ b/resources/js/Pages/Customer/Index.jsx
@@ -0,0 +1,196 @@
+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 Customer(props) {
+ const {
+ query: { links, data },
+ auth,
+ } = props
+
+ const [search, setSearch] = useState('')
+ const preValue = usePrevious(search)
+
+ const confirmModal = useModalState()
+ const formModal = useModalState()
+
+ const toggleFormModal = (customer = null) => {
+ formModal.setData(customer)
+ formModal.toggle()
+ }
+
+ const handleDeleteClick = (customer) => {
+ confirmModal.setData(customer)
+ confirmModal.toggle()
+ }
+
+ const onDelete = () => {
+ if (confirmModal.data !== null) {
+ router.delete(route('customer.destroy', confirmModal.data.id))
+ }
+ }
+
+ const params = { q: search }
+ useEffect(() => {
+ if (preValue) {
+ router.get(
+ route(route().current()),
+ { q: search },
+ {
+ replace: true,
+ preserveState: true,
+ }
+ )
+ }
+ }, [search])
+
+ const canCreate = hasPermission(auth, 'create-customer')
+ const canUpdate = hasPermission(auth, 'update-customer')
+ const canDelete = hasPermission(auth, 'delete-customer')
+
+ return (
+
+
+
+
+
+
+
+ {canCreate && (
+
+ )}
+
+ setSearch(e.target.value)}
+ value={search}
+ />
+
+
+
+
+
+
+
+
+ Code
+ |
+
+ Name
+ |
+
+ Point
+ |
+ |
+
+
+
+ {data.map((customer) => (
+
+
+ {customer.code}
+ |
+
+ {customer.name}
+ |
+
+ {customer.last_point}
+ |
+
+
+ {canUpdate && (
+
+ toggleFormModal(
+ customer
+ )
+ }
+ >
+
+
+ )}
+ {canDelete && (
+
+ handleDeleteClick(
+ customer
+ )
+ }
+ >
+
+
+ )}
+
+ |
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/resources/js/Pages/Customer/SelectionInput.jsx b/resources/js/Pages/Customer/SelectionInput.jsx
new file mode 100644
index 0000000..8950c8b
--- /dev/null
+++ b/resources/js/Pages/Customer/SelectionInput.jsx
@@ -0,0 +1,263 @@
+import React, { useRef, useEffect, useState } from 'react'
+import { useDebounce } from '@/hooks'
+import { usePage } from '@inertiajs/react'
+import axios from 'axios'
+import { HiChevronDown, HiChevronUp, HiX } from 'react-icons/hi'
+import { Spinner } from 'flowbite-react'
+
+export default function SelectionInput(props) {
+ const ref = useRef()
+ const {
+ props: { auth },
+ } = usePage()
+
+ const {
+ label = '',
+ itemSelected = null,
+ onItemSelected = () => {},
+ disabled = false,
+ placeholder = '',
+ error = '',
+ all = 0,
+ } = props
+
+ const [showItems, setShowItem] = useState([])
+
+ const [isSelected, setIsSelected] = useState(true)
+ const [selected, setSelected] = useState(null)
+
+ const [query, setQuery] = useState('')
+ const q = useDebounce(query, 300)
+
+ const [isOpen, setIsOpen] = useState(false)
+ const [loading, setLoading] = useState(false)
+
+ const toggle = () => {
+ setQuery('')
+ setIsOpen(!isOpen)
+ }
+
+ const onInputMouseDown = () => {
+ setIsSelected(false)
+ setQuery('')
+ setIsOpen(!isOpen)
+ }
+
+ const handleSelectItem = (item) => {
+ setIsSelected(true)
+ onItemSelected(item.id)
+ setSelected(item.name)
+ setIsOpen(false)
+ }
+
+ const removeItem = () => {
+ setIsSelected(false)
+ setSelected('')
+ onItemSelected(null)
+ }
+
+ const filterItems = (value) => {
+ setIsSelected(false)
+ setQuery(value)
+ }
+
+ useEffect(() => {
+ if (isOpen === true) {
+ const checkIfClickedOutside = (e) => {
+ if (isOpen && ref.current && !ref.current.contains(e.target)) {
+ setIsOpen(false)
+ if (selected !== null) {
+ setIsSelected(true)
+ }
+ }
+ }
+ document.addEventListener('mousedown', checkIfClickedOutside)
+ return () => {
+ document.removeEventListener('mousedown', checkIfClickedOutside)
+ }
+ }
+ }, [isOpen])
+
+ const fetch = (q = '') => {
+ setLoading(true)
+ axios
+ .get(route('api.customer.index', { q: q, all: all }), {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + auth.user.jwt_token,
+ },
+ })
+ .then((response) => {
+ setShowItem(response.data)
+ })
+ .catch((err) => {
+ alert(err)
+ })
+ .finally(() => setLoading(false))
+ }
+
+ // every select item open
+ useEffect(() => {
+ if (isOpen) {
+ fetch(q)
+ }
+ }, [q, isOpen])
+
+ // once page load
+ useEffect(() => {
+ fetch()
+ }, [])
+
+ useEffect(() => {
+ if (disabled) {
+ setSelected('')
+ }
+ }, [disabled])
+
+ useEffect(() => {
+ if (itemSelected !== null) {
+ const item = showItems.find((item) => item.id === itemSelected)
+ if (item) {
+ setSelected(item.name)
+ setIsSelected(true)
+ }
+ return
+ }
+ setIsSelected(false)
+ }, [itemSelected, loading])
+
+ useEffect(() => {
+ if (isSelected && selected === '') {
+ setSelected('')
+ setIsSelected(false)
+ }
+ }, [isSelected])
+
+ return (
+
+
+
+
+ {label !== '' && (
+
+ )}
+
+
+
+ filterItems(e.target.value)
+ }
+ disabled={disabled}
+ />
+ {isSelected && (
+
{} : removeItem
+ }
+ >
+
+
+ )}
+
{} : toggle}>
+
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+ {isOpen && (
+
+
+ {loading ? (
+
+ ) : (
+ <>
+ {showItems.map((item, index) => (
+
+ handleSelectItem(item)
+ }
+ >
+
+
+ ))}
+ {showItems.length <= 0 && (
+
+
+
+
+
+ No Items
+ Found
+
+
+
+
+
+ )}
+ >
+ )}
+
+
+ )}
+
+
+
+
+ )
+}
diff --git a/resources/js/Pages/Home.jsx b/resources/js/Pages/Home.jsx
new file mode 100644
index 0000000..4aea277
--- /dev/null
+++ b/resources/js/Pages/Home.jsx
@@ -0,0 +1,69 @@
+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({ app_name }) {
+ const { data, setData, post, processing, errors, reset } = useForm({
+ customer_code: '',
+ })
+
+ const onHandleChange = (event) => {
+ setData(
+ event.target.name,
+ event.target.type === 'checkbox'
+ ? event.target.checked
+ : event.target.value
+ )
+ }
+
+ const handleKeyDown = (e) => {
+ if (e.code === 'Enter') {
+ post(route('home'))
+ }
+ }
+
+ const submit = (e) => {
+ e.preventDefault()
+
+ post(route('home'))
+ }
+
+ return (
+
+
+
+
+ )
+}
diff --git a/resources/js/Pages/Setting/Index.jsx b/resources/js/Pages/Setting/Index.jsx
new file mode 100644
index 0000000..6dc5892
--- /dev/null
+++ b/resources/js/Pages/Setting/Index.jsx
@@ -0,0 +1,76 @@
+import React from 'react'
+import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
+import FormInput from '@/Components/FormInput'
+import Button from '@/Components/Button'
+import { Head, useForm } from '@inertiajs/react'
+import TextArea from '@/Components/TextArea'
+import { isEmpty } from 'lodash'
+
+const extractValue = (set, key) => {
+ const find = set.find((s) => s.key === key)
+ if (isEmpty(find) === false) {
+ if (find.type === 'image') {
+ return find?.url
+ }
+ return find?.value
+ }
+ return ''
+}
+
+export default function Setting(props) {
+ const { setting } = props
+
+ const { data, setData, post, processing, errors } = useForm({
+ app_name: extractValue(setting, 'app_name'),
+ })
+
+ const handleOnChange = (event) => {
+ setData(
+ event.target.name,
+ event.target.type === 'checkbox'
+ ? event.target.checked
+ ? 1
+ : 0
+ : event.target.value
+ )
+ }
+
+ const handleSubmit = () => {
+ post(route('setting.update'))
+ }
+
+ return (
+
+
+
+
+
+
+
Setting
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/routes/api.php b/routes/api.php
index 1b98e1b..47fa82f 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -1,6 +1,7 @@
get('/user', function (Request $request) {
return $request->user();
});
+Route::get('/customers', [CustomerController::class, 'index'])->name('api.customer.index');
Route::get('/roles', [RoleController::class, 'index'])->name('api.role.index');
diff --git a/routes/web.php b/routes/web.php
index 0ad6d53..20f7073 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,9 +1,13 @@
route('login');
-});
+Route::get('/', [HomeController::class, 'index'])->name('home');
+Route::post('/', [HomeController::class, 'check']);
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [GeneralController::class, 'index'])->name('dashboard');
@@ -33,6 +36,24 @@ Route::middleware(['auth'])->group(function () {
// Role
Route::resource('/roles', RoleController::class);
+
+ // Setting
+ Route::get('/setting', [SettingController::class, 'index'])->name('setting.index');
+ Route::post('/setting', [SettingController::class, 'update'])->name('setting.update');
+
+ // Customer
+ Route::get('/customers', [CustomerController::class, 'index'])->name('customer.index');
+ Route::post('/customers/import', [CustomerController::class, 'import'])->name('customer.import');
+ Route::post('/customers', [CustomerController::class, 'store'])->name('customer.store');
+ Route::put('/customers/{customer}', [CustomerController::class, 'update'])->name('customer.update');
+ Route::delete('/customers/{customer}', [CustomerController::class, 'destroy'])->name('customer.destroy');
+
+ // Customer Point
+ Route::get('/customers-points', [CustomerPointController::class, 'index'])->name('customer-point.index');
+ Route::post('/customers-points/import', [CustomerPointController::class, 'import'])->name('customer-point.import');
+ Route::post('/customers-points', [CustomerPointController::class, 'store'])->name('customer-point.store');
+ Route::put('/customers-points/{customer}', [CustomerPointController::class, 'update'])->name('customer-point.update');
+ Route::delete('/customers-points/{customer}', [CustomerPointController::class, 'destroy'])->name('customer-point.destroy');
});
Route::middleware('auth')->group(function () {
@@ -41,4 +62,4 @@ Route::middleware('auth')->group(function () {
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
-require __DIR__.'/auth.php';
+require __DIR__ . '/auth.php';