init commit,
This commit is contained in:
204
03_source/frontend/src/sections/invoice/invoice-details.tsx
Normal file
204
03_source/frontend/src/sections/invoice/invoice-details.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import type { IInvoice } from 'src/types/invoice';
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import Table from '@mui/material/Table';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import TableRow from '@mui/material/TableRow';
|
||||
import TableHead from '@mui/material/TableHead';
|
||||
import TableBody from '@mui/material/TableBody';
|
||||
import TableCell from '@mui/material/TableCell';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
import { fDate } from 'src/utils/format-time';
|
||||
import { fCurrency } from 'src/utils/format-number';
|
||||
|
||||
import { INVOICE_STATUS_OPTIONS } from 'src/_mock';
|
||||
|
||||
import { Label } from 'src/components/label';
|
||||
import { Scrollbar } from 'src/components/scrollbar';
|
||||
|
||||
import { InvoiceToolbar } from './invoice-toolbar';
|
||||
import { InvoiceTotalSummary } from './invoice-total-summary';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
invoice?: IInvoice;
|
||||
};
|
||||
|
||||
export function InvoiceDetails({ invoice }: Props) {
|
||||
const [currentStatus, setCurrentStatus] = useState(invoice?.status);
|
||||
|
||||
const handleChangeStatus = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setCurrentStatus(event.target.value);
|
||||
}, []);
|
||||
|
||||
const renderFooter = () => (
|
||||
<Box
|
||||
sx={{
|
||||
py: 3,
|
||||
gap: 2,
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Typography variant="subtitle2" sx={{ mb: 0.5 }}>
|
||||
NOTES
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
We appreciate your business. Should you need us to add VAT or extra notes let us know!
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<Box sx={{ flexGrow: { md: 1 }, textAlign: { md: 'right' } }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 0.5 }}>
|
||||
Have a question?
|
||||
</Typography>
|
||||
<Typography variant="body2">support@minimals.cc</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
const renderList = () => (
|
||||
<Scrollbar sx={{ mt: 5 }}>
|
||||
<Table sx={{ minWidth: 960 }}>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell width={40}>#</TableCell>
|
||||
<TableCell sx={{ typography: 'subtitle2' }}>Description</TableCell>
|
||||
<TableCell>Qty</TableCell>
|
||||
<TableCell align="right">Unit price</TableCell>
|
||||
<TableCell align="right">Total</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{invoice?.items.map((row, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<Box sx={{ maxWidth: 560 }}>
|
||||
<Typography variant="subtitle2">{row.title}</Typography>
|
||||
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
|
||||
{row.description}
|
||||
</Typography>
|
||||
</Box>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{row.quantity}</TableCell>
|
||||
<TableCell align="right">{fCurrency(row.price)}</TableCell>
|
||||
<TableCell align="right">{fCurrency(row.price * row.quantity)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Scrollbar>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<InvoiceToolbar
|
||||
invoice={invoice}
|
||||
currentStatus={currentStatus || ''}
|
||||
onChangeStatus={handleChangeStatus}
|
||||
statusOptions={INVOICE_STATUS_OPTIONS}
|
||||
/>
|
||||
|
||||
<Card sx={{ pt: 5, px: 5 }}>
|
||||
<Box
|
||||
sx={{
|
||||
rowGap: 5,
|
||||
display: 'grid',
|
||||
alignItems: 'center',
|
||||
gridTemplateColumns: { xs: 'repeat(1, 1fr)', sm: 'repeat(2, 1fr)' },
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component="img"
|
||||
alt="Invoice logo"
|
||||
src="/logo/logo-single.svg"
|
||||
sx={{ width: 48, height: 48 }}
|
||||
/>
|
||||
|
||||
<Stack spacing={1} sx={{ alignItems: { xs: 'flex-start', md: 'flex-end' } }}>
|
||||
<Label
|
||||
variant="soft"
|
||||
color={
|
||||
(currentStatus === 'paid' && 'success') ||
|
||||
(currentStatus === 'pending' && 'warning') ||
|
||||
(currentStatus === 'overdue' && 'error') ||
|
||||
'default'
|
||||
}
|
||||
>
|
||||
{currentStatus}
|
||||
</Label>
|
||||
|
||||
<Typography variant="h6">{invoice?.invoiceNumber}</Typography>
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ typography: 'body2' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Invoice from
|
||||
</Typography>
|
||||
{invoice?.invoiceFrom.name}
|
||||
<br />
|
||||
{invoice?.invoiceFrom.fullAddress}
|
||||
<br />
|
||||
Phone: {invoice?.invoiceFrom.phoneNumber}
|
||||
<br />
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ typography: 'body2' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Invoice to
|
||||
</Typography>
|
||||
{invoice?.invoiceTo.name}
|
||||
<br />
|
||||
{invoice?.invoiceTo.fullAddress}
|
||||
<br />
|
||||
Phone: {invoice?.invoiceTo.phoneNumber}
|
||||
<br />
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ typography: 'body2' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Date create
|
||||
</Typography>
|
||||
{fDate(invoice?.createDate)}
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ typography: 'body2' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Due date
|
||||
</Typography>
|
||||
{fDate(invoice?.dueDate)}
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
{renderList()}
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
|
||||
<InvoiceTotalSummary
|
||||
taxes={invoice?.taxes}
|
||||
subtotal={invoice?.subtotal}
|
||||
discount={invoice?.discount}
|
||||
shipping={invoice?.shipping}
|
||||
totalAmount={invoice?.totalAmount}
|
||||
/>
|
||||
|
||||
<Divider sx={{ mt: 5, borderStyle: 'dashed' }} />
|
||||
|
||||
{renderFooter()}
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user