added expense status logs
This commit is contained in:
parent
1e26b1261c
commit
68bd0d6bb5
5
public/assets/vendor/css/core.css
vendored
5
public/assets/vendor/css/core.css
vendored
@ -20473,7 +20473,10 @@ li:not(:first-child) .dropdown-item,
|
|||||||
word-wrap: break-word !important;
|
word-wrap: break-word !important;
|
||||||
word-break: break-word !important;
|
word-break: break-word !important;
|
||||||
}
|
}
|
||||||
|
/* text-size */
|
||||||
|
.text-tiny{
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
/* rtl:end:remove */
|
/* rtl:end:remove */
|
||||||
.text-primary {
|
.text-primary {
|
||||||
--bs-text-opacity: 1;
|
--bs-text-opacity: 1;
|
||||||
|
|||||||
63
src/components/Expenses/ExpenseStatusLogs.jsx
Normal file
63
src/components/Expenses/ExpenseStatusLogs.jsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import Avatar from "../common/Avatar";
|
||||||
|
|
||||||
|
const ExpenseStatusLogs = ({ data }) => {
|
||||||
|
const [visibleCount, setVisibleCount] = useState(4);
|
||||||
|
|
||||||
|
const logsToShow = data?.expenseLogs?.slice(0, visibleCount) || [];
|
||||||
|
|
||||||
|
const handleShowMore = () => {
|
||||||
|
setVisibleCount((prev) => prev + 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="row g-2">
|
||||||
|
{logsToShow.map((log, index) => (
|
||||||
|
<div
|
||||||
|
key={log.id}
|
||||||
|
className="col-12 d-flex align-items-start mb-2"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
size="xs"
|
||||||
|
firstName={log.updatedBy.firstName}
|
||||||
|
lastName={log.updatedBy.lastName}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="flex-grow-1">
|
||||||
|
<div className="d-flex justify-content-start">
|
||||||
|
<div className="text-start">
|
||||||
|
<div >
|
||||||
|
<div className="flex">
|
||||||
|
<span>{`${log.updatedBy.firstName} ${log.updatedBy.lastName}`}</span>
|
||||||
|
<small className="text-secondary text-tiny ms-2">
|
||||||
|
<em>{log.action}</em>
|
||||||
|
</small>
|
||||||
|
<span className="text-tiny text-secondary d-block small">{log?.updateAt ?? "14-Aug-2025"}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex align-items-center text-muted small mt-1">
|
||||||
|
<span className="small">{log.comment}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{data?.expenseLogs?.length > visibleCount && (
|
||||||
|
<div className="text-center my-1">
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-outline-primary"
|
||||||
|
onClick={handleShowMore}
|
||||||
|
>
|
||||||
|
Show More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExpenseStatusLogs;
|
||||||
@ -27,6 +27,7 @@ import { useEmployeeRoles, useEmployeesName } from "../../hooks/useEmployees";
|
|||||||
import EmployeeSearchInput from "../common/EmployeeSearchInput";
|
import EmployeeSearchInput from "../common/EmployeeSearchInput";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import ExpenseStatusLogs from "./ExpenseStatusLogs";
|
||||||
|
|
||||||
const ViewExpense = ({ ExpenseId }) => {
|
const ViewExpense = ({ ExpenseId }) => {
|
||||||
const { data, isLoading, isError, error } = useExpense(ExpenseId);
|
const { data, isLoading, isError, error } = useExpense(ExpenseId);
|
||||||
@ -111,7 +112,12 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
<h5 className="fw-semibold">Expense Details</h5>
|
<h5 className="fw-semibold">Expense Details</h5>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-start mb-2">
|
||||||
|
{/* <label className="form-label me-2 mb-0 fw-semibold">
|
||||||
|
Description :
|
||||||
|
</label> */}
|
||||||
|
<div className="text-muted">{data?.description}</div>
|
||||||
|
</div>
|
||||||
{/* Row 1 */}
|
{/* Row 1 */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
@ -270,7 +276,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{data.reviewedBy && (
|
{/* {data.reviewedBy && (
|
||||||
<div className="col-md-6 mb-3 text-start">
|
<div className="col-md-6 mb-3 text-start">
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center">
|
||||||
<label
|
<label
|
||||||
@ -345,17 +351,17 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
{data.expensesReimburse && (
|
{data.expensesReimburse && (
|
||||||
<div className="row text-start">
|
<div className="row text-start">
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 ">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Transaction ID :
|
Transaction ID :
|
||||||
</label>
|
</label>
|
||||||
{data.expensesReimburse.reimburseTransactionId || "N/A"}
|
{data.expensesReimburse.reimburseTransactionId || "N/A"}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 ">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Reimburse Date :
|
Reimburse Date :
|
||||||
</label>
|
</label>
|
||||||
@ -364,7 +370,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
|
|
||||||
{data.expensesReimburse && (
|
{data.expensesReimburse && (
|
||||||
<>
|
<>
|
||||||
<div className="col-md-6 mb-3 d-flex align-items-center">
|
<div className="col-md-6 d-flex align-items-center">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Reimburse By :
|
Reimburse By :
|
||||||
</label>
|
</label>
|
||||||
@ -380,20 +386,15 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-md-6 mb-3">
|
|
||||||
<label className="form-label me-2 mb-0 fw-semibold"> Note :</label>{" "}
|
|
||||||
{data.expensesReimburse.reimburseNote}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="text-start">
|
{/* <div className="text-start">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Description :
|
Description :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">{data?.description}</div>
|
<div className="text-muted">{data?.description}</div>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="col-12 my-2 text-start">
|
<div className="col-12 my-2 text-start">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">Attachment :</label>
|
<label className="form-label me-2 mb-0 fw-semibold">Attachment :</label>
|
||||||
|
|
||||||
@ -540,7 +541,12 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ExpenseStatusLogs data={data}/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,22 +3,54 @@ import { useRouteError, isRouteErrorResponse } from 'react-router-dom';
|
|||||||
|
|
||||||
const ErrorPage = () => {
|
const ErrorPage = () => {
|
||||||
const error = useRouteError();
|
const error = useRouteError();
|
||||||
console.error(error);
|
console.error('Route Error:', error);
|
||||||
|
|
||||||
if (isRouteErrorResponse(error)) {
|
if (isRouteErrorResponse(error)) {
|
||||||
|
const { status, statusText, data } = error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="container mt-5">
|
||||||
<h1>{error.status}</h1>
|
<h1 className="text-danger">Oops! Something went wrong.</h1>
|
||||||
<p>{error.statusText}</p>
|
<p className="lead">We couldn’t load the page you requested.</p>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h4>Error Details</h4>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Status:</strong> {status}</li>
|
||||||
|
<li><strong>Status Text:</strong> {statusText}</li>
|
||||||
|
{data && <li><strong>Message:</strong> {typeof data === 'string' ? data : JSON.stringify(data)}</li>}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
message = 'An unexpected error occurred.',
|
||||||
|
name,
|
||||||
|
stack,
|
||||||
|
} = error || {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="container mt-5">
|
||||||
<h1>Something went wrong.</h1>
|
<h1 className="text-danger">Something went wrong.</h1>
|
||||||
<p>{error?.message || 'Unknown error occurred'}</p>
|
<p className="lead">Sorry, we couldn’t complete your request.</p>
|
||||||
|
|
||||||
|
{message && (
|
||||||
|
<div className="alert alert-warning mt-4">
|
||||||
|
<strong>{name ? `${name}: ` : ''}</strong>
|
||||||
|
{message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{stack && (
|
||||||
|
<details className="mt-3 text-muted">
|
||||||
|
<summary>Developer Details (Stack Trace)</summary>
|
||||||
|
<pre>{stack}</pre>
|
||||||
|
</details>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
export default ErrorPage
|
|
||||||
|
export default ErrorPage;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user