From c8df4033a52acc8a12944f8c46487e9c167aba60 Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Thu, 30 Dec 2021 20:59:16 +0700 Subject: [PATCH] done crud employee --- .../Api/EmployeeQueryController.php | 21 + app/Http/Controllers/EmployeeController.php | 103 +++++ app/Models/Employee.php | 11 + public/css/app.css | 5 + public/js/app.js | 389 +++++++++++++++++- resources/js/Modals/FormEmployeeModal.js | 169 ++++++++ resources/js/Pages/Dashboard.js | 4 +- resources/js/Pages/Employees.js | 176 +++++++- routes/api.php | 2 + routes/web.php | 7 +- 10 files changed, 850 insertions(+), 37 deletions(-) create mode 100644 app/Http/Controllers/Api/EmployeeQueryController.php create mode 100644 app/Http/Controllers/EmployeeController.php create mode 100644 resources/js/Modals/FormEmployeeModal.js diff --git a/app/Http/Controllers/Api/EmployeeQueryController.php b/app/Http/Controllers/Api/EmployeeQueryController.php new file mode 100644 index 0000000..f949618 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeQueryController.php @@ -0,0 +1,21 @@ +q != null) { + $query = Employee::where('name', 'like', '%'.$request->q.'%')->orWhere('whatsapp', 'like', '%'.$request->q.'%')->orderBy('id'); + } else { + $query = Employee::orderBy('id'); + } + + return $query->paginate(10); + } +} diff --git a/app/Http/Controllers/EmployeeController.php b/app/Http/Controllers/EmployeeController.php new file mode 100644 index 0000000..c8b7955 --- /dev/null +++ b/app/Http/Controllers/EmployeeController.php @@ -0,0 +1,103 @@ +q != null) { + $query = Employee::where('name', 'like', '%'.$request->q.'%')->orWhere('whatsapp', 'like', '%'.$request->q.'%')->orderBy('id'); + } else { + $query = Employee::orderBy('id'); + } + + return inertia('Employees', [ + 'employees' => $query->paginate(10), + ]); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string', + 'whatsapp' => 'nullable|string', + 'photo' => 'nullable|image' + ]); + + $employee = Employee::make($request->only(['name', 'whatsapp'])); + $photo = $request->file('photo'); + if ($photo != null) { + $photo->store('public'); + $employee->photo = $photo->hashName(); + } + + $employee->save(); + + return redirect()->route('employees.index'); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, Employee $employee) + { + $request->validate([ + 'name' => 'required|string', + 'whatsapp' => 'nullable|string', + 'photo' => 'nullable|image' + ]); + + $employee->fill($request->only(['name', 'whatsapp'])); + + $photo = $request->file('photo'); + if ($photo != null) { + if ($employee->photo != null) { + Storage::delete('public/'.$employee->photo); + $employee->photo = null; + } + $photo->store('public'); + $employee->photo = $photo->hashName(); + } + + $employee->save(); + + return redirect()->route('employees.index'); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy(Employee $employee) + { + if ($employee->photo != null) { + Storage::delete('public/'.$employee->photo); + } + + $employee->delete(); + + return redirect()->route('employees.index'); + } +} diff --git a/app/Models/Employee.php b/app/Models/Employee.php index 9bb65a4..e0ea094 100644 --- a/app/Models/Employee.php +++ b/app/Models/Employee.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Support\Facades\Storage; use Illuminate\Database\Eloquent\Model; class Employee extends Model @@ -15,4 +16,14 @@ class Employee extends Model 'whatsapp', 'basic_salary', ]; + + protected $appends = ['photo_url']; + + public function getPhotoUrlAttribute() + { + if ($this->photo != null) { + return asset(Storage::url($this->photo)); + } + return null; + } } diff --git a/public/css/app.css b/public/css/app.css index aa8e49b..68ea5dc 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -2833,6 +2833,11 @@ html { margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} .overflow-hidden { overflow: hidden; } diff --git a/public/js/app.js b/public/js/app.js index d44bdf2..c7b85af 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -4143,6 +4143,203 @@ function Guest(_ref) { /***/ }), +/***/ "./resources/js/Modals/FormEmployeeModal.js": +/*!**************************************************!*\ + !*** ./resources/js/Modals/FormEmployeeModal.js ***! + \**************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (/* binding */ FormEmployeeModal) +/* harmony export */ }); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); +/* harmony import */ var _inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @inertiajs/inertia-react */ "./node_modules/@inertiajs/inertia-react/dist/index.js"); +/* harmony import */ var react_toastify__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-toastify */ "./node_modules/react-toastify/dist/react-toastify.esm.js"); +/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); + + + + + +function FormEmployeeModal(props) { + var isOpen = props.isOpen, + _props$toggle = props.toggle, + toggle = _props$toggle === void 0 ? function () {} : _props$toggle, + _props$employee = props.employee, + employee = _props$employee === void 0 ? null : _props$employee; + + var _useForm = (0,_inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_1__.useForm)({ + name: '', + whatsapp: '', + photo: null, + img_alt: null + }), + data = _useForm.data, + setData = _useForm.setData, + post = _useForm.post, + processing = _useForm.processing, + errors = _useForm.errors, + clearErrors = _useForm.clearErrors; + + var inputPhoto = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(); + + var handleOnChange = function handleOnChange(event) { + setData(event.target.name, event.target.value); + }; + + var handleReset = function handleReset() { + setData({ + name: '', + whatsapp: '', + photo: null, + img_alt: null + }); + clearErrors(); + }; + + var handleCancel = function handleCancel() { + handleReset(); + toggle(); + }; + + var handleSubmit = function handleSubmit() { + if (employee !== null) { + post(route('employees.update', employee), { + forceFormData: true, + onSuccess: function onSuccess() { + return Promise.all([handleReset(), toggle(), react_toastify__WEBPACK_IMPORTED_MODULE_2__.toast.success('The Data has been changed')]); + } + }); + return; + } + + post(route('employees.store'), { + onSuccess: function onSuccess() { + return Promise.all([handleReset(), toggle(), react_toastify__WEBPACK_IMPORTED_MODULE_2__.toast.success('The Data has been saved')]); + } + }); + }; + + (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () { + setData({ + name: employee !== null && employee !== void 0 && employee.name ? employee.name : '', + whatsapp: employee !== null && employee !== void 0 && employee.whatsapp ? employee.whatsapp : '', + img_alt: employee !== null && employee !== void 0 && employee.photo_url ? employee.photo_url : null + }); + }, [employee]); + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + className: "modal", + style: isOpen ? { + opacity: 1, + pointerEvents: 'auto', + visibility: 'visible' + } : {}, + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { + className: "modal-box", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("h1", { + className: "font-bold text-2xl pb-8", + children: "Barang" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { + className: "form-control", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text", + children: "Nama" + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("input", { + type: "text", + placeholder: "nama", + className: "input input-bordered ".concat(errors.name && 'input-error'), + name: "name", + value: data.name, + onChange: handleOnChange + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text-alt", + children: errors.name + }) + })] + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { + className: "form-control", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text", + children: "Whatsapp" + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("input", { + type: "text", + placeholder: "whatsapp", + className: "input input-bordered ".concat(errors.whatsapp && 'input-error'), + name: "whatsapp", + value: data.whatsapp, + onChange: handleOnChange + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text-alt", + children: errors.whatsapp + }) + })] + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { + className: "form-control", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text", + children: "Foto" + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + className: "input input-bordered ".concat(errors.photo && 'input-error'), + onClick: function onClick() { + console.log(inputPhoto.current.click()); + }, + children: data.photo ? data.photo.name : '' + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("input", { + ref: inputPhoto, + type: "file", + className: "hidden", + name: "photo", + onChange: function onChange(e) { + return setData('photo', e.target.files[0]); + }, + accept: "image/png, image/jpeg, image/jpg" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("label", { + className: "label", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("span", { + className: "label-text-alt", + children: errors.photo + }) + })] + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + className: "form-control", + children: data.img_alt !== null && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("img", { + src: data.img_alt + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { + className: "modal-action", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + onClick: handleSubmit, + className: "btn btn-primary", + disabled: processing, + children: "Simpan" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + onClick: handleCancel, + className: "btn btn-secondary", + disabled: processing, + children: "Batal" + })] + })] + }) + }); +} + +/***/ }), + /***/ "./resources/js/Modals/FormProductModal.js": /*!*************************************************!*\ !*** ./resources/js/Modals/FormProductModal.js ***! @@ -5200,19 +5397,19 @@ function Dashboard(props) { className: "bg-white overflow-hidden shadow-sm rounded-lg w-full", children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { className: "py-4 px-4 font-bold text-xl", - children: ["Barang", /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { className: "text-4xl", children: product - })] + }), "Barang"] }) }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { className: "bg-white overflow-hidden shadow-sm rounded-lg w-full", children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)("div", { className: "py-4 px-4 font-bold text-xl", - children: ["Karyawan", /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { className: "text-4xl", children: employee - })] + }), "Karyawan"] }) })] }) @@ -5234,29 +5431,195 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ "default": () => (/* binding */ Employees) /* harmony export */ }); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); -/* harmony import */ var _Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/Layouts/Authenticated */ "./resources/js/Layouts/Authenticated.js"); -/* harmony import */ var _inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @inertiajs/inertia-react */ "./node_modules/@inertiajs/inertia-react/dist/index.js"); -/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); +/* harmony import */ var _inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @inertiajs/inertia-react */ "./node_modules/@inertiajs/inertia-react/dist/index.js"); +/* harmony import */ var _inertiajs_inertia__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @inertiajs/inertia */ "./node_modules/@inertiajs/inertia/dist/index.js"); +/* harmony import */ var react_use__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! react-use */ "./node_modules/react-use/esm/usePrevious.js"); +/* harmony import */ var react_toastify__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-toastify */ "./node_modules/react-toastify/dist/react-toastify.esm.js"); +/* harmony import */ var _Hooks__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/Hooks */ "./resources/js/Hooks/index.js"); +/* harmony import */ var _Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @/Layouts/Authenticated */ "./resources/js/Layouts/Authenticated.js"); +/* harmony import */ var _Components_Pagination__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/Components/Pagination */ "./resources/js/Components/Pagination.js"); +/* harmony import */ var _Components_ModalConfirm__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/Components/ModalConfirm */ "./resources/js/Components/ModalConfirm.js"); +/* harmony import */ var _Modals_FormEmployeeModal__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/Modals/FormEmployeeModal */ "./resources/js/Modals/FormEmployeeModal.js"); +/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } + +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + + + + + + + + function Employees(props) { - return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxs)(_Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_1__["default"], { + var _props$employees = props.employees, + employees = _props$employees.data, + links = _props$employees.links; + + var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''), + _useState2 = _slicedToArray(_useState, 2), + search = _useState2[0], + setSearch = _useState2[1]; + + var preValue = (0,react_use__WEBPACK_IMPORTED_MODULE_10__["default"])(search); + + var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null), + _useState4 = _slicedToArray(_useState3, 2), + employee = _useState4[0], + setEmployee = _useState4[1]; + + var formModal = (0,_Hooks__WEBPACK_IMPORTED_MODULE_4__.useModalState)(false); + + var toggle = function toggle() { + var employee = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + setEmployee(employee); + formModal.toggle(); + }; + + var confirmModal = (0,_Hooks__WEBPACK_IMPORTED_MODULE_4__.useModalState)(false); + + var handleDelete = function handleDelete(employee) { + confirmModal.setData(employee); + confirmModal.toggle(); + }; + + var onDelete = function onDelete() { + var employee = confirmModal.data; + + if (employee != null) { + _inertiajs_inertia__WEBPACK_IMPORTED_MODULE_2__.Inertia["delete"](route('employees.destroy', employee), { + onSuccess: function onSuccess() { + return react_toastify__WEBPACK_IMPORTED_MODULE_3__.toast.success('The Data has been deleted'); + } + }); + } + }; + + (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () { + if (preValue) { + _inertiajs_inertia__WEBPACK_IMPORTED_MODULE_2__.Inertia.get(route(route().current()), { + q: search + }, { + replace: true, + preserveState: true + }); + } + }, [search]); + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)(_Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_5__["default"], { auth: props.auth, errors: props.errors, - header: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("h2", { + header: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("h2", { className: "font-semibold text-xl text-gray-800 leading-tight", children: "Keryawan" }), - children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)(_inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_2__.Head, { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)(_inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_1__.Head, { title: "Employees" - }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { className: "py-12", - children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("div", { - className: "flex flex-row w-full sm:px-6 lg:px-8 space-x-4" + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "flex flex-col w-full sm:px-6 lg:px-8 space-y-2", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "card bg-white w-full", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("div", { + className: "card-body", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("div", { + className: "flex w-full mb-4 justify-between", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "btn btn-neutral", + onClick: function onClick() { + return toggle(); + }, + children: "Tambah" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "form-control", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("input", { + type: "text", + className: "input input-bordered", + value: search, + onChange: function onChange(e) { + return setSearch(e.target.value); + }, + placeholder: "Search" + }) + })] + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "overflow-x-auto", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("table", { + className: "table w-full table-zebra", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("thead", { + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("tr", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", { + children: "Id" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", { + children: "Nama" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", { + children: "Whatsapp" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", { + children: "Foto" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", {})] + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("tbody", { + children: employees === null || employees === void 0 ? void 0 : employees.map(function (employee) { + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("tr", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("th", { + children: employee.id + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("td", { + children: employee.name + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("td", { + children: employee.whatsapp + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("td", { + children: employee.photo_url !== null && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("img", { + width: "100px", + src: employee.photo_url + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsxs)("td", { + className: "text-right", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "btn btn-primary mx-1", + onClick: function onClick() { + return toggle(employee); + }, + children: "Edit" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)("div", { + className: "btn btn-secondary mx-1", + onClick: function onClick() { + return handleDelete(employee); + }, + children: "Delete" + })] + })] + }, employee.id); + }) + })] + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)(_Components_Pagination__WEBPACK_IMPORTED_MODULE_6__["default"], { + links: links + })] + }) + }) }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)(_Modals_FormEmployeeModal__WEBPACK_IMPORTED_MODULE_8__["default"], { + isOpen: formModal.isOpen, + toggle: toggle, + employee: employee + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_9__.jsx)(_Components_ModalConfirm__WEBPACK_IMPORTED_MODULE_7__["default"], { + isOpen: confirmModal.isOpen, + toggle: confirmModal.toggle, + onConfirm: onDelete })] }); } diff --git a/resources/js/Modals/FormEmployeeModal.js b/resources/js/Modals/FormEmployeeModal.js new file mode 100644 index 0000000..b2cc221 --- /dev/null +++ b/resources/js/Modals/FormEmployeeModal.js @@ -0,0 +1,169 @@ +import React, { useEffect, useRef } from 'react' +import { useForm } from '@inertiajs/inertia-react' +import { toast } from 'react-toastify' + +export default function FormEmployeeModal(props) { + const { isOpen, toggle = () => {}, employee = null } = props + + const { data, setData, post, processing, errors, clearErrors } = + useForm({ + name: '', + whatsapp: '', + photo: null, + img_alt: null, + }) + + const inputPhoto = useRef() + + const handleOnChange = (event) => { + setData(event.target.name, event.target.value) + } + + const handleReset = () => { + setData({ + name: '', + whatsapp: '', + photo: null, + img_alt: null, + }) + clearErrors() + } + + const handleCancel = () => { + handleReset() + toggle() + } + + const handleSubmit = () => { + if (employee !== null) { + post(route('employees.update', employee), { + forceFormData: true, + onSuccess: () => + Promise.all([ + handleReset(), + toggle(), + toast.success('The Data has been changed'), + ]), + }) + return + } + post(route('employees.store'), { + onSuccess: () => + Promise.all([ + handleReset(), + toggle(), + toast.success('The Data has been saved'), + ]), + }) + } + + useEffect(() => { + setData({ + name: employee?.name ? employee.name : '', + whatsapp: employee?.whatsapp ? employee.whatsapp : '', + img_alt: employee?.photo_url ? employee.photo_url : null, + }) + }, [employee]) + + return ( +
+
+

Barang

+
+ + + +
+
+ + + +
+
+ +
{ + console.log(inputPhoto.current.click()) + }} + > + {data.photo ? data.photo.name : ''} +
+ setData('photo', e.target.files[0])} + accept="image/png, image/jpeg, image/jpg" + /> + +
+
+ {data.img_alt !== null && } +
+
+
+ Simpan +
+
+ Batal +
+
+
+
+ ) +} diff --git a/resources/js/Pages/Dashboard.js b/resources/js/Pages/Dashboard.js index ecb60a8..752c383 100644 --- a/resources/js/Pages/Dashboard.js +++ b/resources/js/Pages/Dashboard.js @@ -20,14 +20,14 @@ export default function Dashboard(props) {
- Barang
{product}
+ Barang
- Karyawan
{employee}
+ Karyawan
diff --git a/resources/js/Pages/Employees.js b/resources/js/Pages/Employees.js index 3597041..7497245 100644 --- a/resources/js/Pages/Employees.js +++ b/resources/js/Pages/Employees.js @@ -1,24 +1,158 @@ -import React from 'react' -import Authenticated from '@/Layouts/Authenticated' +import React, { useState, useEffect } from 'react' import { Head } from '@inertiajs/inertia-react' +import { Inertia } from '@inertiajs/inertia' +import { usePrevious } from 'react-use' +import { toast } from 'react-toastify' + +import { useModalState } from '@/Hooks' +import Authenticated from '@/Layouts/Authenticated' +import Pagination from '@/Components/Pagination' +import ModalConfirm from '@/Components/ModalConfirm' +import FormEmployeeModal from '@/Modals/FormEmployeeModal' export default function Employees(props) { - return ( - - Keryawan - - } - > - -
-
- -
-
-
- ) -} \ No newline at end of file + const { data: employees, links } = props.employees + + const [search, setSearch] = useState('') + const preValue = usePrevious(search) + + const [employee, setEmployee] = useState(null) + const formModal = useModalState(false) + const toggle = (employee = null) => { + setEmployee(employee) + formModal.toggle() + } + + const confirmModal = useModalState(false) + const handleDelete = (employee) => { + confirmModal.setData(employee) + confirmModal.toggle() + } + + const onDelete = () => { + const employee = confirmModal.data + if (employee != null) { + Inertia.delete(route('employees.destroy', employee), { + onSuccess: () => toast.success('The Data has been deleted'), + }) + } + } + + useEffect(() => { + if (preValue) { + Inertia.get( + route(route().current()), + { q: search }, + { + replace: true, + preserveState: true, + } + ) + } + }, [search]) + + return ( + + Keryawan + + } + > + +
+
+
+
+
+
toggle()} + > + Tambah +
+
+ + setSearch(e.target.value) + } + placeholder="Search" + /> +
+
+
+ + + + + + + + + + + + {employees?.map((employee) => ( + + + + + + + + ))} + +
IdNamaWhatsappFoto
{employee.id}{employee.name}{employee.whatsapp} + {employee.photo_url !== + null && ( + + )} + +
+ toggle(employee) + } + > + Edit +
+
+ handleDelete( + employee + ) + } + > + Delete +
+
+
+ +
+
+
+
+ + +
+ ) +} diff --git a/routes/api.php b/routes/api.php index eb6fa48..0076622 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\Api\EmployeeQueryController; /* |-------------------------------------------------------------------------- @@ -13,6 +14,7 @@ use Illuminate\Support\Facades\Route; | is assigned the "api" middleware group. Enjoy building your API! | */ +Route::get('employees', EmployeeQueryController::class)->name('api.employees.query'); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); diff --git a/routes/web.php b/routes/web.php index 9ee7485..9f96b2e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\DashboardController; use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; +use App\Http\Controllers\EmployeeController; /* |-------------------------------------------------------------------------- @@ -34,7 +35,11 @@ Route::middleware(['auth'])->group(function () { Route::post('/products/{product}', [ProductController::class, 'update'])->name('products.update'); Route::delete('/products/{product}', [ProductController::class, 'destroy'])->name('products.destroy'); - Route::get('/employees', fn () => inertia('Employees'))->name('employees.index'); + Route::get('/employees', [EmployeeController::class, 'index'])->name('employees.index'); + Route::post('/employees', [EmployeeController::class, 'store'])->name('employees.store'); + Route::post('/employees/{employee}', [EmployeeController::class, 'update'])->name('employees.update'); + Route::delete('/employees/{employee}', [EmployeeController::class, 'destroy'])->name('employees.destroy'); + Route::get('/payrolls', fn () => inertia('Payrolls'))->name('payrolls.index'); Route::get('/report', fn () => inertia('Report'))->name('report'); });