Compare commits

..

4 Commits

38 changed files with 2127 additions and 1313 deletions

View File

@ -29,7 +29,7 @@
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> -->
<style>
body {
background-color: #f9fff6;
background-color: #E9ECFF;
background-image: url('../src/assets/Image/Pattern.png');
background-size: cover;
background-repeat: no-repeat;

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

BIN
src/assets/Image/owner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

BIN
src/assets/Image/store.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

BIN
src/assets/Image/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

View File

@ -37,6 +37,7 @@ body {
color: #000;
box-shadow: none;
}
.btn-primary {
width: 100px;
@ -108,6 +109,7 @@ body {
padding: 10px 20px;
border-radius: 10px;
display: flex;
justify-content: space-between;
box-shadow: 0px 0px 10px rgba(66, 71, 76, 0.08);
align-items: center;
@ -122,6 +124,7 @@ body {
color: #ffffff; /* Active link color */
background-color: #282e26;
border-radius: 20px;
padding: 10px 15px;
font-weight: bold; /* Bold text for active link */
}
.nav-list {
@ -142,7 +145,7 @@ body {
}
.nav-link {
font-family: "Manrope";
font-size: 18px !important;
font-size: 16px !important;
color: #002300;
text-decoration: none;
@ -367,7 +370,7 @@ body {
.row {
display: flex;
flex-wrap: wrap;
gap: 40px;
gap: 20px;
}
.col-2 {
@ -494,6 +497,7 @@ body {
}
.search-container input {
width: 100%;
color: #000;
height: 50px;
background: #f4f4f4;
border-radius: 50px;
@ -503,7 +507,7 @@ body {
box-sizing: border-box;
}
.search-container input::placeholder {
color: #ffffff;
color: #282E26;
}
.search-container input:focus {
outline: none;
@ -789,7 +793,8 @@ h3 {
.table-responsive th {
background-color: #f4f4f4;
background-color: #282e26;
color: white;
}
.table-responsives {
border: 0.5px solid #f4f4f4;
@ -850,14 +855,18 @@ h5 {
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-container {
max-width: 768px; /* Updated to 768px */
margin: 0;
background-color: white;
border-radius: 0.5rem;
}
.modal-header,
.modal-body,
.modal-footer {

View File

@ -320,7 +320,7 @@ function AddInvoice() {
type: "pay-bank-options",
},
{
row: 5,
row: 3,
column: "col-md-3",
label: "Due Days",
type: "select-dueDays",
@ -443,7 +443,7 @@ function AddInvoice() {
case "prefix-input":
return (
<div
className="form-group col-md-6"
className="form-group col-md-12"
style={{
display: "flex",
alignItems: "center",
@ -781,7 +781,7 @@ function AddInvoice() {
<div className="row mb-3">
<div className="col-md-6">
<div className="form-group">
{/* <label htmlFor="prepaid_amount">Prepaid Tax</label> */}
<input
type="text"
className="form-control-borderless"

View File

@ -197,8 +197,8 @@ function BankDeposit() {
<div className="col-md-12 row mb-3">
<div className="mb-3 col-md-4">
<div className="col-md-12 row ">
<div className=" col-md-4">
<input
type="date"
className="form-control-borderless"
@ -245,12 +245,13 @@ function BankDeposit() {
<div
className="col-md-12"
className="col-md-12 mb-12"
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between", // Adjust spacing between items
gap: "50px", // Add gap for consistent spacing
// marginBottom:"30px",
}}
>
<div
@ -278,7 +279,7 @@ function BankDeposit() {
</div>
<div
className="form-group "
className="form-group "
style={{
display: "flex",
alignItems: "center",

View File

@ -89,12 +89,12 @@
.input-group {
flex-wrap: nowrap;
border-radius: 50px;
background-color: #f4f4f4;
/* background-color: #f4f4f4; */
}
.input-group .form-control {
border: none;
/* background-color: transparent; */
background-color: transparent;
outline: none; /* Removes the outline */
}
@ -102,12 +102,12 @@
.table th {
justify-content: center;
height: 60px;
background-color: #f9f9f9;
background-color: #ffffff;
font-weight: bold;
}
.table td {
border-bottom: .5px solid #f4f4f4;
border-bottom: 1px solid #EBEAF2;
text-align: left;
vertical-align: middle;
}
@ -127,8 +127,8 @@
border-end-start-radius: 24px;
border-end-end-radius: 24px;
padding: 10px;
background-color: #f4f4f4;
border-bottom: 2px solid #EBEAF2;
background-color: #ffffff;
justify-content: center;
align-items: center;
}
@ -324,4 +324,3 @@ input[type="color"]:focus,
box-shadow: none; /* Remove any shadow */
}

View File

@ -763,24 +763,50 @@ const paymentMethodStyles = {
const getPaymentMethodStyle = (method) => ({
...(paymentMethodStyles[method] || { backgroundColor: "#6c757d" }),
borderRadius: "5px",
padding: "10px 20px",
color: "#000",
});
const statusStyles = {
All: { backgroundColor: "#4545DB" },
// draft: { backgroundColor: '#4545DB7C' },
unpaid: { backgroundColor: "#ff2024" },
partially_paid: { backgroundColor: "#0c8ce9" },
All: {
backgroundColor: "#4545DB",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
paid: {
backgroundColor: "#198f51",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
unpaid: {
backgroundColor: "#ff2024",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
partially_paid: {
backgroundColor: "#0c8ce9",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
};
const getStatusStyle = (status) => ({
...(statusStyles[status] || { backgroundColor: "#198f51" }),
...(statusStyles[status] || { backgroundColor: "#198f51", width: "150px", height: "40px" }), // Default style
borderRadius: "5px",
padding: "10px 20px",
padding: "5px 20px",
textAlign: "center",
display: "flex", // Use flexbox for alignment
justifyContent: "center", // Center horizontally
alignItems: "center", // Center vertically
color: "#fff",
});
const getCountClass = (status) => ({
...statusStyles[status],
padding: "10px",

View File

@ -19,13 +19,13 @@ function PayInvoice() {
const navigate = useNavigate();
const [activeButton, setActiveButton] = useState('');
const location = useLocation();
useEffect(() => {
setActiveButton(location.pathname); // Set the active button based on the current location
}, [location.pathname]);
const [activeButton, setActiveButton] = useState('');
const location = useLocation();
useEffect(() => {
setActiveButton(location.pathname); // Set the active button based on the current location
}, [location.pathname]);
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);
@ -63,7 +63,7 @@ function PayInvoice() {
bank: "",
});
const makeBlank = ()=>{
const makeBlank = () => {
setFormData({
store_id: user.store,
invoice_no: "",
@ -200,14 +200,14 @@ function PayInvoice() {
setInitialAmount("");
}
};
const handleSubmit = async (e) => {
e.preventDefault();
// Check if the payment method is selected
if (!formData.pay_method) {
toast.error("Please select a payment method before submitting.");
return; // Prevent form submission if payment method is not selected
toast.error("Please select a payment method before submitting.");
return; // Prevent form submission if payment method is not selected
}
const payAmount = parseFloat(formData.pay_amount);
@ -218,58 +218,58 @@ function PayInvoice() {
if (newRemainingAmount < 0) {
toast.error("Payment amount exceeds the remaining amount. Please enter a valid amount.");
return; // Prevent form submission if payment exceeds remaining amount
toast.error("Payment amount exceeds the remaining amount. Please enter a valid amount.");
return; // Prevent form submission if payment exceeds remaining amount
}
const status = newRemainingAmount <= 0 ? "paid" : "partially_paid"; // If remaining is 0 or less, mark it as 'paid'
const finalRemainingAmount =
newRemainingAmount <= 0 ? "0.00" : newRemainingAmount.toFixed(2); // If fully paid, remaining should be 0
newRemainingAmount <= 0 ? "0.00" : newRemainingAmount.toFixed(2); // If fully paid, remaining should be 0
let updatedFormData = {
...formData,
remaining_amount: finalRemainingAmount, // Update the remaining amount
status: status, // Set the status based on the remaining amount
cheque_no: formData.pay_method === "cheque" ? formData.cheque_no : null,
bank: formData.pay_method === "bank" ? formData.bank : null,
...formData,
remaining_amount: finalRemainingAmount, // Update the remaining amount
status: status, // Set the status based on the remaining amount
cheque_no: formData.pay_method === "cheque" ? formData.cheque_no : null,
bank: formData.pay_method === "bank" ? formData.bank : null,
};
// Check if the pay_method_status is 'credit_invoice'
if (updatedFormData.pay_method_status !== "credit_invoice") {
updatedFormData = {
...updatedFormData,
pay_method_status: "credit_invoice", // Force setting pay_method_status to 'credit_invoice'
};
updatedFormData = {
...updatedFormData,
pay_method_status: "credit_invoice", // Force setting pay_method_status to 'credit_invoice'
};
}
console.log("Submitting:", updatedFormData);
try {
if (!updatedFormData.id) {
toast.error("No invoice selected. Please select an invoice before submitting.");
return;
}
if (!updatedFormData.id) {
toast.error("No invoice selected. Please select an invoice before submitting.");
return;
}
const response = await Patch(`invoiceData`, updatedFormData.id, updatedFormData);
const response = await Patch(`invoiceData`, updatedFormData.id, updatedFormData);
if (response && response.status === 200) {
console.log("Submission successful:", response.data);
toast.success("Invoice payment submitted successfully!");
setReloadData(!reloadData);
makeBlank();
// window.location.reload(); // Reload the page to reflect changes
} else {
setReloadData(!reloadData);
if (response && response.status === 200) {
console.log("Submission successful:", response.data);
toast.success("Invoice payment submitted successfully!");
setReloadData(!reloadData);
makeBlank();
// window.location.reload(); // Reload the page to reflect changes
} else {
setReloadData(!reloadData);
console.error("Failed to submit:", response.data);
toast.error(`Error: ${response.data.message || "Failed to update invoice."}`);
}
console.error("Failed to submit:", response.data);
toast.error(`Error: ${response.data.message || "Failed to update invoice."}`);
}
} catch (error) {
setReloadData(!reloadData);
console.error("Error:", error);
toast.error(`An unexpected error occurred: ${error.message || "Please try again later."}`);
console.error("Error:", error);
toast.error(`An unexpected error occurred: ${error.message || "Please try again later."}`);
}
};
};
const handleCancel = () => {
navigate("/");
@ -300,49 +300,49 @@ function PayInvoice() {
return (
<div className="dashboard-container">
<div className="d-flex justify-content-between mb-4">
<div className="button-groups">
<button
className={`btn ${activeButton === '/' ? 'active' : ''}`}
onClick={() => handleLinkClick('/')}
>
Add Invoice
</button>
<button
className={`btn ${activeButton === '/payInvoice' ? 'active' : ''}`}
onClick={() => handleLinkClick('/payInvoice')}
>
Pay Invoice
</button>
<button
className={`btn ${activeButton === '/bankDeposit' ? 'active' : ''}`}
onClick={() => handleLinkClick('/bankDeposit')}
>
Bank Deposit
</button>
<button
className={`btn ${activeButton === '/atmDeposit' ? 'active' : ''}`}
onClick={() => handleLinkClick('/atmDeposit')}
>
ATM Deposit
</button>
<div className="d-flex justify-content-between mb-4">
<div className="button-groups">
<button
className={`btn ${activeButton === '/' ? 'active' : ''}`}
onClick={() => handleLinkClick('/')}
>
Add Invoice
</button>
<button
className={`btn ${activeButton === '/payInvoice' ? 'active' : ''}`}
onClick={() => handleLinkClick('/payInvoice')}
>
Pay Invoice
</button>
<button
className={`btn ${activeButton === '/bankDeposit' ? 'active' : ''}`}
onClick={() => handleLinkClick('/bankDeposit')}
>
Bank Deposit
</button>
<button
className={`btn ${activeButton === '/atmDeposit' ? 'active' : ''}`}
onClick={() => handleLinkClick('/atmDeposit')}
>
ATM Deposit
</button>
</div>
</div>
</div>
<div className="formcontainer">
<div
className="container"
style={{
backgroundColor: "white",
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.1)",
borderRadius:"40px"
borderRadius: "40px"
}}
>
<form onSubmit={handleSubmit}>
<div className="">
</div>
<div className="col-md-12 row" style={{gap:"10%"}}>
<div className="col-md-12 row" style={{ gap: "15%" }}>
<div className="mb-3 col-md-2" >
<input
type="date"
@ -410,19 +410,21 @@ function PayInvoice() {
</select> */}
</div>
</div>
<div className="mb-3 col-md-12 row">
<div className="col-md-2">
<div className="mb-3 col-md-12 row mt-3" style={{gap:"70px"}} >
<div className="col-md-3">
<input
name="amount"
type="text"
className="form-control-borderless"
className="form-control"
value={formData.amount}
readOnly
placeholder="Amount"
style={{ backgroundColor: "#fafafa" }}
/>
</div>
<div className="col-md-2">
<input
type="text"
className="form-control-borderless"
name="pay_amount"
@ -454,72 +456,33 @@ function PayInvoice() {
.slice(0, 7); // Limit input length (10 digits + 1 decimal + 2 decimal places)
}}
/>
</div>
<div className="col-md-3">
<input
type="text"
className="form-control"
placeholder="Grand Total"
value={grandTotal || ""}
readOnly
style={{
border: 'none', // Remove all borders
backgroundColor:'transparent',
borderBottom: '1px solid #ACB4AA', // Add only the bottom border
outline: 'none', // Remove outline
padding: '6px 0', // Optional: Add padding to the top and bottom
}}
/>
</div>
<input
type="text"
className="form-control"
placeholder="Grand Total"
value={grandTotal || ""}
readOnly
style={{
<div
className=" d-flex align-items-center"
style={{
border: '2px solid #ACB4AA',
padding: '5px 40px',
width: 'fit-content',
borderRadius: '40px',
}}
>
{['cash', 'cheque', 'bank'].map((method) => (
<div className="me-3" key={method}>
<input
type="radio"
className="form-check-input"
name="pay_method"
value={method}
checked={formData.pay_method === method}
onChange={handleChange}
id={`pay_method_${method}`} // Unique ID for each radio input
style={{ display: 'none' }} // Hide the actual radio button
/>
<label
className="form-check-label cursor-pointer"
htmlFor={`pay_method_${method}`} // Link label to the input
onClick={() => handleChange({ target: { name: 'pay_method', value: method } })} // Custom onClick to change the state
style={{
color: formData.pay_method === method ? 'white' : '#282e26', // Change text color based on active state
backgroundColor: formData.pay_method === method ? '#4a5546' : 'transparent', // Change background when active
padding: '5px 25px', // Add padding for better appearance
borderRadius: '20px', // Optional: Round the corners of the label
}}
>
{method.charAt(0).toUpperCase() + method.slice(1)} {/* Capitalize first letter */}
</label>
</div>
))}
</div>
backgroundColor: '#fafafa',
}}
/>
</div>
<div className="">
{/* <div className="col-md-3 mt-4">
{/* <div className="col-md-3 mt-4">
<input
name="after_discount"
type="text"
@ -531,44 +494,92 @@ function PayInvoice() {
/>
</div> */}
</div>
</div>
<div className="col-md-6">
{formData.pay_method === "cheque" && (
<div className="">
<div className="col-md-12 row">
<div className="mb-3 col-md-6">
<select
required
className="form-control-borderless"
name="bank"
value={formData.bank}
onChange={handleChange}
>
<option value="">Select Bank</option>
{banks.map((bank) => (
<option key={bank.id} value={bank.id}>
{bank.name}
</option>
))}
</select>
</div>
<div className="mb-3 col-md-6">
<div className="md-col-12 ">
<div
className="d-flex align-items-center"
style={{
border: '2px solid #ACB4AA',
padding: '2px 20px', // Same left and right padding
width: 'fit-content',
borderRadius: '40px',
}}
>
{['cash', 'cheque', 'bank'].map((method) => (
<div className="" key={method}>
<input
required
type="text"
className="form-control-borderless"
name="cheque_no"
placeholder="Check Number"
value={formData.cheque_no}
type="radio"
className="form-check-input"
name="pay_method"
value={method}
checked={formData.pay_method === method}
onChange={handleChange}
id={`pay_method_${method}`} // Unique ID for each radio input
style={{ display: 'none' }} // Hide the actual radio button
/>
<label
className="form-check-label cursor-pointer"
htmlFor={`pay_method_${method}`} // Link label to the input
onClick={() => handleChange({ target: { name: 'pay_method', value: method } })} // Custom onClick to change the state
style={{
color: formData.pay_method === method ? 'white' : '#282e26', // Change text color based on active state
backgroundColor: formData.pay_method === method ? '#4a5546' : 'transparent', // Change background when active
padding: '5px 25px', // Add padding for better appearance
borderRadius: '20px', // Optional: Round the corners of the label
}}
>
{method.charAt(0).toUpperCase() + method.slice(1)} {/* Capitalize first letter */}
</label>
</div>
))}
</div>
</div>
<div className="col-md-12 mt-3" >
{formData.pay_method === "cheque" && (
<div className="row "> {/* Use row class for Bootstrap grid */}
<div className="col-md-2 mb-3"> {/* First column for bank select */}
<select
required
className="form-control-borderless" // Keep Bootstrap styles
name="bank"
value={formData.bank}
onChange={handleChange}
>
<option value="">Select Bank</option>
{banks.map((bank) => (
<option key={bank.id} value={bank.id}>
{bank.name}
</option>
))}
</select>
</div>
<div className="col-md-2 mb-3"> {/* Second column for cheque number input */}
<input
required
type="text"
className="form-control-borderless"
name="cheque_no"
placeholder="Check Number"
value={formData.cheque_no}
onChange={handleChange}
/>
</div>
</div>
)}
{formData.pay_method === "bank" && (
<div className="mb-3">
<div className="col-md-12 row">
@ -615,18 +626,18 @@ function PayInvoice() {
)}
</div>
<div className="d-flex justify-content-end">
<button
type="button"
className="btn btn-contained me-2"
onClick={handleCancel}
style={{border: " 1px solid #282e26", borderRadius:'20px' }}
>
Cancel
</button>
<button type="submit" className="btn" style={{color:"white", backgroundColor:'#282e26', borderRadius:'20px'}}>
Save
</button>
</div>
<button
type="button"
className="btn btn-contained me-2"
onClick={handleCancel}
style={{ border: " 1px solid #282e26", borderRadius: '20px' }}
>
Cancel
</button>
<button type="submit" className="btn" style={{ color: "white", backgroundColor: '#282e26', borderRadius: '20px' }}>
Save
</button>
</div>
</form>
</div>
</div>
@ -638,7 +649,7 @@ function PayInvoice() {
}}
>
<TableComponent reloadData={reloadData} onEdit={handleInvoiceSelect} />
<ToastContainer/>
<ToastContainer />
<AddVendorModal
show={showModal}
handleClose={handleClose}

View File

@ -866,16 +866,40 @@ const getPaymentMethodStyle = (method) => ({
});
const statusStyles = {
All: { backgroundColor: "#4545DB" },
// draft: { backgroundColor: "#4545DB7C" },
unpaid: { backgroundColor: "#ff2024" },
partially_paid: { backgroundColor: "#0c8ce9" },
All: {
backgroundColor: "#4545DB",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
paid: {
backgroundColor: "#198f51",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
unpaid: {
backgroundColor: "#ff2024",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
partially_paid: {
backgroundColor: "#0c8ce9",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
};
const getStatusStyle = (status) => ({
...(statusStyles[status] || { backgroundColor: "#198f51" }),
...(statusStyles[status] || { backgroundColor: "#198f51", width: "150px", height: "40px" }), // Default style
borderRadius: "5px",
padding: "10px 20px",
padding: "5px 20px",
textAlign: "center",
display: "flex", // Use flexbox for alignment
justifyContent: "center", // Center horizontally
alignItems: "center", // Center vertically
color: "#fff",
});

View File

@ -811,6 +811,7 @@ export default function Expense() {
</h5>
<svg
onClick={toggleModal}
width="14"
height="14"
@ -951,7 +952,7 @@ export default function Expense() {
<div
className="input-group-prepend"
style={{
background: "#ffffff",
backgroundColor: "#ffffff",
height: "100%",
display: "flex",
@ -1079,53 +1080,53 @@ export default function Expense() {
{showPaymentOptions && (
<div
className="d-flex col-md-6 mb-3"
style={{
border: '2px solid #ACB4AA',
padding: '10px 10px',
width: 'fit-content',
borderRadius: '40px',
display: 'flex', // Use flexbox for inner items
gap: '10px', // Add spacing between the options
marginTop: '20px', // Keep this if you want some space above
}}
>
{[
{ value: "cash", label: "Cash" },
{ value: "cheque", label: "Check" },
{ value: "bank", label: "Bank Card/ACH/EFT" }
].map((method) => (
<label
key={method.value}
className="radio-inline"
style={{
backgroundColor: formData.pay_method === method.value ? "#4a5546" : "transparent",
color: formData.pay_method === method.value ? "white" : "black",
padding: '5px 10px', // Add padding for better appearance
borderRadius: '20px', // Optional: Round the corners of the label
cursor: "pointer",
}}
>
<input
type="radio"
name="specificPaymentMethod"
value={method.value}
onChange={handleSpecificPaymentMethodChange}
style={{ display: 'none' }}
/>
{method.label} {/* Use the label defined in the array */}
</label>
))}
</div>
)}
<div
className="d-flex col-md-6 mb-3"
style={{
border: '2px solid #ACB4AA',
padding: '10px 10px',
width: 'fit-content',
borderRadius: '40px',
display: 'flex', // Use flexbox for inner items
gap: '10px', // Add spacing between the options
marginTop: '20px', // Keep this if you want some space above
}}
>
{[
{ value: "cash", label: "Cash" },
{ value: "cheque", label: "Check" },
{ value: "bank", label: "Bank Card/ACH/EFT" }
].map((method) => (
<label
key={method.value}
className="radio-inline"
style={{
backgroundColor: formData.pay_method === method.value ? "#4a5546" : "transparent",
color: formData.pay_method === method.value ? "white" : "black",
padding: '5px 10px', // Add padding for better appearance
borderRadius: '20px', // Optional: Round the corners of the label
cursor: "pointer",
}}
>
<input
type="radio"
name="specificPaymentMethod"
value={method.value}
onChange={handleSpecificPaymentMethodChange}
style={{ display: 'none' }}
/>
{method.label} {/* Use the label defined in the array */}
</label>
))}
</div>
)}
{(formData.pay_method_status === "pay_later" ||
formData.pay_method_status === "credit_invoice") && (
<div className="col-md-6 d-flex" style={{ paddingRight: "10px", marginTop:'20px' }}>
<div className="col-md-6 d-flex" style={{ paddingRight: "10px", marginTop: '20px' }}>
<select
className="form-control col-md-6 me-2"
name="days"
@ -1133,7 +1134,7 @@ export default function Expense() {
onChange={handleChange}
style={{
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
@ -1153,7 +1154,7 @@ export default function Expense() {
type="text"
style={{
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
@ -1175,7 +1176,7 @@ export default function Expense() {
<select
style={{
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
@ -1239,8 +1240,8 @@ export default function Expense() {
style={{
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
marginRight: "10px",
}}
@ -1347,12 +1348,13 @@ export default function Expense() {
type="button"
className="btn btn-secondary-outline"
onClick={toggleModal}
style={{ border: " 1px solid #282e26", borderRadius: '20px' }}
>
Close
</button>
<button
type="submit"
style={{backgroundColor:'#282E26' ,color:"#fff"}}
style={{ color: "white", backgroundColor: '#282e26', borderRadius: '20px' }}
className="btn"
onClick={handleSubmit}
>

View File

@ -296,7 +296,7 @@ const GasTypeTable = ({
</select>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">

View File

@ -321,7 +321,7 @@ const HouseChargeTable = ({
</select>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">

View File

@ -90,7 +90,7 @@ const LotteryInventoryTable = ({
return (
<div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
{columns.map((col, index) => (

View File

@ -194,7 +194,7 @@ const LotteryReportTable = ({
<div className="d-flex mb-3">
<div className="expense-searchcontainerstart d-flex"></div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">

View File

@ -190,7 +190,7 @@ const LotteryTable = ({
</select>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
{columns.map((col, index) => (

View File

@ -335,7 +335,7 @@ const WeeklyInvoiceTable = ({
</select>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">

View File

@ -84,7 +84,7 @@ const DataTable = ({
};
return (
<div className="data-table-container">
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">
@ -180,7 +180,7 @@ const DataTable = ({
{showFooter && (
<nav>
<ul className="pagination">
<li className={`prev-next ${currentPage === 1 ? "disabled" : ""}`}>
{/* <li className={`prev-next ${currentPage === 1 ? "disabled" : ""}`}>
<span
style={{
@ -196,9 +196,9 @@ const DataTable = ({
textAlign: "center"
}}
onClick={handlePrev}>&lt;</span>&nbsp;
</li>
</li> */}
{renderPagination()}
<li
{/* <li
className={`prev-next ${currentPage === totalPages ? "disabled" : ""
}`}
>
@ -219,7 +219,7 @@ const DataTable = ({
textAlign: "center"
}}
onClick={handleNext}>&gt; </span>
</li>
</li> */}
</ul>
</nav>
)}

View File

@ -126,32 +126,44 @@ const PayrollTable = ({
draft: {
backgroundColor: "#D1D1EF",
color: "#fff",
borderRadius: "30px",
borderRadius: "5px",
padding: "5px 10px",
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
unpaid: {
backgroundColor: "#ff2024",
color: "#fff",
borderRadius: "10px",
borderRadius: "5px",
padding: "5px 20px",
textAlign:'center',
alignItems:'center'
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px",
textAlign: 'center',
alignItems: 'center'
},
paid: {
backgroundColor: "#198f51",
color: "#fff",
borderRadius: "10px",
borderRadius: "5px",
padding: "5px 20px",
textAlign:'center',
alignItems:'center'
textAlign: 'center',
alignItems: 'center',
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
partially_paid: {
backgroundColor: "#0c8ce9",
color: "#fff",
borderRadius: "10px",
borderRadius: "5px",
padding: "5px 20px",
textAlign:'center',
alignItems:'center'
textAlign: 'center',
alignItems: 'center',
width: "130px", // Set a fixed width
height: "30px", // Set a fixed height
fontSize:"14px"
},
};
const paymentMethodStyles = {
@ -250,55 +262,71 @@ const PayrollTable = ({
</button> */}
</div>
<div style={{marginRight:"60%"}}>
<div
className="expense-search d-flex align-items-center"
style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}
>
<h6 className="" style={{margin:'10px'}}>Show</h6>
<select
name="option"
id="pageSelect"
className="selectoptions"
<div style={{ marginRight: "58%" }}>
<div
className="expense-search d-flex align-items-center"
style={{
height: "30px",
padding: "2px 6px",
border: "1px solid #ccc",
backgroundColor: "#282E26",
color: "#fff",
fontSize: "14px",
}}
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to first page on change
display: "flex",
alignItems: "center",
backgroundColor: "#FFFFFF",
border: "1px solid #DBDBDB",
borderRadius: "10px",
// boxSizing: "border-box",
cursor: "pointer",
width: "170px",
gap: "10px",
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
</div>
</div>
<span
style={{
fontFamily: "'Comfortaa'",
fontStyle: "normal",
fontWeight: "400",
fontSize: "16px",
padding: "5px",
color: "#000000",
}}
>
Show Rows:
</span>
<select
name="option"
id="pageSelect"
className="selectoptions"
style={{
backgroundColor: "#282E26",
borderRadius: "0px 10px 10px 0px",
color: "#F4FFEE",
fontFamily: "'Comfortaa'",
fontStyle: "normal",
fontWeight: "700",
fontSize: "16px",
lineHeight: "18px",
padding: "5px 8px",
border: "none",
cursor: "pointer",
}}
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to the first page on change
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
</div>
</div>
</div>
<table className="data-table custom-table rounded-table">
<thead className="table-header">
<table className="data-table custom-table ">
<thead className="table-header" >
<tr>
{columns.map((col, index) => (
<th key={index} scope="col" onClick={() => handleSort(col.field)}>

View File

@ -107,15 +107,15 @@ function ManageDepartments() {
(dept) => dept.type === "department"
);
return (
<div className="store-container">
<div className="" style={{marginTop:"5%"}}>
<ToastContainer />
<p className="setting-title">Manage Departments</p>
<div className="create-department-section">
{/* <p className="setting-title">Manage Departments</p> */}
<div className="department-container">
<div className="input-container">
<div className="input-row">
<input
type="text"
placeholder="New Department"
placeholder="Enter Department Name"
className="input-field"
value={editDepartmentId ? editDepartmentTitle : newDepartment}
onChange={(e) => {
@ -125,15 +125,22 @@ function ManageDepartments() {
setNewDepartment(e.target.value);
}
}}
style={{
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
required
/>
<button className="dept-button" onClick={handleSaveDepartment}>
{editDepartmentId ? "Update" : " + Add"}
<button className="btn cus d-flex align-items-center" onClick={handleSaveDepartment}>
{editDepartmentId ? "Update Department" : " + Add Department"}
</button>
</div>
</div>
</div>
<div className="show-department-section">
<div className="store-container">
<div className="show-department-section">
<div className="dept-cards-row">
{filteredDepartments.length === 0 ? (
<p
@ -201,6 +208,8 @@ function ManageDepartments() {
</div>
</div>
</div>
</div>
);
}

View File

@ -179,6 +179,7 @@ const ManageUserTable = ({
<div className="expense-searchcontainerstart d-flex">
<div className="search-container">
<input
style={{ height: "50px", backgroundColor: "#fff", border: '1px solid #DBDBDB', boxShadow: "0px 0px 10px rgba(187, 187, 187, 0.25)" }}
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
@ -276,26 +277,71 @@ const ManageUserTable = ({
</div>
)}
</div>
<div className="expense-searchcontainerend d-flex align-items-center">
<h3 className="me-2">Show</h3>
<select
name="option"
id="pageSelect"
className="selectoptions"
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to first page on change
<div style={{ marginRight: "69%" }}>
<div
className="expense-search d-flex align-items-center"
style={{
display: "flex",
alignItems: "center",
backgroundColor: "#FFFFFF",
border: "1px solid #DBDBDB",
borderRadius: "10px",
// boxSizing: "border-box",
cursor: "pointer",
width: "170px",
gap: "10px",
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
</div>
<span
style={{
fontFamily: "'Comfortaa'",
fontStyle: "normal",
fontWeight: "400",
fontSize: "16px",
padding: "5px",
color: "#000000",
}}
>
Show Rows:
</span>
<select
name="option"
id="pageSelect"
className="selectoptions"
style={{
backgroundColor: "#282E26",
borderRadius: "0px 10px 10px 0px",
color: "#F4FFEE",
fontFamily: "'Comfortaa'",
fontStyle: "normal",
fontWeight: "700",
fontSize: "16px",
lineHeight: "18px",
padding: "5px 8px",
border: "none",
cursor: "pointer",
}}
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to the first page on change
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
</div>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">
@ -418,7 +464,7 @@ const ManageUserTable = ({
{showFooter && (
<nav>
<ul className="pagination">
<li className={`prev-next ${currentPage === 1 ? "disabled" : ""}`}>
{/* <li className={`prev-next ${currentPage === 1 ? "disabled" : ""}`}>
<span
style={{
fontSize: "24px",
@ -437,9 +483,9 @@ const ManageUserTable = ({
&lt;
</span>
&nbsp;
</li>
</li> */}
{renderPagination()}
<li
{/* <li
className={`prev-next ${
currentPage === totalPages ? "disabled" : ""
}`}
@ -462,7 +508,7 @@ const ManageUserTable = ({
>
&gt;{" "}
</span>
</li>
</li> */}
</ul>
</nav>
)}

View File

@ -10,6 +10,10 @@ import { toast, ToastContainer } from "react-toastify";
import CustomSwitch from "./CustomSwitch";
import ManageUserTable from "./ManageUserTable";
import Swal from "sweetalert2";
import userIcon from '../../../../assets/Image/user.png'
import storeIcon from '../../../../assets/Image/store.png'
import ownerIcon from '../../../../assets/Image/owner.png'
function ManageUsers() {
@ -113,17 +117,17 @@ function ManageUsers() {
cancelButtonColor: "#3085d6",
confirmButtonText: "Yes, delete it!",
});
// Check if the user clicked the confirm button
if (!result.isConfirmed) return; // Exit if the user cancels
try {
await Delete("user", id);
setUsers((prev) => prev.filter((user) => user.id !== id)); // Remove the user from the list
toast.success("User deleted successfully!");
} catch (error) {
console.error("Error deleting user:", error);
// Check if the error response contains the specific message
if (error.response && error.response.data && error.response.data.detail === "Store owners cannot be deleted.") {
toast.error("Store owners cannot be deleted.");
@ -135,22 +139,22 @@ function ManageUsers() {
const handleSaveUser = async () => {
const emailRegex = /^[\w.-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/; // Email regex without #
const phoneRegex = /^[0-9]{10}$/; // US phone number regex for exactly 11 digits (starts with '1' for the country code)
// Validate email
if (!emailRegex.test(email)) {
toast.error("Please enter a valid email address (no '#' allowed).");
return;
}
// Validate phone number
if (!phoneRegex.test(phoneNumber)) {
toast.error("Please enter a valid US phone number (11 digits, starts with '1').");
return;
}
// Derive role name from roles array
const roleName = roles.find((r) => String(r.id) === String(role))?.name || "";
const payload = {
first_name: fullName,
email: email,
@ -161,35 +165,35 @@ function ManageUsers() {
groups: [],
ms_role_name: roleName, // Derived role name
};
try {
if (currentUserId) {
// Update user
await Patch("user", currentUserId, payload);
// Update local state
setUsers((prevUsers) =>
prevUsers.map((user) =>
user.id === currentUserId ? { ...user, ...payload } : user
)
);
toast.success("User updated successfully!");
} else {
// Add new user
await Post("user", payload);
// Fetch updated users
const updatedUsers = await Get("user");
setUsers(updatedUsers.results);
toast.success("User added successfully!");
}
handleCloseUserModal();
} catch (error) {
console.error("Error saving user:", error);
// Check for specific error responses
if (error.response && error.response.data) {
if (error.response.data.ms_role === "You cannot change the role of a store owner.") {
@ -204,23 +208,23 @@ function ManageUsers() {
}
}
};
const handleAssignOwnerSubmit = async (e) => {
e.preventDefault();
try {
const response = await Post("assignAsOwner", { email: ownerEmail });
// If successful, show success message
toast.success("User assigned as owner successfully!");
setOwnerEmail(""); // Clear input
fetchUsersAndRoles(); // Refresh the users and roles
handleCloseAssignOwnerModal(); // Close the modal
} catch (error) {
console.error("Error assigning owner:", error);
// Check if the error contains a specific message
if (error.response && error.response.data && error.response.data.error === "User with this email does not exist.") {
toast.error("The email you provided does not exist.");
@ -229,7 +233,7 @@ function ManageUsers() {
}
}
};
const handleSwitchChange = (id) => {
setStatus((prevStatus) => !prevStatus);
@ -265,16 +269,16 @@ function ManageUsers() {
const numericValue = value.replace(/[^0-9]/g, '');
setFormData((prevData) => ({
...prevData,
pincode: numericValue,
...(numericValue.trim() === "" && { city: "", state: "", country: "" }),
...prevData,
pincode: numericValue,
...(numericValue.trim() === "" && { city: "", state: "", country: "" }),
}));
// Trigger fetching location details if the length is valid
if (numericValue.length === 5 || numericValue.length === 6) {
fetchLocationDetails(numericValue);
fetchLocationDetails(numericValue);
}
};
};
// Handle pincode blur
const handlePincodeBlur = () => {
const { pincode } = formData;
@ -389,27 +393,67 @@ function ManageUsers() {
<div className="due-days">
<div className="header-row">
<div className="setting-title">Manage Users</div>
<div className="btn-position">
<div className="btn-position" style={{ display: "flex", gap: "10px" }}> {/* Set up flex with gap */}
<button
className="vendor-add-button"
className="btn cus d-flex align-items-center"
onClick={() => handleShowUserModal()} // Open modal for adding a user
>
+ Add New User
<img
src={userIcon}
alt="user Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
<button
className="vendor-add-button"
style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}
onClick={() => handleShowStoreModal()} // Open modal for adding a user
>
+ Add New Store
<img
src={storeIcon}
alt="store Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
<button
className="vendor-add-button"
style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}
onClick={() => setAssignOwnerModal(true)} // Open modal for assigning an owner
>
+ Assign Existing User As Owner
<img
src={ownerIcon}
alt="owner Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
</div>
</div>
<ManageUserTable
data={users}
columns={columns}
@ -425,18 +469,24 @@ function ManageUsers() {
show={true}
handleClose={handleCloseUserModal}
title={currentUserId ? "Edit User" : "Add New User"}
width="1054px"
width="700px"
>
<form>
<div className="form-group d-flex flex-column">
<div className="d-flex align-items-center mb-3">
<div className="form-group d-flex flex-column p-5">
<div className="d-flex align-items-center mb-3 ">
<input
type="text"
className="input-field"
placeholder="Full Name"
value={fullName}
onChange={(e) => setFullName(e.target.value)}
style={{ width: "483px", marginRight: "10px" }}
style={{
width: "483px", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
<input
type="email"
@ -444,14 +494,20 @@ function ManageUsers() {
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
style={{ width: "483px", marginRight: "10px" }}
style={{
width: "483px", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
<div className="d-flex align-items-center mb-3">
<input
type="tel"
className="input-field"
placeholder="Phone Number (without country code)"
placeholder="Phone Number "
value={phoneNumber}
onChange={(e) => {
@ -461,13 +517,25 @@ function ManageUsers() {
}
}}
maxLength={10}
style={{ width: "483px", marginRight: "10px" }}
style={{
width: "483px", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
<select
className="input-field"
value={role}
onChange={(e) => setRole(e.target.value)}
style={{ width: "483px", marginRight: "10px" }}
style={{
width: "483px", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
>
<option value="">Select Role for User</option>
{roles.map((r) => (
@ -493,7 +561,7 @@ function ManageUsers() {
style={{
marginRight: "40px",
padding: "4px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
@ -521,10 +589,10 @@ function ManageUsers() {
show={true}
handleClose={handleCloseStoreModal}
title={"Add New Store"}
width="1054px"
width="700px"
>
<form>
<div className="form-group">
<div className="form-group p-5">
{/* Wrapper for Flexbox */}
<div className="d-flex flex-wrap">
{/* Left Side */}
@ -541,7 +609,12 @@ function ManageUsers() {
store_name: e.target.value,
}))
}
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
<div className="mb-3">
@ -556,7 +629,12 @@ function ManageUsers() {
address_line1: e.target.value,
}))
}
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
<div className="mb-3">
@ -566,7 +644,12 @@ function ManageUsers() {
placeholder="City"
value={formData.city}
readOnly
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
</div>
@ -581,7 +664,12 @@ function ManageUsers() {
value={formData.pincode}
onChange={handlePincodeChange}
onBlur={handlePincodeBlur}
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
maxLength={5}
/>
</div>
@ -595,7 +683,12 @@ function ManageUsers() {
placeholder="State"
value={formData.state}
readOnly
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
<div className="mb-3">
@ -605,7 +698,12 @@ function ManageUsers() {
placeholder="Country"
value={formData.country}
readOnly
style={{ width: "100%" }}
style={{
width: "100%", marginRight: "10px", backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
</div>
@ -617,7 +715,7 @@ function ManageUsers() {
style={{
marginRight: "40px",
padding: "4px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
@ -643,26 +741,32 @@ function ManageUsers() {
<ReusableModal
show={true}
handleClose={handleCloseAssignOwnerModal}
title="Assign Admin"
title="Assign Admin as Owner"
width="600px"
>
<form onSubmit={handleAssignOwnerSubmit}>
<div className="form-group d-flex align-items-center mt-1">
<div className="form-group d-flex flex-column mt-1 p-3 ">
<input
type="email"
className="input-field"
placeholder="Enter User Email"
value={ownerEmail}
onChange={(e) => setOwnerEmail(e.target.value)}
style={{ width: "483px", marginRight: "20px" }}
style={{
width: "483px",
marginBottom: "20px", // Add margin between email and button
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
required
/>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<button
style={{
marginRight: "40px",
padding: "4px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
@ -678,8 +782,6 @@ function ManageUsers() {
</button>
</div>
</div>
</form>
</ReusableModal>

View File

@ -47,7 +47,7 @@ const ReusableModal = ({
};
const modalContentStyle = {
borderRadius: "15px",
borderRadius: "30px",
overflow: "hidden",
width: width, // use the width prop
height: height, // use the height prop
@ -57,21 +57,32 @@ const ReusableModal = ({
};
const headerStyle = {
backgroundColor: "#F0F0F0",
backgroundColor: "#fff",
borderTopLeftRadius: "15px",
borderTopRightRadius: "15px",
height: "55px",
display: "flex",
border:'none',
justifyContent: "space-between",
alignItems: "center",
padding: "0 16px", // Add padding for space between the content and edges
};
const titleStyle = {
fontFamily: "'Manrope', sans-serif",
fontWeight: "600", // semibold
fontWeight: "600",
fontSize: "20px",
color: "#002300",
margin: 0, // remove default margin
margin: 0,
textAlign: "center",
flex: 1, // Allow the title to take up available space
};
const closeButtonStyle = {
cursor: "pointer",
marginLeft: "auto", // Push the close button to the far right
};
return (
@ -88,21 +99,23 @@ const ReusableModal = ({
<h5 className="modal-title" style={titleStyle}>
{title}
</h5>
<svg
onClick={handleClose}
width="26"
height="24"
viewBox="0 0 26 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20.4226 6.45104C20.5153 6.36563 20.5888 6.26421 20.6389 6.15258C20.6891 6.04094 20.715 5.92127 20.7151 5.80041C20.7152 5.67954 20.6894 5.55985 20.6394 5.44815C20.5894 5.33646 20.516 5.23496 20.4235 5.14944C20.331 5.06393 20.2211 4.99607 20.1001 4.94975C19.9792 4.90343 19.8496 4.87955 19.7186 4.87947C19.5877 4.8794 19.458 4.90313 19.337 4.94931C19.216 4.9955 19.1061 5.06323 19.0134 5.14864L13.0005 10.699L6.98928 5.14864C6.80218 4.97593 6.54841 4.87891 6.28381 4.87891C6.01921 4.87891 5.76545 4.97593 5.57835 5.14864C5.39125 5.32135 5.28613 5.55559 5.28613 5.79984C5.28613 6.04409 5.39125 6.27833 5.57835 6.45104L11.5913 11.9998L5.57835 17.5486C5.4857 17.6342 5.41221 17.7357 5.36208 17.8474C5.31194 17.9591 5.28613 18.0789 5.28613 18.1998C5.28613 18.3208 5.31194 18.4405 5.36208 18.5523C5.41221 18.664 5.4857 18.7655 5.57835 18.851C5.76545 19.0237 6.01921 19.1208 6.28381 19.1208C6.41483 19.1208 6.54456 19.097 6.66561 19.0507C6.78665 19.0044 6.89664 18.9366 6.98928 18.851L13.0005 13.3006L19.0134 18.851C19.2005 19.0235 19.4542 19.1204 19.7186 19.1202C19.9831 19.1201 20.2366 19.0229 20.4235 18.8502C20.6104 18.6775 20.7152 18.4434 20.7151 18.1993C20.7149 17.9552 20.6097 17.7211 20.4226 17.5486L14.4097 11.9998L20.4226 6.45104Z"
fill="black"
/>
</svg>
<div style={closeButtonStyle}>
<svg
onClick={handleClose}
width="26"
height="24"
viewBox="0 0 26 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20.4226 6.45104C20.5153 6.36563 20.5888 6.26421 20.6389 6.15258C20.6891 6.04094 20.715 5.92127 20.7151 5.80041C20.7152 5.67954 20.6894 5.55985 20.6394 5.44815C20.5894 5.33646 20.516 5.23496 20.4235 5.14944C20.331 5.06393 20.2211 4.99607 20.1001 4.94975C19.9792 4.90343 19.8496 4.87955 19.7186 4.87947C19.5877 4.8794 19.458 4.90313 19.337 4.94931C19.216 4.9955 19.1061 5.06323 19.0134 5.14864L13.0005 10.699L6.98928 5.14864C6.80218 4.97593 6.54841 4.87891 6.28381 4.87891C6.01921 4.87891 5.76545 4.97593 5.57835 5.14864C5.39125 5.32135 5.28613 5.55559 5.28613 5.79984C5.28613 6.04409 5.39125 6.27833 5.57835 6.45104L11.5913 11.9998L5.57835 17.5486C5.4857 17.6342 5.41221 17.7357 5.36208 17.8474C5.31194 17.9591 5.28613 18.0789 5.28613 18.1998C5.28613 18.3208 5.31194 18.4405 5.36208 18.5523C5.41221 18.664 5.4857 18.7655 5.57835 18.851C5.76545 19.0237 6.01921 19.1208 6.28381 19.1208C6.41483 19.1208 6.54456 19.097 6.66561 19.0507C6.78665 19.0044 6.89664 18.9366 6.98928 18.851L13.0005 13.3006L19.0134 18.851C19.2005 19.0235 19.4542 19.1204 19.7186 19.1202C19.9831 19.1201 20.2366 19.0229 20.4235 18.8502C20.6104 18.6775 20.7152 18.4434 20.7151 18.1993C20.7149 17.9552 20.6097 17.7211 20.4226 17.5486L14.4097 11.9998L20.4226 6.45104Z"
fill="black"
/>
</svg>
</div>
</div>
<div className="modal-body">{children}</div>
</div>

View File

@ -312,7 +312,7 @@ const SettingTable = ({
</select>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table" style={{borderRadius:"none"}} >
<thead className="table-header">
<tr>
<th scope="col" className="no-column">

View File

@ -167,10 +167,12 @@
.due-days {
padding: 20px; /* Adjust as needed */
margin: 20px auto;
background-color: #ffffff;
border-radius: 10px;
border: 1px solid #EBEAF2;
box-shadow: "0px 2px 8px rgba(6, 12, 34, 0.0392157)";
border-radius: 40px;
width: 1600px;
max-width: 100%;
background-color: #ffffff;
}
.due-card {
position: relative;
@ -262,13 +264,35 @@
flex-direction: column;
justify-content: flex-start;
align-items: flex-start; /* Align items to the start (left) */
border-radius: 10px;
border-radius: 40px;
padding: 30px;
margin: 20px auto;
background-color: #ffffff;
width: 1600px;
max-width: 100%;
}
.department-container {
display: flex;
flex-direction: column;
justify-content: flex-start; /* Align items to the start (top) */
align-items: flex-start; /* Align items to the start (left) */
border-radius: 20px;
padding: 30px;
border: none; /* Ensure no border */
border-bottom: 2px solid #ccc; /* Set a bottom border */
margin: 20px 0; /* Center vertically with top and bottom margins */
background-color: #ffffff;
width: 850px; /* Set a fixed width */
max-width: 100%; /* Ensure it doesn't exceed the screen width */
margin-left: 160px; /* Align to the left with 9% margin */
}
.setting-title {
margin-bottom: 10px; /* Space between title and inputs */
font-size: 24px; /* Adjust as needed */
@ -284,7 +308,7 @@
padding: 10px;
width: 600px;
height: 40px;
background-color: #f6f6f6;
background-color: #fff;
border: 1px solid #f6f6f6;
border-radius: 5px;
}
@ -445,22 +469,25 @@
gap: 10px; /* Space between cards */ /* space above cards */
}
.dept-card {
width: 474px; /* fixed width */
height: 70px; /* fixed height */
width: 474px; /* Fixed width */
height: 70px; /* Fixed height */
padding: 10px;
border: 1px solid #f6f6f6;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #EBEAF2; /* Add border color */
border-radius: 20px; /* Rounded corners */
display: flex; /* Flexbox layout */
align-items: center; /* Center items vertically */
justify-content: space-between; /* Space items evenly */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Add box shadow */
}
.dept-info {
width: 386px;
height: 50px;
padding: 10px;
background-color: #f6f6f6;
border: 1px solid rgba(0, 35, 0, 0.1);
border-radius: 4px;
background-color: #ffffff;
border: none; /* Remove the redundant border */
border-radius: 10px; /* Rounded corners */
}
.create-department-section {
width: 100%;
@ -514,31 +541,34 @@ input[type="date"] {
}
.data-table {
width: 100%;
border: 1px solid #F4F4F4;
border: 2px solid #F4F4F4;
border-collapse: collapse;
border-radius: 20px 20px 0 0;
/* border-radius: 20px 20px 0 0; */
overflow: hidden;
}
.table-header th, .table-body td {
border: 1px solid #F4F4F4;
/* border: 1px solid #F4F4F4; */
padding: 12px;
text-align: left;
padding-left: 20px;
}
.table-header th {
background-color: #f2f2f2;
color: #002300;
background-color: #282e26;
color: white;
cursor: pointer; /* Added cursor for sortable columns */
}
.table-body td {
padding-left: 20px;
color: #002300;
background-color: #ffffff;
border-bottom: 1px solid #EBEAF2;
}
.table-body tr:last-child td {
border-bottom: 1px solid #F4F4F4;
border-bottom: 1px solid #ffffff;
}
.table-body {
border-bottom: 1px solid #F4F4F4;
border-bottom: 2px solid #EBEAF2;
}
.no-column {
width: 100px;
@ -568,6 +598,8 @@ input[type="date"] {
display: flex;
justify-content: end;
padding: 10px 0;
background-color: #ffffff;
}
.pagination .page-item {
margin: 0 5px;
@ -575,21 +607,26 @@ input[type="date"] {
.pagination .page-link {
padding: 10px;
border: 1px solid #F4F4F4;
/* background-color: #ffffff; */
background-color: #b6d7a8;
border-radius: 50%;
border-radius: 30px;
color: #002300;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
width: 30px;
height: 30px;
transition: background-color 0.3s, color 0.3s;
}
.pagination .page-link:hover {
background-color: #ffaf32;
background-color: red;
}
.pagination .page-item.active .page-link {
width: 30px;
height: 30px;
border-radius: 30px;
background-color: #ffaf32; /* Yellow background */
color: #002300;
border-color:#fbfbfbfb;

View File

@ -336,9 +336,9 @@ function StoreInformation() {
maxWidth: '300px',
textAlign: 'center',
borderRadius: '20px',
border: '1px solid #6666ff',
border: '1px solid #282E26',
fontWeight: '800',
backgroundColor: plan.is_active ? 'transparent' : '#6666ff',
backgroundColor: plan.is_active ? 'transparent' : '#282E26',
color: plan.is_active ? '#000' : '#fff',
}}
onClick={(e) => {

View File

@ -7,6 +7,8 @@ import useApi from "../../../../utils/api-manager/Helper/useApi";
import { toast, ToastContainer } from "react-toastify";
import PayrollTableWithButton from "./PayrollTableWithButton";
import Swal from "sweetalert2";
import employeeIcon from '../../../../assets/Image/employee.png'
export default function Payroll() {
const { user } = useContext(AuthContext);
@ -112,7 +114,7 @@ export default function Payroll() {
const handleChange = (e) => {
const { name, value } = e.target;
// Restrict non-numeric input for contact_no
if (name === "contact_no") {
const numericValue = value.replace(/[^0-9]/g, ""); // Allow only digits
@ -121,7 +123,7 @@ export default function Payroll() {
setFormData((prevData) => ({ ...prevData, [name]: value }));
}
};
const handlePaymentChange = (e) => {
const { name, value } = e.target;
@ -210,53 +212,53 @@ export default function Payroll() {
const updatedFormData = { ...formData, store: storeId };
try {
let response;
try {
let response;
// If there's an editing payroll ID, we want to PATCH the payroll employee data
if (editingPayrollId) {
response = await Patch("payrollEmployeeData", editingPayrollId, updatedFormData);
// If there's an editing payroll ID, we want to PATCH the payroll employee data
if (editingPayrollId) {
response = await Patch("payrollEmployeeData", editingPayrollId, updatedFormData);
if (response.status === 200) {
setPayrollData(prevData =>
prevData.map(payroll =>
payroll.id === editingPayrollId ? { ...payroll, ...updatedFormData } : payroll
)
);
toast.success("Payroll updated successfully!");
if (response.status === 200) {
setPayrollData(prevData =>
prevData.map(payroll =>
payroll.id === editingPayrollId ? { ...payroll, ...updatedFormData } : payroll
)
);
toast.success("Payroll updated successfully!");
}
} else {
// If there's no editingPayrollId, it's a new payroll record
response = await Post("payrollEmployeeData", updatedFormData);
if (response.status === 201) {
setPayrollData(prevData => [...prevData, response.data]);
toast.success("Payroll added successfully!");
} else if (response.data) {
// Extract specific error messages and display them
const errorMessages = Object.entries(response.data)
.map(([field, messages]) => `${messages.join(", ")}`)
.join("\n");
toast.error(errorMessages || "An unknown error occurred.");
} else {
toast.error("Please Validate Fields");
}
}
closeModal(); // Close the modal after submitting the form
} catch (error) {
console.error("Error submitting form", error);
if (error.response?.data) {
// Handle API response errors
const errorMessages = Object.entries(error.response.data)
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
.join("\n");
toast.error(errorMessages || "An unknown error occurred.");
} else {
// Handle generic errors
toast.error("Error submitting form: " + error.message);
}
}
} else {
// If there's no editingPayrollId, it's a new payroll record
response = await Post("payrollEmployeeData", updatedFormData);
if (response.status === 201) {
setPayrollData(prevData => [...prevData, response.data]);
toast.success("Payroll added successfully!");
} else if (response.data) {
// Extract specific error messages and display them
const errorMessages = Object.entries(response.data)
.map(([field, messages]) => `${messages.join(", ")}`)
.join("\n");
toast.error(errorMessages || "An unknown error occurred.");
} else {
toast.error("Please Validate Fields");
}
}
closeModal(); // Close the modal after submitting the form
} catch (error) {
console.error("Error submitting form", error);
if (error.response?.data) {
// Handle API response errors
const errorMessages = Object.entries(error.response.data)
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
.join("\n");
toast.error(errorMessages || "An unknown error occurred.");
} else {
// Handle generic errors
toast.error("Error submitting form: " + error.message);
}
}
}
@ -297,11 +299,11 @@ export default function Payroll() {
bank: paymentData.payment_method === "cheque" ? paymentData.bank : "",
bank_name: bankName, // Include bank_name in the payload
cheque_no:
paymentData.payment_method === "cheque"
? paymentData.cheque_no || ""
: editingPayrollId
? paymentData.cheque_no // Preserve existing cheque_no if editing
: null,
paymentData.payment_method === "cheque"
? paymentData.cheque_no || ""
: editingPayrollId
? paymentData.cheque_no // Preserve existing cheque_no if editing
: null,
note: paymentData.note,
};
@ -332,45 +334,45 @@ export default function Payroll() {
const handleDelete = async (id, type) => {
const result = await Swal.fire({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Yes, delete it!",
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Yes, delete it!",
});
// Check if the user clicked the confirm button
if (!result.isConfirmed) return; // Exit if the user cancels
try {
if (type === "payroll") {
// Delete payroll record
await Delete(`payrollEmployeeData`, id);
// Update payroll data in the frontend
setPayrollData((prevPayrollData) => prevPayrollData.filter((p) => p.id !== id));
if (type === "payroll") {
// Delete payroll record
await Delete(`payrollEmployeeData`, id);
// Update payroll data in the frontend
setPayrollData((prevPayrollData) => prevPayrollData.filter((p) => p.id !== id));
// Fetch updated salary history data from the backend
const updatedSalaryHistory = await Get("payrollSalaryData");
setSalaryHistory(updatedSalaryHistory);
// Fetch updated salary history data from the backend
const updatedSalaryHistory = await Get("payrollSalaryData");
setSalaryHistory(updatedSalaryHistory);
toast.success("Payroll record deleted successfully!");
} else if (type === "salaryHistory") {
// Delete salary history record
await Delete(`payrollSalaryData`, id);
// Update salary history data in the frontend
setSalaryHistory((prevSalaryHistory) =>
prevSalaryHistory.filter((s) => s.id !== id)
);
toast.success("Payroll record deleted successfully!");
} else if (type === "salaryHistory") {
// Delete salary history record
await Delete(`payrollSalaryData`, id);
// Update salary history data in the frontend
setSalaryHistory((prevSalaryHistory) =>
prevSalaryHistory.filter((s) => s.id !== id)
);
toast.success("Salary history record deleted successfully!");
}
toast.success("Salary history record deleted successfully!");
}
} catch (error) {
console.error("Error deleting record:", error);
toast.error("Error deleting record: " + (error.response?.data || error.message));
console.error("Error deleting record:", error);
toast.error("Error deleting record: " + (error.response?.data || error.message));
}
};
};
return (
@ -378,9 +380,9 @@ export default function Payroll() {
<div className="p-2">
<div className="expensecontainer d-flex flex-column pd-2 mb-2">
<div className="d-flex justify-content-between align-items-center mb-3">
<h3 className="mb-1">Manage Payroll</h3>
<h3 className="mb-1">Manage Employee</h3>
<button
className="btn btn-primary cus"
className="btn cus d-flex align-items-center"
onClick={() => {
// fetchBankData();
setModalType('new');
@ -388,6 +390,11 @@ export default function Payroll() {
}}
>
+ Add Employee
<img
src={employeeIcon}
alt="employee Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
</div>
<PayrollTableWithButton
@ -407,69 +414,117 @@ export default function Payroll() {
</div>
{ }
{showModal && (
<div className="modal-overlay" onClick={closeModal}>
<div className="modal" style={{}} onClick={closeModal}>
<div
className="modal-container"
onClick={(e) => e.stopPropagation()}
style={{ width: modalType === 'payment' ? '800px' : '700px' }}
style={{ width: modalType === 'payment' ? '650px' : '700px', borderRadius: '40px' }}
>
<div className="modal-header" style={{ borderBottom: "1px solid lightgray" }}>
<h3>
{modalType === 'new' && "Add Employee"}
{modalType === 'edit' && "Edit Employee"}
{modalType === 'payment' && `Process Payment for ${selectedPayroll?.full_name || ''}`}
</h3>
<button className="btn" onClick={closeModal}>X</button>
<div
className="modal-header"
style={{
display: 'flex',
justifyContent: 'space-between', // Distribute space between items
alignItems: 'center',
border: "none"
}}
>
<div style={{ flex: 1, textAlign: 'center' }}>
<h3 style={{ margin: 0 }}>
{modalType === 'new' && 'Add Employee'}
{modalType === 'edit' && 'Edit Employee'}
{modalType === 'payment' && `Pay Salary For ${selectedPayroll?.full_name || ''}`}
</h3>
</div>
<svg
onClick={closeModal}
width="14"
height="14"
marginLeft="20px"
marginBottom="20px"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L13 13M13 1L1 13"
stroke="black"
stroke-linecap="round"
/>
</svg>
</div>
{ }
{(modalType === 'new' || modalType === 'edit') && (
<form onSubmit={handleSubmit}>
<div className="modal-body">
<div className="form-group">
<label htmlFor="full_name">Employee Name</label>
<div className="modal-body ">
<div className="form-group -flex flex-column justify-content-center align-items-center px-5 ">
{/* <label htmlFor="full_name">Employee Name</label> */}
<input
type="text"
className="form-control"
id="full_name"
name="full_name"
placeholder="Employees Full Name"
value={formData.full_name}
onChange={handleChange}
style={{
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
required
/>
</div>
<div className="form-group">
<label htmlFor="contact_no">Contact Number</label>
<div className="form-group -flex flex-column justify-content-center align-items-center px-5 ">
{/* <label htmlFor="contact_no">Contact Number</label> */}
<input
type="tel"
className="form-control"
id="contact_no"
placeholder="Contact Number"
name="contact_no"
value={formData.contact_no}
onChange={handleChange}
required
maxLength={10}
style={{
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
</div>
<div className="form-group">
<label htmlFor="email">Email Address</label>
<div className="form-group -flex flex-column justify-content-center align-items-center px-5 ">
{/* <label htmlFor="email">Email Address</label> */}
<input
type="email"
className="form-control"
id="email"
name="email"
placeholder="Email Address"
value={formData.email}
onChange={handleChange}
style={{
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
required
/>
</div>
</div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary">
<div className="modal-footer" style={{ border: "none" }}>
<button type="submit" style={{ color: "white", backgroundColor: '#282e26', borderRadius: '20px', padding: '5px 15px' }}>
{modalType === 'edit' ? "Update Employee" : "Add Employee"}
</button>
<button type="button" className="btn btn-contained" onClick={closeModal}>
<button type="button" onClick={closeModal} style={{ border: '1px solid #282E26', backgroundColor: "transparent", borderRadius: '20px', padding: '5px 45px' }}>
Close
</button>
</div>
@ -478,166 +533,253 @@ export default function Payroll() {
{ }
{modalType === 'payment' && (
<form onSubmit={handlePaymentSubmit}>
<div className="modal-body">
<div className="form-group">
<label htmlFor="salary_amount">Amount</label>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text">$</span>
<div className="modal-body">
<div className="form-group row col-md-12 justify-content-between"> {/* Added justify-content-between */}
{/* Salary Amount Input */}
<div className="col-md-5 mb-3"> {/* Added margin bottom for spacing */}
<input
type="text"
className="form-control"
id="salary_amount"
name="salary_amount"
placeholder="Amount"
value={paymentData.salary_amount}
onChange={handlePaymentChange}
onKeyDown={(e) => {
if (e.key === "-" || e.key === "+") {
e.preventDefault();
}
}}
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
required
onInput={(e) => {
let value = e.target.value;
value = value.replace(/[^0-9.]/g, "");
if (value.indexOf(".") !== -1) {
const parts = value.split(".");
value = parts[0] + "." + parts[1].substring(0, 2);
}
e.target.value = value;
handlePaymentChange(e);
}}
/>
</div>
<input
type="text" // Keeping text type for more flexible input control
className="form-control"
id="salary_amount"
name="salary_amount"
value={paymentData.salary_amount}
onChange={handlePaymentChange}
onKeyDown={(e) => {
// Prevent negative and positive signs
if (e.key === "-" || e.key === "+") {
e.preventDefault();
}
}}
required
onInput={(e) => {
let value = e.target.value;
// Remove all characters except numbers and the decimal point
value = value.replace(/[^0-9.]/g, '');
// Ensure only one decimal point
if (value.indexOf('.') !== -1) {
const parts = value.split('.');
value = parts[0] + '.' + parts[1].substring(0, 2); // Keep only two digits after the decimal
}
// Update the value on the input element
e.target.value = value;
// Call the onChange handler to update the state
handlePaymentChange(e);
}}
/>
{/* Salary Unit Select */}
<div className="col-md-5 mb-3"> {/* Added margin bottom for spacing */}
<select
className="form-control"
name="salary_unit"
value={paymentData.salary_unit}
onChange={handlePaymentChange}
required
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
>
<option value="" disabled>
Per Unit
</option>
<option value="hourly">Hourly</option>
<option value="weekly">Weekly</option>
<option value="bi weekly">Bi Weekly</option>
<option value="monthly">Monthly</option>
</select>
</div>
</div>
</div>
<div className="form-row form-group col-md-6">
<label htmlFor="salary_unit">Salary Unit</label>
<select
className="form-control"
name="salary_unit"
value={paymentData.salary_unit}
onChange={handlePaymentChange}
required
>
<option value="hourly">Hourly</option>
<option value="weekly">Weekly</option>
<option value="bi weekly">Bi Weekly</option>
<option value="monthly">Monthly</option>
</select>
</div>
<div className="form-row form-group col-md-6">
<label htmlFor="start_date">Start Date</label>
<input
type="date"
className="form-control"
name="start_date"
value={paymentData.start_date}
onChange={handlePaymentChange}
required
/>
</div>
<div className="form-row form-group col-md-6">
<label htmlFor="end_date">End Date</label>
<input
type="date"
className="form-control"
name="end_date"
value={paymentData.end_date}
onChange={handlePaymentChange}
required
/>
</div>
{/* <ToastContainer /> */}
<div className="form-row form-group col-md-6">
<label htmlFor="total_hour">Total Hours</label>
<input
type="number"
className="form-control"
placeholder="Total Hours"
name="total_hour"
value={paymentData.total_hour}
onChange={handlePaymentChange}
onInput={(e) => {
// Allow only numbers and a decimal point with two digits after it
e.target.value = e.target.value
.replace(/[^0-9]/g, '') // Remove non-numeric characters
.slice(0, 3); // Limit input length (10 digits + 1 decimal + 2 decimal places)
}}
required
/>
</div>
<div className="form-group">
<label htmlFor="payment_method">Payment Method</label>
<select
name="payment_method"
id="payment_method"
className="form-control"
value={paymentData.payment_method}
onChange={handlePaymentChange}
>
<option value="cash">Cash</option>
<option value="cheque">Bank Transfer</option>
</select>
</div>
{paymentData.payment_method === "cheque" && (
<div className="form-group">
<label htmlFor="bank">Bank</label>
<select
name="bank"
id="bank"
<div className="form-group row col-md-12 justify-content-between">
{/* Start Date Input */}
<div className="form-group col-md-5">
<input
type="date"
className="form-control"
value={paymentData.bank}
name="start_date"
value={paymentData.start_date}
onChange={handlePaymentChange}
>
<option value="">Select Bank</option>
{bankdata.map((bank) => (
<option key={bank.id} value={bank.id}>
{bank.name}
</option>
))}
</select>
<label htmlFor="cheque_no">Cheque Number</label>
required
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
/>
</div>
{/* End Date Input */}
<div className="form-group col-md-5">
<input
type="date"
className="form-control"
name="end_date"
value={paymentData.end_date}
onChange={handlePaymentChange}
required
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
/>
</div>
</div>
{/* <ToastContainer /> */}
<div className="form-group row col-md-12 justify-content-between">
{/* Total Hours Input */}
<div className="form-group col-md-5" >
<input
type="number"
className="form-control"
id="cheque_no"
name="cheque_no"
value={paymentData.cheque_no}
placeholder="Total Hours"
name="total_hour"
value={paymentData.total_hour}
onChange={handlePaymentChange}
onInput={(e) => {
// Allow only numbers and limit input to 3 digits
e.target.value = e.target.value.replace(/[^0-9]/g, '').slice(0, 3);
}}
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border,
borderRadius: "0px",
}}
required
/>
</div>
)}
<div className="form-row form-group col-md-6">
<label htmlFor="note">Notes</label>
<input
type="text"
className="form-control"
placeholder="Notes"
name="note"
value={paymentData.note}
onChange={handlePaymentChange}
/>
{/* Payment Method Select */}
<div className="form-group col-md-5">
<div style={{ border: '2px solid #ACB4AA', padding: '5px 5px', width: "fit-content", borderRadius: '40px', display: 'flex', }}>
<button
type="button"
className="btn"
onClick={() => handlePaymentChange({ target: { name: "payment_method", value: "cash" } })}
style={{
backgroundColor: paymentData.payment_method === "cash" ? "#4a5546" : "transparent",
color: paymentData.payment_method === "cash" ? "#ffffff" : "#000000",
border: 'none',
padding: '5px 5px',
borderRadius: '20px',
cursor: 'pointer',
}}
>
Cash
</button>
<button
type="button"
className="btn"
onClick={() => handlePaymentChange({ target: { name: "payment_method", value: "cheque" } })}
style={{
backgroundColor: paymentData.payment_method === "cheque" ? "#4a5546" : "transparent",
color: paymentData.payment_method === "cheque" ? "#ffffff" : "#000000",
border: 'none',
padding: '5px 5px',
borderRadius: '20px',
cursor: 'pointer',
}}
>
Bank Transfer
</button>
</div>
</div>
</div>
{paymentData.payment_method === "cheque" && (
<div className="form-group row col-md-12 justify-content-between">
<div className="form-group col-md-5">
<select
name="bank"
id="bank"
className="form-control"
value={paymentData.bank}
onChange={handlePaymentChange}
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
>
<option value="">Select Bank</option>
{bankdata.map((bank) => (
<option key={bank.id} value={bank.id}>
{bank.name}
</option>
))}
</select>
</div>
<div className="form-group col-md-5">
<input
type="number"
className="form-control"
id="cheque_no"
placeholder="Cheque No"
name="cheque_no"
value={paymentData.cheque_no}
onChange={handlePaymentChange}
required
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
/>
</div>
<div className="form-group col-md-5">
<input
type="text"
className="form-control"
placeholder="Notes"
name="note"
value={paymentData.note}
onChange={handlePaymentChange}
style={{
backgroundColor: "#ffffff",
border: "none",
borderBottom: "1px solid #9e9e9e", // Set bottom border
borderRadius: "0px",
}}
/>
</div>
</div>
)}
</div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary" style={{}}>
<div className="modal-footer" style={{border:"none"}}>
<button type="submit" className="btn " style={{ color: "white", backgroundColor: '#282e26', borderRadius: '20px' }}>
Payment
</button>
<button type="button" className="btn btn-contained" onClick={closeModal}>
<button type="button" className="btn " onClick={closeModal} style={{ border: " 1px solid #282e26", borderRadius: '20px' }}>
Close
</button>
</div>

View File

@ -16,6 +16,7 @@ const DataTable = ({
direction: "ascending",
});
const [rowsPerPage, setRowsPerPage] = useState(5);
const [searchTerm, setSearchTerm] = useState(""); // State for search term
const totalPages = Math.ceil(data.length / rowsPerPage);
@ -32,7 +33,7 @@ const DataTable = ({
const getDisplayedData = () => {
const startIndex = (currentPage - 1) * rowsPerPage;
const endIndex = startIndex + rowsPerPage;
return data.slice(startIndex, endIndex);
return sortedData.slice(startIndex, endIndex); // Return sorted data
};
// Sorting the data based on the selected column
@ -51,8 +52,16 @@ const DataTable = ({
return dataToSort;
};
// Search functionality
const filteredData = data.filter(item =>
columns.some(col => {
const value = item[col.field] ? item[col.field].toString().toLowerCase() : "";
return value.includes(searchTerm.toLowerCase());
})
);
const sortedData = sortData(filteredData);
const displayedData = getDisplayedData();
const sortedData = sortData(displayedData);
// Pagination
const handleNext = () => {
@ -90,7 +99,40 @@ const DataTable = ({
return (
<div className="data-table-container">
<table className="data-table custom-table rounded-table">
<div className="search-container" style={{marginBottom:"20px"}}>
<input
type="text"
style={{ width: "300px", height: "50px", backgroundColor: "#fff", border: '1px solid #DBDBDB', boxShadow: "0px 0px 10px rgba(187, 187, 187, 0.25)" }}
placeholder="Search..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="search-input"
/>
<svg
className="search-container-icon"
width="22"
height="22"
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.5416 19.2497C15.3511 19.2497 19.2499 15.3508 19.2499 10.5413C19.2499 5.73186 15.3511 1.83301 10.5416 1.83301C5.73211 1.83301 1.83325 5.73186 1.83325 10.5413C1.83325 15.3508 5.73211 19.2497 10.5416 19.2497Z"
stroke="#292D32"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M20.1666 20.1663L18.3333 18.333"
stroke="#292D32"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
{columns.map((col, index) => (
@ -134,17 +176,19 @@ const DataTable = ({
<tbody className="table-body">
{sortedData.length === 0 ? (
<tr>
<td colSpan={columns.length + (showAction ? 2 : 1)} style={{ textAlign: "center", fontFamily: 'Manrope',
fontWeight: '600',
fontSize: '40px',
background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) -92.86%, #4545DB 71.43%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent', }}>
<td colSpan={columns.length + (showAction ? 2 : 1)} style={{
textAlign: "center", fontFamily: 'Manrope',
fontWeight: '600',
fontSize: '40px',
background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) -92.86%, #4545DB 71.43%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}>
No data found
</td>
</tr>
) : (
sortedData.map((item, index) => (
displayedData.map((item, index) => (
<tr key={item.id || index}>
{columns.map((col, colIndex) => (
<td key={colIndex}>
@ -200,55 +244,18 @@ const DataTable = ({
)}
</tbody>
</table>
{showFooter && (
<nav>
<ul className="pagination">
<li className={`prev-next ${currentPage === 1 ? "disabled" : ""}`}>
<span
style={{
fontSize: "24px",
width: "40px",
height: "40px",
paddingLeft: "10px",
paddingRight: "10px",
borderRadius: "50%",
border: "1px solid #bfbfbfbf",
alignItems: "center",
justifyContent: "center",
display: "flex",
cursor: "pointer",
}}
onClick={handlePrev}
>
{"<"}
&lt;
</span>
&nbsp;
</li>
<div className="pagination">
<button onClick={handlePrev} disabled={currentPage === 1}>
Previous
</button>
<ul className="pagination-list">
{renderPagination()}
<li className={`prev-next ${currentPage === totalPages ? "disabled" : ""}`}>
<span
style={{
fontSize: "24px",
width: "40px",
height: "40px",
paddingLeft: "10px",
paddingRight: "10px",
borderRadius: "50%",
border: "1px solid #bfbfbfbf",
alignItems: "center",
justifyContent: "center",
display: "flex",
cursor: "pointer",
}}
onClick={handleNext}
>
{">"}
</span>
</li>
</ul>
</nav>
<button onClick={handleNext} disabled={currentPage === totalPages}>
Next
</button>
</div>
)}
</div>
);

View File

@ -154,18 +154,19 @@ const PayrollTableWithButton = ({
borderRadius: "4px",
zIndex: "1",
};
// Calculate the total net sales from the data
// const totalNetSales = data.reduce((acc, item) => {
// const amount = Number(item.total_net_sales) || 0; // Make sure to handle non-numeric values
// return acc + amount;
// }, 0).toFixed(2); //
// Calculate the total net sales from the data
// const totalNetSales = data.reduce((acc, item) => {
// const amount = Number(item.total_net_sales) || 0; // Make sure to handle non-numeric values
// return acc + amount;
// }, 0).toFixed(2); //
return (
<div className="data-table-container">
<div className="d-flex mb-3">
<div className="expense-searchcontainerstart d-flex">
<div className="search-container">
<div className="expense-searchcontainerstart d-flex" >
<div className="search-container" >
<input
type="text"
style={{ width: "300px", height: "50px", backgroundColor: "#fff", border: '1px solid #DBDBDB', boxShadow: "0px 0px 10px rgba(187, 187, 187, 0.25)" }}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search"
@ -237,7 +238,7 @@ const PayrollTableWithButton = ({
Export To Excel
</button>
)}
{showFilter && (
{showFilter && (
<div className="filter-button-container" style={{ position: "relative" }}>
<button className="btn custbtn2" type="button" onClick={handleFilterClick}>
<svg
@ -262,26 +263,54 @@ const PayrollTableWithButton = ({
</div>
)}
</div>
<div className="expense-searchcontainerend d-flex align-items-center">
<h3 className="me-2">Show</h3>
<select
name="option"
id="pageSelect"
className="selectoptions"
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to first page on change
<div >
<div
className="expense-search d-flex align-items-center"
style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
<h6 className="" style={{ margin: '10px' }}>Show</h6>
<select
name="option"
id="pageSelect"
className="selectoptions"
style={{
height: "30px",
padding: "2px 6px",
border: "1px solid #ccc",
backgroundColor: "#282E26",
color: "#fff",
fontSize: "14px",
}}
value={rowsPerPage}
onChange={(e) => {
setRowsPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to first page on change
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
<option value={20}>20</option>
</select>
</div>
</div>
</div>
<table className="data-table custom-table rounded-table">
<table className="data-table custom-table ">
<thead className="table-header">
<tr>
<th scope="col" className="no-column">
@ -324,78 +353,80 @@ const PayrollTableWithButton = ({
</tr>
</thead>
<tbody className="table-body">
{sortedDisplayedData.length === 0 ? (
<tr>
<td colSpan={columns.length + (showAction ? 2 : 1)} style={{ textAlign: "center", fontFamily: 'Manrope',
fontWeight: '600',
fontSize: '40px',
background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) -92.86%, #4545DB 71.43%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent', }}>
No data found
</td>
</tr>
) : (
sortedDisplayedData.map((item) => (
<tr key={item.id || item.index}>
<td>
{(currentPage - 1) * rowsPerPage + sortedDisplayedData.indexOf(item) + 1}
</td>
{columns.map((col, colIndex) => (
<td key={colIndex}>
{col.field === "status" ? (
<div className={`status ${item[col.field]}`}>{item[col.field]}</div>
) : col.field === "pay_salary" ? (
<button
className="btn btn-primary"
onClick={() => togglePaymentModal(item)} // Pass item to payment modal
>
Pay Salary
</button>
) : (
item[col.field]
)}
{sortedDisplayedData.length === 0 ? (
<tr>
<td colSpan={columns.length + (showAction ? 2 : 1)} style={{
textAlign: "center", fontFamily: 'Manrope',
fontWeight: '600',
fontSize: '40px',
background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) -92.86%, #4545DB 71.43%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}>
No data found
</td>
</tr>
) : (
sortedDisplayedData.map((item) => (
<tr key={item.id || item.index}>
<td>
{(currentPage - 1) * rowsPerPage + sortedDisplayedData.indexOf(item) + 1}
</td>
))}
{showAction && (
<td className="action-column">
<button className="action-button" onClick={() => onEdit(item.id)}>
{columns.map((col, colIndex) => (
<td key={colIndex}>
{col.field === "status" ? (
<div className={`status ${item[col.field]}`}>{item[col.field]}</div>
) : col.field === "pay_salary" ? (
<button
style={{ backgroundColor: "#CCF4BB", border: 'none', boxShadow: "4px 4px 4px rgba(0, 0, 0, 0.25)", borderRadius: '4px', fontSize: "16px", alignItems: "center", width: '122px' }}
onClick={() => togglePaymentModal(item)} // Pass item to payment modal
>
Pay Salary
</button>
) : (
item[col.field]
)}
</td>
))}
{showAction && (
<td className="action-column">
<button className="action-button" onClick={() => onEdit(item.id)}>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.8067 4.695C14.0667 4.435 14.0667 4.00167 13.8067 3.755L12.2467 2.195C12 1.935 11.5667 1.935 11.3067 2.195L10.08 3.415L12.58 5.915M2 11.5017V14.0017H4.5L11.8733 6.62167L9.37333 4.12167L2 11.5017Z"
fill="#002300"
/>
</svg>
</button>
<button className="action-button" onClick={() => onDelete(item.id)}>
{/* Delete icon */}
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.00016 12.6667C4.00016 13.4 4.60016 14 5.3335 14H10.6668C11.4002 14 12.0002 13.4 12.0002 12.6667V6C12.0002 5.26667 11.4002 4.66667 10.6668 4.66667H5.3335C4.60016 4.66667 4.00016 5.26667 4.00016 6V12.6667ZM12.0002 2.66667H10.3335L9.86016 2.19333C9.74016 2.07333 9.56683 2 9.3935 2H6.60683C6.4335 2 6.26016 2.07333 6.14016 2.19333L5.66683 2.66667H4.00016C3.6335 2.66667 3.3335 2.96667 3.3335 3.33333C3.3335 3.7 3.6335 4 4.00016 4H12.0002C12.3668 4 12.6668 3.7 12.6668 3.33333C12.6668 2.96667 12.3668 2.66667 12.0002 2.66667Z"
fill="#002300"
/>
</svg>
</button>
</td>
)}
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.8067 4.695C14.0667 4.435 14.0667 4.00167 13.8067 3.755L12.2467 2.195C12 1.935 11.5667 1.935 11.3067 2.195L10.08 3.415L12.58 5.915M2 11.5017V14.0017H4.5L11.8733 6.62167L9.37333 4.12167L2 11.5017Z"
fill="#002300"
/>
</svg>
</button>
<button className="action-button" onClick={() => onDelete(item.id)}>
{/* Delete icon */}
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.00016 12.6667C4.00016 13.4 4.60016 14 5.3335 14H10.6668C11.4002 14 12.0002 13.4 12.0002 12.6667V6C12.0002 5.26667 11.4002 4.66667 10.6668 4.66667H5.3335C4.60016 4.66667 4.00016 5.26667 4.00016 6V12.6667ZM12.0002 2.66667H10.3335L9.86016 2.19333C9.74016 2.07333 9.56683 2 9.3935 2H6.60683C6.4335 2 6.26016 2.07333 6.14016 2.19333L5.66683 2.66667H4.00016C3.6335 2.66667 3.3335 2.96667 3.3335 3.33333C3.3335 3.7 3.6335 4 4.00016 4H12.0002C12.3668 4 12.6668 3.7 12.6668 3.33333C12.6668 2.96667 12.3668 2.66667 12.0002 2.66667Z"
fill="#002300"
/>
</svg>
</button>
</td>
)}
</tr>
))
)}
</tbody>
</tr>
))
)}
</tbody>
</table>
{showFooter && (
@ -423,9 +454,8 @@ const PayrollTableWithButton = ({
</li>
{renderPagination()}
<li
className={`prev-next ${
currentPage === totalPages ? "disabled" : ""
}`}
className={`prev-next ${currentPage === totalPages ? "disabled" : ""
}`}
>
&nbsp;
<span

View File

@ -8,6 +8,9 @@ import { toast, ToastContainer } from "react-toastify";
import AddDepartmentModal from "../ReusableForm/AddDepartmentModal";
import AddVendorModal from "../ReusableForm/AddVendorModal";
import Swal from "sweetalert2";
import invoiceIcon from '../../../../assets/Image/invoiceIcon.png'
import vendor from '../../../../assets/Image/vendor.png'
import department from '../../../../assets/Image/Department.png'
export default function Purchase() {
const { user } = useContext(AuthContext);
@ -40,7 +43,7 @@ export default function Purchase() {
const { Get, Post, Delete, Patch } = useApi();
const [reloadTotal, setReloadTotal] = useState(false);
const [filteredDepartments, setFilteredDepartments] = useState([]);
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState("");
// Handle checkbox change
const [formData, setFormData] = useState({
@ -200,6 +203,7 @@ export default function Purchase() {
const handleSpecificPaymentMethodChange = (e) => {
const value = e.target.value;
setSelectedPaymentMethod(value); // Update selected payment method state
setShowCheckFields(value === "cheque");
setShowBankFields(value === "bank");
@ -514,8 +518,8 @@ export default function Purchase() {
// Editing an existing invoice
const originalInvoice = invoices.find((invoice) => invoice.id === editingInvoiceId);
if (!originalInvoice) {
console.error("Invoice not found for editingInvoiceId:", editingInvoiceId);
return;
console.error("Invoice not found for editingInvoiceId:", editingInvoiceId);
return;
}
// Determine the new status based on payment method and remaining amount
@ -523,11 +527,11 @@ export default function Purchase() {
let newStatus = originalInvoice.status; // Start with the original status
if (formData.pay_method_status === "pay_now") {
newStatus = "paid"; // Always "paid" if paid now
newStatus = "paid"; // Always "paid" if paid now
} else if (formData.pay_method_status === "pay_later") {
newStatus = "unpaid"; // Ensure unpaid if paying later
newStatus = "unpaid"; // Ensure unpaid if paying later
} else if (newRemainingAmount < originalInvoice.amount) {
newStatus = "partially_paid"; // Adjust if partially paid
newStatus = "partially_paid"; // Adjust if partially paid
}
@ -619,12 +623,141 @@ export default function Purchase() {
<div className="main-container">
<div className="d-flex p-2">
<div className="expensecontainer d-flex flex-column pd-2">
<div className="d-flex justify-content-between align-items-center mb-3">
<h3 className="mb-1">Purchase</h3>
<button className="btn btn-primary cus" onClick={toggleModal}>
<div className="d-flex align-items-center mb-3" style={{ gap: "10px" }}>
<button className="btn cus d-flex align-items-center" onClick={toggleModal}>
{" "}
+ Add Invoice
<img
src={invoiceIcon}
alt="Invoice Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
<button style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}>
+ Add New Vendor
<img
src={vendor}
alt="Invoice Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
<button style={{
backgroundColor: "#4A5546",
boxShadow: "none",
outline: "none",
width: "auto",
height: "42px",
padding: "8px 12px",
fontSize: "16px",
border: "none",
borderRadius: "10px",
color: "#F4FFEE",
cursor: "pointer",
}}
>
+ Add Department
<img
src={department}
alt="Invoice Icon"
style={{ width: "20px", height: "20px", marginLeft: "8px" }}
/>
</button>
<div
style={{
display: "flex",
gap: "16px",
justifyContent: "center",
alignItems: "center",
margin: "20px",
}}
>
{/* Invoice due this month */}
<div
style={{
backgroundColor: "#fff8e6",
border: "1px solid #ffd700",
borderRadius: "8px",
padding: "16px 24px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "flex-start",
width: "300px",
textAlign: "left",
}}
>
<p style={{ fontSize: "24px", fontWeight: "bold", margin: "0" }}>
$500
</p>
<p style={{ fontSize: "14px", color: "#555", margin: "4px 0" }}>
Invoice due this month
</p>
</div>
{/* Last 7 days sale */}
<div
style={{
backgroundColor: "#e6ffee",
border: "1px solid #00b300",
borderRadius: "8px",
padding: "16px 24px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "flex-start",
width: "300px",
textAlign: "left",
}}
>
<p style={{ fontSize: "24px", fontWeight: "bold", margin: "0" }}>
$1900
</p>
<p style={{ fontSize: "14px", color: "#555", margin: "4px 0" }}>
Last 7 days sale
</p>
</div>
{/* Expense this month */}
<div
style={{
backgroundColor: "#ffe6e6",
border: "1px solid #ff4d4d",
borderRadius: "8px",
padding: "16px 24px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "flex-start",
width: "300px",
textAlign: "left",
}}
>
<p style={{ fontSize: "24px", fontWeight: "bold", margin: "0" }}>
$0.00
</p>
<p style={{ fontSize: "14px", color: "#555", margin: "4px 0" }}>
Expense this month
</p>
</div>
</div>
</div>
{/* Table Start */}
@ -695,8 +828,10 @@ export default function Purchase() {
<input
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
}}
type="date"
@ -714,8 +849,10 @@ export default function Purchase() {
<input
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
}}
type="text"
@ -733,8 +870,9 @@ export default function Purchase() {
<div className="col-md-6" style={{ paddingRight: "10px" }}>
<select
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
height: "52px",
}}
className="form-control"
@ -771,8 +909,9 @@ export default function Purchase() {
<select
className="form-control"
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
height: "52px",
}}
name="vendor_department_service_titles"
@ -807,107 +946,210 @@ export default function Purchase() {
</div>
</div>
<div className="d-flex col-md-12">
<div className="d-flex col-md-12 mt-2">
<div
className="form-row d-flex col-md-5 p-2 mt-2"
style={{
backgroundColor: "#ffffff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
}}
>
<div className="input-group col-md-6">
<div
className="input-group-prepend"
style={{
</div>
<div
className="d-flex col-md-12"
style={{ paddingLeft: "5px", paddingTop: "15px" }}
>
<p>Payment Method : </p>
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
background: "#ffffff",
height: "100%",
display: "flex",
alignItems: "center",
}}
>
{/* <span className="input-group-text prefixtext"
style={{ border: "none", fontSize: "14px" }}>
USD
</span> */}
</div>
<input
required
type="number"
className="form-control sampletext"
placeholder="Amount"
aria-label="Username"
aria-describedby="addon-wrapping"
name={editingInvoiceId ? "pay_amount" : "amount"}
value={
editingInvoiceId && formData.pay_amount === undefined
? formData.remaining_amount
: formData.pay_amount || formData.amount
}
onChange={handleChange}
onInput={(e) => {
// Allow only numbers and a decimal point with two digits after it
e.target.value = e.target.value
.replace(/[^0-9.]/g, '') // Remove non-numeric characters except the decimal point
.replace(/^(\d*\.?\d{0,2}).*/g, '$1') // Allow only two decimal places
.slice(0, 12); // Limit input length (10 digits + 1 decimal + 2 decimal places)
}}
/>
</div>
</div>
<div
style={{
border: '2px solid #ACB4AA',
padding: '5px 10px',
marginTop: '20px',
width: 'fit-content',
borderRadius: '40px',
display: 'flex', // Use flexbox
gap: '10px', // Add spacing between the options
}}
>
<input
type="radio"
name="pay_method_status"
value="pay_later"
checked={formData.pay_method_status === "pay_later"}
onChange={handlePaymentMethodChange}
/>{" "}
Pay Later
</label>
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
>
<input
type="radio"
name="pay_method_status"
value="pay_now"
checked={formData.pay_method_status === "pay_now"}
onChange={handlePaymentMethodChange}
/>{" "}
Pay Now
</label>
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
>
<input
type="radio"
name="pay_method_status"
value="credit_invoice"
checked={
formData.pay_method_status === "credit_invoice"
}
onChange={handlePaymentMethodChange}
/>{" "}
Credit Invoice
</label>
</div>
{showPaymentOptions && (
<div className="d-flex col-md-6 mb-3">
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
style={{
backgroundColor: formData.pay_method_status === "pay_later" ? "#4a5546" : "transparent",
color: formData.pay_method_status === "pay_later" ? "white" : "black",
padding: '5px 10px',
borderRadius: '20px',
}}
>
<input
type="radio"
name="specificPaymentMethod"
value="cash"
onChange={handleSpecificPaymentMethodChange}
name="pay_method_status"
value="pay_later"
checked={formData.pay_method_status === "pay_later"}
onChange={handlePaymentMethodChange}
style={{ display: 'none' }} // Hide the radio button
/>{" "}
Cash
Pay Later
</label>
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
style={{
backgroundColor: formData.pay_method_status === "pay_now" ? "#4a5546" : "transparent",
color: formData.pay_method_status === "pay_now" ? "white" : "black",
padding: '5px 10px',
borderRadius: '20px',
}}
>
<input
type="radio"
name="specificPaymentMethod"
value="cheque"
onChange={handleSpecificPaymentMethodChange}
name="pay_method_status"
value="pay_now"
checked={formData.pay_method_status === "pay_now"}
onChange={handlePaymentMethodChange}
style={{ display: 'none' }} // Hide the radio button
/>{" "}
Check
Pay Now
</label>
<label
className="radio-inline"
style={{ paddingLeft: "10px" }}
style={{
backgroundColor: formData.pay_method_status === "credit_invoice" ? "#4a5546" : "transparent",
color: formData.pay_method_status === "credit_invoice" ? "white" : "black",
padding: '5px 10px',
borderRadius: '20px',
}}
>
<input
type="radio"
name="specificPaymentMethod"
value="bank"
onChange={handleSpecificPaymentMethodChange}
name="pay_method_status"
value="credit_invoice"
checked={formData.pay_method_status === "credit_invoice"}
onChange={handlePaymentMethodChange}
style={{ display: 'none' }} // Hide the radio button
/>{" "}
Bank Card/ACH/EFT
Credit Invoice
</label>
</div>
</div>
{showPaymentOptions && (
<div
className="d-flex col-md-6 mb-3"
style={{
border: "2px solid #ACB4AA",
padding: "5px 10px",
width: "fit-content",
borderRadius: "40px",
display: "flex",
gap: "10px",
marginTop: "20px",
}}
>
<div
className="payment-option"
onClick={() => handleSpecificPaymentMethodChange({ target: { value: "cash" } })}
style={{
padding: '5px 10px',
cursor: "pointer",
borderRadius: "20px",
backgroundColor: selectedPaymentMethod === "cash" ? "#4a5546" : "transparent", // Change background based on selection
color: selectedPaymentMethod === "cash" ? "white" : "black", // Change text color based on selection
textAlign: "center",
}}
>
Cash
</div>
<div
className="payment-option"
onClick={() => handleSpecificPaymentMethodChange({ target: { value: "cheque" } })}
style={{
padding: '5px 10px',
cursor: "pointer",
borderRadius: "20px",
backgroundColor: selectedPaymentMethod === "cheque" ? "#4a5546" : "transparent",
color: selectedPaymentMethod === "cheque" ? "white" : "black",
textAlign: "center",
}}
>
Check
</div>
<div
className="payment-option"
onClick={() => handleSpecificPaymentMethodChange({ target: { value: "bank" } })}
style={{
padding: '5px 10px',
cursor: "pointer",
borderRadius: "20px",
backgroundColor: selectedPaymentMethod === "bank" ? "#4a5546" : "transparent",
color: selectedPaymentMethod === "bank" ? "white" : "black",
textAlign: "center",
}}
>
Bank Card/ACH/EFT
</div>
</div>
)}
{showAdditionalFields && (
<div className="d-flex col-md-5 mt-2">
<div className="d-flex col-md-5 mt-2" style={{ marginTop: '20px' }}>
<select
className="form-control col-md-5 me-2"
name="days"
value={formData.days || ""}
onChange={handleChange}
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
}}
required
>
@ -920,8 +1162,11 @@ export default function Purchase() {
</select>
<input
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "50px",
}}
className="form-control d-flex col-md-5"
@ -938,8 +1183,11 @@ export default function Purchase() {
<div className="d-flex col-md-4 mt-2">
<select
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
marginRight: "10px",
}}
@ -962,8 +1210,11 @@ export default function Purchase() {
className="form-control me-2"
placeholder="Check Number"
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
marginRight: "10px",
}}
@ -978,8 +1229,11 @@ export default function Purchase() {
<div className="d-flex col-md-4 mt-2">
<input
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
}}
className="form-control col-md-3"
@ -994,8 +1248,11 @@ export default function Purchase() {
<div className="d-flex col-md-6 mt-2">
<select
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
marginRight: "10px",
}}
@ -1015,8 +1272,11 @@ export default function Purchase() {
<div className="d-flex col-md-6 mt-2">
<input
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
}}
className="form-control col-md-3"
@ -1047,8 +1307,11 @@ export default function Purchase() {
<div
className="form-row d-flex col-md-6 p-2 mt-2"
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
backgroundColor: "#fff",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
height: "52px",
height: "52px",
}}
>
@ -1056,19 +1319,19 @@ export default function Purchase() {
<div
className="input-group-prepend"
style={{
background: "#F5F5F5",
background: "#ffffff",
height: "100%",
borderRadius: "10px 0 0 10px",
display: "flex",
alignItems: "center",
}}
>
<span
{/* <span
className="input-group-text prefixtext"
style={{ border: "none", fontSize: "14px" }}
>
USD
</span>
</span> */}
</div>
<input
type="text"
@ -1089,56 +1352,7 @@ export default function Purchase() {
</div>
</div>
)}
<div
className="form-row d-flex col-md-6 p-2 mt-2"
style={{
backgroundColor: "#0023000C",
borderRadius: "10px",
height: "52px",
}}
>
<div className="input-group col-md-6">
<div
className="input-group-prepend"
style={{
background: "#F5F5F5",
height: "100%",
borderRadius: "10px 0 0 10px",
display: "flex",
alignItems: "center",
}}
>
<span className="input-group-text prefixtext"
style={{ border: "none", fontSize: "14px" }}>
USD
</span>
</div>
<input
required
type="number"
className="form-control sampletext"
placeholder="Amount"
aria-label="Username"
aria-describedby="addon-wrapping"
name={editingInvoiceId ? "pay_amount" : "amount"}
value={
editingInvoiceId && formData.pay_amount === undefined
? formData.remaining_amount
: formData.pay_amount || formData.amount
}
onChange={handleChange}
onInput={(e) => {
// Allow only numbers and a decimal point with two digits after it
e.target.value = e.target.value
.replace(/[^0-9.]/g, '') // Remove non-numeric characters except the decimal point
.replace(/^(\d*\.?\d{0,2}).*/g, '$1') // Allow only two decimal places
.slice(0, 12); // Limit input length (10 digits + 1 decimal + 2 decimal places)
}}
/>
</div>
</div>
</form>
</div>
<div className="modal-footer" style={{ border: "none" }}>
@ -1146,13 +1360,15 @@ export default function Purchase() {
type="button"
className="btn btn-secondary-outline"
onClick={toggleModal}
style={{ border: " 1px solid #282e26", borderRadius: '20px' }}
>
Close
</button>
<button
type="submit"
className="btn btn-primary"
className="btn "
onClick={handleSubmit}
style={{ color: "white", backgroundColor: '#282e26', borderRadius: '20px' }}
>
Submit
</button>

View File

@ -37,23 +37,33 @@ const AddDepartmentModal = ({ show, handleClose, onDepartmentAdded }) => {
};
return (
<ReusableModal show={show} handleClose={handleClose} title="Add Department" width="760px" height="175px">
<ReusableModal show={show} handleClose={handleClose} title="Add Department" width="760px" height="250px">
<form onSubmit={handleSave}>
<div className="form-group d-flex align-items-center mt-1">
<div className="form-group ">
<input
type="text"
className="input-field"
placeholder="Department Name"
value={departmentName}
onChange={(e) => setDepartmentName(e.target.value)}
style={{ width: "483px", marginRight: "10px" }}
style={{ width: "483px", border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
marginBottom: "20px",
borderRadius: "0px", // Remove border radius
}}
required
/>
</div>
<div
style={{
textAlign: "right", // Align content to the right
}}
>
<button
type="submit"
style={{
padding: "6px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
@ -61,11 +71,11 @@ const AddDepartmentModal = ({ show, handleClose, onDepartmentAdded }) => {
width: "103px",
height: "42px",
fontSize: "18px",
marginLeft: "20px",
}}
>
Submit
</button>
</div>
</form>
</ReusableModal>

View File

@ -37,23 +37,35 @@ const AddExpenseTypeModal = ({ show, handleClose, onExpenseTypeAdded }) => {
};
return (
<ReusableModal show={show} handleClose={handleClose} title="Add Expense Type" width="760px" height="175px">
<ReusableModal show={show} handleClose={handleClose} title="Add Expense Type" width="760px" height="250px">
<form onSubmit={handleSave}>
<div className="form-group d-flex align-items-center">
<div className="form-group">
<input
type="text"
className="input-field"
placeholder="Expense Type"
value={expenseType}
onChange={(e) => setExpenseType(e.target.value)}
style={{ width: "483px", marginRight: "10px" }}
style={{
width: "483px",
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
marginBottom: "20px",
borderRadius: "0px", // Remove border radius
}}
required
/>
</div>
<div
style={{
textAlign: "right", // Align content to the right
}}
>
<button
type="submit"
style={{
padding: "6px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
@ -61,7 +73,6 @@ const AddExpenseTypeModal = ({ show, handleClose, onExpenseTypeAdded }) => {
width: "103px",
height: "42px",
fontSize: "18px",
marginLeft: "20px",
}}
>
Submit
@ -70,6 +81,5 @@ const AddExpenseTypeModal = ({ show, handleClose, onExpenseTypeAdded }) => {
</form>
</ReusableModal>
);
};
}
export default AddExpenseTypeModal;

View File

@ -93,18 +93,26 @@ const AddVendorModal = ({ show, handleClose, reloadData }) => {
placeholder="Vendor Name"
value={vendorName}
onChange={(e) => setVendorName(e.target.value)}
style={{ width: "400px", marginRight: "10px", height: "44px" }}
style={{ width: "400px", marginRight: "10px", height: "44px" ,
border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
<select
className="input-field"
value={vendorType}
onChange={(e) => {
onChange={(e) => {
setVendorType(e.target.value);
setVendorDepartments([]); // Reset departments when type changes
setOpeningBalance("");
}}
style={{ width: "400px", marginRight: "10px", height: "44px" }}
style={{ width: "400px", marginRight: "10px", height: "44px" , border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
>
<option value="">Vendor Type</option>
@ -136,7 +144,10 @@ const AddVendorModal = ({ show, handleClose, reloadData }) => {
<select
className="input-field"
onChange={handleDepartmentChange}
style={{ width: "400px", marginRight: "10px", height: "44px" }}
style={{ width: "400px", marginRight: "10px", height: "44px" , border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
>
<option value="">
{vendorType === "purchase"
@ -159,7 +170,10 @@ const AddVendorModal = ({ show, handleClose, reloadData }) => {
placeholder="Opening Balance"
value={openingBalance}
onChange={(e) => setOpeningBalance(e.target.value)}
style={{ width: "400px", marginRight: "10px", height: "44px" }}
style={{ width: "400px", marginRight: "10px", height: "44px" , border: "none", // Remove all borders
borderBottom: "2px solid #ccc", // Set bottom border
borderRadius: "0px", // Remove border radius
}}
/>
)}
</div>
@ -170,10 +184,10 @@ const AddVendorModal = ({ show, handleClose, reloadData }) => {
style={{
marginLeft: "690px",
padding: "4px 8px",
backgroundColor: "#4545db",
backgroundColor: "#282e26",
color: "white",
border: "none",
borderRadius: "40px",
borderRadius: "20px",
cursor: "pointer",
width: "124px",
height: "42px",

View File

@ -34,9 +34,14 @@ const Header = () => {
const settingsRef = useRef(null);
const lotteryRef = useRef(null);
const gasRef = useRef(null);
const [selectedNav, setSelectedNav] = useState("/");
// const [selectedNav, setSelectedNav] = useState("/");
const { Get, getAPI, Post } = useApi();
const [parentLabel, setParentLabel] = useState("Expense"); // Parent label
const [selectedChild, setSelectedChild] = useState(""); // Selected child label
const [selectedNav, setSelectedNav] = useState("Expense");
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const toggleMobileMenu = () => {
setIsMobileMenuOpen(!isMobileMenuOpen);
@ -59,6 +64,18 @@ const Header = () => {
logOutUser();
};
const handleChildSelection = (childLabel) => {
setSelectedChild(childLabel); // Update the selected child label
setExpenseDropdownOpen(false); // Close the dropdown
};
const toggleDropdown = () => {
setExpenseDropdownOpen(!expenseDropdownOpen);
if (expenseDropdownOpen) {
setSelectedChild(""); // Clear selected child if closing
}
};
const handleStoreManageClick = async () => {
setDropdownVisible(!isDropdownVisible);
@ -141,6 +158,8 @@ const Header = () => {
setLotteryDropdownOpen(false);
setGasDropdownOpen(false);
setDropdownVisible(false);
setSelectedChild("");
};
useEffect(() => {
@ -151,43 +170,42 @@ const Header = () => {
}, []);
return (
<header className="header-container">
<div className="navbar-left">
<img src={paisavalaLogo} alt="Logo" />
</div>
<div className="navbar-left">
<img src={paisavalaLogo} alt="Logo" />
</div>
<nav className="navbar navbar-expand-lg">
<div className="container-fluid">
{/* <Link to="/">
<img src={logo} alt="Logo" className="logo" />
</Link> */}
<button
className="navbar-toggler"
type="button"
onClick={toggleMobileMenu}
>
<i className="fas fa-bars"></i>
</button>
<div
className={`collapse navbar-collapse ${isMobileMenuOpen ? 'show' : ''}`}
id="navbarNav"
> <ul className="navbar-nav me-auto">
{userRole === "store owner" && (
<li
className={`nav-item ${
selectedNav === "/owner-dashboard" ? "active" : ""
}`}
className="navbar-toggler"
type="button"
onClick={toggleMobileMenu}
>
<Link
className="nav-link"
to="/owner-dashboard"
onClick={() => {
setSelectedNav("/owner-dashboard");
closeDropdowns();
}}
>
Owner Dashboard
</Link>
</li>
)}
<i className="fas fa-bars"></i>
</button>
<div
className={`collapse navbar-collapse ${isMobileMenuOpen ? 'show' : ''}`}
id="navbarNav"
> <ul className="navbar-nav me-auto">
{userRole === "store owner" && (
<li
className={`nav-item ${selectedNav === "/owner-dashboard" ? "active" : ""
}`}
>
<Link
className="nav-link"
to="/owner-dashboard"
onClick={() => {
setSelectedNav("/owner-dashboard");
closeDropdowns();
}}
>
Owner Dashboard
</Link>
</li>
)}
<li className={`nav-item ${selectedNav === "/" ? "active" : ""}`}>
<Link
@ -201,28 +219,80 @@ const Header = () => {
Dashboard
</Link>
</li>
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
className={`nav-item ${expenseDropdownOpen ? "active" : ""}`}
ref={expenseRef}
onClick={() => {
closeDropdowns();
setExpenseDropdownOpen(!expenseDropdownOpen);
}}
style={{
display: "flex",
flexDirection: "column", // Ensures child label is displayed below
alignItems: "flex-start", // Align labels to the left
position: "relative",
marginTop: "12px",
}}
>
{/* Parent Label */}
<a
className="nav-link"
href="#"
onClick={(e) => e.preventDefault()}
>
Expense
{parentLabel}
</a>
{/* Selected Child Label Below Parent Label */}
{selectedChild && (
<span
style={{
fontSize: "14px",
color: "white",
// borderBottom:'1px solid blue',
backgroundColor: "#282e26",
padding: "0px 20px",
borderRadius: '20px',
fontStyle: "normal",
}}
>
{selectedChild}
</span>
)}
{/* Dropdown Menu */}
{expenseDropdownOpen && (
<ul className="nav-menu-drop">
<ul
className="nav-menu-drop"
style={{
listStyle: "none",
padding: "10px",
margin: "0px",
border: "1px solid #ccc",
borderRadius: "4px",
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
backgroundColor: "#fff",
position: "absolute",
top: "100%", // Ensures dropdown appears below labels
left: "0",
zIndex: 10,
transform: "translateY(20px)", // Moves dropdown below header area
}}
>
<li>
<Link
className="nav-menu-drop-item"
to="/expense"
onClick={closeDropdowns}
onClick={() => handleChildSelection("Expense")}
style={{
display: "block",
padding: "8px 12px",
color: "#000",
textDecoration: "none",
}}
>
Expense
</Link>
@ -231,7 +301,13 @@ const Header = () => {
<Link
className="nav-menu-drop-item"
to="/purchase"
onClick={closeDropdowns}
onClick={() => handleChildSelection("Purchase")}
style={{
display: "block",
padding: "8px 12px",
color: "#000",
textDecoration: "none",
}}
>
Purchase
</Link>
@ -239,10 +315,10 @@ const Header = () => {
</ul>
)}
</li>
<li
className={`nav-item ${
selectedNav === "/payroll" ? "active" : ""
}`}
className={`nav-item ${selectedNav === "/payroll" ? "active" : ""
}`}
>
<Link
className="nav-link"
@ -257,9 +333,8 @@ const Header = () => {
</li>
<li
className={`nav-item ${
selectedNav === "/reportDateSelection" ? "active" : ""
}`}
className={`nav-item ${selectedNav === "/reportDateSelection" ? "active" : ""
}`}
>
<Link
className="nav-link"
@ -272,92 +347,92 @@ const Header = () => {
Reports
</Link>
</li>
{(userRole === "store owner" || userRole === "store manager") &&(
{(userRole === "store owner" || userRole === "store manager") && (
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
ref={generalRef}
onClick={() => {
closeDropdowns();
setGeneralDropdownOpen(!generalDropdownOpen);
}}
>
<a
className="nav-link"
href="#"
onClick={(e) => e.preventDefault()}
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
ref={generalRef}
onClick={() => {
closeDropdowns();
setGeneralDropdownOpen(!generalDropdownOpen);
}}
>
General
</a>
{generalDropdownOpen && (
<ul className="nav-menu-drop">
<li>
<Link
className="nav-menu-drop-item"
to="/ATM"
onClick={closeDropdowns}
>
ATM
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/Bank"
onClick={closeDropdowns}
>
Bank
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/OtherIncome"
onClick={closeDropdowns}
>
Other Income
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/SalesTax"
onClick={closeDropdowns}
>
Sales Tax
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/bankLedger"
onClick={closeDropdowns}
>
Bank Ledger
</Link>
</li>
<a
className="nav-link"
href="#"
onClick={(e) => e.preventDefault()}
>
General
</a>
{generalDropdownOpen && (
<ul className="nav-menu-drop">
<li>
<Link
className="nav-menu-drop-item"
to="/ATM"
onClick={closeDropdowns}
>
ATM
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/Bank"
onClick={closeDropdowns}
>
Bank
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/OtherIncome"
onClick={closeDropdowns}
>
Other Income
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/SalesTax"
onClick={closeDropdowns}
>
Sales Tax
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/bankLedger"
onClick={closeDropdowns}
>
Bank Ledger
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/cashLedger"
onClick={closeDropdowns}
>
Cash Ledger
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/OwnerDist"
onClick={closeDropdowns}
>
Owner Distribution
</Link>
</li>
</ul>
)}
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/cashLedger"
onClick={closeDropdowns}
>
Cash Ledger
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/OwnerDist"
onClick={closeDropdowns}
>
Owner Distribution
</Link>
</li>
</ul>
)}
</li>
)}
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
@ -472,191 +547,191 @@ const Header = () => {
</ul>
)}
</li>
{userRole === "store owner" &&(
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
ref={settingsRef}
onClick={() => {
closeDropdowns();
setSettingsDropdownOpen(!settingsDropdownOpen);
}}
>
<a
className="nav-link"
href="#"
onClick={(e) => e.preventDefault()}
>
Settings
{userRole === "store owner" && (
<li
className={`nav-item ${selectedNav === "#" ? "active" : ""}`}
ref={settingsRef}
onClick={() => {
closeDropdowns();
setSettingsDropdownOpen(!settingsDropdownOpen);
}}
>
<a
className="nav-link"
href="#"
onClick={(e) => e.preventDefault()}
>
Settings
</a>
{settingsDropdownOpen && (
<ul className="nav-menu-drop">
<li>
<Link
className="nav-menu-drop-item"
to="/store-information"
onClick={closeDropdowns}
>
Store Information
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-users"
onClick={closeDropdowns}
>
Manage Users
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-departments"
onClick={closeDropdowns}
>
Manage Departments
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-expense-type"
onClick={closeDropdowns}
>
Manage Expense Type
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/other-income-type"
onClick={closeDropdowns}
>
Other Income Type
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-vendor"
onClick={closeDropdowns}
>
Manage Vendor
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-settings"
onClick={closeDropdowns}
>
Manage Settings
</Link>
</li>
</ul>
)}
</li>
)}
</a>
{settingsDropdownOpen && (
<ul className="nav-menu-drop">
<li>
<Link
className="nav-menu-drop-item"
to="/store-information"
onClick={closeDropdowns}
>
Store Information
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-users"
onClick={closeDropdowns}
>
Manage Users
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-departments"
onClick={closeDropdowns}
>
Manage Departments
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-expense-type"
onClick={closeDropdowns}
>
Manage Expense Type
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/other-income-type"
onClick={closeDropdowns}
>
Other Income Type
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-vendor"
onClick={closeDropdowns}
>
Manage Vendor
</Link>
</li>
<li>
<Link
className="nav-menu-drop-item"
to="/manage-settings"
onClick={closeDropdowns}
>
Manage Settings
</Link>
</li>
</ul>
)}
</li>
)}
</ul>
<div className="d-flex align-items-center" >
{/* <div className={`trail me-3 ${getColorClass()}`}>
<p>Remaining days: {remainingDays}</p>
</div> */}
</div>
</div>
</div>
</div>
</nav>
<div className="navbar-left">
<div className="avatar-container" ref={avatarRef}>
<img
src={shopeKeeper}
className="avatar"
alt="User Avatar"
/>
{/* Display role_name here */}
<div className="user-role">
{userRole && <span>{userRole}</span>}
</div>
{/* Settings Icon Button */}
<button
className="settings-button"
onClick={(e) => {
e.stopPropagation(); // Prevent the click from triggering the avatar's click
closeDropdowns();
setsettingsDropOpen(!settingsDropOpen); // Toggle dropdown
}}
>
{/* Optional: Add an icon here */}
</button>
<div className="avatar-container" ref={avatarRef}>
<img
src={shopeKeeper}
className="avatar"
alt="User Avatar"
{settingsDropOpen && (
<ul className="nav-menu-drop">
<li>
<Link className="nav-menu-drop-item" to="#" onClick={closeDropdowns}>
Profile
</Link>
</li>
{(userRole === "store owner" || userRole === "store manager") && (
<li>
<a
className="nav-menu-drop-item"
href="#"
onClick={(e) => {
e.preventDefault();
handleStoreManageClick();
}}
>
Switch Store
</a>
</li>
)}
{isDropdownVisible && (
<div className="dropdown-container">
<ul className="dropdown-list">
{loading ? (
<li>Loading...</li>
) : (
stores.map((store) => (
<li key={store.id} className="dropdown-item">
<a
href="#"
className="dropdown-link"
onClick={(e) => {
handleStoreClick(store.id);
window.location.reload();
}}
>
{store.name}
</a>
</li>
))
)}
</ul>
/>
{/* Display role_name here */}
<div className="user-role">
{userRole && <span>{userRole}</span>}
</div>
)}
<li>
<a
className="nav-menu-drop-item"
href="#"
onClick={() => {
handleLogout();
{/* Settings Icon Button */}
<button
className="settings-button"
onClick={(e) => {
e.stopPropagation(); // Prevent the click from triggering the avatar's click
closeDropdowns();
setsettingsDropOpen(!settingsDropOpen); // Toggle dropdown
}}
>
Logout
</a>
</li>
</ul>
)}
</div>
</div>
{/* Optional: Add an icon here */}
</button>
{settingsDropOpen && (
<ul className="nav-menu-drop">
<li>
<Link className="nav-menu-drop-item" to="#" onClick={closeDropdowns}>
Profile
</Link>
</li>
{(userRole === "store owner" || userRole === "store manager") && (
<li>
<a
className="nav-menu-drop-item"
href="#"
onClick={(e) => {
e.preventDefault();
handleStoreManageClick();
}}
>
Switch Store
</a>
</li>
)}
{isDropdownVisible && (
<div className="dropdown-container">
<ul className="dropdown-list">
{loading ? (
<li>Loading...</li>
) : (
stores.map((store) => (
<li key={store.id} className="dropdown-item">
<a
href="#"
className="dropdown-link"
onClick={(e) => {
handleStoreClick(store.id);
window.location.reload();
}}
>
{store.name}
</a>
</li>
))
)}
</ul>
</div>
)}
<li>
<a
className="nav-menu-drop-item"
href="#"
onClick={() => {
handleLogout();
closeDropdowns();
}}
>
Logout
</a>
</li>
</ul>
)}
</div>
</div>

View File

@ -8,6 +8,7 @@
.navbar {
padding: 10px 15px;
font-family: Comfortaa;
}
/* Dropdown Styles */
@ -26,6 +27,7 @@
padding: 10px 15px;
display: block;
transition: background-color 0.2s ease;
}
.nav-menu-drop-item:hover {
@ -49,6 +51,7 @@
.navbar-nav {
flex-direction: column;
}
.nav-menu-drop {