Files
portal/app/resources/js/components/projects/RegionsBulkDialog.vue
T
Дмитрий cfe94d9178 fix(projects): closable-chips на селекторах регионов — удаление по одному
Раньше чтобы убрать один регион из выбора, приходилось сбрасывать все
и выбирать заново. Добавлен closable-chips на v-autocomplete регионов в
трёх местах: карточка создания проекта (NewProjectDialog), панель
редактирования (ProjectDetailsDrawer) и массовое изменение регионов
(RegionsBulkDialog). Теперь у каждого чипа есть крестик.

Покрыто Vitest: closableChips=true на каждом селекторе.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 10:21:10 +03:00

117 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<v-dialog v-model="open" max-width="560">
<v-card>
<v-card-title>Регионы для {{ count }} проектов</v-card-title>
<v-card-text>
<p class="text-caption text-medium-emphasis mb-4">
Изменения применяются к каждому из {{ count }} выбранных проектов: выбранные субъекты
добавляются к их регионам или убираются из них.
</p>
<div class="mb-2">
<div class="text-caption text-success font-weight-medium mb-2"> Добавить регионы</div>
<v-autocomplete
v-model="addRegions"
:items="selectableRegions"
item-title="name"
item-value="code"
label="Субъекты РФ"
multiple
chips
closable-chips
clearable
density="comfortable"
data-testid="region-add-select"
@update:menu="repositionMenuAfterOpen"
>
<template #item="{ props: itemProps, item }">
<v-list-item v-bind="itemProps">
<template #subtitle>
{{ FEDERAL_DISTRICT_NAMES[item.raw.federalDistrict] || '' }}
</template>
</v-list-item>
</template>
</v-autocomplete>
</div>
<div>
<div class="text-caption text-error font-weight-medium mb-2"> Убрать регионы</div>
<v-autocomplete
v-model="removeRegions"
:items="selectableRegions"
item-title="name"
item-value="code"
label="Субъекты РФ"
multiple
chips
closable-chips
clearable
density="comfortable"
data-testid="region-remove-select"
@update:menu="repositionMenuAfterOpen"
>
<template #item="{ props: itemProps, item }">
<v-list-item v-bind="itemProps">
<template #subtitle>
{{ FEDERAL_DISTRICT_NAMES[item.raw.federalDistrict] || '' }}
</template>
</v-list-item>
</template>
</v-autocomplete>
</div>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn data-testid="cancel" @click="open = false">Отмена</v-btn>
<v-btn
color="primary"
data-testid="apply"
:disabled="addRegions.length === 0 && removeRegions.length === 0"
@click="apply"
>Применить к {{ count }}</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { REGIONS, FEDERAL_DISTRICT_NAMES } from '../../constants/regions';
import { repositionMenuAfterOpen } from '../../utils/menuRepositionFix';
const props = defineProps<{ modelValue: boolean; count: number }>();
const emit = defineEmits<{
'update:modelValue': [value: boolean];
apply: [payload: { add_regions: number[]; remove_regions: number[] }];
}>();
// code:0 — sentinel «Вся РФ»; в bulk add/remove субъектов не выбирается.
const selectableRegions = REGIONS.filter((r) => r.code !== 0);
const open = ref(props.modelValue);
const addRegions = ref<number[]>([]);
const removeRegions = ref<number[]>([]);
watch(
() => props.modelValue,
(val) => {
open.value = val;
if (val) {
addRegions.value = [];
removeRegions.value = [];
}
},
);
watch(open, (val) => emit('update:modelValue', val));
function apply() {
emit('apply', { add_regions: [...addRegions.value], remove_regions: [...removeRegions.value] });
addRegions.value = [];
removeRegions.value = [];
open.value = false;
}
defineExpose({ addRegions, removeRegions, apply });
</script>