Fixing typescript errors

This commit is contained in:
Khalim Conn-Kowlessar 2024-04-15 19:54:41 +01:00
parent 661cb80414
commit 4346660a35
4 changed files with 325 additions and 0 deletions

View file

@ -0,0 +1,41 @@
import { BarChart } from "@tremor/react";
const dataFormatter = (number: number) =>
Intl.NumberFormat("us").format(number).toString();
const EpcBarChart = ({
chartdata,
}: {
chartdata: {
name: string;
A?: number;
B?: number;
C?: number;
D?: number;
E?: number;
F?: number;
G?: number;
}[];
}) => (
<BarChart
className="w-64 h-40"
data={chartdata}
index="name"
categories={["G", "F", "E", "D", "C", "B", "A"]} // Each treated as a separate series
colors={[
"#e41e3b", // Color for 'G'
"#ef8026", // Color for 'F'
"#f3a96a", // Color for 'E'
"#f7cd14", // Color for 'D'
"#8dbd40", // Color for 'C'
"#2da55c", // Color for 'B'
"#117d58", // Color for 'A'
]}
valueFormatter={dataFormatter}
yAxisWidth={48}
stack={true}
showLegend={false}
/>
);
export default EpcBarChart;

View file

@ -0,0 +1,99 @@
import { Dialog, Transition } from "@headlessui/react";
import { Fragment, useState } from "react";
const SelectComparisonModal = ({
isOpen,
setIsOpen,
userPortfolios,
onAddColumn,
}: {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
userPortfolios: { name: string; id: bigint }[];
onAddColumn: (columnName: string) => void;
}) => {
const [selectedPortfolio, setSelectedPortfolio] = useState("");
const addColumn = () => {
onAddColumn(selectedPortfolio);
setIsOpen(false);
};
return (
<Transition show={isOpen} as={Fragment}>
<Dialog
as="div"
className="fixed inset-0 z-10 overflow-y-auto"
onClose={setIsOpen}
>
<div className="min-h-screen px-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-black opacity-30" />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<span
className="inline-block h-screen align-middle"
aria-hidden="true"
>
&#8203;
</span>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<div className="inline-block w-full max-w-md p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-white shadow-xl rounded-2xl">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900"
>
Add Comparison
</Dialog.Title>
<div className="mt-2">
<select
className="w-full p-2 border border-gray-300 rounded-md"
value={selectedPortfolio}
onChange={(e) => setSelectedPortfolio(e.target.value)}
>
{userPortfolios.map((portfolio) => (
<option
key={portfolio.id.toString()}
value={portfolio.name}
>
{portfolio.name}
</option>
))}
</select>
</div>
<div className="mt-4">
<button
type="button"
className="inline-flex justify-center px-4 py-2 text-sm font-medium text-blue-900 bg-blue-100 border border-transparent rounded-md hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500"
onClick={addColumn}
>
Add
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
);
};
export default SelectComparisonModal;

View file

@ -0,0 +1,146 @@
"use client";
import React, { useState } from "react";
import {
useReactTable,
flexRender,
getCoreRowModel,
ColumnDef,
CellContext,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/app/shadcn_components/ui/table";
import SelectComparisonModal from "./SelectComparisonModal";
import EpcBarChart from "./EpcBarChart";
interface DataItem {
title: string;
today: string;
summary: string;
}
const SummaryTable = ({
portfolioName,
data,
userPortfolios,
}: {
portfolioName: string;
data: DataItem[];
userPortfolios: { name: string; id: bigint }[];
}) => {
const initialchartdata = [
{ name: "G", G: 2488 },
{ name: "F", F: 1445 },
{ name: "E", E: 743 },
{ name: "D", D: 281 },
{ name: "C", C: 251 },
{ name: "B", B: 232 },
{ name: "A", A: 98 },
];
// Initial columns
// Initial columns
const [columns, setColumns] = useState<ColumnDef<DataItem>[]>([
{
accessorKey: "title",
header: () => null,
cell: (info) => <b>{info.getValue() as string}</b>,
},
{
accessorKey: "today",
header: () => <span>Today</span>,
cell: (info) => {
// Check if the title is "EPCs" and render the bar chart
if (info.row.original.title === "EPCs") {
return <EpcBarChart chartdata={initialchartdata} />;
}
// Otherwise, just return the text
return <span>{info.getValue() as string}</span>;
},
},
{
accessorKey: "summary",
header: () => <span>{portfolioName}</span>,
cell: (info) => {
return <span>{info.getValue() as string}</span>;
},
},
]);
const [isModalOpen, setIsModalOpen] = useState(false);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
const addColumn = (columnName: string) => {
const newColumn: ColumnDef<DataItem> = {
accessorKey: columnName.toLowerCase().replace(/\s+/g, "_"),
header: () => <span>{columnName}</span>,
cell: ({ getValue }: CellContext<DataItem, unknown>) => {
const value = getValue();
return (
<span>{typeof value === "string" ? value : "Invalid data"}</span>
);
},
};
setColumns((oldColumns) => [...oldColumns, newColumn]);
};
return (
<div className="my-8">
<button
onClick={() => setIsModalOpen(true)}
className="mb-4 p-2 bg-brandgold text-white rounded"
>
Add Comparison
</button>
<SelectComparisonModal
isOpen={isModalOpen}
setIsOpen={setIsModalOpen}
userPortfolios={userPortfolios}
onAddColumn={addColumn}
/>
<div className="overflow-x-auto shadow-md sm:rounded-lg">
<Table className="min-w-full">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id} className="px-6 py-3">
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="px-6 py-4">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
};
export default SummaryTable;

View file

@ -0,0 +1,39 @@
import SummaryTable from "@/app/components/portfolio/summary/SummaryTable";
import { getPortfolio, getUserPortfolios } from "../../utils";
import { getSession } from "next-auth/react";
export default async function PortfolioSummary({
params,
}: {
params: { slug: string };
}) {
const portfolioId = params.slug;
const { name: portfolioName } = await getPortfolio(portfolioId);
// Retrieve all of the names and ids of the portfolios, attributed to this user
// Get user id from the session
const userPortfolios = await getUserPortfolios(portfolioId);
// Dummy data for rows
const data = [
{
title: "EPCs",
today: "Initial Bar Chart Here",
summary: "Comparison Bar Chart",
},
{ title: "Total Co2", today: "100t", summary: "50t" },
{ title: "Energy bills", today: "£20,000", summary: "£10,000" },
{ title: "Cost", today: "", summary: "£32,412" },
{ title: "Cost per CO2 reduction", today: "", summary: "£50" },
];
return (
<div className="container mx-auto px-4">
<h1 className="text-3xl text-gray-700 font-bold my-4">Overview</h1>
<SummaryTable
portfolioName={portfolioName}
data={data}
userPortfolios={userPortfolios}
/>
</div>
);
}