@evenicanpm/portal-table-ui 2.1.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evenicanpm/portal-table-ui",
3
- "version": "2.1.0",
3
+ "version": "2.2.2",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -47,5 +47,5 @@
47
47
  "@tanstack/react-query": "^5.90.11",
48
48
  "date-fns": "^4.1.0"
49
49
  },
50
- "gitHead": "8227589295d3d63586f9b26fff8d643b070989b3"
50
+ "gitHead": "eb81763cdb511681ffaf1da5140e957afa149816"
51
51
  }
@@ -87,13 +87,28 @@ const Details = ({
87
87
  mb={2}
88
88
  height="100%"
89
89
  >
90
- <Button onClick={handleBack} startIcon={<ArrowBackIcon />}>
90
+ <Button
91
+ onClick={handleBack}
92
+ startIcon={<ArrowBackIcon />}
93
+ sx={{ "@media print": { display: "none" } }}
94
+ >
91
95
  {documentTypeLabel}
92
96
  </Button>
93
- <H6 color="grey.800">
97
+ <H6 color="grey.800" sx={{ "@media print": { display: "none" } }}>
94
98
  {documentTypeLabel}-{id}
95
99
  </H6>
96
- <Subtitle>DETAILS</Subtitle>
100
+ <H6
101
+ color="grey.800"
102
+ sx={{
103
+ display: "none",
104
+ "@media print": { display: "inline-block" },
105
+ }}
106
+ >
107
+ {documentTypeLabel.slice(0, documentTypeLabel.length - 1)} #{id}
108
+ </H6>
109
+ <Subtitle sx={{ "@media print": { display: "none" } }}>
110
+ DETAILS
111
+ </Subtitle>
97
112
  </FlexBox>
98
113
  </Box>
99
114
 
@@ -2,6 +2,7 @@
2
2
  import FlagIcon from "@mui/icons-material/Flag";
3
3
  import {
4
4
  Box,
5
+ Button,
5
6
  Card,
6
7
  Divider,
7
8
  Paper,
@@ -79,6 +80,12 @@ interface InvoiceData {
79
80
  OrderedByCustomerName?: string;
80
81
  }
81
82
 
83
+ interface TableColumn {
84
+ label: string;
85
+ width: number;
86
+ aligned: "inherit" | "left" | "center" | "right" | "justify";
87
+ }
88
+
82
89
  const detailSkeletonKeys = ["from", "bill-to", "invoice-date", "due-date"];
83
90
  const tableSkeletonRowKeys = ["line-1", "line-2", "line-3", "line-4"];
84
91
  const totalSkeletonKeys = ["subtotal", "tax", "total"];
@@ -133,15 +140,15 @@ export const InvoiceDetailsTemplate = ({
133
140
  const total = invoice?.Amount ?? 0;
134
141
 
135
142
  // Fixed column definitions with specific widths
136
- const columns = [
137
- { label: "#", width: 60 },
138
- { label: "Product", width: 200 },
139
- { label: "Qty", width: 60 },
140
- { label: "Unit", width: 60 },
141
- { label: "Unit Price", width: 120 },
142
- { label: "Discount", width: 100 },
143
- { label: "Line Total", width: 120 },
144
- { label: "", width: 40 },
143
+ const columns: TableColumn[] = [
144
+ { label: "#", width: 60, aligned: "left" },
145
+ { label: "Product", width: 200, aligned: "left" },
146
+ { label: "Qty", width: 60, aligned: "right" },
147
+ { label: "Unit", width: 60, aligned: "right" },
148
+ { label: "Unit Price", width: 120, aligned: "right" },
149
+ { label: "Discount", width: 100, aligned: "right" },
150
+ { label: "Line Total", width: 120, aligned: "right" },
151
+ { label: "", width: 40, aligned: "center" },
145
152
  ];
146
153
 
147
154
  // Calculate total width for table container
@@ -221,8 +228,19 @@ export const InvoiceDetailsTemplate = ({
221
228
  );
222
229
  }
223
230
 
231
+ function handleOnClick() {
232
+ window.print();
233
+ }
234
+
224
235
  return (
225
- <Box sx={{ p: { xs: 2, sm: 3 }, width: containerWidth, mx: "auto" }}>
236
+ <Box
237
+ sx={{
238
+ p: { xs: 2, sm: 3 },
239
+ width: containerWidth,
240
+ mx: "auto",
241
+ "@media print": { p: 0, width: "100%" },
242
+ }}
243
+ >
226
244
  {/* Header */}
227
245
  <Box
228
246
  display="flex"
@@ -239,7 +257,12 @@ export const InvoiceDetailsTemplate = ({
239
257
  statusTextMap={statusTextMap}
240
258
  />
241
259
  )}
242
- <Box display="flex" gap={2} alignItems="center">
260
+ <Box
261
+ display="flex"
262
+ gap={2}
263
+ alignItems="center"
264
+ sx={{ "@media print": { display: "none" } }}
265
+ >
243
266
  {actions?.map((action) => {
244
267
  const enabled = !action.isEnabled || action.isEnabled(row);
245
268
  if (!enabled) {
@@ -263,14 +286,26 @@ export const InvoiceDetailsTemplate = ({
263
286
  />
264
287
  );
265
288
  })}
289
+ <Button
290
+ onClick={handleOnClick}
291
+ variant="outlined"
292
+ size="small"
293
+ sx={{ "@media print": { display: "none" } }}
294
+ >
295
+ Print Invoice
296
+ </Button>
266
297
  </Box>
267
298
  </Box>
268
299
 
269
300
  {/* Notes Section */}
270
301
  {invoice?.Notes && (
271
302
  <Card
272
- variant="outlined"
273
- sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3, mb: 3 }}
303
+ sx={{
304
+ p: { xs: 2, sm: 3 },
305
+ borderRadius: 3,
306
+ mb: 3,
307
+ "@media print": { border: "none", boxShadow: "none", p: 0 },
308
+ }}
274
309
  >
275
310
  <Typography variant="subtitle1" color="text.secondary" mb={1}>
276
311
  Notes
@@ -286,7 +321,13 @@ export const InvoiceDetailsTemplate = ({
286
321
  )}
287
322
 
288
323
  {/* Main Invoice Card */}
289
- <Card variant="outlined" sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3 }}>
324
+ <Card
325
+ sx={{
326
+ p: { xs: 2, sm: 3 },
327
+ borderRadius: 3,
328
+ "@media print": { border: "none", boxShadow: "none", p: 0 },
329
+ }}
330
+ >
290
331
  {/* Details Section */}
291
332
  {(invoice?.CompanyName ||
292
333
  invoice?.Name ||
@@ -400,7 +441,17 @@ export const InvoiceDetailsTemplate = ({
400
441
  {items.length > 0 ? (
401
442
  <>
402
443
  <TableContainer>
403
- <Table sx={{ minWidth: totalTableWidth }}>
444
+ <Table
445
+ sx={{
446
+ minWidth: totalTableWidth,
447
+ "@media print": {
448
+ p: 0,
449
+ scrollbarWidth: "none !important",
450
+ msOverflowStyle: "none !important",
451
+ overflow: "visible !important",
452
+ },
453
+ }}
454
+ >
404
455
  <TableHead>
405
456
  <TableRow>
406
457
  {columns.map((col) => (
@@ -412,6 +463,7 @@ export const InvoiceDetailsTemplate = ({
412
463
  fontWeight: 600,
413
464
  backgroundColor: theme.palette.background.paper,
414
465
  }}
466
+ align={col.aligned}
415
467
  >
416
468
  <Typography variant="body2" fontWeight={600}>
417
469
  {col.label}
@@ -435,29 +487,35 @@ export const InvoiceDetailsTemplate = ({
435
487
  ].join("-");
436
488
 
437
489
  return (
438
- <TableRow key={itemKey}>
439
- <TableCell sx={{ width: 60, minWidth: 60 }}>
490
+ <TableRow key={`${item.ItemId}-${idx}`}>
491
+ <TableCell
492
+ sx={{
493
+ width: "100%",
494
+ textAlign: "left",
495
+ "@media print": { width: 60, px: 1 },
496
+ }}
497
+ >
440
498
  <Typography variant="body2">
441
499
  {item?.ItemId || idx + 1}
442
500
  </Typography>
443
501
  </TableCell>
444
- <TableCell sx={{ width: 200, minWidth: 200 }}>
502
+ <TableCell sx={{ width: "100%", textAlign: "left" }}>
445
503
  <Typography variant="body2">{productName}</Typography>
446
504
  </TableCell>
447
- <TableCell sx={{ width: 60, minWidth: 60 }}>
505
+ <TableCell sx={{ width: "100%", textAlign: "right" }}>
448
506
  <Typography variant="body2">{quantity}</Typography>
449
507
  </TableCell>
450
- <TableCell sx={{ width: 60, minWidth: 60 }}>
508
+ <TableCell sx={{ width: "100%", textAlign: "right" }}>
451
509
  <Typography variant="body2">
452
510
  {item?.UnitOfMeasure || "—"}
453
511
  </Typography>
454
512
  </TableCell>
455
- <TableCell sx={{ width: 120, minWidth: 120 }}>
513
+ <TableCell sx={{ width: "100%", textAlign: "right" }}>
456
514
  <Typography variant="body2">
457
515
  {formatCurrency(unitPrice)}
458
516
  </Typography>
459
517
  </TableCell>
460
- <TableCell sx={{ width: 100, minWidth: 100 }}>
518
+ <TableCell sx={{ width: "100%", textAlign: "right" }}>
461
519
  <Typography
462
520
  variant="body2"
463
521
  color={
@@ -469,13 +527,17 @@ export const InvoiceDetailsTemplate = ({
469
527
  : formatCurrency(0)}
470
528
  </Typography>
471
529
  </TableCell>
472
- <TableCell sx={{ width: 100, minWidth: 100 }}>
530
+ <TableCell sx={{ width: "100%", textAlign: "right" }}>
473
531
  <Typography variant="body2" fontWeight={500}>
474
532
  {formatCurrency(lineTotal)}
475
533
  </Typography>
476
534
  </TableCell>
477
535
  <TableCell
478
- sx={{ width: 40, minWidth: 40 }}
536
+ sx={{
537
+ width: "100%",
538
+ textAlign: "center",
539
+ "@media print": { width: "auto", minWidth: 0 },
540
+ }}
479
541
  align="center"
480
542
  >
481
543
  {item.HasDiscount && (
@@ -32,6 +32,11 @@ export type DocumentTableProps = {
32
32
  queryKey: QueryKey;
33
33
  queryFn: () => Promise<Types.Queries.TableConfig>;
34
34
  };
35
+
36
+ selectedDocument?: string | number | null;
37
+ setSelectedDocument?: React.Dispatch<
38
+ React.SetStateAction<string | number | null>
39
+ >;
35
40
  };
36
41
 
37
42
  /**
@@ -44,11 +49,20 @@ export default function DocumentTable({
44
49
  pageSize,
45
50
  setPageSize,
46
51
  viewConfigQuery,
52
+ selectedDocument: selectedDocumentProp,
53
+ setSelectedDocument: setSelectedDocumentProp,
47
54
  }: Readonly<DocumentTableProps>) {
48
55
  const [page, setPage] = useState(0);
49
- const [selectedDocument, setSelectedDocument] = useState<
56
+ const [selectedDocumentLocal, setSelectedDocumentLocal] = useState<
50
57
  string | number | null
51
58
  >(null);
59
+
60
+ const selectedDocument =
61
+ selectedDocumentProp !== undefined
62
+ ? selectedDocumentProp
63
+ : selectedDocumentLocal;
64
+ const setSelectedDocument =
65
+ setSelectedDocumentProp ?? setSelectedDocumentLocal;
52
66
  const [filters, setFilters] = useState<Record<string, string>>({});
53
67
  const [searchTerm, setSearchTerm] = useState("");
54
68
 
@@ -19,6 +19,11 @@ export interface TableProps {
19
19
  queryFn: () => Promise<Types.Queries.TableConfig>;
20
20
  };
21
21
  resources: Types.Schemas.Resource[];
22
+
23
+ selectedDocument?: string | number | null;
24
+ setSelectedDocument?: React.Dispatch<
25
+ React.SetStateAction<string | number | null>
26
+ >;
22
27
  }
23
28
 
24
29
  /**
@@ -28,7 +33,12 @@ export interface TableProps {
28
33
  *
29
34
  * @params props
30
35
  */
31
- export const TableDashboard = ({ resources, viewConfigQuery }: TableProps) => {
36
+ export const TableDashboard = ({
37
+ resources,
38
+ viewConfigQuery,
39
+ selectedDocument,
40
+ setSelectedDocument,
41
+ }: TableProps) => {
32
42
  const [value, setValue] = useState(resources[0]?.name);
33
43
  const [pageSize, setPageSize] = useState(5); // better if this is global to not reset when switching tables
34
44
 
@@ -39,7 +49,13 @@ export const TableDashboard = ({ resources, viewConfigQuery }: TableProps) => {
39
49
  return (
40
50
  <Box sx={{ width: "100%", minHeight: "70vh" }}>
41
51
  <TabContext value={value}>
42
- <Box sx={{ borderBottom: 1, borderColor: "divider" }}>
52
+ <Box
53
+ sx={{
54
+ borderBottom: 1,
55
+ borderColor: "divider",
56
+ "@media print": { display: "none" },
57
+ }}
58
+ >
43
59
  <TabList onChange={handleChange}>
44
60
  {resources?.map((resource, i) => (
45
61
  <Tab
@@ -61,6 +77,8 @@ export const TableDashboard = ({ resources, viewConfigQuery }: TableProps) => {
61
77
  resource={resource}
62
78
  pageSize={pageSize}
63
79
  setPageSize={setPageSize}
80
+ selectedDocument={selectedDocument}
81
+ setSelectedDocument={setSelectedDocument}
64
82
  />
65
83
  {/* CHILD TABLE */}
66
84
  {resource.children?.length ? (