From ef668a6f5ca46be59e59a406d06f4d8b891a387b Mon Sep 17 00:00:00 2001 From: ValeriGuerrero Date: Thu, 26 Dec 2024 17:51:46 -0600 Subject: [PATCH] add edit for error handling and validation --- src/components/AddMedicineForm.jsx | 2 +- src/components/EditMedicineForm.jsx | 52 +++-- src/pages/AddDrug.jsx | 189 ++++++++++----- src/pages/EditDrug.jsx | 344 +++++++++++++++++----------- 4 files changed, 380 insertions(+), 207 deletions(-) diff --git a/src/components/AddMedicineForm.jsx b/src/components/AddMedicineForm.jsx index 778c321..182048b 100644 --- a/src/components/AddMedicineForm.jsx +++ b/src/components/AddMedicineForm.jsx @@ -13,7 +13,7 @@ const AddMedicineForm = ({ id, value, handleMedChange, placeholder }) => { { const inputRef = useRef(); useEffect(() => { - if (inputRef.current) { + if (id === 'name' && inputRef.current) { inputRef.current.focus(); } - }, []); + }, [id]); + + const formatForDatetimeLocal = (isoDate) => { + if (!isoDate) return ''; + const date = new Date(isoDate); + if (isNaN(date.getTime())) { + console.warn(`Invalid ISO date provided: ${isoDate}`); + return ''; + } + const offsetDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000); + return offsetDate.toISOString().slice(0, 16); + }; + + // Format value for datetime-local if it's for expirationDate + const formattedValue = id === 'expirationDate' ? formatForDatetimeLocal(value) : value; return ( - <> - - + ); }; @@ -53,11 +65,9 @@ export const StyleInput = styled.input` border: 1px solid var(--grey-300); color: black; height: 35px; - margin-bottom: 15px; /* Placeholder text color */ &::placeholder { color: black; /* Set placeholder text to black */ - margin-bottom: 0px; } `; diff --git a/src/pages/AddDrug.jsx b/src/pages/AddDrug.jsx index d18bd20..39eaf5e 100644 --- a/src/pages/AddDrug.jsx +++ b/src/pages/AddDrug.jsx @@ -27,9 +27,15 @@ export default function AddDrug({ addDrugs }) { lot: '', }); + const formatForDatetimeLocal = (isoDate) => { + const date = new Date(isoDate); + const offsetDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000); + return offsetDate.toISOString().slice(0, 16); + }; + const formatDate = (date) => { if (!date) return ''; - return new Date(date).toISOString().split('T')[0]; + return formatForDatetimeLocal(date); }; const drugClasses = [ @@ -42,6 +48,82 @@ export default function AddDrug({ addDrugs }) { ]; const handleMedChange = ({ target: { id, value } }) => { + if (id === 'name') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + name: 'Please provide Medication Name', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'genericName') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + genericName: 'Please provide Generic Medication Name', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'quantity') { + if (parseInt(value) < 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + quantity: 'Please provide Quantity must be a non-negative number', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'threshold') { + if (parseInt(value) < 10) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + threshold: 'Please provide threshold quantity greater than 10', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'expirationDate') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + expirationDate: 'Please provide Expiration Date', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'ndcNumber') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + ndcNumber: 'Please provide NDC Number', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'lot') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + lot: 'Please provide LOT Number', + })); + } else { + setErrorsForm({}); + } + } setFormData((prev) => ({ ...prev, [id]: @@ -81,11 +163,10 @@ export default function AddDrug({ addDrugs }) { return errors; }; const isEmpty = (obj) => Object.keys(obj).length === 0; + const handleAddMed = (event) => { event.preventDefault(); - const errors = validate(formData); - setErrorsForm(errors); addDrugs = { @@ -93,28 +174,28 @@ export default function AddDrug({ addDrugs }) { }; const token = localStorage.getItem('token'); - if (formData.threshold > 10) { - fetch('http://localhost:8000/api/v1/inventory', { - method: 'POST', - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(addDrugs), + + fetch('http://localhost:8000/api/v1/inventory', { + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(addDrugs), + }) + .then((response) => { + return response.json(); }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to add drug, please try again.'); - } - return response.json(); - }) - .then(() => { + .then((data) => { + if (data.success) { toast.success('Registration Successful'); - }) - .catch((error) => { - console.error(error); - }); - } + } else { + toast.error(data.error); + } + }) + .catch((error) => { + console.error(error); + }); if (isEmpty(errors)) { console.log('this are errors', errors); @@ -217,7 +298,6 @@ export default function AddDrug({ addDrugs }) { ))} - SAVE DRUG @@ -227,23 +307,22 @@ export default function AddDrug({ addDrugs }) { AddDrug.propTypes = { addDrugs: PropTypes.func.isRequired, - drugs: PropTypes.arrayOf(PropTypes.object), }; export const Wrapper = styled.section` - min-height: 100vh; - display: grid; - align-items: center; - h4 { - text - align: center; - margin-bottom: 1.38rem; - } - .logo { - display: block; - margin: 0 auto; - margin-bottom: 1.38rem; - } - `; + min-height: 100vh; + display: grid; + align-items: center; + h4 { + text - align: center; + margin-bottom: 1.38rem; + } + .logo { + display: block; + margin: 0 auto; + margin-bottom: 1.38rem; + } + `; export const FormField = styled.div``; @@ -277,23 +356,23 @@ export const FormSection = styled.div` `; export const Fieldwrapper = styled.div` - .form-row { - margin - bottom: 0.5rem; - } - input { - width: 100%; - padding: 0.375rem 0.75rem; - border-radius: var(--border-radius); - border: 1px solid var(--grey-300); - color: var(--text-color); - height: 35px; - background-color: white; - } - label { - font - size: 0.9rem; - text-transform: lowercase; - } - `; + .form-row { + margin - bottom: 0.5rem; + } + input { + width: 100%; + padding: 0.375rem 0.75rem; + border-radius: var(--border-radius); + border: 1px solid var(--grey-300); + color: var(--text-color); + height: 35px; + background-color: white; + } + label { + font - size: 0.9rem; + text-transform: lowercase; + } + `; export const AddButton = styled.button` margin-top: 1rem; diff --git a/src/pages/EditDrug.jsx b/src/pages/EditDrug.jsx index 5d45b7e..6731463 100644 --- a/src/pages/EditDrug.jsx +++ b/src/pages/EditDrug.jsx @@ -2,10 +2,13 @@ import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import EditMedicineForm from '../components/EditMedicineForm'; import styled from 'styled-components'; -import { FaEdit } from 'react-icons/fa'; +import Logo from '../components/Logo'; +import { toast } from 'react-toastify'; +import { useNavigate } from 'react-router-dom'; export default function EditDrug() { - const { id } = useParams(); // Get drug ID from URL + const { id } = useParams(); + const navigate = useNavigate(); const [editData, setEditData] = useState({ name: '', genericName: '', @@ -16,6 +19,23 @@ export default function EditDrug() { ndcNumber: '', lot: '', }); + + const [errorsForm, setErrorsForm] = useState({ + name: '', + genericName: '', + class: '', + quantity: '', + threshold: '', + expirationDate: '', + ndcNumber: '', + lot: '', + }); + const formatForDatetimeLocal = (isoDate) => { + const date = new Date(isoDate); + const offsetDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000); + return offsetDate.toISOString().slice(0, 16); + }; + const drugClasses = [ 'Antibiotic', 'Analgesic', @@ -27,7 +47,6 @@ export default function EditDrug() { ]; useEffect(() => { - // Fetch existing drug data to populate form const token = localStorage.getItem('token'); fetch(`http://localhost:8000/api/v1/inventory/${id}`, { method: 'GET', @@ -55,129 +74,200 @@ export default function EditDrug() { const handleInputChange = (event) => { const { id, value } = event.target; + if (id === 'name') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + name: 'Please provide Medication Name', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'genericName') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + genericName: 'Please provide Generic Medication Name', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'quantity') { + if (parseInt(value) < 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + quantity: 'Please provide Quantity must be a non-negative number', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'threshold') { + if (parseInt(value) < 10) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + threshold: 'Please provide threshold quantity greater than 10', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'expirationDate') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + expirationDate: 'Please provide Expiration Date', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'ndcNumber') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + ndcNumber: 'Please provide NDC Number', + })); + } else { + setErrorsForm({}); + } + } + + if (id === 'lot') { + if (value.length <= 0) { + setErrorsForm((prevErrors) => ({ + ...prevErrors, + lot: 'Please provide LOT Number', + })); + } else { + setErrorsForm({}); + } + } + setEditData((prev) => ({ ...prev, - [id]: id === 'quantity' || id === 'threshold' ? parseInt(value, 10) || '' : value, + [id]: + id === 'quantity' || id === 'threshold' + ? Math.max(0, parseInt(value, 10)) || '' + : id === 'expirationDate' + ? value + : value, })); }; + const validate = (values) => { + const errors = {}; + + if (!values.name) { + errors.name = 'Please provide Medication Name'; + } + if (!values.genericName) { + errors.genericName = 'Please provide Generic Medication Name'; + } + if (!values.quantity) { + errors.quantity = 'Please provide Quantity must be a non-negative number'; + } + if (!values.threshold) { + errors.threshold = 'Please provide threshold quantity'; + } else if (values.threshold < 10) { + errors.threshold = 'Threshold must be higher than 10'; + } + if (!values.expirationDate) { + errors.expirationDate = 'Please provide Expiration Date'; + } + if (!values.ndcNumber) { + errors.ndcNumber = 'Please provide NDC Number'; + } + if (!values.lot) { + errors.lot = 'Please provide Lot Code'; + } + return errors; + }; + const isEmpty = (obj) => Object.keys(obj).length === 0; + const handleSaveChanges = (event) => { event.preventDefault(); - - const token = localStorage.getItem('token'); - fetch(`http://localhost:8000/api/v1/inventory/${id}`, { - method: 'PATCH', // Or other HTTP methods like POST, PUT, DELETE, etc. - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(editData), - }) - .then((response) => { - // Handle the response - if (!response.ok) { - throw new Error('Network response was not ok'); - } - return response.json(); // Assuming the response is JSON + const errors = validate(editData); + setErrorsForm(errors); + if (isEmpty(errors)) { + const token = localStorage.getItem('token'); + fetch(`http://localhost:8000/api/v1/inventory/${id}`, { + method: 'PATCH', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + ...editData, + expirationDate: formatForDatetimeLocal(editData.expirationDate), // Format the date before sending + }), }) - .then((data) => { - // Do something with the data - console.log(data); - }) - .catch((error) => { - // Handle errors - console.error('Error:', error); - }); - - setEditData({ - name: '', - genericName: '', - class: '', - quantity: '', - threshold: '', - expirationDate: '', - ndcNumber: '', - lot: '', - }); + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + if (data.success) { + toast.success('Changes saved successfully'); + navigate('/dashboard'); + } else { + toast.error(data.error || 'Failed to save changes'); + } + }) + .catch((error) => console.error('Error:', error)); + } }; - return ( - -
-
-
-

Edit Medication

- -
- {Object.entries(editData).map(([id, value]) => ( -
- - {id.replace(/([A-Z])/g, ' $1').toLowerCase()}{' '} - {/* This will render the label text */} - - {id === 'class' ? ( -
- -
- ) : ( - - - - Quantity - - - -
- - Min Amount - - -
-
-
-
- )} -
+ const renderFormRow = (id, value) => ( +
+ {id.replace(/([A-Z])/g, ' $1').toLowerCase()} + {id === 'class' ? ( + + ) : ( + + )} + {errorsForm[id] && ( +

+ {errorsForm[id]} +

+ )} +
+ ); - {/* Add other form fields as needed */} - -
-
+ return ( + + +
+ +

EDIT DRUG

+ {Object.entries(editData).map(([id, value]) => renderFormRow(id, value))} +
+ Save Changes +
); } @@ -186,20 +276,6 @@ export const Wrapper = styled.section` min-height: 100vh; display: grid; align-items: center; - .icon-heading { - display: flex; - } - .heading { - font-size: 2rem; - margin-bottom: 1rem; - font-weight: bold; - color: var(--color-blue-dark); - } - .icon { - font-size: 2rem; - margin-left: 1rem; - color: var(--color-green-dark); - } h4 { text-align: center; margin-bottom: 1.38rem; @@ -223,7 +299,15 @@ export const AddForm = styled.form` margin: 3rem auto; `; -export const StyledLabel = styled.label``; +export const StyledLabel = styled.label` + text-transform: lowercase; + display: block; + font-size: var(--small-text); + margin-bottom: 0.75rem; + text-transform: capitalize; + letter-spacing: var(--letter-spacing); + line-height: 1.5; +`; export const FormSection = styled.div` width: 90vw; @@ -253,7 +337,7 @@ export const Fieldwrapper = styled.div` } `; -export const AddButton = styled.button` +export const SaveButton = styled.button` margin-top: 1rem; background-color: var(--color-blue-dark); width: 100%;