feature/syasya/testlayout #7
@ -43,7 +43,7 @@ const Sales = () => {
 | 
				
			|||||||
            <p className="mt-4 text-green-700">You selected: {selectedSite}</p>
 | 
					            <p className="mt-4 text-green-700">You selected: {selectedSite}</p>
 | 
				
			||||||
            <button
 | 
					            <button
 | 
				
			||||||
              onClick={handleGoToDashboard}
 | 
					              onClick={handleGoToDashboard}
 | 
				
			||||||
              className="bg-yellow-400 hover:bg-yellow-500 text-white font-semibold py-2 px-4 rounded"
 | 
					              className="btn-primary"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              Go to Dashboard
 | 
					              Go to Dashboard
 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								app/api/sites/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/api/sites/route.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					// app/api/sites/route.ts
 | 
				
			||||||
 | 
					import { NextResponse } from 'next/server';
 | 
				
			||||||
 | 
					import prisma from '@/lib/prisma';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function GET() {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const sites = await prisma.site.findMany({
 | 
				
			||||||
 | 
					      include: {
 | 
				
			||||||
 | 
					        consumptionData: true,
 | 
				
			||||||
 | 
					        generationData: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    console.log('✅ Sites:', sites);
 | 
				
			||||||
 | 
					    return NextResponse.json(sites);
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    console.error('❌ Error fetching sites:', error);
 | 
				
			||||||
 | 
					    return new NextResponse('Failed to fetch sites', { status: 500 });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,16 +40,19 @@ const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteData }) => {
 | 
				
			|||||||
            generation: 0,
 | 
					            generation: 0,
 | 
				
			||||||
        }));
 | 
					        }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Group daily data into months (assume data is in order from Jan 1 to Dec 31)
 | 
				
			||||||
        // Group daily data into months (assume data is in order from Jan 1 to Dec 31)
 | 
					        // Group daily data into months (assume data is in order from Jan 1 to Dec 31)
 | 
				
			||||||
        for (let i = 0; i < siteData.consumptionData.length; i++) {
 | 
					        for (let i = 0; i < siteData.consumptionData.length; i++) {
 | 
				
			||||||
            const monthIndex = Math.floor(i / 30.42); // Rough approximation (or replace with actual dates if available)
 | 
					            const monthIndex = Math.floor(i / 30.42); // Rough approximation
 | 
				
			||||||
            if (monthIndex < 12) {
 | 
					            if (monthIndex < 12) {
 | 
				
			||||||
                monthlyData[monthIndex].consumption += siteData.consumptionData[i];
 | 
					                monthlyData[monthIndex].consumption += siteData.consumptionData[i];
 | 
				
			||||||
                monthlyData[monthIndex].generation += siteData.generationData[i];
 | 
					                monthlyData[monthIndex].generation += siteData.generationData[i];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return monthlyData;
 | 
					        // ✅ Only return the last 3 months
 | 
				
			||||||
 | 
					        return monthlyData.slice(-6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }, [siteData]);
 | 
					    }, [siteData]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!siteData || chartData.length === 0) {
 | 
					    if (!siteData || chartData.length === 0) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								lib/prisma.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								lib/prisma.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					// lib/prisma.ts (create this file to reuse Prisma client instance)
 | 
				
			||||||
 | 
					import { PrismaClient } from '@prisma/client';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const prisma = new PrismaClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default prisma;
 | 
				
			||||||
@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					-- CreateTable
 | 
				
			||||||
 | 
					CREATE TABLE "Site" (
 | 
				
			||||||
 | 
					    "id" SERIAL NOT NULL,
 | 
				
			||||||
 | 
					    "name" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "location" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "inverterProvider" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "emergencyContact" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "lastSyncTimestamp" TIMESTAMP(3) NOT NULL,
 | 
				
			||||||
 | 
					    "theoreticalMaxGeneration_kWh" DOUBLE PRECISION NOT NULL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CONSTRAINT "Site_pkey" PRIMARY KEY ("id")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateTable
 | 
				
			||||||
 | 
					CREATE TABLE "EnergyData" (
 | 
				
			||||||
 | 
					    "id" SERIAL NOT NULL,
 | 
				
			||||||
 | 
					    "type" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "timestamp" TIMESTAMP(3) NOT NULL,
 | 
				
			||||||
 | 
					    "value" DOUBLE PRECISION NOT NULL,
 | 
				
			||||||
 | 
					    "consumptionSiteId" INTEGER,
 | 
				
			||||||
 | 
					    "generationSiteId" INTEGER,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CONSTRAINT "EnergyData_pkey" PRIMARY KEY ("id")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateIndex
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX "Site_name_key" ON "Site"("name");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateIndex
 | 
				
			||||||
 | 
					CREATE INDEX "EnergyData_consumptionSiteId_idx" ON "EnergyData"("consumptionSiteId");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateIndex
 | 
				
			||||||
 | 
					CREATE INDEX "EnergyData_generationSiteId_idx" ON "EnergyData"("generationSiteId");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- AddForeignKey
 | 
				
			||||||
 | 
					ALTER TABLE "EnergyData" ADD CONSTRAINT "EnergyData_consumptionSiteId_fkey" FOREIGN KEY ("consumptionSiteId") REFERENCES "Site"("id") ON DELETE SET NULL ON UPDATE CASCADE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- AddForeignKey
 | 
				
			||||||
 | 
					ALTER TABLE "EnergyData" ADD CONSTRAINT "EnergyData_generationSiteId_fkey" FOREIGN KEY ("generationSiteId") REFERENCES "Site"("id") ON DELETE SET NULL ON UPDATE CASCADE;
 | 
				
			||||||
							
								
								
									
										44
									
								
								prisma/seed.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								prisma/seed.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					const { PrismaClient } = require('@prisma/client');
 | 
				
			||||||
 | 
					const prisma = new PrismaClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function main() {
 | 
				
			||||||
 | 
					  const site = await prisma.site.create({
 | 
				
			||||||
 | 
					    data: {
 | 
				
			||||||
 | 
					      name: 'Solar Rooftop 2',
 | 
				
			||||||
 | 
					      location: 'Malaysia',
 | 
				
			||||||
 | 
					      inverterProvider: 'Huawei',
 | 
				
			||||||
 | 
					      emergencyContact: '012-3456789',
 | 
				
			||||||
 | 
					      lastSyncTimestamp: new Date(),
 | 
				
			||||||
 | 
					      theoreticalMaxGeneration_kWh: 5000,
 | 
				
			||||||
 | 
					      consumptionData: {
 | 
				
			||||||
 | 
					        create: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'consumption',
 | 
				
			||||||
 | 
					            timestamp: new Date('2025-01-01T00:00:00Z'),
 | 
				
			||||||
 | 
					            value: 120.5,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      generationData: {
 | 
				
			||||||
 | 
					        create: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'generation',
 | 
				
			||||||
 | 
					            timestamp: new Date('2025-01-01T00:00:00Z'),
 | 
				
			||||||
 | 
					            value: 200.75,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log('Seeded site:', site.name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main()
 | 
				
			||||||
 | 
					  .then(() => prisma.$disconnect())
 | 
				
			||||||
 | 
					  .catch(async (e) => {
 | 
				
			||||||
 | 
					    console.error(e);
 | 
				
			||||||
 | 
					    await prisma.$disconnect();
 | 
				
			||||||
 | 
					    process.exit(1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user