feature/syasya/testlayout #7
@ -43,7 +43,7 @@ const Sales = () => {
 | 
			
		||||
            <p className="mt-4 text-green-700">You selected: {selectedSite}</p>
 | 
			
		||||
            <button
 | 
			
		||||
              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
 | 
			
		||||
            </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,
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        // 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++) {
 | 
			
		||||
            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) {
 | 
			
		||||
                monthlyData[monthIndex].consumption += siteData.consumptionData[i];
 | 
			
		||||
                monthlyData[monthIndex].generation += siteData.generationData[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return monthlyData;
 | 
			
		||||
        // ✅ Only return the last 3 months
 | 
			
		||||
        return monthlyData.slice(-6);
 | 
			
		||||
 | 
			
		||||
    }, [siteData]);
 | 
			
		||||
 | 
			
		||||
    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