Skip to content

Commit 878f61d

Browse files
committed
Last piece of kerfluffle ?
1 parent 2466192 commit 878f61d

File tree

1 file changed

+216
-62
lines changed

1 file changed

+216
-62
lines changed

apps/internal-portal/frontend/src/pages/Contact/components/ContactCard.tsx

Lines changed: 216 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,25 @@ import {
1010
TableHead,
1111
CircularProgress,
1212
Collapse,
13+
Skeleton,
14+
Link,
1315
} from '@mui/material'
14-
import { Contact, Lease, LeaseStatus, PaymentStatus } from '@onecore/types'
15-
16-
import { InvoiceWithRows, useContact } from '../hooks/useContact'
1716
import { useState } from 'react'
17+
import {
18+
Contact,
19+
Invoice,
20+
Lease,
21+
LeaseStatus,
22+
PaymentStatus,
23+
} from '@onecore/types'
24+
25+
import { useContact } from '../hooks/useContact'
26+
import { useInvoicePaymentEvents } from '../hooks/useInvoicePaymentEvents'
27+
28+
const moneyFormatter = new Intl.NumberFormat('sv-SE', {
29+
minimumFractionDigits: 2,
30+
maximumFractionDigits: 2,
31+
})
1832

1933
export function ContactCard(props: { contactCode: string }) {
2034
const query = useContact(props.contactCode)
@@ -33,6 +47,12 @@ export function ContactCard(props: { contactCode: string }) {
3347

3448
const { data: contact } = query
3549

50+
const invoices = contact.invoices.sort((a, b) =>
51+
a.invoiceDate < b.invoiceDate ? 1 : -1
52+
)
53+
54+
const leases = contact.leases.sort((a, b) => (a.status < b.status ? -1 : 1))
55+
3656
return (
3757
<Box>
3858
<Typography variant="h2" fontSize={24}>
@@ -46,16 +66,14 @@ export function ContactCard(props: { contactCode: string }) {
4666
{!contact.leases?.length ? (
4767
<Typography fontStyle="italic">Inga kontrakt hittades</Typography>
4868
) : (
49-
<Leases
50-
leases={contact.leases.sort((a, b) => (a.status < b.status ? -1 : 1))}
51-
/>
69+
<Leases leases={leases} />
5270
)}
5371
<Divider />
5472
<Typography variant="h2">Fakturor</Typography>
5573
{!contact.invoices.length ? (
5674
<Typography fontStyle="italic">Inga fakturor hittades</Typography>
5775
) : (
58-
<Invoices invoices={contact.invoices} />
76+
<Invoices invoices={invoices} />
5977
)}
6078
<Divider />
6179
</Box>
@@ -130,7 +148,7 @@ function Leases(props: { leases: Lease[] }) {
130148
))
131149
}
132150

133-
function Invoices(props: { invoices: InvoiceWithRows[] }) {
151+
function Invoices(props: { invoices: Invoice[] }) {
134152
return (
135153
<Table stickyHeader={true} sx={{ tableLayout: 'fixed' }}>
136154
<TableHead>
@@ -139,25 +157,20 @@ function Invoices(props: { invoices: InvoiceWithRows[] }) {
139157
<TableCell sx={{ fontWeight: 'bold' }}>Fakturadatum</TableCell>
140158
<TableCell sx={{ fontWeight: 'bold' }}>Förfallodatum</TableCell>
141159
<TableCell sx={{ fontWeight: 'bold' }}>Belopp</TableCell>
142-
<TableCell sx={{ fontWeight: 'bold' }}>Referens</TableCell>
160+
<TableCell sx={{ fontWeight: 'bold' }}>Återstående belopp</TableCell>
143161
<TableCell sx={{ fontWeight: 'bold' }}>Fakturatyp</TableCell>
144162
<TableCell sx={{ fontWeight: 'bold' }}>Betalstatus</TableCell>
145-
<TableCell sx={{ fontWeight: 'bold' }}>
146-
Skickad till inkasso
147-
</TableCell>
163+
<TableCell sx={{ fontWeight: 'bold' }}>Inkasso</TableCell>
164+
<TableCell sx={{ fontWeight: 'bold' }}>Källa</TableCell>
148165
</TableRow>
149166
</TableHead>
150167
<TableBody>
151-
{Array.from(props.invoices)
152-
.sort((invoice1, invoice2) =>
153-
invoice1.invoiceDate < invoice2.invoiceDate ? 1 : -1
154-
)
155-
.map((invoice) => (
156-
<InvoiceTableRow
157-
key={`${invoice.invoiceId}-${invoice.invoiceDate}`}
158-
invoice={invoice}
159-
/>
160-
))}
168+
{props.invoices.map((invoice) => (
169+
<InvoiceTableRow
170+
key={`${invoice.invoiceId}-${invoice.invoiceDate}`}
171+
invoice={invoice}
172+
/>
173+
))}
161174
</TableBody>
162175
</Table>
163176
)
@@ -178,7 +191,7 @@ function getStatusName(status: LeaseStatus) {
178191
}
179192
}
180193

181-
function InvoiceTableRow(props: { invoice: InvoiceWithRows }) {
194+
function InvoiceTableRow(props: { invoice: Invoice }) {
182195
const { invoice } = props
183196
const [open, setOpen] = useState(false)
184197

@@ -189,6 +202,7 @@ function InvoiceTableRow(props: { invoice: InvoiceWithRows }) {
189202
onClick={() => setOpen((prev) => !prev)}
190203
sx={{
191204
cursor: 'pointer',
205+
backgroundColor: open ? 'rgba(0, 0, 0, 0.04)' : 'inherit',
192206
}}
193207
role="button"
194208
tabIndex={0}
@@ -207,8 +221,12 @@ function InvoiceTableRow(props: { invoice: InvoiceWithRows }) {
207221
? yyyymmdd(new Date(invoice.expirationDate))
208222
: '-'}
209223
</TableCell>
210-
<TableCell>{invoice.amount}</TableCell>
211-
<TableCell>{invoice.reference}</TableCell>
224+
<TableCell>{moneyFormatter.format(invoice.amount)}</TableCell>
225+
<TableCell>
226+
{invoice.remainingAmount
227+
? moneyFormatter.format(invoice.remainingAmount)
228+
: '-'}
229+
</TableCell>
212230
<TableCell>
213231
{invoice.type === 'Other' ? 'Ströfaktura' : 'Avi'}
214232
</TableCell>
@@ -218,53 +236,189 @@ function InvoiceTableRow(props: { invoice: InvoiceWithRows }) {
218236
<TableCell>
219237
{invoice.sentToDebtCollection
220238
? new Date(invoice.sentToDebtCollection).toLocaleDateString()
221-
: '-'}
239+
: 'Nej'}
240+
</TableCell>
241+
<TableCell>
242+
{invoice.source === 'legacy' ? 'xpand' : 'xledger'}
222243
</TableCell>
223244
</TableRow>
224245
<TableRow>
225-
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
226-
<Collapse in={open} timeout={0} unmountOnExit>
227-
<Box margin={1}>
228-
{invoice.type === 'Other' ? (
229-
<p>Text: {invoice.description}</p>
230-
) : (
231-
<Table size="small">
232-
<TableHead>
233-
<TableRow>
234-
<TableCell sx={{ fontWeight: 'bold' }}>
235-
Beskrivning
236-
</TableCell>
237-
<TableCell sx={{ fontWeight: 'bold' }}>Belopp</TableCell>
238-
<TableCell sx={{ fontWeight: 'bold' }}>Moms</TableCell>
239-
<TableCell sx={{ fontWeight: 'bold' }}>Totalt</TableCell>
240-
</TableRow>
241-
</TableHead>
242-
<TableBody>
243-
{invoice.invoiceRows.map((row, index) => (
244-
<TableRow key={index}>
245-
<TableCell>{row.invoiceRowText}</TableCell>
246-
<TableCell>
247-
{row.rowType === 3 ? null : row.amount}
248-
</TableCell>
249-
<TableCell>
250-
{row.rowType === 3 ? null : row.vat}
251-
</TableCell>
252-
<TableCell>
253-
{row.rowType === 3 ? null : row.totalAmount}
254-
</TableCell>
255-
</TableRow>
256-
))}
257-
</TableBody>
258-
</Table>
259-
)}
260-
</Box>
246+
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={9}>
247+
<Collapse
248+
in={open}
249+
timeout={0}
250+
unmountOnExit
251+
sx={{ backgroundColor: open ? 'rgba(0, 0, 0, 0.04)' : 'inherit' }}
252+
>
253+
<InvoiceDetails invoice={invoice} />
261254
</Collapse>
262255
</TableCell>
263256
</TableRow>
264257
</>
265258
)
266259
}
267260

261+
function InvoiceDetails(props: { invoice: Invoice }) {
262+
const { invoice } = props
263+
264+
if (invoice.type === 'Other') {
265+
return (
266+
<Box>
267+
<Typography>Text: {invoice.description}</Typography>
268+
{invoice.invoiceFileUrl && (
269+
<Link target="_blank" href={invoice.invoiceFileUrl}>
270+
Länk till faktura
271+
</Link>
272+
)}
273+
</Box>
274+
)
275+
}
276+
277+
const renderInvoiceRows = () => {
278+
if (!invoice.invoiceRows.length) {
279+
return (
280+
<TableRow>
281+
<TableCell colSpan={9}>
282+
<Typography fontStyle="italic">
283+
Inga fakturarader hittades
284+
</Typography>
285+
</TableCell>
286+
</TableRow>
287+
)
288+
}
289+
290+
return invoice.invoiceRows.map((row, index) => (
291+
<TableRow key={index}>
292+
<TableCell colSpan={2}>{row.invoiceRowText}</TableCell>
293+
<TableCell>
294+
{row.rowType === 3 ? null : moneyFormatter.format(row.amount)}
295+
</TableCell>
296+
<TableCell>
297+
{row.rowType === 3 ? null : moneyFormatter.format(row.deduction)}
298+
</TableCell>
299+
<TableCell>
300+
{row.rowType === 3 ? null : moneyFormatter.format(row.vat)}
301+
</TableCell>
302+
<TableCell>
303+
{row.rowType === 3 ? null : moneyFormatter.format(row.totalAmount)}
304+
</TableCell>
305+
</TableRow>
306+
))
307+
}
308+
309+
return (
310+
<Box padding={2}>
311+
<Typography variant="h2" sx={{ mt: 1, mb: 1, fontSize: 18 }}>
312+
Fakturarader
313+
</Typography>
314+
<Table size="small" sx={{ tableLayout: 'fixed' }}>
315+
<TableHead>
316+
<TableRow>
317+
<TableCell sx={{ fontWeight: 'bold' }} colSpan={2}>
318+
Beskrivning
319+
</TableCell>
320+
<TableCell sx={{ fontWeight: 'bold' }}>Belopp</TableCell>
321+
<TableCell sx={{ fontWeight: 'bold' }}>Avdrag</TableCell>
322+
<TableCell sx={{ fontWeight: 'bold' }}>Moms</TableCell>
323+
<TableCell sx={{ fontWeight: 'bold' }}>Totalt</TableCell>
324+
</TableRow>
325+
</TableHead>
326+
<TableBody>{renderInvoiceRows()}</TableBody>
327+
</Table>
328+
{invoice.source === 'next' && (
329+
<>
330+
<Typography variant="h2" sx={{ mt: 2, mb: 1, fontSize: 18 }}>
331+
Betalningshändelser
332+
</Typography>
333+
<InvoicePaymentEvents invoiceId={invoice.invoiceId} />
334+
</>
335+
)}
336+
</Box>
337+
)
338+
}
339+
340+
function InvoicePaymentEvents(props: { invoiceId: string }) {
341+
const eventsQuery = useInvoicePaymentEvents(props.invoiceId)
342+
343+
const render = () => {
344+
if (eventsQuery.isLoading) {
345+
return (
346+
<TableRow>
347+
<TableCell>
348+
<Skeleton variant="text" width="40%" height="25px" />
349+
</TableCell>
350+
<TableCell>
351+
<Skeleton variant="text" width="30%" height="25px" />
352+
</TableCell>
353+
<TableCell>
354+
<Skeleton variant="text" width="30%" height="25px" />
355+
</TableCell>
356+
<TableCell>
357+
<Skeleton variant="text" width="30%" height="25px" />
358+
</TableCell>
359+
</TableRow>
360+
)
361+
}
362+
363+
if (eventsQuery.error) {
364+
return (
365+
<TableRow>
366+
<TableCell>
367+
<Typography fontStyle="italic">
368+
{eventsQuery.error.status === 404
369+
? 'Inga betalningshändelser hittades'
370+
: 'Ett fel uppstod när betalningshändelser hämtades'}
371+
</Typography>
372+
</TableCell>
373+
</TableRow>
374+
)
375+
}
376+
377+
if (eventsQuery.data?.length) {
378+
return eventsQuery.data.map((event, index) => (
379+
<TableRow key={index}>
380+
<TableCell>{event.transactionSourceCode}</TableCell>
381+
<TableCell>{moneyFormatter.format(event.amount)}</TableCell>
382+
<TableCell>{event.text}</TableCell>
383+
<TableCell>{yyyymmdd(new Date(event.paymentDate))}</TableCell>
384+
</TableRow>
385+
))
386+
}
387+
388+
return (
389+
<TableRow>
390+
<TableCell>
391+
<Typography fontStyle="italic">
392+
Inga betalningshändelser hittades
393+
</Typography>
394+
</TableCell>
395+
</TableRow>
396+
)
397+
}
398+
399+
return (
400+
<Table size="small" sx={{ tableLayout: 'fixed' }}>
401+
<TableHead>
402+
<TableRow>
403+
<TableCell sx={{ fontWeight: 'bold', backgroundColor: 'inherit' }}>
404+
Källa
405+
</TableCell>
406+
<TableCell sx={{ fontWeight: 'bold', backgroundColor: 'inherit' }}>
407+
Belopp
408+
</TableCell>
409+
<TableCell sx={{ fontWeight: 'bold', backgroundColor: 'inherit' }}>
410+
Text
411+
</TableCell>
412+
<TableCell sx={{ fontWeight: 'bold', backgroundColor: 'inherit' }}>
413+
Betaldatum
414+
</TableCell>
415+
</TableRow>
416+
</TableHead>
417+
<TableBody>{render()}</TableBody>
418+
</Table>
419+
)
420+
}
421+
268422
function yyyymmdd(d: Date) {
269423
return d.toISOString().split('T')[0]
270424
}

0 commit comments

Comments
 (0)