mantine-entity
Version:
A library combining Mantine, TanStack Query, and Mantine React Table for efficient entity management
192 lines (191 loc) • 7.02 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useMemo } from "react";
import { Flex, rgba, Table, Text } from "@mantine/core";
import dayjs from "dayjs";
import { normalizeText, toSentenceCase } from "../../utils/string";
export const renderTableCellValue = (value) => {
// console.log({
// type: typeof value,
// value,
// });
try {
if (typeof value === "string") {
return renderCellValue(value);
}
if (typeof value === "object" && Object.keys(value).length === 0) {
return _jsx(Text, { color: "dimmed", children: " Empty " });
}
if (React.isValidElement(value)) {
return value;
}
if (typeof value === "object" && "value" in value) {
return _jsxs(Text, { fz: 13, children: [value.value, " "] });
}
if (Array.isArray(value)) {
return value.map((item, index) => (_jsxs("div", { className: " flex flex-row", children: [renderTableCellValue(item), " "] }, index)));
}
return _jsxs(Text, { children: [JSON.stringify(value), " "] });
}
catch {
return _jsx(Text, { color: "red", children: " " });
}
};
export const renderCellValue = (value) => {
const date = new Date(value).getTime();
if (!isNaN(date)) {
return formatDateTimeFromString(value); // Invalid date string
}
else {
return value;
}
};
export function formatDateTimeFromString(dateString, withoutTime = false) {
const date = new Date(dateString);
if (isNaN(date.getTime())) {
return null; // Invalid date string
}
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
const day = date.getDate();
const month = months[date.getMonth()];
const year = date.getFullYear();
const hours = date.getHours();
const minutes = date.getMinutes();
const period = hours >= 12 ? "PM" : "AM";
const twelveHourFormat = hours % 12 || 12; // Convert 24-hour to 12-hour format
const formattedDate = `${day.toString().padStart(2, "0")}-${month}-${year}`;
const formattedTime = `${twelveHourFormat}:${minutes
.toString()
.padStart(2, "0")}${period}`;
if (!withoutTime)
return `${formattedDate} ${formattedTime}`;
else
return `${formattedDate}`;
}
export const transformFormData = (data) => {
const result = {};
delete data.id;
const isDate = (value) => {
// First check for obvious non-date cases
if (typeof value === "number") {
// Numbers should only be considered dates if they're timestamps
// Assuming you don't want to treat regular numbers as dates
return false;
}
if (typeof value === "string") {
// Check if it's a numeric string (like "153")
if (/^\d+$/.test(value.trim()))
return false;
// Check if it's a boolean string
if (value.trim().toLowerCase() === "true" ||
value.trim().toLowerCase() === "false")
return false;
// Now check with dayjs
return dayjs(value).isValid();
}
// For objects, check if it's a Date instance
return value instanceof Date;
};
const isNumber = (value) => {
return (typeof value === "number" ||
(typeof value === "string" && !isNaN(Number(value)) && !isDate(value)));
};
Object?.entries(data)?.forEach(([key, value]) => {
if (value === null || value === undefined) {
result[key] = { value: "" };
return;
}
console.log({
key,
value,
isDate: isDate(value),
});
// Handle Date values
if (isDate(value)) {
result[key] = {
value: formatDateTimeFromString(value), // Format as YYYY-MM-DD
label: key,
};
return;
}
// Handle Number values
if (isNumber(value)) {
result[key] = {
value: Number(value).toString(),
label: key,
};
return;
}
// Original processing logic
if (typeof value === "object" && !Array.isArray(value)) {
result[key] = {};
Object?.entries(value).forEach(([subKey, subValue]) => {
if (typeof subValue === "object" &&
subValue !== null &&
"label" in subValue &&
"value" in subValue) {
result[key][subKey] = subValue.label;
}
else if (typeof subValue === "string" ||
React.isValidElement(subValue)) {
result[key][subKey] = subValue;
}
else if (isDate(subValue)) {
result[key][subKey] = new Date(subValue).toISOString().split("T")[0];
}
else if (isNumber(subValue)) {
result[key][subKey] = Number(subValue).toString();
}
else {
result[key][subKey] = subValue;
}
});
}
else if (Array.isArray(value)) {
result[key] = {};
Object.entries(value).forEach(([subKey, subValue]) => {
if (isDate(subValue)) {
result[key][subKey] = new Date(subValue).toISOString().split("T")[0];
}
else if (isNumber(subValue)) {
result[key][subKey] = Number(subValue).toString();
}
else {
result[key][subKey] = subValue;
}
});
}
else if (typeof value === "string") {
result[key] = {
value: value,
label: key,
};
}
else {
result[key] = {
value: JSON.stringify(value),
};
}
});
return result;
};
const DynamicTable = ({ data }) => {
const formattedValues = useMemo(() => transformFormData(data ?? {}), [data]);
console.log(formattedValues);
return (_jsxs(Table, { striped: true, stripedColor: rgba("var(--mantine-primary-color-4)", 0.2), className: " bg-[var(--card)]", children: [_jsx(Table.Thead, {}), _jsx(Table.Tbody, { className: "rounded-md", children: Object.entries(formattedValues).map(([key, value]) => (_jsxs(Table.Tr, { children: [_jsx(Table.Td, { fw: 600, w: 200, children: toSentenceCase(normalizeText(key)) }), _jsx(Table.Td, { w: 200, children: _jsx(Flex, { direction: "row", gap: "md", children: renderTableCellValue(value) }) })] }, key))) })] }));
};
export default DynamicTable;