Added the documents table to the app - needs api setup to generate pre-signed urls

This commit is contained in:
Khalim Conn-Kowlessar 2024-09-09 12:15:55 +01:00
parent b550c47e1a
commit 8147a0d4b7
5 changed files with 191 additions and 8 deletions

View file

@ -18,3 +18,22 @@ export function TanButton({
</button>
);
}
export function BrandBlueButton({
label,
onClick,
}: {
label: string;
onClick: Dispatch<SetStateAction<any>>;
}) {
// General tan colored button
return (
<button
type="button"
className="inline-flex justify-center rounded-md border border-transparent bg-brandblue px-4 py-2 text-sm font-medium text-white hover:bg-hoverblue focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={onClick}
>
{label}
</button>
);
}

View file

@ -195,3 +195,11 @@ export const energyAssessmentDocuments = pgTable(
// Types for the new table
export type EnergyAssessment = InferModel<typeof energyAssessment, "select">;
export type EnergyAssessmentScenario = InferModel<
typeof energyAssessmentScenarios,
"select"
>;
export type EnergyAssessmentDocument = InferModel<
typeof energyAssessmentDocuments,
"select"
>;

View file

@ -0,0 +1,85 @@
"use client";
import React from "react";
import {
Table,
TableBody,
TableCell,
TableRow,
} from "@/app/shadcn_components/ui/table";
import { BrandBlueButton } from "@/app/components/Buttons";
import { DocumentType } from "@/app/db/schema/energy_assessments";
// Use the type directly from the array
type Document = {
id: bigint;
documentType: (typeof DocumentType)[number]; // Create a union type from the array
documentLocation: string;
uploadedAt: Date;
};
type Props = {
documents: Document[];
allowedTypes: (typeof DocumentType)[number][]; // Use the union type for allowedTypes as well
};
// Descriptions based on the document types
const descriptions: { [key in (typeof DocumentType)[number]]: string } = {
EPR: "Contains current energy performance of your home, and recommendations for improvement",
"Condition Report":
"Detailed report on property condition, including photographs",
"Evidence Report": "Additional photographic evidence from the survey",
"Summary Information": "Summarized survey outputs and site notes",
"Floor Plan": "Layout of the property and room/window dimensions",
"Scenario Draft EPC": "Draft EPC based on a given scenario",
"Scenario Site Notes": "Site notes from the scenario analysis",
};
export const DocumentsTable: React.FC<Props> = ({
documents,
allowedTypes,
}) => {
const relevantDocuments = documents.filter((doc) =>
allowedTypes.includes(doc.documentType)
);
// Track displayed descriptions
const displayedDescriptions: Record<(typeof DocumentType)[number], boolean> =
allowedTypes.reduce((acc, type) => {
acc[type] = false;
return acc;
}, {} as Record<(typeof DocumentType)[number], boolean>);
const processedDocuments = relevantDocuments.map((doc) => {
const showDescription = !displayedDescriptions[doc.documentType];
if (showDescription) {
displayedDescriptions[doc.documentType] = true;
}
return { ...doc, showDescription };
});
return (
<Table className="min-w-full divide-y divide-gray-200 shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<TableBody className="bg-white divide-y divide-gray-200">
{processedDocuments.map((doc) => (
<TableRow key={doc.id.toString()}>
<TableCell className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{doc.documentType}
</TableCell>
<TableCell className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{doc.showDescription ? descriptions[doc.documentType] : ""}
</TableCell>
<TableCell className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<BrandBlueButton
label="Download"
onClick={() =>
console.log(`Downloading ${doc.documentLocation}`)
}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
};

View file

@ -1,17 +1,51 @@
import {
getEnergyAssessment,
getEnergyAssessmentDocuments,
getPropertyMeta,
} from "../utils";
// EnergyAssessmentsPage.tsx
import { DocumentsTable } from "./DocumentsTable";
export default async function EnergyAssessmentsPage({
params,
}: {
params: { slug: string; propertyId: string };
}) {
// If there's no solar data, we cannot display the page
const propertyMeta = await getPropertyMeta(params.propertyId);
const ea = await getEnergyAssessment(propertyMeta.uprn);
if (!ea) {
return (
<div className="flex items-center justify-center min-h-screen">
<div className="text-center text-gray-500">
<div className="text-2xl font-semibold mb-4">
This property does not have a Domna energy assessment
</div>
<p className="text-lg">Please check back later for updates.</p>
</div>
</div>
);
}
const documents = await getEnergyAssessmentDocuments(ea.id);
const table1AllowedTypes = [
"EPR",
"Condition Report",
"Evidence Report",
"Summary Information",
"Floor Plan",
];
return (
<div className="flex items-center justify-center min-h-screen">
<div className="text-center text-gray-500">
<div className="text-2xl font-semibold mb-4">
This property does not have a Domna energy assessement
</div>
<p className="text-lg">Please check back later for updates.</p>
<div>
<div className="flex pt-8 text-lg">Core Survey Documents</div>
<div className="py-4 max-w-8xl">
<DocumentsTable
documents={documents}
allowedTypes={table1AllowedTypes}
/>
</div>
</div>
);

View file

@ -1,4 +1,3 @@
import { recommendation } from "../../../../db/schema/recommendations";
import {
Recommendation,
planRecommendations,
@ -18,11 +17,49 @@ import {
import { plan, Plan } from "@/app/db/schema/recommendations";
import { getRating } from "@/app/utils";
import { eq, desc } from "drizzle-orm";
import {
energyAssessment,
EnergyAssessment,
energyAssessmentDocuments,
EnergyAssessmentDocument,
} from "@/app/db/schema/energy_assessments";
type RecommendationList = {
recommendation: Recommendation;
}[];
export async function getEnergyAssessment(
uprn: number
): Promise<EnergyAssessment> {
const data = await db.query.energyAssessment.findFirst({
where: eq(energyAssessment.uprn, BigInt(uprn)),
});
if (!data) {
// If there's no data, we return an empty array. This signififies that no energy assessment has been conducted
return {} as EnergyAssessment;
}
return data;
}
export async function getEnergyAssessmentDocuments(
energyAssessmentId: bigint
): Promise<EnergyAssessmentDocument[]> {
const data = await db.query.energyAssessmentDocuments.findMany({
where: eq(
energyAssessmentDocuments.energyAssessmentId,
BigInt(energyAssessmentId)
),
});
if (!data) {
throw new Error("Network response was not ok");
}
return data;
}
export async function getRecommendations(
planId: string
): Promise<Recommendation[]> {