glide-design-system
Version:
Glide design system is an open-source React component library. It offers numerous benefits that make them essential tools for design and development teams.
361 lines (352 loc) • 12.1 kB
JavaScript
import React from "react";
import "./table.css";
import { Chip } from "../chip/Chip";
import { ProgressCircle } from "../loader/ProgressCircle";
export const Table = ({
columns,
data,
sortHandler,
sortItem,
sortOrder,
tableRowStyles,
tableHeaderStyle,
linkHandler,
actionHandler,
style,
loading,
chipStyle,
progressCircleStyle,
progressCircleClass,
progressCircleContainerClass,
message,
tableContainerStyle,
containerClass,
id,
name,
key,
noDataStyle,
}) => {
const columnWidth = `${100 / columns.length}%`;
const camelCaseToWords = (word) => {
return word
.replace(/([A-Z])/g, " $1") // Insert a space before each capital letter
.trim() // Remove any leading/trailing spaces
.toUpperCase(); // Convert the whole string to uppercase
};
const formatTimestampToDateString = (timestamp) => {
const dateObj = new Date(timestamp);
const monthNames = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = monthNames[dateObj.getMonth()];
const day = dateObj.getDate();
const year = dateObj.getFullYear();
return `${month} ${day} ${year}`;
};
const renderChip = (data, column) => {
if (column?.type === "chip") {
const statusValue =
data?.[column?.fieldName ? column?.fieldName : column?.label];
const chipProperties = column?.chipOptions?.filter((chipvalue) => {
return chipvalue?.value === statusValue;
});
const { value, ...chipStyles } = chipProperties?.[0];
return <Chip style={{ ...chipStyle, ...chipStyles }}>{statusValue}</Chip>;
}
};
const combinedStyle = {
...style,
};
return (
<div
style={{ overflowX: "auto", overflowY: "hidden", ...tableContainerStyle }}
className={containerClass ? containerClass : ""}
>
<table
style={combinedStyle}
className="table"
data-testid={id}
id={id}
name={name}
>
<thead style={{ borderBottom: "1px solid #d7d7d7" }}>
<tr
className="tr"
style={{
height: 40,
backgroundColor: "#f9f9f9",
borderBottom: "1px solid #d7d7d7",
...tableHeaderStyle,
}}
>
{columns.map((column, index) => {
return (
<th
key={column?.fieldName ? column?.fieldName : column?.label}
id={column?.fieldName ? column?.fieldName : column?.label}
style={{
width: column?.style?.width || columnWidth,
textAlign: "left",
borderRight:
index !== columns.length - 1
? "1px solid #d7d7d7"
: "none",
color: "#7f7f7f",
fontSize: "12px",
fontWeight: "700",
fontFamily: "Roboto, sans-serif",
paddingLeft: "12.5px",
...column?.style,
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
<p
fontWeight="bold"
fontSize={12}
//style={styles.tableHeader}
>
{camelCaseToWords(column?.label)}
</p>
{column?.sort && (
<div
data-testid={`${
column?.fieldName ? column?.fieldName : column?.label
}SortIcon`}
id={`${
column?.fieldName ? column?.fieldName : column?.label
}SortIcon`}
className="sortIcon"
style={{ paddingLeft: "5px" }}
onClick={() => {
sortHandler &&
sortHandler(
sortOrder === "asc" ? "desc" : "asc",
column?.fieldName
? column?.fieldName
: column?.label
);
}}
>
{sortItem ===
(column?.fieldName
? column?.fieldName
: column?.label) ? (
sortOrder === "desc" ? (
<span
style={{
color: "#7f7f7f",
}}
className="material-symbols-outlined"
>
expand_more
</span>
) : (
<span
style={{
color: "#7f7f7f",
}}
className="material-symbols-outlined"
>
expand_less
</span>
)
) : (
<span
style={{
color: "#7f7f7f",
writingMode: "vertical-lr",
direction: "rtl",
fontSize: "18px",
}}
className="material-symbols-outlined"
>
code
</span>
)}
</div>
)}
</div>
</th>
);
})}
</tr>
</thead>
<tbody>
{loading ? (
<tr
style={{
height: 40,
fontFamily: "Roboto, sans-serif",
fontSize: "14px",
...tableRowStyles,
}}
>
{columns.map((column, index) => {
return (
<td
key={`loader-${index + 1}-${key ? key : ""}`}
style={{
justifyContent: "center",
alignItems: "center",
width: columnWidth,
paddingInline: "6px",
...column?.style,
}}
>
{index === Math.floor(columns.length / 2) ? (
<ProgressCircle
size="medium"
style={{ ...progressCircleStyle }}
className={progressCircleClass}
containerClass={progressCircleContainerClass}
/>
) : (
""
)}
</td>
);
})}
</tr>
) : message ? (
<tr
style={{
height: 40,
fontFamily: "Roboto, sans-serif",
fontSize: "16px",
...tableRowStyles,
}}
>
{columns.map((column, index) => {
return (
<td
key={`message-${index}-${key ? key : ""}`}
style={{
justifyContent: "center",
alignItems: "center",
width: columnWidth,
paddingInline: "6px",
...column?.style,
}}
>
{index === Math.floor(columns.length / 2) ? (
<div style={{ fontSize: "14px", ...noDataStyle }}>
{message ? message : ""}
</div>
) : (
""
)}
</td>
);
})}
</tr>
) : (
data?.map((value, rowIndex) => {
return (
<tr
key={`tableRow-${rowIndex}-${key ? key : ""}`}
id={value?.id}
style={{
borderBottom:
rowIndex !== data?.length - 1 ? "1px solid #d7d7d7" : "",
height: 40,
fontFamily: "Roboto, sans-serif",
fontSize: "16px",
...tableRowStyles,
}}
>
{columns?.map((column, index) => {
return (
<td
key={`tableColumn-${index}-${key ? key : ""}`}
id={
value?.hasOwnProperty(column?.fieldName)
? value[column?.fieldName]
: value?.hasOwnProperty(column?.label)
? value[column?.label]
: `action-${value?.id}`
}
style={{
width: columnWidth,
paddingInline: "12.5px",
...column?.style,
}}
>
{column?.customBodyRenderer ? (
column.customBodyRenderer(value, rowIndex)
) : column?.type === "date" ? (
formatTimestampToDateString(
value?.[
column?.fieldName
? column?.fieldName
: column?.label
]
)
) : column?.type === "chip" ? (
renderChip(value, column)
) : column?.element ? (
<div
onClick={(e) =>
actionHandler &&
actionHandler(e.currentTarget, value)
}
className="sortIcon"
>
{column?.element}
</div>
) : column?.type === "link" ? (
<span
onClick={(e) =>
linkHandler && linkHandler(e, value)
}
className="sortIcon"
style={{
color: "rgb(2, 167, 240)",
}}
>
{
value?.[
column?.fieldName
? column?.fieldName
: column?.label
]
}
</span>
) : (
value?.[
column?.fieldName
? column?.fieldName
: column?.label
]
)}
</td>
);
})}
</tr>
);
})
)}
</tbody>
</table>
</div>
);
};
const styles = {
tableHeader: {
color: "#7f7f7f",
fontSize: "12px",
fontWeight: "700",
fontFamily: "Roboto, sans-serif",
paddingLeft: "12.5px",
},
};