All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 58s
- 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
75 lines
2.4 KiB
Vue
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>
|