Concentrators create and edit form logic with TTS mock data
This commit is contained in:
@@ -19,11 +19,6 @@ export interface ConcentratorRecord {
|
|||||||
"Installed Time": string;
|
"Installed Time": string;
|
||||||
"Communication Time": string;
|
"Communication Time": string;
|
||||||
"Instruction Manual": string;
|
"Instruction Manual": string;
|
||||||
"Gateway ID": number;
|
|
||||||
"Gateway EUI": string;
|
|
||||||
"Gateway Name": string;
|
|
||||||
"Gateway Description": string;
|
|
||||||
"Antenna Placement": string;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,11 +41,6 @@ export interface Concentrator {
|
|||||||
"Installed Time": string;
|
"Installed Time": string;
|
||||||
"Communication Time": string;
|
"Communication Time": string;
|
||||||
"Instruction Manual": string;
|
"Instruction Manual": string;
|
||||||
"Gateway ID": number;
|
|
||||||
"Gateway EUI": string;
|
|
||||||
"Gateway Name": string;
|
|
||||||
"Gateway Description": string;
|
|
||||||
"Antenna Placement": string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchConcentrators = async (): Promise<Concentrator[]> => {
|
export const fetchConcentrators = async (): Promise<Concentrator[]> => {
|
||||||
@@ -77,11 +67,6 @@ export const fetchConcentrators = async (): Promise<Concentrator[]> => {
|
|||||||
"Installed Time": r.fields["Installed Time"] || "",
|
"Installed Time": r.fields["Installed Time"] || "",
|
||||||
"Communication Time": r.fields["Communication Time"] || "",
|
"Communication Time": r.fields["Communication Time"] || "",
|
||||||
"Instruction Manual": r.fields["Instruction Manual"] || "",
|
"Instruction Manual": r.fields["Instruction Manual"] || "",
|
||||||
"Gateway ID": r.fields["Gateway ID"] || 0,
|
|
||||||
"Gateway EUI": r.fields["Gateway EUI"] || "",
|
|
||||||
"Gateway Name": r.fields["Gateway Name"] || "",
|
|
||||||
"Gateway Description": r.fields["Gateway Description"] || "",
|
|
||||||
"Antenna Placement": r.fields["Antenna Placement"] || "Indoor",
|
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching concentrators:", error);
|
console.error("Error fetching concentrators:", error);
|
||||||
@@ -107,11 +92,6 @@ export const createConcentrator = async (
|
|||||||
"Installed Time": concentratorData["Installed Time"],
|
"Installed Time": concentratorData["Installed Time"],
|
||||||
"Communication Time": concentratorData["Communication Time"],
|
"Communication Time": concentratorData["Communication Time"],
|
||||||
"Instruction Manual": concentratorData["Instruction Manual"],
|
"Instruction Manual": concentratorData["Instruction Manual"],
|
||||||
"Gateway ID": concentratorData["Gateway ID"],
|
|
||||||
"Gateway EUI": concentratorData["Gateway EUI"],
|
|
||||||
"Gateway Name": concentratorData["Gateway Name"],
|
|
||||||
"Gateway Description": concentratorData["Gateway Description"],
|
|
||||||
"Antenna Placement": concentratorData["Antenna Placement"],
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -138,11 +118,6 @@ export const createConcentrator = async (
|
|||||||
"Installed Time": createdRecord.fields["Installed Time"] || concentratorData["Installed Time"],
|
"Installed Time": createdRecord.fields["Installed Time"] || concentratorData["Installed Time"],
|
||||||
"Communication Time": createdRecord.fields["Communication Time"] || concentratorData["Communication Time"],
|
"Communication Time": createdRecord.fields["Communication Time"] || concentratorData["Communication Time"],
|
||||||
"Instruction Manual": createdRecord.fields["Instruction Manual"] || concentratorData["Instruction Manual"],
|
"Instruction Manual": createdRecord.fields["Instruction Manual"] || concentratorData["Instruction Manual"],
|
||||||
"Gateway ID": createdRecord.fields["Gateway ID"] || concentratorData["Gateway ID"],
|
|
||||||
"Gateway EUI": createdRecord.fields["Gateway EUI"] || concentratorData["Gateway EUI"],
|
|
||||||
"Gateway Name": createdRecord.fields["Gateway Name"] || concentratorData["Gateway Name"],
|
|
||||||
"Gateway Description": createdRecord.fields["Gateway Description"] || concentratorData["Gateway Description"],
|
|
||||||
"Antenna Placement": createdRecord.fields["Antenna Placement"] || concentratorData["Antenna Placement"],
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error creating concentrator:", error);
|
console.error("Error creating concentrator:", error);
|
||||||
@@ -170,11 +145,6 @@ export const updateConcentrator = async (
|
|||||||
"Installed Time": concentratorData["Installed Time"],
|
"Installed Time": concentratorData["Installed Time"],
|
||||||
"Communication Time": concentratorData["Communication Time"],
|
"Communication Time": concentratorData["Communication Time"],
|
||||||
"Instruction Manual": concentratorData["Instruction Manual"],
|
"Instruction Manual": concentratorData["Instruction Manual"],
|
||||||
"Gateway ID": concentratorData["Gateway ID"],
|
|
||||||
"Gateway EUI": concentratorData["Gateway EUI"],
|
|
||||||
"Gateway Name": concentratorData["Gateway Name"],
|
|
||||||
"Gateway Description": concentratorData["Gateway Description"],
|
|
||||||
"Antenna Placement": concentratorData["Antenna Placement"],
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -205,11 +175,6 @@ export const updateConcentrator = async (
|
|||||||
"Installed Time": updatedRecord.fields["Installed Time"] || concentratorData["Installed Time"],
|
"Installed Time": updatedRecord.fields["Installed Time"] || concentratorData["Installed Time"],
|
||||||
"Communication Time": updatedRecord.fields["Communication Time"] || concentratorData["Communication Time"],
|
"Communication Time": updatedRecord.fields["Communication Time"] || concentratorData["Communication Time"],
|
||||||
"Instruction Manual": updatedRecord.fields["Instruction Manual"] || concentratorData["Instruction Manual"],
|
"Instruction Manual": updatedRecord.fields["Instruction Manual"] || concentratorData["Instruction Manual"],
|
||||||
"Gateway ID": updatedRecord.fields["Gateway ID"] || concentratorData["Gateway ID"],
|
|
||||||
"Gateway EUI": updatedRecord.fields["Gateway EUI"] || concentratorData["Gateway EUI"],
|
|
||||||
"Gateway Name": updatedRecord.fields["Gateway Name"] || concentratorData["Gateway Name"],
|
|
||||||
"Gateway Description": updatedRecord.fields["Gateway Description"] || concentratorData["Gateway Description"],
|
|
||||||
"Antenna Placement": updatedRecord.fields["Antenna Placement"] || concentratorData["Antenna Placement"],
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error updating concentrator:", error);
|
console.error("Error updating concentrator:", error);
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ interface User {
|
|||||||
project?: string; // asignado si no es superadmin
|
project?: string; // asignado si no es superadmin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GatewayData {
|
||||||
|
"Gateway ID": number;
|
||||||
|
"Gateway EUI": string;
|
||||||
|
"Gateway Name": string;
|
||||||
|
"Gateway Description": string;
|
||||||
|
"Antenna Placement": "Indoor" | "Outdoor";
|
||||||
|
concentratorId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================= COMPONENT ================= */
|
/* ================= COMPONENT ================= */
|
||||||
export default function ConcentratorsPage() {
|
export default function ConcentratorsPage() {
|
||||||
// Simulación de usuario actual
|
// Simulación de usuario actual
|
||||||
@@ -99,6 +108,9 @@ export default function ConcentratorsPage() {
|
|||||||
"Installed Time": new Date().toISOString().slice(0, 10),
|
"Installed Time": new Date().toISOString().slice(0, 10),
|
||||||
"Communication Time": new Date().toISOString(),
|
"Communication Time": new Date().toISOString(),
|
||||||
"Instruction Manual": "",
|
"Instruction Manual": "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const getEmptyGatewayData = (): GatewayData => ({
|
||||||
"Gateway ID": 0,
|
"Gateway ID": 0,
|
||||||
"Gateway EUI": "",
|
"Gateway EUI": "",
|
||||||
"Gateway Name": "",
|
"Gateway Name": "",
|
||||||
@@ -107,10 +119,51 @@ export default function ConcentratorsPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [form, setForm] = useState<Omit<Concentrator, "id">>(getEmptyConcentrator());
|
const [form, setForm] = useState<Omit<Concentrator, "id">>(getEmptyConcentrator());
|
||||||
|
const [gatewayForm, setGatewayForm] = useState<GatewayData>(getEmptyGatewayData());
|
||||||
|
const [errors, setErrors] = useState<{ [key: string]: boolean }>({});
|
||||||
|
|
||||||
/* ================= CRUD ================= */
|
/* ================= CRUD ================= */
|
||||||
|
const createOrUpdateGateway = async (gatewayData: GatewayData): Promise<void> => {
|
||||||
|
//await fetch('/api/gateways', { method: 'POST', body: JSON.stringify(gatewayData) })
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('Gateway data that would be sent to API:', gatewayData);
|
||||||
|
resolve();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateForm = (): boolean => {
|
||||||
|
const newErrors: { [key: string]: boolean } = {};
|
||||||
|
|
||||||
|
if (!form["Device Name"].trim()) newErrors["Device Name"] = true;
|
||||||
|
if (!form["Device S/N"].trim()) newErrors["Device S/N"] = true;
|
||||||
|
if (!form["Operator"].trim()) newErrors["Operator"] = true;
|
||||||
|
if (!form["Instruction Manual"].trim()) newErrors["Instruction Manual"] = true;
|
||||||
|
if (!form["Installed Time"]) newErrors["Installed Time"] = true;
|
||||||
|
if (!form["Device Time"]) newErrors["Device Time"] = true;
|
||||||
|
if (!form["Communication Time"]) newErrors["Communication Time"] = true;
|
||||||
|
|
||||||
|
if (!gatewayForm["Gateway ID"] || gatewayForm["Gateway ID"] === 0) {
|
||||||
|
newErrors["Gateway ID"] = true;
|
||||||
|
}
|
||||||
|
if (!gatewayForm["Gateway EUI"].trim()) newErrors["Gateway EUI"] = true;
|
||||||
|
if (!gatewayForm["Gateway Name"].trim()) newErrors["Gateway Name"] = true;
|
||||||
|
if (!gatewayForm["Gateway Description"].trim()) newErrors["Gateway Description"] = true;
|
||||||
|
|
||||||
|
setErrors(newErrors);
|
||||||
|
return Object.keys(newErrors).length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
|
if (!validateForm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let savedConcentrator: Concentrator;
|
||||||
|
|
||||||
if (editingSerial) {
|
if (editingSerial) {
|
||||||
const concentratorToUpdate = concentrators.find(c => c["Device S/N"] === editingSerial);
|
const concentratorToUpdate = concentrators.find(c => c["Device S/N"] === editingSerial);
|
||||||
if (!concentratorToUpdate) {
|
if (!concentratorToUpdate) {
|
||||||
@@ -123,13 +176,30 @@ export default function ConcentratorsPage() {
|
|||||||
c.id === concentratorToUpdate.id ? updatedConcentrator : c
|
c.id === concentratorToUpdate.id ? updatedConcentrator : c
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
savedConcentrator = updatedConcentrator;
|
||||||
} else {
|
} else {
|
||||||
const newConcentrator = await createConcentrator(form);
|
const newConcentrator = await createConcentrator(form);
|
||||||
setConcentrators((prev) => [...prev, newConcentrator]);
|
setConcentrators((prev) => [...prev, newConcentrator]);
|
||||||
|
savedConcentrator = newConcentrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const gatewayDataWithRef = {
|
||||||
|
...gatewayForm,
|
||||||
|
concentratorId: savedConcentrator.id,
|
||||||
|
};
|
||||||
|
await createOrUpdateGateway(gatewayDataWithRef);
|
||||||
|
console.log('Gateway data saved successfully');
|
||||||
|
} catch (gatewayError) {
|
||||||
|
console.error('Error saving gateway data:', gatewayError);
|
||||||
|
alert('Concentrator saved, but there was an error saving gateway data.');
|
||||||
|
}
|
||||||
|
|
||||||
setShowModal(false);
|
setShowModal(false);
|
||||||
setEditingSerial(null);
|
setEditingSerial(null);
|
||||||
setForm({ ...getEmptyConcentrator(), "Area Name": selectedProject });
|
setForm({ ...getEmptyConcentrator(), "Area Name": selectedProject });
|
||||||
|
setGatewayForm(getEmptyGatewayData());
|
||||||
|
setErrors({});
|
||||||
setActiveConcentrator(null);
|
setActiveConcentrator(null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving concentrator:', error);
|
console.error('Error saving concentrator:', error);
|
||||||
@@ -223,6 +293,8 @@ export default function ConcentratorsPage() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setForm({ ...getEmptyConcentrator(), "Area Name": selectedProject });
|
setForm({ ...getEmptyConcentrator(), "Area Name": selectedProject });
|
||||||
|
setGatewayForm(getEmptyGatewayData());
|
||||||
|
setErrors({});
|
||||||
setEditingSerial(null);
|
setEditingSerial(null);
|
||||||
setShowModal(true);
|
setShowModal(true);
|
||||||
}}
|
}}
|
||||||
@@ -246,12 +318,9 @@ export default function ConcentratorsPage() {
|
|||||||
"Installed Time": activeConcentrator["Installed Time"],
|
"Installed Time": activeConcentrator["Installed Time"],
|
||||||
"Communication Time": activeConcentrator["Communication Time"],
|
"Communication Time": activeConcentrator["Communication Time"],
|
||||||
"Instruction Manual": activeConcentrator["Instruction Manual"],
|
"Instruction Manual": activeConcentrator["Instruction Manual"],
|
||||||
"Gateway ID": activeConcentrator["Gateway ID"],
|
|
||||||
"Gateway EUI": activeConcentrator["Gateway EUI"],
|
|
||||||
"Gateway Name": activeConcentrator["Gateway Name"],
|
|
||||||
"Gateway Description": activeConcentrator["Gateway Description"],
|
|
||||||
"Antenna Placement": activeConcentrator["Antenna Placement"],
|
|
||||||
});
|
});
|
||||||
|
setGatewayForm(getEmptyGatewayData());
|
||||||
|
setErrors({});
|
||||||
setShowModal(true);
|
setShowModal(true);
|
||||||
}}
|
}}
|
||||||
disabled={!activeConcentrator}
|
disabled={!activeConcentrator}
|
||||||
@@ -337,48 +406,96 @@ export default function ConcentratorsPage() {
|
|||||||
|
|
||||||
{/* MODAL */}
|
{/* MODAL */}
|
||||||
{showModal && (
|
{showModal && (
|
||||||
<div className="fixed inset-0 bg-black/40 flex items-center justify-center">
|
<div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-xl p-6 w-96 space-y-3">
|
<div className="bg-white rounded-xl p-6 w-[600px] max-h-[90vh] overflow-y-auto space-y-4">
|
||||||
<h2 className="text-lg font-semibold">
|
<h2 className="text-lg font-semibold">
|
||||||
{editingSerial ? "Edit Concentrator" : "Add Concentrator"}
|
{editingSerial ? "Edit Concentrator" : "Add Concentrator"}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
<h3 className="text-sm font-semibold text-gray-700 border-b pb-2">
|
||||||
|
Concentrator Information
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Device Name"
|
errors["Device Name"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Device Name *"
|
||||||
value={form["Device Name"]}
|
value={form["Device Name"]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, "Device Name": e.target.value })
|
setForm({ ...form, "Device Name": e.target.value });
|
||||||
|
if (errors["Device Name"]) {
|
||||||
|
setErrors({ ...errors, "Device Name": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Device Name"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Device S/N"
|
errors["Device S/N"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Device S/N *"
|
||||||
value={form["Device S/N"]}
|
value={form["Device S/N"]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, "Device S/N": e.target.value })
|
setForm({ ...form, "Device S/N": e.target.value });
|
||||||
|
if (errors["Device S/N"]) {
|
||||||
|
setErrors({ ...errors, "Device S/N": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Device S/N"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Operator"
|
errors["Operator"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Operator *"
|
||||||
value={form["Operator"]}
|
value={form["Operator"]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, "Operator": e.target.value })
|
setForm({ ...form, "Operator": e.target.value });
|
||||||
|
if (errors["Operator"]) {
|
||||||
|
setErrors({ ...errors, "Operator": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Operator"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Instruction Manual"
|
errors["Instruction Manual"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Instruction Manual *"
|
||||||
value={form["Instruction Manual"]}
|
value={form["Instruction Manual"]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, "Instruction Manual": e.target.value })
|
setForm({ ...form, "Instruction Manual": e.target.value });
|
||||||
|
if (errors["Instruction Manual"]) {
|
||||||
|
setErrors({ ...errors, "Instruction Manual": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Instruction Manual"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -390,98 +507,202 @@ export default function ConcentratorsPage() {
|
|||||||
}
|
}
|
||||||
className="w-full border rounded px-3 py-2 hover:bg-gray-50 text-left"
|
className="w-full border rounded px-3 py-2 hover:bg-gray-50 text-left"
|
||||||
>
|
>
|
||||||
Device Status: {form["Device Status"]}
|
Device Status: {form["Device Status"]} *
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
|
errors["Installed Time"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Installed Time *"
|
||||||
value={form["Installed Time"]}
|
value={form["Installed Time"]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, "Installed Time": e.target.value })
|
setForm({ ...form, "Installed Time": e.target.value });
|
||||||
|
if (errors["Installed Time"]) {
|
||||||
|
setErrors({ ...errors, "Installed Time": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Installed Time"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
|
errors["Device Time"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Device Time *"
|
||||||
value={form["Device Time"].slice(0, 16)}
|
value={form["Device Time"].slice(0, 16)}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({
|
setForm({
|
||||||
...form,
|
...form,
|
||||||
"Device Time": new Date(e.target.value).toISOString(),
|
"Device Time": new Date(e.target.value).toISOString(),
|
||||||
})
|
});
|
||||||
|
if (errors["Device Time"]) {
|
||||||
|
setErrors({ ...errors, "Device Time": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Device Time"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
|
errors["Communication Time"] ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
placeholder="Communication Time *"
|
||||||
value={form["Communication Time"].slice(0, 16)}
|
value={form["Communication Time"].slice(0, 16)}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({
|
setForm({
|
||||||
...form,
|
...form,
|
||||||
"Communication Time": new Date(e.target.value).toISOString(),
|
"Communication Time": new Date(e.target.value).toISOString(),
|
||||||
})
|
});
|
||||||
|
if (errors["Communication Time"]) {
|
||||||
|
setErrors({ ...errors, "Communication Time": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Communication Time"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-3 pt-4">
|
||||||
|
<h3 className="text-sm font-semibold text-gray-700 border-b pb-2">
|
||||||
|
Gateway Information
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Gateway ID"
|
errors["Gateway ID"] ? "border-red-500" : ""
|
||||||
value={form["Gateway ID"]}
|
}`}
|
||||||
onChange={(e) =>
|
placeholder="Gateway ID *"
|
||||||
setForm({ ...form, "Gateway ID": parseInt(e.target.value) || 0 })
|
value={gatewayForm["Gateway ID"] || ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
setGatewayForm({
|
||||||
|
...gatewayForm,
|
||||||
|
"Gateway ID": parseInt(e.target.value) || 0,
|
||||||
|
});
|
||||||
|
if (errors["Gateway ID"]) {
|
||||||
|
setErrors({ ...errors, "Gateway ID": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
min="1"
|
||||||
/>
|
/>
|
||||||
|
{errors["Gateway ID"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Gateway EUI"
|
errors["Gateway EUI"] ? "border-red-500" : ""
|
||||||
value={form["Gateway EUI"]}
|
}`}
|
||||||
onChange={(e) =>
|
placeholder="Gateway EUI *"
|
||||||
setForm({ ...form, "Gateway EUI": e.target.value })
|
value={gatewayForm["Gateway EUI"]}
|
||||||
|
onChange={(e) => {
|
||||||
|
setGatewayForm({ ...gatewayForm, "Gateway EUI": e.target.value });
|
||||||
|
if (errors["Gateway EUI"]) {
|
||||||
|
setErrors({ ...errors, "Gateway EUI": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Gateway EUI"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<input
|
<input
|
||||||
className="w-full border px-3 py-2 rounded"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
placeholder="Gateway Name"
|
errors["Gateway Name"] ? "border-red-500" : ""
|
||||||
value={form["Gateway Name"]}
|
}`}
|
||||||
onChange={(e) =>
|
placeholder="Gateway Name *"
|
||||||
setForm({ ...form, "Gateway Name": e.target.value })
|
value={gatewayForm["Gateway Name"]}
|
||||||
|
onChange={(e) => {
|
||||||
|
setGatewayForm({ ...gatewayForm, "Gateway Name": e.target.value });
|
||||||
|
if (errors["Gateway Name"]) {
|
||||||
|
setErrors({ ...errors, "Gateway Name": false });
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Gateway Name"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<textarea
|
<div>
|
||||||
className="w-full border px-3 py-2 rounded"
|
<input
|
||||||
placeholder="Gateway Description"
|
className={`w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent ${
|
||||||
value={form["Gateway Description"]}
|
errors["Gateway Description"] ? "border-red-500" : ""
|
||||||
onChange={(e) =>
|
}`}
|
||||||
setForm({ ...form, "Gateway Description": e.target.value })
|
placeholder="Gateway Description *"
|
||||||
|
value={gatewayForm["Gateway Description"]}
|
||||||
|
onChange={(e) => {
|
||||||
|
setGatewayForm({
|
||||||
|
...gatewayForm,
|
||||||
|
"Gateway Description": e.target.value,
|
||||||
|
});
|
||||||
|
if (errors["Gateway Description"]) {
|
||||||
|
setErrors({ ...errors, "Gateway Description": false });
|
||||||
}
|
}
|
||||||
rows={3}
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
{errors["Gateway Description"] && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">This field is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
className="w-full border px-3 py-2 rounded"
|
className="w-full border px-3 py-2 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
value={form["Antenna Placement"]}
|
value={gatewayForm["Antenna Placement"]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setForm({ ...form, "Antenna Placement": e.target.value })
|
setGatewayForm({
|
||||||
|
...gatewayForm,
|
||||||
|
"Antenna Placement": e.target.value as "Indoor" | "Outdoor",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
required
|
||||||
>
|
>
|
||||||
<option value="Indoor">Indoor</option>
|
<option value="Indoor">Indoor</option>
|
||||||
<option value="Outdoor">Outdoor</option>
|
<option value="Outdoor">Outdoor</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-2 pt-3 border-t">
|
||||||
<div className="flex justify-end gap-2 pt-3">
|
<button
|
||||||
<button onClick={() => setShowModal(false)}>Cancel</button>
|
onClick={() => {
|
||||||
|
setShowModal(false);
|
||||||
|
setGatewayForm(getEmptyGatewayData());
|
||||||
|
setErrors({});
|
||||||
|
}}
|
||||||
|
className="px-4 py-2 rounded hover:bg-gray-100"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
className="bg-[#4c5f9e] text-white px-4 py-2 rounded"
|
className="bg-[#4c5f9e] text-white px-4 py-2 rounded hover:bg-[#3d4d7e]"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user