Files
social-graph/frontend/src/components/AddContactToMapModal.vue
T
gitrusprusandCursor 5155b3a37a Add multiple network maps, graph UX improvements, and full backup import.
Support per-map contact membership with scoped graph views, relation editing on edges, layout caching, and automatic detection of full JSON backups so contacts and relations import together.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 17:54:51 +03:00

73 lines
1.8 KiB
Vue

<template>
<div v-if="open" class="modal-overlay" @click.self="$emit('close')">
<div class="modal">
<div class="modal-header">
<h3>Добавить на карту</h3>
<button class="btn btn-secondary btn-sm" type="button" @click="$emit('close')"></button>
</div>
<div class="form-group">
<label>Контакт</label>
<SearchableSelect
v-model="selectedContactId"
:options="contactOptions"
placeholder="Выберите контакт..."
/>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" @click="$emit('close')">Отмена</button>
<button
type="button"
class="btn btn-primary"
:disabled="!selectedContactId"
@click="onAdd"
>
Добавить
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import SearchableSelect from './SearchableSelect.vue'
const props = defineProps({
open: { type: Boolean, default: false },
contacts: { type: Array, default: () => [] },
memberContactIds: { type: Array, default: () => [] },
})
const emit = defineEmits(['close', 'add'])
const selectedContactId = ref('')
const memberSet = computed(() => new Set(props.memberContactIds.map(String)))
const contactOptions = computed(() =>
props.contacts
.filter((c) => !memberSet.value.has(String(c.id)))
.map((c) => ({ value: String(c.id), label: c.name }))
)
watch(
() => props.open,
(isOpen) => {
if (isOpen) selectedContactId.value = ''
}
)
function onAdd() {
if (!selectedContactId.value) return
emit('add', selectedContactId.value)
}
</script>
<style scoped>
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 20px;
}
</style>