@evenicanpm/portal-table-ui 1.4.1 → 1.5.0
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/dist/auth/auth-context.d.ts +36 -0
- package/dist/features/settings/index.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/actions.d.ts +14 -0
- package/dist/features/table/components/dashboard/table/data-mask-map.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/details/details.d.ts +27 -0
- package/dist/features/table/components/dashboard/table/details/label.d.ts +5 -0
- package/dist/features/table/components/dashboard/table/details/rows/downloads.d.ts +6 -0
- package/dist/features/table/components/dashboard/table/details/rows/primitive.d.ts +6 -0
- package/dist/features/table/components/dashboard/table/details/rows/table.d.ts +17 -0
- package/{src/features/table/components/dashboard/table/details/styles.ts → dist/features/table/components/dashboard/table/details/styles.d.ts} +2 -10
- package/dist/features/table/components/dashboard/table/filter-render-map.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/filters/date-filter.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/filters/status-filter.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/no-results.d.ts +2 -0
- package/dist/features/table/components/dashboard/table/status-pill.d.ts +8 -0
- package/dist/features/table/components/dashboard/table/table-header.d.ts +16 -0
- package/dist/features/table/components/dashboard/table/table-input.d.ts +11 -0
- package/dist/features/table/components/dashboard/table/table-row/action-button.d.ts +8 -0
- package/dist/features/table/components/dashboard/table/table-row/table-row.d.ts +32 -0
- package/dist/features/table/components/dashboard/table/table-row-skeleton.d.ts +6 -0
- package/dist/features/table/components/dashboard/table/table.d.ts +18 -0
- package/dist/features/table/components/dashboard/table-dashboard.d.ts +22 -0
- package/{src/features/table/index.ts → dist/features/table/index.d.ts} +1 -7
- package/dist/features/table/logic/resolvers.d.ts +21 -0
- package/dist/features/table/logic/transformers.d.ts +35 -0
- package/dist/features/table/logic/types.d.ts +8 -0
- package/{src/features/table/types/handlers.ts → dist/features/table/types/handlers.d.ts} +12 -30
- package/{src/features/table/types/index.ts → dist/features/table/types/index.d.ts} +0 -1
- package/{src/features/table/types/queries.ts → dist/features/table/types/queries.d.ts} +3 -10
- package/dist/features/table/types/schemas.d.ts +31 -0
- package/{src/index.ts → dist/index.d.ts} +0 -2
- package/dist/portal.d.ts +38 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +6 -3
- package/src/auth/auth-context.tsx +0 -86
- package/src/features/table/components/dashboard/table/actions.ts +0 -59
- package/src/features/table/components/dashboard/table/data-mask-map.ts +0 -26
- package/src/features/table/components/dashboard/table/details/details.tsx +0 -164
- package/src/features/table/components/dashboard/table/details/label.tsx +0 -26
- package/src/features/table/components/dashboard/table/details/rows/downloads.tsx +0 -26
- package/src/features/table/components/dashboard/table/details/rows/primitive.tsx +0 -26
- package/src/features/table/components/dashboard/table/details/rows/table.tsx +0 -74
- package/src/features/table/components/dashboard/table/filter-render-map.tsx +0 -9
- package/src/features/table/components/dashboard/table/filters/date-filter.tsx +0 -31
- package/src/features/table/components/dashboard/table/filters/status-filter.tsx +0 -36
- package/src/features/table/components/dashboard/table/no-results.tsx +0 -26
- package/src/features/table/components/dashboard/table/status-pill.tsx +0 -18
- package/src/features/table/components/dashboard/table/table-header.tsx +0 -62
- package/src/features/table/components/dashboard/table/table-input.tsx +0 -94
- package/src/features/table/components/dashboard/table/table-row/action-button.tsx +0 -39
- package/src/features/table/components/dashboard/table/table-row/table-row.tsx +0 -96
- package/src/features/table/components/dashboard/table/table-row-skeleton.tsx +0 -36
- package/src/features/table/components/dashboard/table/table.tsx +0 -250
- package/src/features/table/components/dashboard/table-dashboard.tsx +0 -71
- package/src/features/table/logic/resolvers.ts +0 -68
- package/src/features/table/logic/transformers.ts +0 -56
- package/src/features/table/logic/types.ts +0 -8
- package/src/features/table/types/schemas.ts +0 -50
- package/src/portal.tsx +0 -68
- package/tsconfig.json +0 -28
- package/typedoc.json +0 -10
- /package/{src/features/table/components/dashboard/index.tsx → dist/features/table/components/dashboard/index.d.ts} +0 -0
- /package/{src/features/table/components/dashboard/table/details/index.ts → dist/features/table/components/dashboard/table/details/index.d.ts} +0 -0
- /package/{src/features/table/components/dashboard/table/details/rows/index.ts → dist/features/table/components/dashboard/table/details/rows/index.d.ts} +0 -0
- /package/{src/features/table/components/dashboard/table/index.ts → dist/features/table/components/dashboard/table/index.d.ts} +0 -0
- /package/{src/features/table/logic/index.ts → dist/features/table/logic/index.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/portal-table-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
".": "./src/index.ts"
|
|
16
16
|
},
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"@emotion/react": "^11.11.3",
|
|
20
23
|
"@emotion/styled": "^11.11.0",
|
|
@@ -37,11 +40,11 @@
|
|
|
37
40
|
},
|
|
38
41
|
"dependencies": {
|
|
39
42
|
"@arrows/multimethod": "^2.1.0",
|
|
40
|
-
"@evenicanpm/portal-types-schemas": "
|
|
43
|
+
"@evenicanpm/portal-types-schemas": "^1.5.0",
|
|
41
44
|
"@evenicanpm/ui": "^1.4.0",
|
|
42
45
|
"@mui/lab": "^7.0.1-beta.19",
|
|
43
46
|
"@tanstack/react-query": "^5.90.11",
|
|
44
47
|
"date-fns": "^4.1.0"
|
|
45
48
|
},
|
|
46
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "5c5e3fe19b92a17cbaf897b4cee20ee59331603f"
|
|
47
50
|
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { createContext, type PropsWithChildren, useContext } from "react";
|
|
2
|
-
|
|
3
|
-
// --- 1. Types --- //
|
|
4
|
-
/**
|
|
5
|
-
* Powers the auth provider that portal is wrapped in
|
|
6
|
-
* Aggregates user and session related data that is needed
|
|
7
|
-
* within the portal
|
|
8
|
-
*/
|
|
9
|
-
interface AuthProviderProps {
|
|
10
|
-
/** The user details returned from auth framework eg. next-auth **/
|
|
11
|
-
session: Session;
|
|
12
|
-
/** how to handle logout **/
|
|
13
|
-
logout: () => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The context value
|
|
18
|
-
*/
|
|
19
|
-
interface AuthContext {
|
|
20
|
-
session: Session | null;
|
|
21
|
-
/** how to handle logout **/
|
|
22
|
-
logout: (() => void) | null;
|
|
23
|
-
isAuthenticated: boolean | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/*
|
|
27
|
-
* Session details returned from authentication
|
|
28
|
-
*
|
|
29
|
-
*/
|
|
30
|
-
interface Session {
|
|
31
|
-
email: string | null | undefined;
|
|
32
|
-
name: string | null | undefined;
|
|
33
|
-
token: string | null | undefined;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// --- 2. Context --- //
|
|
37
|
-
const AuthContext = createContext<AuthContext>({
|
|
38
|
-
session: null,
|
|
39
|
-
logout: null,
|
|
40
|
-
isAuthenticated: null,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// --- 3. Hook --- //
|
|
44
|
-
/**
|
|
45
|
-
* Used to access auth details and callback handlers within the portal auth context
|
|
46
|
-
*/
|
|
47
|
-
const useAuth = () => {
|
|
48
|
-
const context = useContext(AuthContext);
|
|
49
|
-
if (!context) {
|
|
50
|
-
// This error helps developers debug if they forget to wrap the component.
|
|
51
|
-
throw new Error("useAuth must be used within a PortalAuthProvider");
|
|
52
|
-
}
|
|
53
|
-
return context;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// --- Provider --- //
|
|
57
|
-
/**
|
|
58
|
-
*
|
|
59
|
-
*/
|
|
60
|
-
const PortalAuthProvider = ({
|
|
61
|
-
session,
|
|
62
|
-
logout,
|
|
63
|
-
children,
|
|
64
|
-
}: PropsWithChildren<AuthProviderProps>) => {
|
|
65
|
-
const isAuthenticated = !!session?.email;
|
|
66
|
-
|
|
67
|
-
const authValue = {
|
|
68
|
-
isAuthenticated,
|
|
69
|
-
session,
|
|
70
|
-
logout,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<AuthContext.Provider value={{ ...authValue }}>
|
|
75
|
-
{children}
|
|
76
|
-
</AuthContext.Provider>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export {
|
|
81
|
-
PortalAuthProvider,
|
|
82
|
-
useAuth,
|
|
83
|
-
type AuthProviderProps,
|
|
84
|
-
AuthContext,
|
|
85
|
-
type Session,
|
|
86
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
|
|
2
|
-
import { UseMutationOptions, mutationOptions } from "@tanstack/react-query";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* Map of action types -> MUI Icons
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
export const actionIconMap: Record<string, typeof FileDownloadOutlinedIcon> = {
|
|
10
|
-
download: FileDownloadOutlinedIcon,
|
|
11
|
-
archive: FileDownloadOutlinedIcon,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// Don't like this type but required for map below.
|
|
15
|
-
type MutationFactory = (
|
|
16
|
-
resourceName: string,
|
|
17
|
-
docId: string,
|
|
18
|
-
) => UseMutationOptions<any, any, any, any>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*/
|
|
23
|
-
export const actionMutationMap: Record<string, MutationFactory> = {
|
|
24
|
-
download: (resourceName: string, docId: string) =>
|
|
25
|
-
mutationOptions({
|
|
26
|
-
mutationKey: [resourceName, "download", docId],
|
|
27
|
-
mutationFn: async (input: { docId: number }) => {
|
|
28
|
-
const res = await fetch(
|
|
29
|
-
`/api/resource/${resourceName}/download?docId=${encodeURIComponent(String(input.docId))}`,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
const text = await res.text().catch(() => "");
|
|
34
|
-
throw new Error(text || `Download failed (${res.status})`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const blob = await res.blob();
|
|
38
|
-
|
|
39
|
-
const disposition = res.headers.get("content-disposition") || "";
|
|
40
|
-
const match = /filename\*?=(?:UTF-8'')?["']?([^"';]+)["']?/i.exec(
|
|
41
|
-
disposition,
|
|
42
|
-
);
|
|
43
|
-
const filename = match
|
|
44
|
-
? decodeURIComponent(match[1])
|
|
45
|
-
: `${resourceName}-${input.docId}.pdf`;
|
|
46
|
-
|
|
47
|
-
const href = URL.createObjectURL(blob);
|
|
48
|
-
const a = document.createElement("a");
|
|
49
|
-
a.href = href;
|
|
50
|
-
a.download = filename;
|
|
51
|
-
document.body.appendChild(a);
|
|
52
|
-
a.click();
|
|
53
|
-
a.remove();
|
|
54
|
-
URL.revokeObjectURL(href);
|
|
55
|
-
|
|
56
|
-
return true;
|
|
57
|
-
},
|
|
58
|
-
}),
|
|
59
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as Table from "../../../types/";
|
|
3
|
-
import { format } from "date-fns";
|
|
4
|
-
|
|
5
|
-
export const dataMaskMap: Table.Handlers.DataMaskMap = {
|
|
6
|
-
// DATE TIME HAS SPECIFIC MASK HANDLING
|
|
7
|
-
datetime: (value: string | number, _dataMask: string) => {
|
|
8
|
-
return format(new Date(value), "MM/dd/yyyy");
|
|
9
|
-
},
|
|
10
|
-
date: (value: string | number, _dataMask: string) => {
|
|
11
|
-
return format(new Date(value), "MM/dd/yyyy");
|
|
12
|
-
},
|
|
13
|
-
numeric: (value: string | number, dataMask: string) => {
|
|
14
|
-
// IS CURRENCY?
|
|
15
|
-
if (dataMask.includes("$")) {
|
|
16
|
-
// Very generic stub... project fill out.
|
|
17
|
-
return new Intl.NumberFormat("en-US", {
|
|
18
|
-
style: "currency",
|
|
19
|
-
currency: "USD",
|
|
20
|
-
}).format(Number(value));
|
|
21
|
-
}
|
|
22
|
-
// IS ...X?
|
|
23
|
-
// IS ...Y?
|
|
24
|
-
return String(value);
|
|
25
|
-
},
|
|
26
|
-
};
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { method, multi } from "@arrows/multimethod";
|
|
3
|
-
import type { Column } from "@evenicanpm/portal-types-schemas";
|
|
4
|
-
import { FlexBox, H6, Subtitle } from "@evenicanpm/ui";
|
|
5
|
-
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
|
6
|
-
import { Box, Button } from "@mui/material";
|
|
7
|
-
import Grid from "@mui/material/Grid2";
|
|
8
|
-
import { resolvers, transformers } from "../../../../logic";
|
|
9
|
-
import type * as Types from "../../../../types";
|
|
10
|
-
import type { StatusColorMap, StatusTextMap } from "../../../../types/schemas";
|
|
11
|
-
import { StatusPill } from "../status-pill";
|
|
12
|
-
import { DetailsRowLabel } from "./label";
|
|
13
|
-
import { DetailsDownloads, DetailsPrimitive, DetailsTable } from "./rows";
|
|
14
|
-
|
|
15
|
-
interface DetailsProps {
|
|
16
|
-
/** What do we do when use clicks back button? */
|
|
17
|
-
handleBack: () => void;
|
|
18
|
-
/** What is the id field name */
|
|
19
|
-
id: string | number;
|
|
20
|
-
/** The actual pojo of data from the API */
|
|
21
|
-
documentData: Types.Queries.Row;
|
|
22
|
-
/* the label of the document type ie 'INVOICES' */
|
|
23
|
-
documentTypeLabel: string;
|
|
24
|
-
/** Special instructions for how to render certain properties */
|
|
25
|
-
detailsRenderMap?: Types.Handlers.DetailsRenderMap;
|
|
26
|
-
/** Data mask map */
|
|
27
|
-
dataMaskMap: Types.Handlers.DataMaskMap;
|
|
28
|
-
/** Table columns **/
|
|
29
|
-
columns: Column[];
|
|
30
|
-
/** */
|
|
31
|
-
statusColorMap: StatusColorMap;
|
|
32
|
-
/** */
|
|
33
|
-
statusTextMap: StatusTextMap;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* The Details Page
|
|
38
|
-
*/
|
|
39
|
-
const Details = ({
|
|
40
|
-
id,
|
|
41
|
-
documentTypeLabel,
|
|
42
|
-
documentData,
|
|
43
|
-
handleBack,
|
|
44
|
-
columns,
|
|
45
|
-
dataMaskMap,
|
|
46
|
-
statusColorMap,
|
|
47
|
-
statusTextMap,
|
|
48
|
-
}: DetailsProps) => {
|
|
49
|
-
const visibleDetails = transformers.getVisibleDetails(columns);
|
|
50
|
-
|
|
51
|
-
// Build Primtive Values (string or number)
|
|
52
|
-
const primtiveItems = visibleDetails?.map((col) => ({
|
|
53
|
-
key: col?.Data,
|
|
54
|
-
value: documentData?.[col?.Data],
|
|
55
|
-
maskFn: resolvers.resolveDataMask(col, dataMaskMap),
|
|
56
|
-
mask: col?.DataMask,
|
|
57
|
-
col: col,
|
|
58
|
-
}));
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<Box>
|
|
62
|
-
{/* Header */}
|
|
63
|
-
<Box height={48} sx={{ borderBottom: 1, borderColor: "divider" }}>
|
|
64
|
-
<FlexBox
|
|
65
|
-
alignItems="center"
|
|
66
|
-
justifyContent="space-between"
|
|
67
|
-
mb={2}
|
|
68
|
-
height={"100%"}
|
|
69
|
-
>
|
|
70
|
-
<Button onClick={handleBack} startIcon={<ArrowBackIcon />}>
|
|
71
|
-
{documentTypeLabel}
|
|
72
|
-
</Button>
|
|
73
|
-
<H6 color={"grey.800"}>
|
|
74
|
-
{documentTypeLabel}-{id}
|
|
75
|
-
</H6>
|
|
76
|
-
<Subtitle>DETAILS</Subtitle>
|
|
77
|
-
</FlexBox>
|
|
78
|
-
</Box>
|
|
79
|
-
|
|
80
|
-
<Grid container spacing={2} sx={{ mt: 2 }}>
|
|
81
|
-
{primtiveItems?.map((col) => {
|
|
82
|
-
const maskedValue = col.maskFn(col?.value, col?.mask);
|
|
83
|
-
const Component = getRowComponent(maskedValue, col?.key);
|
|
84
|
-
const sx = getRowLayout(maskedValue, col?.key);
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<Grid key={col?.key} {...sx}>
|
|
88
|
-
<DetailsRowLabel label={col?.col?.Label} />
|
|
89
|
-
<Component
|
|
90
|
-
key={col?.key}
|
|
91
|
-
value={maskedValue}
|
|
92
|
-
label={col?.key}
|
|
93
|
-
column={col?.col}
|
|
94
|
-
dataMaskMap={dataMaskMap}
|
|
95
|
-
statusColorMap={statusColorMap}
|
|
96
|
-
statusTextMap={statusTextMap}
|
|
97
|
-
status={col?.value}
|
|
98
|
-
/>
|
|
99
|
-
</Grid>
|
|
100
|
-
);
|
|
101
|
-
})}
|
|
102
|
-
</Grid>
|
|
103
|
-
</Box>
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Default renders.
|
|
109
|
-
*
|
|
110
|
-
* -- What do we render? --
|
|
111
|
-
*
|
|
112
|
-
*/
|
|
113
|
-
const detailsRenders = {
|
|
114
|
-
DOCUMENTS: DetailsDownloads,
|
|
115
|
-
PRIMITIVE: DetailsPrimitive,
|
|
116
|
-
OBJECT: DetailsTable,
|
|
117
|
-
STATUS: StatusPill,
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Multi-method to resolve the renders.
|
|
122
|
-
*
|
|
123
|
-
* -- How do we know what to render? --
|
|
124
|
-
*
|
|
125
|
-
*/
|
|
126
|
-
const detailTypeDispatch = (detail: Types.Queries.Row, col: string) => {
|
|
127
|
-
if (col === "Documents") return "DOCUMENTS";
|
|
128
|
-
if (col === "Status") return "STATUS";
|
|
129
|
-
if (typeof detail === "string" || typeof detail === "number")
|
|
130
|
-
return "PRIMITIVE";
|
|
131
|
-
if (Array.isArray(detail)) return "OBJECT";
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Multi-method to resolve the renders.
|
|
136
|
-
*
|
|
137
|
-
* -- what do we render? --
|
|
138
|
-
*
|
|
139
|
-
*/
|
|
140
|
-
const getRowComponent = multi(
|
|
141
|
-
detailTypeDispatch,
|
|
142
|
-
method("PRIMITIVE", () => detailsRenders.PRIMITIVE),
|
|
143
|
-
method("DOCUMENTS", () => detailsRenders.DOCUMENTS),
|
|
144
|
-
method("OBJECT", () => detailsRenders.OBJECT),
|
|
145
|
-
method("STATUS", () => detailsRenders.STATUS),
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Multi-method to resolve layout styles
|
|
150
|
-
*
|
|
151
|
-
* -- what do we render? --
|
|
152
|
-
*/
|
|
153
|
-
const getRowLayout = multi(
|
|
154
|
-
detailTypeDispatch,
|
|
155
|
-
method("PRIMITIVE", () => ({ size: 6, display: "flex" })),
|
|
156
|
-
method("STATUS", () => ({ size: 6, display: "flex" })),
|
|
157
|
-
method("DOCUMENTS", () => ({ size: 12 })),
|
|
158
|
-
method("OBJECT", () => ({ size: 12 })),
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
// Note: another way to dispatch table is
|
|
162
|
-
// if the column has a children property
|
|
163
|
-
|
|
164
|
-
export { Details };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Typography } from "@mui/material";
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
label: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const DetailsRowLabel = (props: Props) => {
|
|
10
|
-
const { label } = props;
|
|
11
|
-
return (
|
|
12
|
-
<Typography
|
|
13
|
-
variant="subtitle2"
|
|
14
|
-
color="text.secondary"
|
|
15
|
-
sx={{
|
|
16
|
-
minWidth: 150,
|
|
17
|
-
fontWeight: 600,
|
|
18
|
-
alignSelf: "flex-start",
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
{label}:
|
|
22
|
-
</Typography>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export { DetailsRowLabel };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
|
|
2
|
-
import { Button, Stack } from "@mui/material";
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
label: string;
|
|
6
|
-
value: string[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const DetailsDownloads = ({ value }: Props) => (
|
|
10
|
-
<Stack spacing={1} sx={{ mt: 1 }}>
|
|
11
|
-
{value?.map((doc: string) => (
|
|
12
|
-
<Button
|
|
13
|
-
key={doc}
|
|
14
|
-
variant="outlined"
|
|
15
|
-
size="small"
|
|
16
|
-
startIcon={<FileDownloadOutlinedIcon />}
|
|
17
|
-
onClick={() => window.open(doc, "_blank")}
|
|
18
|
-
sx={{ justifyContent: "flex-start" }}
|
|
19
|
-
>
|
|
20
|
-
Download Document
|
|
21
|
-
</Button>
|
|
22
|
-
))}
|
|
23
|
-
</Stack>
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
export { DetailsDownloads };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Box } from "@mui/material";
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
label: string;
|
|
7
|
-
value: string | number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const DetailsPrimitive = (props: Props) => {
|
|
11
|
-
const { value } = props;
|
|
12
|
-
return (
|
|
13
|
-
<Box
|
|
14
|
-
sx={{
|
|
15
|
-
mb: 2,
|
|
16
|
-
display: "flex",
|
|
17
|
-
alignItems: "flex-start",
|
|
18
|
-
gap: 2,
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
<Box sx={{ flex: 1 }}>{value}</Box>
|
|
22
|
-
</Box>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export { DetailsPrimitive };
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import type { Column } from "@evenicanpm/portal-types-schemas";
|
|
4
|
-
import {
|
|
5
|
-
Table,
|
|
6
|
-
TableBody,
|
|
7
|
-
TableCell,
|
|
8
|
-
TableContainer,
|
|
9
|
-
TableHead,
|
|
10
|
-
TableRow,
|
|
11
|
-
} from "@mui/material";
|
|
12
|
-
import { resolvers } from "../../../../../logic";
|
|
13
|
-
import type { DataMaskMap } from "../../../../../types/handlers";
|
|
14
|
-
|
|
15
|
-
interface Props {
|
|
16
|
-
column: Column;
|
|
17
|
-
value: Record<string, string>[];
|
|
18
|
-
label: string;
|
|
19
|
-
dataMaskMap: DataMaskMap;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Simple table that takes an array of records,
|
|
24
|
-
* builds array of columns from first index and then loops
|
|
25
|
-
* builds table values from rest of the indexes.
|
|
26
|
-
* @param props
|
|
27
|
-
* @returns
|
|
28
|
-
*/
|
|
29
|
-
const DetailsTable = (props: Props) => {
|
|
30
|
-
const { value: rows, dataMaskMap, column } = props;
|
|
31
|
-
|
|
32
|
-
// call resolvers ahead of time on each column once
|
|
33
|
-
// then they are pre-resolved and ready to be used
|
|
34
|
-
// in render body.
|
|
35
|
-
const preparedCols = column?.Children?.map((col) => ({
|
|
36
|
-
key: col?.Data,
|
|
37
|
-
maskFn: resolvers.resolveDataMask(col, dataMaskMap),
|
|
38
|
-
mask: col?.DataMask,
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<TableContainer sx={{ my: 2 }}>
|
|
43
|
-
<Table size="small" sx={{ mt: 1, p: 0 }}>
|
|
44
|
-
<TableHead>
|
|
45
|
-
<TableRow>
|
|
46
|
-
{Object.keys(rows[0])?.map((key) => (
|
|
47
|
-
<TableCell key={key} sx={{ fontWeight: 600 }}>
|
|
48
|
-
{key}
|
|
49
|
-
</TableCell>
|
|
50
|
-
))}
|
|
51
|
-
</TableRow>
|
|
52
|
-
</TableHead>
|
|
53
|
-
<TableBody>
|
|
54
|
-
{rows.map((row) => {
|
|
55
|
-
return (
|
|
56
|
-
<TableRow key={row?.key + row?.value}>
|
|
57
|
-
{preparedCols?.map((col) => (
|
|
58
|
-
<TableCell
|
|
59
|
-
key={col?.key + row?.key + row?.value}
|
|
60
|
-
align={"left"}
|
|
61
|
-
>
|
|
62
|
-
{col.maskFn(row?.[col?.key], col.mask)}
|
|
63
|
-
</TableCell>
|
|
64
|
-
))}
|
|
65
|
-
</TableRow>
|
|
66
|
-
);
|
|
67
|
-
})}
|
|
68
|
-
</TableBody>
|
|
69
|
-
</Table>
|
|
70
|
-
</TableContainer>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export { DetailsTable };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as Table from "../../../types/";
|
|
3
|
-
import { DateFilter } from "./filters/date-filter";
|
|
4
|
-
import { StatusFilter } from "./filters/status-filter";
|
|
5
|
-
|
|
6
|
-
export const filterRenderMapFallback: Table.Handlers.FilterRenderMap = {
|
|
7
|
-
select: (props: Table.Handlers.FilterProps) => <StatusFilter {...props} />,
|
|
8
|
-
date: (props: Table.Handlers.FilterProps) => <DateFilter {...props} />,
|
|
9
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as Table from "../../../../types";
|
|
3
|
-
import MenuItem from "@mui/material/MenuItem";
|
|
4
|
-
import Select, { type SelectChangeEvent } from "@mui/material/Select";
|
|
5
|
-
|
|
6
|
-
export const DateFilter = (props: Table.Handlers.FilterProps) => {
|
|
7
|
-
const { value, filterName, filterOptions, setValue } = props;
|
|
8
|
-
return (
|
|
9
|
-
<Select
|
|
10
|
-
labelId="demo-simple-select-label"
|
|
11
|
-
id="demo-simple-select"
|
|
12
|
-
value={value?.[filterName] || "all"}
|
|
13
|
-
label={filterName}
|
|
14
|
-
sx={{
|
|
15
|
-
height: "100%",
|
|
16
|
-
border: "none",
|
|
17
|
-
backgroundColor: "background.paper",
|
|
18
|
-
}}
|
|
19
|
-
onChange={(e: SelectChangeEvent) => {
|
|
20
|
-
setValue((prev) => ({ ...prev, [filterName]: e.target.value }));
|
|
21
|
-
}}
|
|
22
|
-
>
|
|
23
|
-
<MenuItem value={"all"}>All Transaction Dates</MenuItem>
|
|
24
|
-
{filterOptions?.map((value, i) => (
|
|
25
|
-
<MenuItem key={value?.label + i} value={value.label}>
|
|
26
|
-
{value.label}
|
|
27
|
-
</MenuItem>
|
|
28
|
-
))}
|
|
29
|
-
</Select>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as Table from "../../../../types/";
|
|
3
|
-
import MenuItem from "@mui/material/MenuItem";
|
|
4
|
-
import Select from "@mui/material/Select";
|
|
5
|
-
|
|
6
|
-
export const StatusFilter = (props: Table.Handlers.FilterProps) => {
|
|
7
|
-
const { value, filterName, setValue, resetPagination, filterOptions } = props;
|
|
8
|
-
|
|
9
|
-
const selectedValue = value?.[filterName] ?? "all";
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Select
|
|
13
|
-
value={selectedValue}
|
|
14
|
-
sx={{
|
|
15
|
-
height: "100%",
|
|
16
|
-
border: "none",
|
|
17
|
-
backgroundColor: "background.paper",
|
|
18
|
-
}}
|
|
19
|
-
onChange={(e) => {
|
|
20
|
-
resetPagination();
|
|
21
|
-
setValue((prev) => ({
|
|
22
|
-
...prev,
|
|
23
|
-
[filterName]: e.target.value,
|
|
24
|
-
}));
|
|
25
|
-
}}
|
|
26
|
-
>
|
|
27
|
-
<MenuItem value="all">All Statuses</MenuItem>
|
|
28
|
-
|
|
29
|
-
{filterOptions.map((status) => (
|
|
30
|
-
<MenuItem key={status.label} value={String(status.value)}>
|
|
31
|
-
{status.label}
|
|
32
|
-
</MenuItem>
|
|
33
|
-
))}
|
|
34
|
-
</Select>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as Table from "../../../types/";
|
|
3
|
-
import ArticleOutlinedIcon from "@mui/icons-material/ArticleOutlined";
|
|
4
|
-
import { Typography } from "@mui/material";
|
|
5
|
-
|
|
6
|
-
export const NoResultsComponent: Table.Handlers.NoResultsComponent = ({
|
|
7
|
-
label,
|
|
8
|
-
}: {
|
|
9
|
-
label: string;
|
|
10
|
-
}) => {
|
|
11
|
-
return (
|
|
12
|
-
<Typography
|
|
13
|
-
variant="body2"
|
|
14
|
-
color="text.secondary"
|
|
15
|
-
sx={{
|
|
16
|
-
display: "flex",
|
|
17
|
-
alignItems: "center",
|
|
18
|
-
justifyContent: "center",
|
|
19
|
-
gap: 1,
|
|
20
|
-
}}
|
|
21
|
-
>
|
|
22
|
-
<ArticleOutlinedIcon fontSize="small" />
|
|
23
|
-
No {label.toLowerCase()} found matching your criteria.
|
|
24
|
-
</Typography>
|
|
25
|
-
);
|
|
26
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Chip } from "@mui/material";
|
|
2
|
-
import type { StatusColorMap, StatusTextMap } from "../../../types/schemas";
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
status: number | string | string[];
|
|
6
|
-
statusTextMap: StatusTextMap;
|
|
7
|
-
statusColorMap: StatusColorMap;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const StatusPill = (props: Props) => {
|
|
11
|
-
const { statusColorMap, statusTextMap, status } = props;
|
|
12
|
-
if (typeof status !== "string" && typeof status !== "number") return null;
|
|
13
|
-
return (
|
|
14
|
-
<Chip label={statusTextMap?.[status]} color={statusColorMap[status]} />
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export { StatusPill };
|