agentic-os/interface/hq-dashboard/app/utilities/page.jsx

141 lines
6.4 KiB
JavaScript

"use client";
import React, { useState, useEffect } from "react";
export default function UtilitiesPage() {
const [firstEnergyUser, setFirstEnergyUser] = useState("");
const [firstEnergyPass, setFirstEnergyPass] = useState("");
const [peoplesGasUser, setPeoplesGasUser] = useState("");
const [peoplesGasPass, setPeoplesGasPass] = useState("");
const [status, setStatus] = useState("");
useEffect(() => {
fetch('/proxy/utility/api/credentials')
.then(r => r.json())
.then(data => {
if (data.success) {
setFirstEnergyUser(data.firstEnergyUser || "");
setPeoplesGasUser(data.peoplesGasUser || "");
}
})
.catch(console.error);
}, []);
const handleSave = async (e) => {
e.preventDefault();
setStatus("Saving...");
try {
const res = await fetch('/proxy/utility/api/credentials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
firstEnergyUser,
firstEnergyPass,
peoplesGasUser,
peoplesGasPass
})
});
const data = await res.json();
if (data.success) {
setStatus("✅ Credentials saved securely.");
setFirstEnergyPass("");
setPeoplesGasPass("");
} else {
setStatus("❌ Failed to save.");
}
} catch (err) {
setStatus("❌ Network error.");
}
};
const handleRun = async () => {
setStatus("Starting scraper...");
try {
await fetch('/proxy/utility/api/run', { method: 'POST' });
setStatus("✅ Scraper triggered in background!");
} catch (e) {
setStatus("❌ Failed to run scraper.");
}
};
return (
<div style={{ height: "100vh", width: "100vw", background: "#05070a", overflow: "hidden", color: "white", padding: "40px", fontFamily: "'Inter', sans-serif" }}>
<h1 style={{ fontSize: "2rem", marginBottom: "10px", background: "-webkit-linear-gradient(#fff, #888)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }}>
Utility Agent Configuration
</h1>
<p style={{ color: "#888", marginBottom: "40px", maxWidth: "600px", lineHeight: "1.6" }}>
The Utility Agent securely automates retrieving your daily energy and gas usage data. It uses these credentials locally in your private cluster and sends a summary to your WhatsApp gateway.
</p>
<form onSubmit={handleSave} style={{ display: "flex", flexDirection: "column", gap: "24px", maxWidth: "500px", background: "rgba(255,255,255,0.03)", padding: "30px", borderRadius: "16px", border: "1px solid rgba(255,255,255,0.1)", backdropFilter: "blur(10px)" }}>
{/* FirstEnergy */}
<div>
<h2 style={{ fontSize: "1.2rem", marginBottom: "16px", display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ fontSize: "1.5rem" }}></span> FirstEnergy
</h2>
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<input
type="text"
placeholder="Username"
value={firstEnergyUser}
onChange={e => setFirstEnergyUser(e.target.value)}
style={{ width: "100%", padding: "12px 16px", borderRadius: "8px", border: "1px solid rgba(255,255,255,0.1)", background: "rgba(0,0,0,0.5)", color: "white", outline: "none", fontSize: "0.95rem" }}
/>
<input
type="password"
placeholder="Password (leave blank to keep current)"
value={firstEnergyPass}
onChange={e => setFirstEnergyPass(e.target.value)}
style={{ width: "100%", padding: "12px 16px", borderRadius: "8px", border: "1px solid rgba(255,255,255,0.1)", background: "rgba(0,0,0,0.5)", color: "white", outline: "none", fontSize: "0.95rem" }}
/>
</div>
</div>
<div style={{ height: "1px", background: "rgba(255,255,255,0.1)", margin: "8px 0" }}></div>
{/* Peoples Gas */}
<div>
<h2 style={{ fontSize: "1.2rem", marginBottom: "16px", display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ fontSize: "1.5rem" }}>🔥</span> Peoples Gas
</h2>
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<input
type="text"
placeholder="Username"
value={peoplesGasUser}
onChange={e => setPeoplesGasUser(e.target.value)}
style={{ width: "100%", padding: "12px 16px", borderRadius: "8px", border: "1px solid rgba(255,255,255,0.1)", background: "rgba(0,0,0,0.5)", color: "white", outline: "none", fontSize: "0.95rem" }}
/>
<input
type="password"
placeholder="Password (leave blank to keep current)"
value={peoplesGasPass}
onChange={e => setPeoplesGasPass(e.target.value)}
style={{ width: "100%", padding: "12px 16px", borderRadius: "8px", border: "1px solid rgba(255,255,255,0.1)", background: "rgba(0,0,0,0.5)", color: "white", outline: "none", fontSize: "0.95rem" }}
/>
</div>
</div>
{status && <div style={{ fontSize: "0.9rem", color: "#4ade80", background: "rgba(74, 222, 128, 0.1)", padding: "10px", borderRadius: "6px" }}>{status}</div>}
<div style={{ display: "flex", gap: "12px", marginTop: "8px" }}>
<button type="submit" style={{ flex: 1, padding: "14px", background: "linear-gradient(135deg, #3b82f6, #2563eb)", color: "white", border: "none", borderRadius: "8px", fontSize: "1rem", fontWeight: "600", cursor: "pointer", transition: "transform 0.1s" }}
onMouseOver={e => e.currentTarget.style.transform = "scale(1.02)"}
onMouseOut={e => e.currentTarget.style.transform = "scale(1)"}
>
Save Credentials
</button>
<button type="button" onClick={handleRun} style={{ padding: "14px", background: "rgba(255,255,255,0.1)", color: "white", border: "none", borderRadius: "8px", fontSize: "1rem", fontWeight: "600", cursor: "pointer", transition: "transform 0.1s" }}
onMouseOver={e => e.currentTarget.style.background = "rgba(255,255,255,0.15)"}
onMouseOut={e => e.currentTarget.style.background = "rgba(255,255,255,0.1)"}
>
Run Now
</button>
</div>
</form>
</div>
);
}