Adding in new solar visuals wip

This commit is contained in:
Khalim Conn-Kowlessar 2024-07-10 20:12:04 +01:00
parent e933feb764
commit b622ec3250
5 changed files with 1929 additions and 21 deletions

View file

@ -0,0 +1,27 @@
DO $$ BEGIN
CREATE TYPE "scenario_type" AS ENUM('unit', 'building');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "solar_scenario" (
"id" bigserial PRIMARY KEY NOT NULL,
"solar_id" bigint NOT NULL,
"scenario_type" "scenario_type" NOT NULL,
"number_panels" integer NOT NULL,
"array_kwhp" integer NOT NULL,
"lifetime_dc_kwh" real NOT NULL,
"yearly_dc_kwh" real NOT NULL,
"lifetime_ac_kwh" real,
"yearly_ac_kwh" real,
"cost" real NOT NULL,
"expected_payback_years" real,
"panelled_roof_area" real NOT NULL,
"is_default" boolean NOT NULL
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "solar_scenario" ADD CONSTRAINT "solar_scenario_solar_id_solar_id_fk" FOREIGN KEY ("solar_id") REFERENCES "solar"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

File diff suppressed because it is too large Load diff

View file

@ -36,9 +36,9 @@ export const solar = pgTable("solar", {
export const scenarioType: [string, ...string[]] = ["unit", "building"];
export const scenarioTypeEnum = pgEnum("scenario_type", scenarioType);
export const solarSenario = pgTable("solar_scenario", {
export const solarScenario = pgTable("solar_scenario", {
id: bigserial("id", { mode: "bigint" }).primaryKey(),
solar_id: bigint("solar_id", { mode: "bigint" })
solarId: bigint("solar_id", { mode: "bigint" })
.notNull()
.references(() => solar.id),
scenrioType: scenarioTypeEnum("scenario_type").notNull(),
@ -56,7 +56,7 @@ export const solarSenario = pgTable("solar_scenario", {
// Define types for selecting and inserting data
export type Solar = InferModel<typeof solar, "select">;
export type SolarScenario = InferModel<typeof solarSenario, "select">;
export type SolarScenario = InferModel<typeof solarScenario, "select">;
interface Center {
latitude: number;

View file

@ -5,11 +5,17 @@ import {
InformationCircleIcon,
CloudIcon,
SparklesIcon,
BoltIcon,
CurrencyDollarIcon,
ArrowTrendingUpIcon,
CalendarIcon,
HomeIcon,
} from "@heroicons/react/24/outline";
import { getPropertyMeta } from "../utils";
import { getSolarData, getSolarScenarioData } from "./utils";
import FeatureTable from "@/app/components/building-passport/FeatureTable";
import { roofSegmentsColumns } from "./roof-segments-table";
import { formatNumber } from "@/app/utils";
export default async function SolarAnalysisPage({
params,
@ -138,21 +144,69 @@ export default async function SolarAnalysisPage({
<div className="bg-white shadow-md rounded-lg p-6 mb-8 w-full">
<h2 className="text-l font-semibold text-gray-800 mb-4">
Recommended Solar Configuration
Solar PV Simulation
</h2>
{/*
We want to show:
- Number of panels
- Array ouput
- lifetime dc energy
- yearly dc energy
- lifetime ac energy
- yearly ac energy
- cost
- roi
- expected payback years
- pannelled roof area
*/}
<div className="flex">
<div className="flex flex-col space-y-4 w-1/2">
<ul className="list-none pl-5 text-gray-700">
<li className="flex items-center">
<HomeIcon className="w-5 h-5 text-blue-500 mr-2" />
Number of panels: {solarScenarioData.numberPanels}
</li>
<li className="flex items-center">
<BoltIcon className="w-5 h-5 text-yellow-500 mr-2" />
Array output: {solarScenarioData.arrayKwhp} kWp
</li>
<li className="flex items-center">
<SunIcon className="w-5 h-5 text-orange-500 mr-2" />
Lifetime DC energy:{" "}
{Math.round(solarScenarioData.lifetimeDcKwh)} kWh
</li>
<li className="flex items-center">
<SunIcon className="w-5 h-5 text-orange-500 mr-2" />
Yearly DC energy: {Math.round(
solarScenarioData.yearlyDcKwh
)}{" "}
kWh
</li>
{solarScenarioData.lifetimeAcKwh !== null && (
<li className="flex items-center">
<SunIcon className="w-5 h-5 text-orange-500 mr-2" />
Lifetime AC energy:{" "}
{Math.round(solarScenarioData.lifetimeAcKwh)} kWh
</li>
)}
{solarScenarioData.yearlyAcKwh !== null && (
<li className="flex items-center">
<SunIcon className="w-5 h-5 text-orange-500 mr-2" />
Yearly AC energy:{" "}
{Math.round(solarScenarioData.yearlyAcKwh)} kWh
</li>
)}
<li className="flex items-center">
<CurrencyDollarIcon className="w-5 h-5 text-green-500 mr-2" />
Cost: £{formatNumber(solarScenarioData.cost)}
</li>
<li className="flex items-center">
<ArrowTrendingUpIcon className="w-5 h-5 text-purple-500 mr-2" />
Expected payback years:{" "}
{solarScenarioData.expectedPaybackYears}
</li>
<li className="flex items-center">
<HomeIcon className="w-5 h-5 text-blue-500 mr-2" />
Panelled roof area:{" "}
{solarScenarioData.panelledRoofArea.toFixed(1)} m²
</li>
</ul>
</div>
<div className="w-1/2 flex items-center justify-center">
<img
src="/static/solar_image.png"
alt="Solar Image"
className="w-3/4 h-auto"
/>
</div>
</div>
</div>
</div>
</div>

View file

@ -3,9 +3,9 @@ import {
SolarInterface,
solar,
SolarScenario,
solarSenario,
solarScenario,
} from "@/app/db/schema/solar";
import { eq } from "drizzle-orm";
import { eq, and } from "drizzle-orm";
export async function getSolarData(uprn: number): Promise<SolarInterface> {
const data = await db.query.solar.findFirst({
@ -22,8 +22,12 @@ export async function getSolarData(uprn: number): Promise<SolarInterface> {
export async function getSolarScenarioData(
solarId: string
): Promise<SolarScenario> {
const data = await db.query.solarSenario.findFirst({
where: eq(solarSenario.solar_id, BigInt(solarId)),
const data = await db.query.solarScenario.findFirst({
where: (solarScenario, { eq, and }) =>
and(
eq(solarScenario.solarId, BigInt(solarId)),
eq(solarScenario.isDefault, true)
),
});
if (!data) {