edicion de metadata dispositivos, UI/UX

This commit is contained in:
2025-09-26 18:20:36 -06:00
parent e10d8950d9
commit 9848bd46f1
4 changed files with 93 additions and 2 deletions

View File

@@ -0,0 +1,60 @@
<template>
<form @submit.prevent="submit" class="column" style="gap:10px;">
<div class="row">
<label class="toggle" style="flex:0 0 180px;">
<div class="muted" style="font-size:12px;">ID (DB)</div>
<input :value="model.id" readonly style="width:100%; background:transparent; border:none; outline:none; color:inherit;" />
</label>
<label class="toggle" style="flex:1;">
<div class="muted" style="font-size:12px;">MAC</div>
<input :value="model.mac" readonly style="width:100%; background:transparent; border:none; outline:none; color:inherit;" />
</label>
</div>
<div class="row">
<label class="toggle" style="flex:1;">
<div class="muted" style="font-size:12px;">Nombre</div>
<input v-model="state.nombre" placeholder="Nombre del dispositivo" style="width:100%; background:transparent; border:none; outline:none; color:inherit;" />
</label>
</div>
<label class="toggle" style="width:100%;">
<div class="muted" style="font-size:12px;">Descripción</div>
<textarea v-model="state.descripcion" rows="3" placeholder="Descripción opcional" style="width:100%; background:transparent; border:none; outline:none; color:inherit; resize: vertical;"></textarea>
</label>
<div v-if="error" class="muted" style="color:#ff6b6b;">{{ error }}</div>
<div class="modal-footer">
<button type="button" class="icon-btn" @click="$emit('cancel')">Cancelar</button>
<button type="submit" class="icon-btn">Guardar</button>
</div>
</form>
</template>
<script setup>
import { reactive, watch, ref } from 'vue';
const props = defineProps({ model: { type: Object, required: true } });
const emit = defineEmits(['success', 'cancel']);
const state = reactive({ nombre: '', descripcion: '' });
const error = ref('');
watch(() => props.model, (v) => {
state.nombre = v?.nombre || '';
state.descripcion = v?.descripcion || '';
}, { immediate: true, deep: true });
async function submit() {
error.value = '';
try {
const res = await fetch(`/api/devices/${encodeURIComponent(props.model.id)}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nombre: state.nombre, descripcion: state.descripcion })
});
const data = await res.json().catch(() => ({}));
if (!res.ok || data.ok === false) { error.value = data.error || 'Error al guardar'; return; }
emit('success');
} catch (e) {
error.value = String(e?.message || e) || 'Error';
}
}
</script>

View File

@@ -2,11 +2,17 @@
<div class="card">
<div class="row">
<b>{{ device.nombre || device.mac }}</b>
<span class="chip">{{ device.mac }}</span>
<span class="chip">MAC: {{ device.mac }}</span>
<span class="chip">ID: {{ device.id }}</span>
<span v-if="connectedCount>0 || connected" class="chip" style="background: rgba(255,127,187,.2); border-color: rgba(255,127,187,.5);">Conectado</span>
<span class="spacer"></span>
<button class="icon-btn" @click="$emit('edit', device)">Editar</button>
<button v-if="!simple" class="icon-btn" @click="$emit('toggleExpand')">{{ expanded ? 'Contraer' : 'Expandir' }}</button>
</div>
<div class="muted" style="font-size:12px; margin-top:6px;" v-if="device.nombre || device.descripcion">
<div v-if="device.nombre">Nombre: {{ device.nombre }}</div>
<div v-if="device.descripcion">Descripción: {{ device.descripcion }}</div>
</div>
<div v-if="expanded && users && users.length" style="margin-top:8px;">
<div class="grid">
<UserCard v-for="u in users" :key="u.username" :item="u" :devicesById="devicesById" :expandable="false" />