// 1. Importar tags de VanJS
const { div, input, button, ul, li, span, p } = van.tags;
// 2. Extraer el ID por defecto si entityData está presente en el contexto
const defaultDeviceId = entityData?.['provision.administration.identifier']?._value?._current?.value || "";
// 3. Estados reactivos de VanJS
const statusText = van.state(defaultDeviceId ? "Cargando datos..." : "Introduce un ID de dispositivo y pulsa Consultar");
const fieldsList = van.state([]);
const loadedEntity = van.state(null); // Guardará la entidad en modo flattened
const currentDeviceId = van.state(defaultDeviceId);
// 4. Estilos en línea
const styles = {
container: "padding: 14px; font-family: system-ui, -apple-system, sans-serif; color: #1e293b; height: 100%; box-sizing: border-box; overflow-y: auto;",
searchBox: "display: flex; gap: 8px; margin-bottom: 12px;",
input: "flex: 1; padding: 8px 12px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.875rem; outline: none;",
primaryBtn: "padding: 8px 16px; background-color: #2563eb; color: white; border: none; border-radius: 6px; font-size: 0.875rem; font-weight: 500; cursor: pointer;",
actionsBox: "display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap;",
actionBtn: "padding: 6px 12px; background-color: #0f766e; color: white; border: none; border-radius: 6px; font-size: 0.8125rem; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 6px;",
secondaryActionBtn: "padding: 6px 12px; background-color: #475569; color: white; border: none; border-radius: 6px; font-size: 0.8125rem; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 6px;",
list: "list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px;",
item: "display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; background: #f8fafc; border-radius: 6px; border: 1px solid #e2e8f0; font-size: 0.875rem;",
key: "color: #64748b; font-weight: 500;",
value: "font-weight: 600; color: #0f172a; word-break: break-all;",
status: "color: #64748b; font-size: 0.875rem; text-align: center; padding: 16px 0; margin: 0;"
};
// 5. Función asíncrona para consultar el dispositivo usando $api
async function searchDevice(id) {
const targetId = (id || "").trim();
if (!targetId) {
statusText.val = "⚠️ Por favor, introduce un identificador de dispositivo válido.";
fieldsList.val = [];
loadedEntity.val = null;
return;
}
statusText.val = `Buscando dispositivo "${targetId}"...`;
fieldsList.val = [];
loadedEntity.val = null;
currentDeviceId.val = targetId;
try {
// Consulta en modo .flattened()
const response = await $api.entitiesSearchBuilder()
.filter({
eq: {
'provision.administration.identifier': targetId
}
})
.flattened()
.limit(1)
.build()
.execute();
const entity = response?.data?.entities?.[0];
if (!entity) {
statusText.val = `❌ No se encontró ningún dispositivo con ID: "${targetId}"`;
return;
}
// Guardar la entidad en modo flattened en el estado
loadedEntity.val = entity;
statusText.val = "";
// Mapeo de campos simples a mostrar
fieldsList.val = [
{ label: "Identificador", value: entity['provision.administration.identifier']?._value?._current?.value || targetId },
{ label: "Organización", value: entity['provision.administration.organization']?._value?._current?.value || "N/A" },
{ label: "Canal", value: entity['provision.administration.channel']?._value?._current?.value || "N/A" },
{ label: "Grupo de Servicio", value: entity['provision.administration.serviceGroup']?._value?._current?.value || "N/A" },
{ label: "Tipo Específico", value: entity['provision.device.specificType']?._value?._current?.value || "N/A" },
{ label: "Número de Serie", value: entity['provision.device.serialNumber']?._value?._current?.value || "N/A" },
{ label: "Estado Operacional", value: entity['device.operationalStatus']?._value?._current?.value || "N/A" }
];
} catch (error) {
console.error("Error al consultar el dispositivo:", error);
statusText.val = `❌ Error en la consulta: ${error.message || error}`;
}
}
// 6. Funciones para ejecutar las acciones sobre el dispositivo cargado
function handleOpenDeviceDetails() {
if (!currentDeviceId.val) {
return;
}
// Abrir widget deviceInfoDetails con el identificador del dispositivo
openWidget('deviceInfoDetails', currentDeviceId.val, `Detalles: ${currentDeviceId.val}`);
}
function handleOpenEntitiesWizard() {
if (!loadedEntity.val) {
return;
}
// Abrir wizard entities pasando el objeto de la entidad en modo flattened
openWizard('entities', loadedEntity.val, true);
}
// 7. Input de texto pre-rellenado
const textInput = input({
type: "text",
placeholder: "Identificador del dispositivo...",
value: defaultDeviceId,
style: styles.input,
onkeydown: (e) => {
if (e.key === "Enter") {
searchDevice(textInput.value);
}
}
});
// 8. Búsqueda automática inicial si entityData contenía un ID
if (defaultDeviceId) {
searchDevice(defaultDeviceId);
}
// 9. Retorno del componente reactivo VanJS
return div({ style: styles.container },
// Barra de búsqueda
div({ style: styles.searchBox },
textInput,
button({
style: styles.primaryBtn,
onclick: () => {
searchDevice(textInput.value);
}
}, "Consultar")
),
// Contenido reactivo: Estado o Botones de Acción + Listado
() => {
if (statusText.val) {
return p({ style: styles.status }, statusText.val);
}
return div(
// Barra de acciones disponibles para el dispositivo cargado
div({ style: styles.actionsBox },
button({
style: styles.actionBtn,
onclick: () => {
handleOpenDeviceDetails();
}
}, "📱 Abrir 'deviceInfoDetails'"),
button({
style: styles.secondaryActionBtn,
onclick: () => {
handleOpenEntitiesWizard();
}
}, "🧙 Abrir Wizard 'entities'")
),
// Listado de datos simples
ul({ style: styles.list },
fieldsList.val.map((field) => {
return li({ style: styles.item },
span({ style: styles.key }, field.label),
span({ style: styles.value }, String(field.value))
);
})
)
);
}
);