From 9ece6ff1270eb456562b45df6e364873c48aca90 Mon Sep 17 00:00:00 2001 From: Esteban Date: Sat, 20 Dec 2025 12:21:11 -0600 Subject: [PATCH] Meters fix to show data in table component --- src/api/meters.ts | 235 ++++++++++++--------- src/pages/meters/MeterPage.tsx | 367 +++++++++++++++++---------------- vite.config.ts | 18 +- 3 files changed, 340 insertions(+), 280 deletions(-) diff --git a/src/api/meters.ts b/src/api/meters.ts index 90fc743..29b3468 100644 --- a/src/api/meters.ts +++ b/src/api/meters.ts @@ -10,20 +10,25 @@ const getAuthHeaders = () => ({ export interface MeterRecord { id: string; fields: { - device_id: string; - meter_address: string; - manufacturer_code: string; - forward_cumulative_flow: number; - reverse_cumulative_flow: number; - forward_instantaneous_flow: number; - water_temperature: number; - voltage: number; - echo_amplitude: number; - ultrasonic_flight_time: number; - timestamp: string; - alarm_bytes: string; - checksum_ok: boolean; - received_at: string; + CreatedAt: string; + UpdatedAt: string; + "Area Name": string; + "Account Number": string | null; + "User Name": string | null; + "User Address": string | null; + "Meter S/N": string; + "Meter Name": string; + "Meter Status": string; + "Protocol Type": string; + "Price No.": string | null; + "Price Name": string | null; + "DMA Partition": string | null; + "Supply Types": string; + "Device ID": string; + "Device Name": string; + "Device Type": string; + "Usage Analysis Type": string; + "Installed Time": string; }; } @@ -37,20 +42,25 @@ export interface MetersResponse { export interface Meter { id: string; + createdAt: string; + updatedAt: string; + areaName: string; + accountNumber: string | null; + userName: string | null; + userAddress: string | null; + meterSerialNumber: string; + meterName: string; + meterStatus: string; + protocolType: string; + priceNo: string | null; + priceName: string | null; + dmaPartition: string | null; + supplyTypes: string; deviceId: string; - meterAddress: string; - manufacturerCode: string; - forwardCumulativeFlow: number; - reverseCumulativeFlow: number; - forwardInstantaneousFlow: number; - waterTemperature: number; - voltage: number; - echoAmplitude: number; - ultrasonicFlightTime: number; - timestamp: string; - alarmBytes: string; - checksumOk: boolean; - receivedAt: string; + deviceName: string; + deviceType: string; + usageAnalysisType: string; + installedTime: string; } export const fetchMeters = async (): Promise => { @@ -65,24 +75,31 @@ export const fetchMeters = async (): Promise => { } const data: MetersResponse = await response.json(); - - return data.records.map((r: MeterRecord) => ({ + const ans = data.records.map((r: MeterRecord) => ({ id: r.id, - deviceId: r.fields.device_id || "", - meterAddress: r.fields.meter_address || "", - manufacturerCode: r.fields.manufacturer_code || "", - forwardCumulativeFlow: r.fields.forward_cumulative_flow || 0, - reverseCumulativeFlow: r.fields.reverse_cumulative_flow || 0, - forwardInstantaneousFlow: r.fields.forward_instantaneous_flow || 0, - waterTemperature: r.fields.water_temperature || 0, - voltage: r.fields.voltage || 0, - echoAmplitude: r.fields.echo_amplitude || 0, - ultrasonicFlightTime: r.fields.ultrasonic_flight_time || 0, - timestamp: r.fields.timestamp || "", - alarmBytes: r.fields.alarm_bytes || "", - checksumOk: r.fields.checksum_ok || false, - receivedAt: r.fields.received_at || "", + createdAt: r.fields.CreatedAt || "", + updatedAt: r.fields.UpdatedAt || "", + areaName: r.fields["Area Name"] || "", + accountNumber: r.fields["Account Number"] || null, + userName: r.fields["User Name"] || null, + userAddress: r.fields["User Address"] || null, + meterSerialNumber: r.fields["Meter S/N"] || "", + meterName: r.fields["Meter Name"] || "", + meterStatus: r.fields["Meter Status"] || "", + protocolType: r.fields["Protocol Type"] || "", + priceNo: r.fields["Price No."] || null, + priceName: r.fields["Price Name"] || null, + dmaPartition: r.fields["DMA Partition"] || null, + supplyTypes: r.fields["Supply Types"] || "", + deviceId: r.fields["Device ID"] || "", + deviceName: r.fields["Device Name"] || "", + deviceType: r.fields["Device Type"] || "", + usageAnalysisType: r.fields["Usage Analysis Type"] || "", + installedTime: r.fields["Installed Time"] || "", })); + console.log ("ans", ans); + + return ans; } catch (error) { console.error("Error fetching meters:", error); throw error; @@ -98,20 +115,25 @@ export const createMeter = async ( headers: getAuthHeaders(), body: JSON.stringify({ fields: { - device_id: meterData.deviceId, - meter_address: meterData.meterAddress, - manufacturer_code: meterData.manufacturerCode, - forward_cumulative_flow: meterData.forwardCumulativeFlow, - reverse_cumulative_flow: meterData.reverseCumulativeFlow, - forward_instantaneous_flow: meterData.forwardInstantaneousFlow, - water_temperature: meterData.waterTemperature, - voltage: meterData.voltage, - echo_amplitude: meterData.echoAmplitude, - ultrasonic_flight_time: meterData.ultrasonicFlightTime, - timestamp: meterData.timestamp, - alarm_bytes: meterData.alarmBytes, - checksum_ok: meterData.checksumOk, - received_at: meterData.receivedAt, + CreatedAt: meterData.createdAt, + UpdatedAt: meterData.updatedAt, + "Area Name": meterData.areaName, + "Account Number": meterData.accountNumber, + "User Name": meterData.userName, + "User Address": meterData.userAddress, + "Meter S/N": meterData.meterSerialNumber, + "Meter Name": meterData.meterName, + "Meter Status": meterData.meterStatus, + "Protocol Type": meterData.protocolType, + "Price No.": meterData.priceNo, + "Price Name": meterData.priceName, + "DMA Partition": meterData.dmaPartition, + "Supply Types": meterData.supplyTypes, + "Device ID": meterData.deviceId, + "Device Name": meterData.deviceName, + "Device Type": meterData.deviceType, + "Usage Analysis Type": meterData.usageAnalysisType, + "Installed Time": meterData.installedTime, }, }), }); @@ -129,20 +151,25 @@ export const createMeter = async ( return { id: createdRecord.id, - deviceId: createdRecord.fields.device_id || meterData.deviceId, - meterAddress: createdRecord.fields.meter_address || meterData.meterAddress, - manufacturerCode: createdRecord.fields.manufacturer_code || meterData.manufacturerCode, - forwardCumulativeFlow: createdRecord.fields.forward_cumulative_flow || meterData.forwardCumulativeFlow, - reverseCumulativeFlow: createdRecord.fields.reverse_cumulative_flow || meterData.reverseCumulativeFlow, - forwardInstantaneousFlow: createdRecord.fields.forward_instantaneous_flow || meterData.forwardInstantaneousFlow, - waterTemperature: createdRecord.fields.water_temperature || meterData.waterTemperature, - voltage: createdRecord.fields.voltage || meterData.voltage, - echoAmplitude: createdRecord.fields.echo_amplitude || meterData.echoAmplitude, - ultrasonicFlightTime: createdRecord.fields.ultrasonic_flight_time || meterData.ultrasonicFlightTime, - timestamp: createdRecord.fields.timestamp || meterData.timestamp, - alarmBytes: createdRecord.fields.alarm_bytes || meterData.alarmBytes, - checksumOk: createdRecord.fields.checksum_ok || meterData.checksumOk, - receivedAt: createdRecord.fields.received_at || meterData.receivedAt, + createdAt: createdRecord.fields.CreatedAt || meterData.createdAt, + updatedAt: createdRecord.fields.UpdatedAt || meterData.updatedAt, + areaName: createdRecord.fields["Area Name"] || meterData.areaName, + accountNumber: createdRecord.fields["Account Number"] || meterData.accountNumber, + userName: createdRecord.fields["User Name"] || meterData.userName, + userAddress: createdRecord.fields["User Address"] || meterData.userAddress, + meterSerialNumber: createdRecord.fields["Meter S/N"] || meterData.meterSerialNumber, + meterName: createdRecord.fields["Meter Name"] || meterData.meterName, + meterStatus: createdRecord.fields["Meter Status"] || meterData.meterStatus, + protocolType: createdRecord.fields["Protocol Type"] || meterData.protocolType, + priceNo: createdRecord.fields["Price No."] || meterData.priceNo, + priceName: createdRecord.fields["Price Name"] || meterData.priceName, + dmaPartition: createdRecord.fields["DMA Partition"] || meterData.dmaPartition, + supplyTypes: createdRecord.fields["Supply Types"] || meterData.supplyTypes, + deviceId: createdRecord.fields["Device ID"] || meterData.deviceId, + deviceName: createdRecord.fields["Device Name"] || meterData.deviceName, + deviceType: createdRecord.fields["Device Type"] || meterData.deviceType, + usageAnalysisType: createdRecord.fields["Usage Analysis Type"] || meterData.usageAnalysisType, + installedTime: createdRecord.fields["Installed Time"] || meterData.installedTime, }; } catch (error) { console.error("Error creating meter:", error); @@ -161,20 +188,25 @@ export const updateMeter = async ( body: JSON.stringify({ id: id, fields: { - device_id: meterData.deviceId, - meter_address: meterData.meterAddress, - manufacturer_code: meterData.manufacturerCode, - forward_cumulative_flow: meterData.forwardCumulativeFlow, - reverse_cumulative_flow: meterData.reverseCumulativeFlow, - forward_instantaneous_flow: meterData.forwardInstantaneousFlow, - water_temperature: meterData.waterTemperature, - voltage: meterData.voltage, - echo_amplitude: meterData.echoAmplitude, - ultrasonic_flight_time: meterData.ultrasonicFlightTime, - timestamp: meterData.timestamp, - alarm_bytes: meterData.alarmBytes, - checksum_ok: meterData.checksumOk, - received_at: meterData.receivedAt, + CreatedAt: meterData.createdAt, + UpdatedAt: meterData.updatedAt, + "Area Name": meterData.areaName, + "Account Number": meterData.accountNumber, + "User Name": meterData.userName, + "User Address": meterData.userAddress, + "Meter S/N": meterData.meterSerialNumber, + "Meter Name": meterData.meterName, + "Meter Status": meterData.meterStatus, + "Protocol Type": meterData.protocolType, + "Price No.": meterData.priceNo, + "Price Name": meterData.priceName, + "DMA Partition": meterData.dmaPartition, + "Supply Types": meterData.supplyTypes, + "Device ID": meterData.deviceId, + "Device Name": meterData.deviceName, + "Device Type": meterData.deviceType, + "Usage Analysis Type": meterData.usageAnalysisType, + "Installed Time": meterData.installedTime, }, }), }); @@ -196,20 +228,25 @@ export const updateMeter = async ( return { id: updatedRecord.id, - deviceId: updatedRecord.fields.device_id || meterData.deviceId, - meterAddress: updatedRecord.fields.meter_address || meterData.meterAddress, - manufacturerCode: updatedRecord.fields.manufacturer_code || meterData.manufacturerCode, - forwardCumulativeFlow: updatedRecord.fields.forward_cumulative_flow || meterData.forwardCumulativeFlow, - reverseCumulativeFlow: updatedRecord.fields.reverse_cumulative_flow || meterData.reverseCumulativeFlow, - forwardInstantaneousFlow: updatedRecord.fields.forward_instantaneous_flow || meterData.forwardInstantaneousFlow, - waterTemperature: updatedRecord.fields.water_temperature || meterData.waterTemperature, - voltage: updatedRecord.fields.voltage || meterData.voltage, - echoAmplitude: updatedRecord.fields.echo_amplitude || meterData.echoAmplitude, - ultrasonicFlightTime: updatedRecord.fields.ultrasonic_flight_time || meterData.ultrasonicFlightTime, - timestamp: updatedRecord.fields.timestamp || meterData.timestamp, - alarmBytes: updatedRecord.fields.alarm_bytes || meterData.alarmBytes, - checksumOk: updatedRecord.fields.checksum_ok || meterData.checksumOk, - receivedAt: updatedRecord.fields.received_at || meterData.receivedAt, + createdAt: updatedRecord.fields.CreatedAt || meterData.createdAt, + updatedAt: updatedRecord.fields.UpdatedAt || meterData.updatedAt, + areaName: updatedRecord.fields["Area Name"] || meterData.areaName, + accountNumber: updatedRecord.fields["Account Number"] || meterData.accountNumber, + userName: updatedRecord.fields["User Name"] || meterData.userName, + userAddress: updatedRecord.fields["User Address"] || meterData.userAddress, + meterSerialNumber: updatedRecord.fields["Meter S/N"] || meterData.meterSerialNumber, + meterName: updatedRecord.fields["Meter Name"] || meterData.meterName, + meterStatus: updatedRecord.fields["Meter Status"] || meterData.meterStatus, + protocolType: updatedRecord.fields["Protocol Type"] || meterData.protocolType, + priceNo: updatedRecord.fields["Price No."] || meterData.priceNo, + priceName: updatedRecord.fields["Price Name"] || meterData.priceName, + dmaPartition: updatedRecord.fields["DMA Partition"] || meterData.dmaPartition, + supplyTypes: updatedRecord.fields["Supply Types"] || meterData.supplyTypes, + deviceId: updatedRecord.fields["Device ID"] || meterData.deviceId, + deviceName: updatedRecord.fields["Device Name"] || meterData.deviceName, + deviceType: updatedRecord.fields["Device Type"] || meterData.deviceType, + usageAnalysisType: updatedRecord.fields["Usage Analysis Type"] || meterData.usageAnalysisType, + installedTime: updatedRecord.fields["Installed Time"] || meterData.installedTime, }; } catch (error) { console.error("Error updating meter:", error); diff --git a/src/pages/meters/MeterPage.tsx b/src/pages/meters/MeterPage.tsx index 7b041a9..afe57a3 100644 --- a/src/pages/meters/MeterPage.tsx +++ b/src/pages/meters/MeterPage.tsx @@ -73,20 +73,25 @@ export default function MeterManagement() { const [editingId, setEditingId] = useState(null); const emptyMeter: Omit = { + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + areaName: "", + accountNumber: null, + userName: null, + userAddress: null, + meterSerialNumber: "", + meterName: "", + meterStatus: "Installed", + protocolType: "", + priceNo: null, + priceName: null, + dmaPartition: null, + supplyTypes: "", deviceId: "", - meterAddress: "", - manufacturerCode: "", - forwardCumulativeFlow: 0, - reverseCumulativeFlow: 0, - forwardInstantaneousFlow: 0, - waterTemperature: 0, - voltage: 0, - echoAmplitude: 0, - ultrasonicFlightTime: 0, - timestamp: new Date().toISOString(), - alarmBytes: "", - checksumOk: true, - receivedAt: new Date().toISOString(), + deviceName: "", + deviceType: "", + usageAnalysisType: "", + installedTime: new Date().toISOString(), }; const [form, setForm] = useState>(emptyMeter); @@ -144,7 +149,7 @@ export default function MeterManagement() { if (!activeMeter) return; const confirmDelete = window.confirm( - `Are you sure you want to delete the meter "${activeMeter.deviceId}"?` + `Are you sure you want to delete the meter "${activeMeter.meterName}" (${activeMeter.meterSerialNumber})?` ); if (!confirmDelete) return; @@ -171,9 +176,10 @@ export default function MeterManagement() { /* ================= FILTER ================= */ const filtered = meters.filter( (m) => - (m.deviceId.toLowerCase().includes(search.toLowerCase()) || - m.meterAddress.toLowerCase().includes(search.toLowerCase()) || - m.manufacturerCode.toLowerCase().includes(search.toLowerCase())) + (m.meterName.toLowerCase().includes(search.toLowerCase()) || + m.meterSerialNumber.toLowerCase().includes(search.toLowerCase()) || + m.deviceId.toLowerCase().includes(search.toLowerCase()) || + m.areaName.toLowerCase().includes(search.toLowerCase())) ); /* ================= UI ================= */ @@ -244,20 +250,25 @@ export default function MeterManagement() { if (!activeMeter) return; setEditingId(activeMeter.id); setForm({ + createdAt: activeMeter.createdAt, + updatedAt: activeMeter.updatedAt, + areaName: activeMeter.areaName, + accountNumber: activeMeter.accountNumber, + userName: activeMeter.userName, + userAddress: activeMeter.userAddress, + meterSerialNumber: activeMeter.meterSerialNumber, + meterName: activeMeter.meterName, + meterStatus: activeMeter.meterStatus, + protocolType: activeMeter.protocolType, + priceNo: activeMeter.priceNo, + priceName: activeMeter.priceName, + dmaPartition: activeMeter.dmaPartition, + supplyTypes: activeMeter.supplyTypes, deviceId: activeMeter.deviceId, - meterAddress: activeMeter.meterAddress, - manufacturerCode: activeMeter.manufacturerCode, - forwardCumulativeFlow: activeMeter.forwardCumulativeFlow, - reverseCumulativeFlow: activeMeter.reverseCumulativeFlow, - forwardInstantaneousFlow: activeMeter.forwardInstantaneousFlow, - waterTemperature: activeMeter.waterTemperature, - voltage: activeMeter.voltage, - echoAmplitude: activeMeter.echoAmplitude, - ultrasonicFlightTime: activeMeter.ultrasonicFlightTime, - timestamp: activeMeter.timestamp, - alarmBytes: activeMeter.alarmBytes, - checksumOk: activeMeter.checksumOk, - receivedAt: activeMeter.receivedAt, + deviceName: activeMeter.deviceName, + deviceType: activeMeter.deviceType, + usageAnalysisType: activeMeter.usageAnalysisType, + installedTime: activeMeter.installedTime, }); setShowModal(true); }} @@ -287,7 +298,7 @@ export default function MeterManagement() { {/* SEARCH */} setSearch(e.target.value)} /> @@ -297,41 +308,30 @@ export default function MeterManagement() { title="Meters" isLoading={loadingMeters} columns={[ + { title: "Meter Name", field: "meterName" }, + { title: "Serial Number", field: "meterSerialNumber" }, + { title: "Area", field: "areaName" }, { title: "Device ID", field: "deviceId" }, - { title: "Meter Address", field: "meterAddress" }, - { title: "Manufacturer Code", field: "manufacturerCode" }, + { title: "Device Name", field: "deviceName" }, { - title: "Forward Flow", - field: "forwardCumulativeFlow", - render: (rowData) => `${rowData.forwardCumulativeFlow?.toFixed(3) || 0} m³` - }, - { - title: "Water Temp", - field: "waterTemperature", - render: (rowData) => `${rowData.waterTemperature?.toFixed(1) || 0}°C` - }, - { - title: "Voltage", - field: "voltage", - render: (rowData) => `${rowData.voltage || 0}V` - }, - { - title: "Checksum OK", - field: "checksumOk", + title: "Status", + field: "meterStatus", render: (rowData) => ( - {rowData.checksumOk ? "OK" : "ERROR"} + {rowData.meterStatus} ), }, - { title: "Timestamp", field: "timestamp", type: "datetime" }, - { title: "Received At", field: "receivedAt", type: "datetime" }, + { title: "Protocol", field: "protocolType" }, + { title: "Device Type", field: "deviceType" }, + { title: "Created At", field: "createdAt", type: "datetime" }, + { title: "Updated At", field: "updatedAt", type: "datetime" }, ]} data={filtered} onRowClick={(_, rowData) => setActiveMeter(rowData as Meter)} @@ -365,6 +365,36 @@ export default function MeterManagement() { {editingId ? "Edit Meter" : "Add Meter"} +
+ + setForm({ ...form, meterName: e.target.value })} + /> +
+ +
+ + setForm({ ...form, meterSerialNumber: e.target.value })} + /> +
+ +
+ + setForm({ ...form, areaName: e.target.value })} + /> +
+
- + setForm({ ...form, meterAddress: e.target.value })} + placeholder="Device Name" + value={form.deviceName} + onChange={(e) => setForm({ ...form, deviceName: e.target.value })} />
- + setForm({ ...form, manufacturerCode: e.target.value })} + placeholder="Device Type" + value={form.deviceType} + onChange={(e) => setForm({ ...form, deviceType: e.target.value })} />
- - Meter Status + setForm({ ...form, reverseCumulativeFlow: parseFloat(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, forwardInstantaneousFlow: parseFloat(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, waterTemperature: parseFloat(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, voltage: parseFloat(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, echoAmplitude: parseInt(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, ultrasonicFlightTime: parseInt(e.target.value) || 0 })} - /> -
- -
- - setForm({ ...form, timestamp: new Date(e.target.value).toISOString() })} - /> -
- -
- - setForm({ ...form, alarmBytes: e.target.value })} - /> -
- -
- - + + + +
- + + setForm({ ...form, protocolType: e.target.value })} + /> +
+ +
+ + setForm({ ...form, supplyTypes: e.target.value })} + /> +
+ +
+ + setForm({ ...form, usageAnalysisType: e.target.value })} + /> +
+ +
+ + setForm({ ...form, accountNumber: e.target.value || null })} + /> +
+ +
+ + setForm({ ...form, userName: e.target.value || null })} + /> +
+ +
+ + setForm({ ...form, userAddress: e.target.value || null })} + /> +
+ +
+ + setForm({ ...form, priceNo: e.target.value || null })} + /> +
+ +
+ + setForm({ ...form, priceName: e.target.value || null })} + /> +
+ +
+ + setForm({ ...form, dmaPartition: e.target.value || null })} + /> +
+ +
+ setForm({ ...form, receivedAt: new Date(e.target.value).toISOString() })} + value={form.installedTime ? new Date(form.installedTime).toISOString().slice(0, 16) : ""} + onChange={(e) => setForm({ ...form, installedTime: new Date(e.target.value).toISOString() })} />
diff --git a/vite.config.ts b/vite.config.ts index 53ecb8e..ef01ba3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,15 +1,17 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' -import tailwindcss from "@tailwindcss/vite" +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react(),tailwindcss()], + plugins: [react(), tailwindcss()], server: { - host: '0.0.0.0', + allowedHosts: [ + "localhost", + "127.0.0.1", + "reyna-compressive-shaunna.ngrok-free.dev", + ], port: 5173, }, - -}) - +});