rez-table-listing-mui 0.0.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.
Files changed (65) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/README.md +164 -0
  3. package/dist/index.d.ts +90 -0
  4. package/dist/index.js +1 -0
  5. package/dist/index.mjs +1 -0
  6. package/index.html +13 -0
  7. package/package.json +64 -0
  8. package/public/vite.svg +1 -0
  9. package/rollup.config.js +42 -0
  10. package/src/App.tsx +153 -0
  11. package/src/assets/svg.tsx +833 -0
  12. package/src/components/columm-visibility-modal/column-list-item.tsx +44 -0
  13. package/src/components/columm-visibility-modal/index.scss +72 -0
  14. package/src/components/columm-visibility-modal/index.tsx +175 -0
  15. package/src/components/common/index.scss +11 -0
  16. package/src/components/common/index.tsx +11 -0
  17. package/src/components/dropdown/index.scss +17 -0
  18. package/src/components/dropdown/index.tsx +27 -0
  19. package/src/components/index-table.tsx +266 -0
  20. package/src/components/index.scss +176 -0
  21. package/src/components/inputs/checkbox/index.tsx +58 -0
  22. package/src/components/inputs/index.scss +63 -0
  23. package/src/components/inputs/switch.tsx +14 -0
  24. package/src/components/nestedcomponent/index.scss +14 -0
  25. package/src/components/nestedcomponent/index.tsx +53 -0
  26. package/src/components/pagination/default/index.scss +76 -0
  27. package/src/components/pagination/default/index.tsx +168 -0
  28. package/src/components/sorting-modal.tsx/index.tsx +200 -0
  29. package/src/components/sorting-modal.tsx/sorting-item.tsx +35 -0
  30. package/src/components/table-body-dnd-cell.tsx +50 -0
  31. package/src/components/table-body.tsx +109 -0
  32. package/src/components/table-change-layout.tsx +106 -0
  33. package/src/components/table-dnd.tsx +62 -0
  34. package/src/components/table-head-dnd-cell.tsx +144 -0
  35. package/src/components/table-head-pin.tsx +16 -0
  36. package/src/components/table-head-popover.tsx +85 -0
  37. package/src/components/table-head.tsx +156 -0
  38. package/src/components/table.tsx +38 -0
  39. package/src/components/tabs/index.scss +41 -0
  40. package/src/components/tabs/index.tsx +132 -0
  41. package/src/components/topbar/index.scss +84 -0
  42. package/src/components/topbar/index.tsx +226 -0
  43. package/src/components/viewmore/index.scss +0 -0
  44. package/src/components/viewmore/index.tsx +171 -0
  45. package/src/index.ts +4 -0
  46. package/src/libs/hooks/useCraftTable.tsx +37 -0
  47. package/src/libs/hooks/useDefaultColumns.tsx +96 -0
  48. package/src/libs/hooks/useFullScreen.tsx +25 -0
  49. package/src/libs/hooks/useOutsideClick.tsx +24 -0
  50. package/src/libs/utils/Data-format.ts +18 -0
  51. package/src/libs/utils/amount-format.ts +70 -0
  52. package/src/libs/utils/common.ts +62 -0
  53. package/src/libs/utils/date-format.ts +6 -0
  54. package/src/libs/utils/make-data.ts +79 -0
  55. package/src/libs/utils/make-hierar-data.ts +51 -0
  56. package/src/libs/utils/make-nested-data.ts +86 -0
  57. package/src/libs/utils/rows-data.ts +251 -0
  58. package/src/main.tsx +9 -0
  59. package/src/types/common.ts +30 -0
  60. package/src/types/table-options.ts +38 -0
  61. package/src/types/table.ts +65 -0
  62. package/src/vite-env.d.ts +1 -0
  63. package/tsconfig.json +25 -0
  64. package/tsconfig.node.json +11 -0
  65. package/vite.config.ts +7 -0
@@ -0,0 +1,226 @@
1
+ import React, { useState, useRef, useEffect } from "react";
2
+ import {
3
+ ChangeLayoutIcon,
4
+ SearchIcon,
5
+ SortingIcon,
6
+ CustomizationIcon,
7
+ HideColumnIcon,
8
+ } from "../../assets/svg";
9
+ import { Popover } from "@mui/material";
10
+ import LayoutSelector from "../table-change-layout";
11
+ import useOutsideClick from "../../libs/hooks/useOutsideClick";
12
+ import { Table } from "@tanstack/react-table";
13
+ import { TopbarOptionsProps } from "../../types/table";
14
+ import "./index.scss";
15
+ import ViewMore from "../viewmore";
16
+ import { useFullscreenPopoverContainer } from "../../libs/hooks/useFullScreen";
17
+ import SortPopover from "../sorting-modal.tsx";
18
+ import ColumnToggle from "../columm-visibility-modal/index.tsx";
19
+
20
+ interface TopbarProps<T> {
21
+ table: Table<T>;
22
+ fullscreenToggle: () => void;
23
+ isCompactTable: boolean;
24
+ setIsCompactTable: React.Dispatch<React.SetStateAction<boolean>>;
25
+ paginationComponent?: React.ReactNode;
26
+ topbarOptions?: TopbarOptionsProps;
27
+ columnOrder?: string[];
28
+ setColumnOrder?: React.Dispatch<React.SetStateAction<string[]>>;
29
+ }
30
+
31
+ function Topbar<T>({
32
+ table,
33
+ isCompactTable,
34
+ fullscreenToggle,
35
+ setIsCompactTable,
36
+ paginationComponent,
37
+ topbarOptions,
38
+ }: TopbarProps<T>) {
39
+ const [wrapCell, setWrapCell] = useState(false);
40
+ const [isFullscreen, setIsFullscreen] = useState(false);
41
+ const [sortAnchorEl, setSortAnchorEl] = useState<HTMLElement | null>(null);
42
+ const [groupBy, setGroupBy] = useState<string>("None");
43
+
44
+ const [showColumnHiding, setShowColumnHiding] = useState(false);
45
+ const [layoutAnchorEl, setLayoutAnchorEl] = useState<null | HTMLElement>(
46
+ null
47
+ );
48
+ const [selectedLayout, setSelectedLayout] = useState("Table");
49
+ const [columnAnchorEl, setColumnAnchorEl] = useState<HTMLElement | null>(
50
+ null
51
+ );
52
+ const [columnOrder, setColumnOrder] = useState<string[]>(
53
+ table.getAllLeafColumns().map((col) => col.id)
54
+ );
55
+
56
+ console.log("showColumnHiding", showColumnHiding); //only for built purpose-> remove it later
57
+
58
+ // sync column order with table instance
59
+ useEffect(() => {
60
+ table.setColumnOrder(columnOrder);
61
+ }, [columnOrder]);
62
+
63
+ const {
64
+ leftSideComponent,
65
+ rightSideComponent,
66
+ showColumnToggle,
67
+ showChangeLayoutToggle,
68
+ viewMoreToggle,
69
+ showSearch,
70
+ showFilter,
71
+ showCustomizationToggle,
72
+ } = topbarOptions ?? {};
73
+
74
+ const { container: fullscreenContainer } = useFullscreenPopoverContainer();
75
+
76
+ const dropdownRef = useRef<HTMLDivElement>(null);
77
+ useOutsideClick({
78
+ ref: dropdownRef,
79
+ handler: () => setShowColumnHiding(false),
80
+ });
81
+
82
+ const handleLayoutIconClick = (event: React.MouseEvent<HTMLElement>) => {
83
+ setLayoutAnchorEl(event.currentTarget);
84
+ };
85
+
86
+ const handleLayoutSelect = (layout: string) => {
87
+ setSelectedLayout(layout);
88
+ setLayoutAnchorEl(null);
89
+ };
90
+
91
+ return (
92
+ <div className="ts-topbar">
93
+ <div className="tabs-section">{leftSideComponent}</div>
94
+
95
+ <div className="right-section">
96
+ {rightSideComponent}
97
+ {paginationComponent}
98
+
99
+ {showSearch && (
100
+ <div className="search ts--button" title="Search">
101
+ <SearchIcon />
102
+ </div>
103
+ )}
104
+
105
+ {showChangeLayoutToggle && (
106
+ <>
107
+ <div className="change-layout ts--button" title="Layout">
108
+ <div onClick={handleLayoutIconClick}>
109
+ <ChangeLayoutIcon />
110
+ </div>
111
+ </div>
112
+ <Popover
113
+ open={Boolean(layoutAnchorEl)}
114
+ anchorEl={layoutAnchorEl}
115
+ onClose={() => setLayoutAnchorEl(null)}
116
+ anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
117
+ container={fullscreenContainer}
118
+ // transformOrigin={{ vertical: "top", horizontal: "left" }}
119
+ // PaperProps={{
120
+ // sx: {
121
+ // mt: 2,
122
+ // },
123
+ // }}
124
+ sx={{
125
+ mt: 2.2,
126
+ }}
127
+ >
128
+ <LayoutSelector
129
+ onSelect={handleLayoutSelect}
130
+ selectedLayout={selectedLayout}
131
+ />
132
+ </Popover>
133
+ </>
134
+ )}
135
+
136
+ {showColumnToggle && (
137
+ <>
138
+ <div
139
+ className="hide-column ts--button"
140
+ onClick={(e) => setColumnAnchorEl(e.currentTarget)}
141
+ title="Column"
142
+ >
143
+ <HideColumnIcon />
144
+ </div>
145
+ <ColumnToggle
146
+ anchorEl={columnAnchorEl}
147
+ onClose={() => setColumnAnchorEl(null)}
148
+ table={table}
149
+ columnOrder={columnOrder}
150
+ setColumnOrder={setColumnOrder}
151
+ />
152
+ </>
153
+ )}
154
+
155
+ {showFilter && (
156
+ <>
157
+ <div
158
+ className="filter ts--button"
159
+ title="Sort"
160
+ onClick={(e) => setSortAnchorEl(e.currentTarget)}
161
+ >
162
+ <SortingIcon />
163
+ </div>
164
+ <SortPopover
165
+ anchorEl={sortAnchorEl}
166
+ onClose={() => setSortAnchorEl(null)}
167
+ columns={table.getAllLeafColumns().map((col) => ({
168
+ id: col.id,
169
+ label: (col.columnDef.meta as any)?.label || col.id,
170
+ }))}
171
+ onChange={(sortingRules) => table.setSorting(sortingRules)}
172
+ />
173
+ </>
174
+ )}
175
+
176
+ {showCustomizationToggle && (
177
+ <div className="customization ts--button" title="Filter">
178
+ <CustomizationIcon />
179
+ </div>
180
+ )}
181
+
182
+ {viewMoreToggle && (
183
+ <div className="view-more ts--button" title="View More">
184
+ <ViewMore
185
+ wrapCell={wrapCell}
186
+ onWrapCellToggle={() => setWrapCell((prev) => !prev)}
187
+ compactMode={isCompactTable}
188
+ onCompactToggle={(value: string) =>
189
+ setIsCompactTable(value === "Compact")
190
+ }
191
+ isFullscreen={isFullscreen}
192
+ onFullscreenToggle={() => {
193
+ fullscreenToggle();
194
+ setIsFullscreen((prev) => !prev);
195
+ }}
196
+ groupBy={groupBy}
197
+ onGroupByChange={(value: string) => setGroupBy(value)}
198
+ />
199
+ </div>
200
+ )}
201
+
202
+ {/* {showWrapCell && (
203
+ <div
204
+ className="wrap-cell ts--button"
205
+ onClick={() => setWrapCell((prev) => !prev)}
206
+ title="Wrap Cell"
207
+ >
208
+ <WrapCellIcon />
209
+ </div>
210
+ )} */}
211
+
212
+ {/* {showAddNewButton && (
213
+ <div
214
+ className="add-new-button ts--button"
215
+ title="Add New"
216
+ onClick={() => {}}
217
+ >
218
+ <AddNewButtonIcon />
219
+ </div>
220
+ )} */}
221
+ </div>
222
+ </div>
223
+ );
224
+ }
225
+
226
+ export default Topbar;
File without changes
@@ -0,0 +1,171 @@
1
+ import React from "react";
2
+ import {
3
+ Popover,
4
+ Typography,
5
+ Box,
6
+ MenuItem,
7
+ Select,
8
+ IconButton,
9
+ Switch as MUISwitch,
10
+ } from "@mui/material";
11
+ import { CloseIcon, ViewMoreIcon } from "../../assets/svg";
12
+ import { useFullscreenPopoverContainer } from "../../libs/hooks/useFullScreen";
13
+
14
+ interface ViewMorePopoverProps {
15
+ wrapCell: boolean;
16
+ onWrapCellToggle: () => void;
17
+ compactMode: boolean;
18
+ onCompactToggle: (value: string) => void;
19
+ isFullscreen: boolean;
20
+ onFullscreenToggle: () => void;
21
+ groupBy: string;
22
+ onGroupByChange: (value: string) => void;
23
+ }
24
+
25
+ const ViewMore = ({
26
+ wrapCell,
27
+ onWrapCellToggle,
28
+ compactMode,
29
+ onCompactToggle,
30
+ isFullscreen,
31
+ onFullscreenToggle,
32
+ groupBy,
33
+ onGroupByChange,
34
+ }: ViewMorePopoverProps) => {
35
+ const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
36
+
37
+ const open = Boolean(anchorEl);
38
+ const { container: fullscreenContainer } = useFullscreenPopoverContainer();
39
+
40
+ const handleClick = (event: React.MouseEvent<HTMLElement>) => {
41
+ setAnchorEl(event.currentTarget);
42
+ };
43
+
44
+ const handleClose = () => {
45
+ setAnchorEl(null);
46
+ };
47
+
48
+ return (
49
+ <>
50
+ <div onClick={handleClick}>
51
+ <ViewMoreIcon />
52
+ </div>
53
+
54
+ <Popover
55
+ open={open}
56
+ anchorEl={anchorEl}
57
+ onClose={handleClose}
58
+ container={fullscreenContainer}
59
+ anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
60
+ transformOrigin={{ vertical: "top", horizontal: "left" }}
61
+ PaperProps={{
62
+ sx: {
63
+ mt: 2.3,
64
+ padding: 3,
65
+ width: 380,
66
+ borderRadius: 1,
67
+ boxShadow: 4,
68
+ },
69
+ }}
70
+ >
71
+ <Box
72
+ display="flex"
73
+ justifyContent="space-between"
74
+ alignItems="center"
75
+ px={2}
76
+ py={2}
77
+ sx={{
78
+ backgroundColor: "#F9FAFB",
79
+ // borderBottom: "1px solid #E0E0E0",
80
+ // borderTopLeftRadius: 4,
81
+ // borderTopRightRadius: 4,
82
+ margin: "-24px -24px 24px -24px",
83
+ }}
84
+ >
85
+ <Typography fontSize="18px" fontWeight={400} color="#0C2033">
86
+ View
87
+ </Typography>
88
+ <IconButton size="small" onClick={handleClose}>
89
+ <CloseIcon />
90
+ </IconButton>
91
+ </Box>
92
+
93
+ {/* Wrap Cell */}
94
+ <Box
95
+ display="flex"
96
+ justifyContent="space-between"
97
+ alignItems="center"
98
+ mb={2}
99
+ >
100
+ <Typography fontSize="14px" fontWeight={400} color="#000000DE">
101
+ Wrap Cell
102
+ </Typography>
103
+ <MUISwitch checked={wrapCell} onChange={onWrapCellToggle} />
104
+ </Box>
105
+
106
+ {/* List View */}
107
+ <Box
108
+ display="flex"
109
+ justifyContent="space-between"
110
+ alignItems="center"
111
+ mb={2}
112
+ >
113
+ <Typography fontSize="14px" fontWeight={400} color="#000000DE">
114
+ List View
115
+ </Typography>
116
+ <Select
117
+ size="small"
118
+ value={compactMode ? "Compact" : "Comfy"}
119
+ onChange={(e) => onCompactToggle(e.target.value)}
120
+ sx={{
121
+ minWidth: 120,
122
+ fontWeight: 400,
123
+ color: "#000",
124
+ fontSize: "13px",
125
+ }}
126
+ >
127
+ <MenuItem value="Comfy">Comfy</MenuItem>
128
+ <MenuItem value="Compact">Compact</MenuItem>
129
+ </Select>
130
+ </Box>
131
+
132
+ {/* Group By */}
133
+ <Box
134
+ display="flex"
135
+ justifyContent="space-between"
136
+ alignItems="center"
137
+ mb={2}
138
+ >
139
+ <Typography fontSize="14px" fontWeight={400} color="#000000DE">
140
+ Group By
141
+ </Typography>
142
+ <Select
143
+ size="small"
144
+ value={groupBy}
145
+ onChange={(e) => onGroupByChange(e.target.value)}
146
+ sx={{
147
+ minWidth: 120,
148
+ fontWeight: 400,
149
+ color: "#000",
150
+ fontSize: "13px",
151
+ }}
152
+ >
153
+ <MenuItem value="None">None</MenuItem>
154
+ <MenuItem value="Status">Status</MenuItem>
155
+ <MenuItem value="Owner">Owner</MenuItem>
156
+ </Select>
157
+ </Box>
158
+
159
+ {/* Fullscreen */}
160
+ <Box display="flex" justifyContent="space-between" alignItems="center">
161
+ <Typography fontSize="14px" fontWeight={400} color="#000000DE">
162
+ Fullscreen
163
+ </Typography>
164
+ <MUISwitch checked={isFullscreen} onChange={onFullscreenToggle} />
165
+ </Box>
166
+ </Popover>
167
+ </>
168
+ );
169
+ };
170
+
171
+ export default ViewMore;
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { default as TableWrapper } from "./components/index-table";
2
+ export { useCraftTable } from "./libs/hooks/useCraftTable";
3
+ export * from "./types/table";
4
+ export * from "./types/table-options";
@@ -0,0 +1,37 @@
1
+ import {
2
+ ExpandedState,
3
+ PaginationState,
4
+ RowSelectionState,
5
+ SortingState,
6
+ } from "@tanstack/react-table";
7
+ import { useState } from "react";
8
+ import { CraftTableOptionsProps } from "../../types/table-options";
9
+
10
+ export function useCraftTable() {
11
+ const [pagination, setPagination] = useState<PaginationState>({
12
+ pageIndex: 0,
13
+ pageSize: 25,
14
+ });
15
+ const [sorting, setSorting] = useState<SortingState>([]);
16
+ const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
17
+ const [expanded, setExpanded] = useState<ExpandedState>({});
18
+
19
+ if (pagination.pageIndex < 0 || pagination.pageSize <= 0) {
20
+ throw new Error(
21
+ "Invalid pagination values: pageIndex and pageSize must be positive."
22
+ );
23
+ }
24
+
25
+ const craftTableOptions: CraftTableOptionsProps = {
26
+ sorting: sorting,
27
+ setSorting: setSorting,
28
+ pagination: pagination,
29
+ setPagination: setPagination,
30
+ rowSelection: rowSelection,
31
+ setRowSelection: setRowSelection,
32
+ expanded: expanded,
33
+ setExpanded: setExpanded,
34
+ };
35
+
36
+ return craftTableOptions;
37
+ }
@@ -0,0 +1,96 @@
1
+ import { ColumnDef } from "@tanstack/react-table";
2
+ import React from "react";
3
+ import { Person } from "../utils/make-hierar-data";
4
+ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
5
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
6
+
7
+ export const useDefaultColumns = () => {
8
+ const defaultColumns = React.useMemo<ColumnDef<Person>[]>(
9
+ () => [
10
+ {
11
+ header: "First Name",
12
+ id: "firstName",
13
+ accessorKey: "firstName",
14
+ meta: { label: "First Name" },
15
+ // header: ({ table }) => (
16
+ // <>
17
+ // <button
18
+ // {...{
19
+ // onClick: table.getToggleAllRowsExpandedHandler(),
20
+ // }}
21
+ // >
22
+ // {table.getIsAllRowsExpanded() ? "👇" : "👉"}
23
+ // </button>{" "}
24
+ // First Name
25
+ // </>
26
+ // ),
27
+ cell: ({ row, getValue }) => {
28
+ return (
29
+ <div style={{ paddingLeft: `${row.depth * 2}rem` }}>
30
+ {row.getCanExpand() ? (
31
+ <button
32
+ style={{
33
+ // marginRight: "0.8rem",
34
+ cursor: "pointer",
35
+ background: "none",
36
+ border: "none",
37
+ }}
38
+ onClick={() => {
39
+ row.getToggleExpandedHandler()();
40
+ }}
41
+ >
42
+ {row.getIsExpanded() ? (
43
+ <ExpandMoreIcon />
44
+ ) : (
45
+ <ChevronRightIcon />
46
+ )}{" "}
47
+ </button>
48
+ ) : (
49
+ <span style={{ marginRight: "0.8rem" }}></span>
50
+ )}
51
+ {getValue<boolean>()}
52
+ </div>
53
+ );
54
+ },
55
+ },
56
+ {
57
+ header: "Last Name",
58
+ accessorKey: "lastName",
59
+ size: 100,
60
+ meta: { label: "Last Name" },
61
+ },
62
+ {
63
+ header: "Age",
64
+ accessorKey: "age",
65
+ size: 100,
66
+ meta: { label: "Age" },
67
+ },
68
+ {
69
+ header: "Visits",
70
+ accessorKey: "visits",
71
+ size: 150,
72
+ meta: { label: "Visits" },
73
+ },
74
+ {
75
+ header: "Progress",
76
+ accessorKey: "progress",
77
+ size: 150,
78
+ meta: { label: "Progress" },
79
+ },
80
+ {
81
+ header: "Status",
82
+ accessorKey: "status",
83
+ meta: { label: "Status" },
84
+ },
85
+ {
86
+ header: "Department",
87
+ accessorKey: "department",
88
+ size: 150,
89
+ meta: { label: "Department" },
90
+ },
91
+ ],
92
+ []
93
+ );
94
+
95
+ return { defaultColumns };
96
+ };
@@ -0,0 +1,25 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ export function useFullscreenPopoverContainer() {
4
+ const [isFullscreen, setIsFullscreen] = useState<boolean>(
5
+ !!document.fullscreenElement
6
+ );
7
+ const [container, setContainer] = useState<Element | undefined>(
8
+ document.fullscreenElement ?? undefined
9
+ );
10
+
11
+ useEffect(() => {
12
+ const handleFullscreenChange = () => {
13
+ const el = document.fullscreenElement ?? undefined;
14
+ setIsFullscreen(!!el);
15
+ setContainer(el);
16
+ };
17
+
18
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
19
+ return () => {
20
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
21
+ };
22
+ }, []);
23
+
24
+ return { isFullscreen, container };
25
+ }
@@ -0,0 +1,24 @@
1
+ import React, { useEffect } from "react";
2
+
3
+ interface OutsideClickHandlerProps {
4
+ ref: React.RefObject<HTMLElement>;
5
+ handler: () => void;
6
+ }
7
+
8
+ const useOutsideClick = ({ ref, handler }: OutsideClickHandlerProps) => {
9
+ useEffect(() => {
10
+ const handleClickOutside = (event: MouseEvent) => {
11
+ if (ref.current && !ref.current.contains(event.target as Node)) {
12
+ handler();
13
+ }
14
+ };
15
+
16
+ document.addEventListener("mousedown", handleClickOutside);
17
+
18
+ return () => {
19
+ document.removeEventListener("mousedown", handleClickOutside);
20
+ };
21
+ }, [ref, handler]);
22
+ };
23
+
24
+ export default useOutsideClick;
@@ -0,0 +1,18 @@
1
+ import { formatAmount } from "./amount-format";
2
+ import { formatDate } from "./date-format";
3
+
4
+ export const DataFormat = (value: any, type: string) => {
5
+ if (!value) return "";
6
+
7
+ switch (type) {
8
+ case "date":
9
+ return formatDate({ date: value, style: "DD-MMM-YYYY" });
10
+ case "amount":
11
+ return formatAmount({
12
+ amount: value,
13
+ decimal: false,
14
+ });
15
+ default:
16
+ return value;
17
+ }
18
+ };
@@ -0,0 +1,70 @@
1
+ import { amountFormatProps } from "../../types/common";
2
+
3
+ interface compactAmountProps {
4
+ finalAmount: number;
5
+ format: string;
6
+ }
7
+
8
+ export const formatAmount = ({
9
+ amount,
10
+ decimal,
11
+ removeFloat,
12
+ compactFormat,
13
+ }: amountFormatProps) => {
14
+ let Amt = typeof amount === "string" ? parseFloat(amount) : amount;
15
+
16
+ if (isNaN(Amt || amount)) return decimal ? "0" : "₹0.00";
17
+
18
+ const isCompactAmount = ({ finalAmount, format }: compactAmountProps) => {
19
+ const options: Intl.NumberFormatOptions = {
20
+ style: decimal ? "decimal" : "currency",
21
+ minimumFractionDigits: decimal && !removeFloat ? 2 : undefined,
22
+ currency: !decimal ? "INR" : undefined,
23
+ };
24
+
25
+ if (format) {
26
+ let croreCondition =
27
+ (format === "crore" || "10lakh" || "lakh") && amount >= 10000000;
28
+ let tenlakhCondition =
29
+ (format === "10lakh" || "lakh") && amount >= 1000000;
30
+ let lakhCondition = format === "lakh" && amount >= 100000;
31
+
32
+ if (croreCondition) {
33
+ // Convert to Crores
34
+ amount /= 10000000;
35
+ return decimal
36
+ ? Math.floor(amount * 100) / 100 + " Cr"
37
+ : "₹" + Math.floor(amount * 100) / 100 + " Cr";
38
+ } else if (tenlakhCondition) {
39
+ // Convert to Lakhs if more than 10 Lakhs
40
+ amount /= 1000000;
41
+ return decimal
42
+ ? Math.floor(amount * 1000) / 100 + " L"
43
+ : "₹" + Math.floor(amount * 1000) / 100 + " L";
44
+ } else if (lakhCondition) {
45
+ // Convert to Lakhs if more than 1 Lakh
46
+ amount /= 100000;
47
+ return decimal
48
+ ? Math.floor(amount * 100) / 100 + " L"
49
+ : "₹" + Math.floor(amount * 100) / 100 + " L";
50
+ }
51
+ }
52
+
53
+ if (decimal) return finalAmount?.toLocaleString("en-IN", options);
54
+
55
+ return finalAmount?.toLocaleString("en-IN", options);
56
+ };
57
+
58
+ // Two options for more control when to use compact amount
59
+ if (compactFormat) {
60
+ return isCompactAmount({
61
+ finalAmount: Amt,
62
+ format: compactFormat,
63
+ });
64
+ } else {
65
+ return isCompactAmount({
66
+ finalAmount: Amt,
67
+ format: "",
68
+ });
69
+ }
70
+ };