Files
radiusNucleo/frontend/src/components/UserForm.vue
josedario87 96a8f95f9e
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 58s
Refactor: Migrar UI completa a Tailwind CSS v4 + shadcn-vue
- Reemplazar CSS nativo con Tailwind CSS v4 y utilidades custom
- Crear librería de componentes UI basada en shadcn-vue (Radix Vue)
- Componentes UI: Button, Card, Input, Textarea, Badge, Dialog, Avatar, DropdownMenu
- Migrar todos los componentes existentes a Tailwind utilities
- Convertir EventCard.js (htm) a EventCard.vue (SFC)
- Implementar sistema de temas dark/light con clase .dark
- Mantener efectos glassmorphism via @utility custom
- Eliminar styles.css legacy
2025-11-24 18:12:24 -06:00

75 lines
2.4 KiB
Vue

<script setup>
import { reactive, watch, computed, ref } from 'vue';
import { Input, Label, Button } from '@/components/ui';
const props = defineProps({
modelValue: { type: Object, default: () => ({ username:'', password:'', vlan:'', disabled:false }) },
mode: { type: String, default: 'create' } // 'create' | 'edit' | 'guest'
});
const emit = defineEmits(['update:modelValue', 'submit', 'cancel']);
const state = reactive({ username:'', password:'', vlan:'', disabled:false });
const isEdit = computed(() => props.mode === 'edit');
const etiquetasText = ref('');
watch(() => props.modelValue, (v) => {
Object.assign(state, v || {});
const tags = Array.isArray(v?.etiquetas) ? v.etiquetas : [];
etiquetasText.value = tags.join(', ');
}, { immediate: true, deep: true });
function submit() {
const tags = etiquetasText.value.split(',').map(s => s.trim()).filter(Boolean).slice(0, 100);
emit('submit', { ...state, etiquetas: tags });
}
</script>
<template>
<form @submit.prevent="submit" class="flex flex-col gap-3">
<div class="flex flex-wrap gap-3">
<div class="flex-1 min-w-[140px] space-y-1">
<Label class="text-xs text-muted">Usuario</Label>
<Input
v-model="state.username"
:readonly="isEdit"
placeholder="usuario"
/>
</div>
<div class="flex-1 min-w-[140px] space-y-1">
<Label class="text-xs text-muted">Contraseña</Label>
<Input
v-model="state.password"
placeholder="contraseña"
/>
</div>
</div>
<div class="space-y-1">
<Label class="text-xs text-muted">Etiquetas (separadas por coma)</Label>
<Input
v-model="etiquetasText"
placeholder="invitado, vip"
/>
</div>
<div class="flex flex-wrap gap-3 items-end">
<div class="flex-1 min-w-[100px] space-y-1">
<Label class="text-xs text-muted">VLAN</Label>
<Input
v-model="state.vlan"
placeholder="VLAN"
/>
</div>
<label class="flex items-center gap-2 glass glass-border rounded-md px-3 py-2 cursor-pointer">
<input type="checkbox" v-model="state.disabled" class="accent-pink-500" />
<span class="text-sm">Deshabilitado</span>
</label>
</div>
<div class="flex justify-end gap-2 mt-2">
<Button type="button" variant="ghost" @click="emit('cancel')">Cancelar</Button>
<Button type="submit">Guardar</Button>
</div>
</form>
</template>