final
parent
5743ebb0a1
commit
00d25e09d8
@ -1,57 +1,25 @@
|
||||
import { Fragment } from 'react';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import React from "react";
|
||||
|
||||
export default function Modal({ children, show = false, maxWidth = '2xl', closeable = true, onClose = () => {} }) {
|
||||
const close = () => {
|
||||
if (closeable) {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const maxWidthClass = {
|
||||
sm: 'sm:max-w-sm',
|
||||
md: 'sm:max-w-md',
|
||||
lg: 'sm:max-w-lg',
|
||||
xl: 'sm:max-w-xl',
|
||||
'2xl': 'sm:max-w-2xl',
|
||||
}[maxWidth];
|
||||
|
||||
export default function Modal({ isOpen, toggle = () => {}, children, title = ''}) {
|
||||
return (
|
||||
<Transition show={show} as={Fragment} leave="duration-200">
|
||||
<Dialog
|
||||
as="div"
|
||||
id="modal"
|
||||
className="fixed inset-0 flex overflow-y-auto px-4 py-6 sm:px-0 items-center z-50 transform transition-all"
|
||||
onClose={close}
|
||||
>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="absolute inset-0 bg-gray-500/75" />
|
||||
</Transition.Child>
|
||||
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel
|
||||
className={`mb-6 bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:mx-auto ${maxWidthClass}`}
|
||||
>
|
||||
{children}
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
);
|
||||
}
|
||||
<div
|
||||
className={`modal`}
|
||||
style={
|
||||
isOpen
|
||||
? {
|
||||
opacity: 1,
|
||||
pointerEvents: 'auto',
|
||||
visibility: 'visible',
|
||||
}
|
||||
: {}
|
||||
}>
|
||||
<div className={`modal-box`} style={{minHeight: '40em'}}>
|
||||
<h1 className="font-bold text-2xl pb-8">
|
||||
{title}
|
||||
</h1>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Modal from "@/Components/Modal";
|
||||
import InputError from "@/Components/InputError";
|
||||
import { DatePickerInput } from "@/Components/DatePickerInput";
|
||||
import { useForm, usePage } from "@inertiajs/inertia-react";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
export default function FormModal(props) {
|
||||
const { auth: { user } } = usePage().props
|
||||
|
||||
const { modalState } = props
|
||||
const { data, setData, post, put, processing, errors, reset, clearErrors } = useForm({
|
||||
id: null,
|
||||
name: "",
|
||||
description: "",
|
||||
job_number: "",
|
||||
date_expense: new Date(),
|
||||
amount: "",
|
||||
isIncome: 0,
|
||||
is_paid: 0,
|
||||
})
|
||||
|
||||
const setType = (type) => {
|
||||
setData('isIncome',type)
|
||||
}
|
||||
|
||||
const handleOnChange = (event) => {
|
||||
setData(event.target.name, event.target.value)
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
modalState.setData(null)
|
||||
reset()
|
||||
clearErrors()
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
handleReset()
|
||||
modalState.toggle()
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
const expense = modalState.data
|
||||
if(expense !== null) {
|
||||
put(route('expenses.update', expense), {
|
||||
onSuccess: () => {
|
||||
toast.success('item updated')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
post(route('expenses.store'), {
|
||||
onSuccess: () => {
|
||||
toast.success('item created')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const title = data.id ? 'Edit Data' : 'Tambah Data'
|
||||
|
||||
useEffect(() => {
|
||||
const expense = modalState.data
|
||||
if (expense !== null) {
|
||||
setData({
|
||||
id: expense?.id,
|
||||
name: expense?.name,
|
||||
description: expense?.description,
|
||||
job_number: expense?.job_number,
|
||||
date_expense: new Date(expense?.date_expense),
|
||||
amount: expense?.amount,
|
||||
isIncome: expense?.isIncome,
|
||||
is_paid: expense?.is_paid,
|
||||
})
|
||||
return
|
||||
}
|
||||
}, [modalState])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={modalState.isOpen}
|
||||
toggle={handleClose}
|
||||
title={title}
|
||||
>
|
||||
{+user.role === 1 && (
|
||||
<div className="tabs w-full mb-2">
|
||||
<a
|
||||
className={`tab tab-bordered w-1/2 ${data.isIncome === 0 ? 'tab-active' : ''}`}
|
||||
onClick={() => setType(0)}
|
||||
>
|
||||
Pengeluaran
|
||||
</a>
|
||||
<a
|
||||
className={`tab tab-bordered w-1/2 ${data.isIncome === 1 ? 'tab-active' : ''}`}
|
||||
onClick={() => setType(1)}
|
||||
>
|
||||
Pemasukan
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.isIncome === 0 && (
|
||||
<>
|
||||
<div className="form-control mb-2">
|
||||
<label>Nama</label>
|
||||
<input
|
||||
className="input input-bordered"
|
||||
name="name"
|
||||
value={data.name}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<InputError message={errors.name} className="mt-2" />
|
||||
</div>
|
||||
<div className="form-control mb-2">
|
||||
<label>Job Number</label>
|
||||
<input
|
||||
className="input input-bordered"
|
||||
name="job_number"
|
||||
value={data.job_number}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<InputError message={errors.job_number} className="mt-2" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="form-control mb-2">
|
||||
<label>Deskripsi</label>
|
||||
<textarea
|
||||
className="textarea textarea-bordered"
|
||||
name="description"
|
||||
value={data.description}
|
||||
onChange={handleOnChange}
|
||||
rows={5}
|
||||
/>
|
||||
<InputError message={errors.description} className="mt-2" />
|
||||
</div>
|
||||
<div className="form-control mb-2">
|
||||
<label>Tanggal</label>
|
||||
<DatePickerInput
|
||||
value={data.date_expense}
|
||||
onChange={date => setData('date_expense', date)}
|
||||
/>
|
||||
<InputError message={errors.date_expense} className="mt-2" />
|
||||
</div>
|
||||
<div className="form-control mb-2">
|
||||
<label>Amount</label>
|
||||
<input
|
||||
type="number"
|
||||
className="input input-bordered"
|
||||
name="amount"
|
||||
value={data.amount}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<InputError message={errors.amount} className="mt-2" />
|
||||
</div>
|
||||
|
||||
{data.isIncome === 0 && (
|
||||
<div className="form-control mb-2">
|
||||
<label>Status</label>
|
||||
<select
|
||||
name="is_paid"
|
||||
className="select select-bordered w-full"
|
||||
disabled={+user.role === 2}
|
||||
value={data.is_paid}
|
||||
onChange={handleOnChange}
|
||||
>
|
||||
<option value="0">Draft</option>
|
||||
<option value="1">Paid</option>
|
||||
<option value="2">Approve</option>
|
||||
<option value="3">Reject</option>
|
||||
</select>
|
||||
<InputError message={errors.amount} className="mt-2" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full flex justify-end space-x-1 items-center mt-2">
|
||||
<button
|
||||
className="btn"
|
||||
onClick={handleSubmit}
|
||||
disabled={processing}
|
||||
>
|
||||
Simpan
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={handleClose}
|
||||
type="secondary"
|
||||
>
|
||||
Batal
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import DangerButton from '@/Components/DangerButton';
|
||||
import InputError from '@/Components/InputError';
|
||||
import InputLabel from '@/Components/InputLabel';
|
||||
import Modal from '@/Components/Modal';
|
||||
import SecondaryButton from '@/Components/SecondaryButton';
|
||||
import TextInput from '@/Components/TextInput';
|
||||
import { useForm } from '@inertiajs/inertia-react';
|
||||
|
||||
export default function DeleteUserForm({ className }) {
|
||||
const [confirmingUserDeletion, setConfirmingUserDeletion] = useState(false);
|
||||
const passwordInput = useRef();
|
||||
|
||||
const {
|
||||
data,
|
||||
setData,
|
||||
delete: destroy,
|
||||
processing,
|
||||
reset,
|
||||
errors,
|
||||
} = useForm({
|
||||
password: '',
|
||||
});
|
||||
|
||||
const confirmUserDeletion = () => {
|
||||
setConfirmingUserDeletion(true);
|
||||
};
|
||||
|
||||
const deleteUser = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
destroy(route('profile.destroy'), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => closeModal(),
|
||||
onError: () => passwordInput.current.focus(),
|
||||
onFinish: () => reset(),
|
||||
});
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setConfirmingUserDeletion(false);
|
||||
|
||||
reset();
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={`space-y-6 ${className}`}>
|
||||
<header>
|
||||
<h2 className="text-lg font-medium text-gray-900">Delete Account</h2>
|
||||
|
||||
<p className="mt-1 text-sm text-gray-600">
|
||||
Once your account is deleted, all of its resources and data will be permanently deleted. Before
|
||||
deleting your account, please download any data or information that you wish to retain.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<DangerButton onClick={confirmUserDeletion}>Delete Account</DangerButton>
|
||||
|
||||
<Modal show={confirmingUserDeletion} onClose={closeModal}>
|
||||
<form onSubmit={deleteUser} className="p-6">
|
||||
<h2 className="text-lg font-medium text-gray-900">
|
||||
Are you sure you want to delete your account?
|
||||
</h2>
|
||||
|
||||
<p className="mt-1 text-sm text-gray-600">
|
||||
Once your account is deleted, all of its resources and data will be permanently deleted. Please
|
||||
enter your password to confirm you would like to permanently delete your account.
|
||||
</p>
|
||||
|
||||
<div className="mt-6">
|
||||
<InputLabel for="password" value="Password" className="sr-only" />
|
||||
|
||||
<TextInput
|
||||
id="password"
|
||||
type="password"
|
||||
name="password"
|
||||
ref={passwordInput}
|
||||
value={data.password}
|
||||
handleChange={(e) => setData('password', e.target.value)}
|
||||
className="mt-1 block w-3/4"
|
||||
isFocused
|
||||
placeholder="Password"
|
||||
/>
|
||||
|
||||
<InputError message={errors.password} className="mt-2" />
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex justify-end">
|
||||
<SecondaryButton onClick={closeModal}>Cancel</SecondaryButton>
|
||||
|
||||
<DangerButton className="ml-3" processing={processing}>
|
||||
Delete Account
|
||||
</DangerButton>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue