added custom table component

This commit is contained in:
sara-pervana
2023-11-15 22:21:40 +01:00
parent 21dfc52acc
commit 928d897977
9 changed files with 177 additions and 28 deletions

View File

@@ -47,9 +47,9 @@ export default function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
<head> <head>
<title>Clan.lol</title> <title>Service-Aware Networks</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Clan.lol - build your own network" /> <meta name="description" content="Service-Aware Networks" />
<link rel="icon" href="favicon.ico" sizes="any" /> <link rel="icon" href="favicon.ico" sizes="any" />
</head> </head>
<StyledEngineProvider injectFirst> <StyledEngineProvider injectFirst>
@@ -72,9 +72,8 @@ export default function RootLayout({
onClose={() => setShowSidebar(false)} onClose={() => setShowSidebar(false)}
/> />
<div <div
className={tw`${ className={tw`${!showSidebarDerived && translate
!showSidebarDerived && translate } flex h-full w-full flex-col overflow-y-scroll transition-[margin] duration-150 ease-in-out`}
} flex h-full w-full flex-col overflow-y-scroll transition-[margin] duration-150 ease-in-out`}
> >
<div className="static top-0 mb-2 py-2"> <div className="static top-0 mb-2 py-2">
<div className="grid grid-cols-3"> <div className="grid grid-cols-3">
@@ -89,7 +88,7 @@ export default function RootLayout({
<div className="col-span-1 block w-full bg-fixed text-center font-semibold dark:invert lg:hidden"> <div className="col-span-1 block w-full bg-fixed text-center font-semibold dark:invert lg:hidden">
<Image <Image
src="/favicon.png" src="/favicon.png"
alt="Clan Logo" alt="TUB Logo"
width={58} width={58}
height={58} height={58}
priority priority

View File

@@ -10,7 +10,7 @@ export default function Dashboard() {
<div className="grid h-full place-items-center"> <div className="grid h-full place-items-center">
<div className="mt-8 w-full max-w-xl"> <div className="mt-8 w-full max-w-xl">
<LoadingOverlay <LoadingOverlay
title="Clan Experience" title="Service-Aware Networks"
subtitle="Loading" subtitle="Loading"
variant="circle" variant="circle"
/> />

View File

@@ -4,7 +4,7 @@ import {
createTheme, createTheme,
} from "@mui/material/styles"; } from "@mui/material/styles";
import colors from "@clan/colors/colors.json"; import colors from "../../../../theme/src/colors.json";
const { palette, common } = colors.ref; const { palette, common } = colors.ref;
const commonOptions: Partial<ThemeOptions> = { const commonOptions: Partial<ThemeOptions> = {
@@ -46,8 +46,8 @@ export const darkTheme = createTheme({
mode: "dark", mode: "dark",
...commonPalette, ...commonPalette,
background: { background: {
default: palette.neutral2.value, default: palette.neutral20.value,
paper: palette.neutral5.value, paper: palette.neutral50.value,
}, },
common: { common: {
black: common.black.value, black: common.black.value,

View File

@@ -8,13 +8,17 @@ import {
ListItemText, ListItemText,
} from "@mui/material"; } from "@mui/material";
import Image from "next/image"; import Image from "next/image";
import { ReactNode } from "react"; import React, { ReactNode } from "react";
import { tw } from "@/utils/tailwind"; import { tw } from "@/utils/tailwind";
import AssignmentIndIcon from "@mui/icons-material/AssignmentInd";
import Link from "next/link"; import Link from "next/link";
import WysiwygIcon from "@mui/icons-material/Wysiwyg";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import HomeIcon from '@mui/icons-material/Home';
import HubIcon from '@mui/icons-material/Hub';
import PersonIcon from '@mui/icons-material/Person';
import RouterIcon from '@mui/icons-material/Router';
import StorageIcon from '@mui/icons-material/Storage';
type MenuEntry = { type MenuEntry = {
icon: ReactNode; icon: ReactNode;
@@ -27,17 +31,41 @@ type MenuEntry = {
const menuEntries: MenuEntry[] = [ const menuEntries: MenuEntry[] = [
{ {
icon: <AssignmentIndIcon />, icon: <HomeIcon />,
label: "Freelance", label: "Home",
to: "/", to: "/",
disabled: false, disabled: false,
}, },
{ {
icon: <WysiwygIcon />, icon: <HubIcon />,
label: "Blog", label: "Entities",
to: "/blog", to: "/entities",
disabled: true, disabled: true,
}, },
{
icon: <PersonIcon />,
label: "C1",
to: "/client-1",
disabled: false,
},
{
icon: <PersonIcon />,
label: "C2",
to: "/client-2",
disabled: false,
},
{
icon: <RouterIcon />,
label: "AP",
to: "/access-point",
disabled: false,
},
{
icon: <StorageIcon />,
label: "DLG",
to: "/distributed-ledger-gateway",
disabled: false,
}
]; ];
const hideSidebar = tw`-translate-x-14 lg:-translate-x-64`; const hideSidebar = tw`-translate-x-14 lg:-translate-x-64`;
@@ -50,17 +78,22 @@ interface SidebarProps {
export function Sidebar(props: SidebarProps) { export function Sidebar(props: SidebarProps) {
const { show, onClose } = props; const { show, onClose } = props;
const [activeMenuItem, setActiveMenuItem] = React.useState('/');
const handleMenuItemClick = (path: string) => {
setActiveMenuItem(path);
};
return ( return (
<aside <aside
className={tw`${ className={tw`${show ? showSidebar : hideSidebar
show ? showSidebar : hideSidebar } z-9999 static left-0 top-0 flex h-screen w-14 flex-col overflow-x-hidden overflow-y-hidden bg-neutral-10 transition duration-150 ease-in-out dark:bg-neutral-2 lg:w-64`}
} z-9999 static left-0 top-0 flex h-screen w-14 flex-col overflow-x-hidden overflow-y-hidden bg-neutral-10 transition duration-150 ease-in-out dark:bg-neutral-2 lg:w-64`}
> >
<div className="flex items-center justify-between gap-2 overflow-hidden px-0 py-5 lg:p-6"> <div className="flex items-center justify-between gap-2 overflow-hidden px-0 py-5 lg:p-6">
<div className="mt-8 hidden w-full text-center font-semibold text-white lg:block"> <div className="mt-8 hidden w-full text-center font-semibold text-white lg:block">
<Image <Image
src="/logo.png" src="/logo.png"
alt="Clan Logo" alt="TUB Logo"
width={75} width={75}
height={75} height={75}
priority priority
@@ -90,6 +123,8 @@ export function Sidebar(props: SidebarProps) {
LinkComponent={Link} LinkComponent={Link}
href={menuEntry.to} href={menuEntry.to}
disabled={menuEntry.disabled} disabled={menuEntry.disabled}
selected={activeMenuItem === menuEntry.to}
onClick={() => handleMenuItemClick(menuEntry.to)}
> >
<ListItemIcon <ListItemIcon
color="inherit" color="inherit"

View File

@@ -0,0 +1,66 @@
import React from "react";
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import { NoDataOverlay } from "@/components/noDataOverlay";
import { StyledTableCell, StyledTableRow } from "./style";
import { CustomTableConfiguration, ICustomTable } from "@/types";
const CustomTable = ({ configuration, data }: ICustomTable) => {
// display empty icon in case there is no data
if (!data || data.length === 0)
return <NoDataOverlay label="No Activity yet" />
const renderTableCell = (value: any, cellKey: string, render?: (param: any) => void | undefined) => {
let renderedValue = value;
// cover use case if the data is an array
if (Array.isArray(value)) renderedValue = value.join(', ')
// cover use case if we want to render a component
if (render) renderedValue = render(value);
return (
<StyledTableCell key={cellKey} align="left">
{renderedValue}
</StyledTableCell>
);
}
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 700 }} aria-label="customized table">
<TableHead>
<TableRow>
{configuration.map((header: CustomTableConfiguration) => (
<StyledTableCell key={header.key}>
{header.label}
</StyledTableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{data.map((data: any, rowIndex: number) => (
<StyledTableRow key={rowIndex}>
{configuration.map((column: CustomTableConfiguration) => {
const cellValue: any = data[column.key];
const cellKey = column.key;
const renderComponent = column?.render;
return renderTableCell(cellValue, cellKey, renderComponent);
})}
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
)
}
export default CustomTable;

View File

@@ -0,0 +1,23 @@
import { styled } from '@mui/material/styles';
import TableCell, { tableCellClasses } from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
export const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
backgroundColor: theme.palette.common.black,
color: theme.palette.common.white,
},
[`&.${tableCellClasses.body}`]: {
fontSize: 14,
},
}));
export const StyledTableRow = styled(TableRow)(({ theme }) => ({
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.action.hover,
},
// hide last border
'&:last-child td, &:last-child th': {
border: 0,
},
}));

View File

@@ -0,0 +1,10 @@
export interface CustomTableConfiguration {
key: string;
label: string;
render?: (param: any) => void;
}
export interface ICustomTable {
configuration: CustomTableConfiguration[],
data: any
}

View File

@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
import colors from "@clan/colors/colors.json"; import colors from "@clan/colors/colors.json";
// import colors from "../theme/src/colors.json";
const { const {
ref: { palette, common }, ref: { palette, common },

View File

@@ -1,7 +1,11 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@@ -21,10 +25,21 @@
} }
], ],
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": [
"@API/*": ["./src/api/*"] "./src/*"
],
"@API/*": [
"./src/api/*"
]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": [
"exclude": ["node_modules"] "next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
} }