[C28-38][@ant] правка: управление приватностью КУ — на стол председателя
Перенёс управление приватностью+белым списком в MemberBranchListPage (стол председателя «Кооперативные участки», развёрнутая строка) через компонент BranchPrivacyManager. Откатил KuBranchesPage (стол «Кооперативный участок») к виду без управления — там оно было не к месту. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
export * from './model'
|
export * from './model'
|
||||||
|
export { default as BranchPrivacyManager } from './ui/BranchPrivacyManager.vue'
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.branch-privacy
|
||||||
|
BaseCheckbox(
|
||||||
|
:model-value='isPrivate',
|
||||||
|
:disabled='busy',
|
||||||
|
label='Приватный участок — выбрать его при вступлении или смене может только пайщик из белого списка',
|
||||||
|
@update:model-value='onTogglePrivate'
|
||||||
|
)
|
||||||
|
template(v-if='isPrivate')
|
||||||
|
.branch-privacy__subtitle.t-sm.t-muted Белый список пайщиков
|
||||||
|
.branch-privacy__add
|
||||||
|
UserSearchSelector.branch-privacy__search(
|
||||||
|
v-model='selected',
|
||||||
|
label='Начните ввод ФИО пайщика',
|
||||||
|
dense
|
||||||
|
)
|
||||||
|
BaseButton(
|
||||||
|
variant='primary',
|
||||||
|
:disabled='!selected',
|
||||||
|
:loading='busy',
|
||||||
|
@click='onAdd'
|
||||||
|
) Добавить
|
||||||
|
.branch-privacy__list(v-if='whitelist.length')
|
||||||
|
.branch-privacy__member(v-for='member in whitelist', :key='member.username')
|
||||||
|
span {{ memberName(member) }}
|
||||||
|
button.icon-btn(
|
||||||
|
type='button',
|
||||||
|
aria-label='Удалить из белого списка',
|
||||||
|
:disabled='busy',
|
||||||
|
@click='onRemove(member.username)'
|
||||||
|
)
|
||||||
|
q-icon(name='close')
|
||||||
|
.t-sm.t-muted(v-else) Белый список пуст — добавьте пайщиков, которым разрешён выбор этого участка.
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { useBranchPrivacy } from '../model';
|
||||||
|
import { useSystemStore } from 'src/entities/System/model';
|
||||||
|
import type { IBranch } from 'src/entities/Branch/model';
|
||||||
|
import { FailAlert, SuccessAlert } from 'src/shared/api';
|
||||||
|
import { BaseButton, BaseCheckbox } from 'src/shared/ui/base';
|
||||||
|
import { UserSearchSelector } from 'src/shared/ui';
|
||||||
|
|
||||||
|
const props = defineProps<{ branch: IBranch }>();
|
||||||
|
|
||||||
|
const { info } = useSystemStore();
|
||||||
|
const { setBranchPrivate, addBranchWhitelist, deleteBranchWhitelist } = useBranchPrivacy();
|
||||||
|
|
||||||
|
const busy = ref(false);
|
||||||
|
const selected = ref('');
|
||||||
|
|
||||||
|
const isPrivate = computed(() => props.branch.is_private);
|
||||||
|
const whitelist = computed(() => props.branch.whitelist_certificates ?? []);
|
||||||
|
|
||||||
|
function memberName(member: any): string {
|
||||||
|
return [member.last_name, member.first_name, member.middle_name].filter(Boolean).join(' ') || member.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onTogglePrivate(value: boolean) {
|
||||||
|
busy.value = true;
|
||||||
|
try {
|
||||||
|
await setBranchPrivate({ coopname: info.coopname, braname: props.branch.braname, is_private: value });
|
||||||
|
SuccessAlert(value ? 'Участок сделан приватным' : 'Участок сделан публичным');
|
||||||
|
} catch (e: unknown) {
|
||||||
|
FailAlert(e);
|
||||||
|
} finally {
|
||||||
|
busy.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onAdd() {
|
||||||
|
if (!selected.value) return;
|
||||||
|
busy.value = true;
|
||||||
|
try {
|
||||||
|
await addBranchWhitelist({ coopname: info.coopname, braname: props.branch.braname, account: selected.value });
|
||||||
|
selected.value = '';
|
||||||
|
SuccessAlert('Пайщик добавлен в белый список участка');
|
||||||
|
} catch (e: unknown) {
|
||||||
|
FailAlert(e);
|
||||||
|
} finally {
|
||||||
|
busy.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onRemove(account: string) {
|
||||||
|
busy.value = true;
|
||||||
|
try {
|
||||||
|
await deleteBranchWhitelist({ coopname: info.coopname, braname: props.branch.braname, account });
|
||||||
|
SuccessAlert('Пайщик удалён из белого списка участка');
|
||||||
|
} catch (e: unknown) {
|
||||||
|
FailAlert(e);
|
||||||
|
} finally {
|
||||||
|
busy.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.branch-privacy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--p-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-privacy__subtitle {
|
||||||
|
margin-top: var(--p-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-privacy__add {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--p-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-privacy__search {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
max-width: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-privacy__list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--p-2);
|
||||||
|
max-width: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-privacy__member {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--p-2);
|
||||||
|
padding: var(--p-2) var(--p-3);
|
||||||
|
background: var(--p-surface-1);
|
||||||
|
border: 1px solid var(--p-line);
|
||||||
|
border-radius: var(--p-r-sm);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -57,6 +57,10 @@
|
|||||||
p.t-muted для замены председателя участка — измените его имя аккаунта в карточке участка на аккаунт одного из пайщиков.
|
p.t-muted для замены председателя участка — измените его имя аккаунта в карточке участка на аккаунт одного из пайщиков.
|
||||||
div.q-mt-md.flex.justify-center
|
div.q-mt-md.flex.justify-center
|
||||||
DeleteBranchButton(:branch="props.row")
|
DeleteBranchButton(:branch="props.row")
|
||||||
|
div.row
|
||||||
|
div.col-12.q-pa-sm
|
||||||
|
p.text-center.text-overline доступ к участку
|
||||||
|
BranchPrivacyManager(:branch="props.row")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -65,6 +69,7 @@ import { useBranchStore } from 'src/entities/Branch/model';
|
|||||||
import { useEditableTableRows } from 'src/shared/lib/composables/useEditableTableRows';
|
import { useEditableTableRows } from 'src/shared/lib/composables/useEditableTableRows';
|
||||||
import { CreateBranchButton } from 'src/features/Branch/CreateBranch';
|
import { CreateBranchButton } from 'src/features/Branch/CreateBranch';
|
||||||
import { DeleteBranchButton } from 'src/features/Branch/DeleteBranch';
|
import { DeleteBranchButton } from 'src/features/Branch/DeleteBranch';
|
||||||
|
import { BranchPrivacyManager } from 'src/features/Branch/BranchPrivacy';
|
||||||
import { getNameFromUserData } from 'src/shared/lib/utils/getNameFromUserData';
|
import { getNameFromUserData } from 'src/shared/lib/utils/getNameFromUserData';
|
||||||
import { BranchCard } from 'src/widgets/BranchCard';
|
import { BranchCard } from 'src/widgets/BranchCard';
|
||||||
import { EditableIndividualCard } from 'src/shared/ui/EditableIndividualCard';
|
import { EditableIndividualCard } from 'src/shared/ui/EditableIndividualCard';
|
||||||
|
|||||||
@@ -25,80 +25,33 @@
|
|||||||
table.table
|
table.table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th.col-expand(v-if='isChairman')
|
|
||||||
th Участок
|
th Участок
|
||||||
th Председатель
|
th Председатель
|
||||||
th Доверенные
|
th Доверенные
|
||||||
th.col-count Пайщики
|
th.col-count Пайщики
|
||||||
th.col-action
|
th.col-action
|
||||||
tbody
|
tbody
|
||||||
template(v-for='branch in branches', :key='branch.braname')
|
tr.data-row(
|
||||||
tr.data-row(@click='openDetails(branch.braname)')
|
v-for='branch in branches',
|
||||||
td.col-expand(v-if='isChairman', @click.stop)
|
:key='branch.braname',
|
||||||
ExpandToggleButton(
|
@click='openDetails(branch.braname)'
|
||||||
variant='card',
|
)
|
||||||
:expanded='isExpanded(branch.braname)',
|
td
|
||||||
@click='toggleExpand(branch.braname)'
|
.doc-primary {{ branchTitle(branch) }}
|
||||||
)
|
.t-sm.t-muted(v-if='branch.fact_address') {{ branch.fact_address }}
|
||||||
td
|
td {{ chairmanName(branch) }}
|
||||||
.doc-primary
|
td
|
||||||
span {{ branchTitle(branch) }}
|
template(v-if='trustedNames(branch).length')
|
||||||
BaseChip.q-ml-sm(v-if='branch.is_private', variant='warn')
|
div(v-for='name in trustedNames(branch)', :key='name') {{ name }}
|
||||||
q-icon(name='lock', size='12px')
|
span(v-else) —
|
||||||
span.q-ml-xs Приватный
|
td.col-count {{ branch.participants_count ?? 0 }}
|
||||||
.t-sm.t-muted(v-if='branch.fact_address') {{ branch.fact_address }}
|
td.col-action
|
||||||
td {{ chairmanName(branch) }}
|
button.icon-btn(
|
||||||
td
|
type='button',
|
||||||
template(v-if='trustedNames(branch).length')
|
aria-label='Открыть участок',
|
||||||
div(v-for='name in trustedNames(branch)', :key='name') {{ name }}
|
@click.stop='openDetails(branch.braname)'
|
||||||
span(v-else) —
|
)
|
||||||
td.col-count {{ branch.participants_count ?? 0 }}
|
q-icon(name='chevron_right')
|
||||||
td.col-action
|
|
||||||
button.icon-btn(
|
|
||||||
type='button',
|
|
||||||
aria-label='Открыть участок',
|
|
||||||
@click.stop='openDetails(branch.braname)'
|
|
||||||
)
|
|
||||||
q-icon(name='chevron_right')
|
|
||||||
|
|
||||||
//- Панель управления приватностью и белым списком — только председателю совета
|
|
||||||
tr.expand-row(v-if='isChairman && isExpanded(branch.braname)')
|
|
||||||
td(:colspan='6')
|
|
||||||
.branch-admin
|
|
||||||
BaseCheckbox(
|
|
||||||
:model-value='branch.is_private',
|
|
||||||
:disabled='isBusy(branch.braname)',
|
|
||||||
label='Приватный участок — выбрать его при вступлении или смене может только пайщик из белого списка',
|
|
||||||
@update:model-value='onTogglePrivate(branch, $event)'
|
|
||||||
)
|
|
||||||
template(v-if='branch.is_private')
|
|
||||||
.branch-admin__subtitle.t-sm.t-muted Белый список пайщиков
|
|
||||||
.branch-admin__add
|
|
||||||
UserSearchSelector.branch-admin__search(
|
|
||||||
v-model='whitelistInput[branch.braname]',
|
|
||||||
label='Начните ввод ФИО пайщика',
|
|
||||||
dense
|
|
||||||
)
|
|
||||||
BaseButton(
|
|
||||||
variant='primary',
|
|
||||||
:disabled='!whitelistInput[branch.braname]',
|
|
||||||
:loading='isBusy(branch.braname)',
|
|
||||||
@click='onAddWhitelist(branch)'
|
|
||||||
) Добавить
|
|
||||||
.branch-admin__list(v-if='whitelistOf(branch).length')
|
|
||||||
.branch-admin__member(
|
|
||||||
v-for='member in whitelistOf(branch)',
|
|
||||||
:key='member.username'
|
|
||||||
)
|
|
||||||
span {{ certificateName(member) }}
|
|
||||||
button.icon-btn(
|
|
||||||
type='button',
|
|
||||||
aria-label='Удалить из белого списка',
|
|
||||||
:disabled='isBusy(branch.braname)',
|
|
||||||
@click='onRemoveWhitelist(branch, member.username)'
|
|
||||||
)
|
|
||||||
q-icon(name='close')
|
|
||||||
.t-sm.t-muted(v-else) Белый список пуст — добавьте пайщиков, которым разрешён выбор этого участка.
|
|
||||||
EmptyState(
|
EmptyState(
|
||||||
v-else,
|
v-else,
|
||||||
title='Кооперативных участков пока нет',
|
title='Кооперативных участков пока нет',
|
||||||
@@ -109,19 +62,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, reactive, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useBranchStore, type IBranch, type IPublicBranch } from 'src/entities/Branch/model';
|
import { useBranchStore } from 'src/entities/Branch/model';
|
||||||
import { useSystemStore } from 'src/entities/System/model';
|
import { useSystemStore } from 'src/entities/System/model';
|
||||||
import { useSessionStore } from 'src/entities/Session';
|
|
||||||
import { useBranchPrivacy } from 'src/features/Branch/BranchPrivacy';
|
|
||||||
import { useDismissibleBanner } from 'src/shared/hooks/useDismissibleBanner';
|
import { useDismissibleBanner } from 'src/shared/hooks/useDismissibleBanner';
|
||||||
import { FailAlert, SuccessAlert } from 'src/shared/api';
|
import { FailAlert } from 'src/shared/api';
|
||||||
import { BaseButton, BaseCard, BaseCheckbox, BaseChip, EmptyState, TableSkeleton } from 'src/shared/ui/base';
|
import { BaseCard, BaseChip, EmptyState, TableSkeleton } from 'src/shared/ui/base';
|
||||||
import type { TableSkeletonColumn } from 'src/shared/ui/base';
|
import type { TableSkeletonColumn } from 'src/shared/ui/base';
|
||||||
import { ExpandToggleButton, UserSearchSelector } from 'src/shared/ui';
|
|
||||||
|
|
||||||
type AnyBranch = IBranch | IPublicBranch;
|
|
||||||
|
|
||||||
const skeletonColumns: TableSkeletonColumn[] = [
|
const skeletonColumns: TableSkeletonColumn[] = [
|
||||||
{ label: 'Участок' },
|
{ label: 'Участок' },
|
||||||
@@ -134,18 +82,12 @@ const skeletonColumns: TableSkeletonColumn[] = [
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const branchStore = useBranchStore();
|
const branchStore = useBranchStore();
|
||||||
const system = useSystemStore();
|
const system = useSystemStore();
|
||||||
const session = useSessionStore();
|
|
||||||
const { setBranchPrivate, addBranchWhitelist, deleteBranchWhitelist } = useBranchPrivacy();
|
|
||||||
const { dismissed, dismiss } = useDismissibleBanner('ku:branches:banner-dismissed');
|
const { dismissed, dismiss } = useDismissibleBanner('ku:branches:banner-dismissed');
|
||||||
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|
||||||
// председателю совета доступно управление приватностью — для него грузим полный список
|
// публичные данные участков (сертификаты с ФИО) — доступны любому пайщику
|
||||||
// участков (с белым списком ФИО); остальным достаточно публичных данных
|
const branches = computed(() => branchStore.publicBranches);
|
||||||
const isChairman = computed(() => session.isChairman);
|
|
||||||
const branches = computed<AnyBranch[]>(() =>
|
|
||||||
isChairman.value ? branchStore.branches : branchStore.publicBranches,
|
|
||||||
);
|
|
||||||
|
|
||||||
// состояние системы управления из контракта: is_branched отдаётся системным стором
|
// состояние системы управления из контракта: is_branched отдаётся системным стором
|
||||||
// (system.info.cooperator_account). Контракт включает флаг при 3+ кооперативных участках.
|
// (system.info.cooperator_account). Контракт включает флаг при 3+ кооперативных участках.
|
||||||
@@ -156,27 +98,7 @@ const branchModeText = computed(() =>
|
|||||||
: 'Пока в кооперативе меньше трёх кооперативных участков — все пайщики участвуют в общем собрании напрямую. Когда участков станет три и более, система управления автоматически переключится на мажоритарную: собрания будут проходить через кооперативные участки.',
|
: 'Пока в кооперативе меньше трёх кооперативных участков — все пайщики участвуют в общем собрании напрямую. Когда участков станет три и более, система управления автоматически переключится на мажоритарную: собрания будут проходить через кооперативные участки.',
|
||||||
);
|
);
|
||||||
|
|
||||||
// локальное состояние разворота строк и формы белого списка (per-участок)
|
function branchTitle(branch: any): string {
|
||||||
const expanded = reactive(new Map<string, boolean>());
|
|
||||||
const busy = reactive(new Map<string, boolean>());
|
|
||||||
const whitelistInput = reactive<Record<string, string>>({});
|
|
||||||
|
|
||||||
function isExpanded(braname: string): boolean {
|
|
||||||
return expanded.get(braname) ?? false;
|
|
||||||
}
|
|
||||||
function toggleExpand(braname: string) {
|
|
||||||
expanded.set(braname, !isExpanded(braname));
|
|
||||||
}
|
|
||||||
function isBusy(braname: string): boolean {
|
|
||||||
return busy.get(braname) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// белый список (ФИО) есть только в полном объекте участка (доступен председателю)
|
|
||||||
function whitelistOf(branch: AnyBranch) {
|
|
||||||
return 'whitelist_certificates' in branch ? branch.whitelist_certificates : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function branchTitle(branch: AnyBranch): string {
|
|
||||||
return branch.short_name || branch.full_name || branch.braname;
|
return branch.short_name || branch.full_name || branch.braname;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +110,11 @@ function certificateName(certificate: any): string {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function chairmanName(branch: AnyBranch): string {
|
function chairmanName(branch: any): string {
|
||||||
return certificateName(branch.trustee_certificate);
|
return certificateName(branch.trustee_certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
function trustedNames(branch: AnyBranch): string[] {
|
function trustedNames(branch: any): string[] {
|
||||||
return (branch.trusted_certificates ?? []).map((certificate: any) => certificateName(certificate));
|
return (branch.trusted_certificates ?? []).map((certificate: any) => certificateName(certificate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,53 +122,10 @@ function openDetails(braname: string) {
|
|||||||
router.push({ name: 'ku-branch-details', params: { coopname: system.info.coopname, braname } });
|
router.push({ name: 'ku-branch-details', params: { coopname: system.info.coopname, braname } });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onTogglePrivate(branch: AnyBranch, value: boolean) {
|
|
||||||
busy.set(branch.braname, true);
|
|
||||||
try {
|
|
||||||
await setBranchPrivate({ coopname: system.info.coopname, braname: branch.braname, is_private: value });
|
|
||||||
SuccessAlert(value ? 'Участок сделан приватным' : 'Участок сделан публичным');
|
|
||||||
} catch (e: unknown) {
|
|
||||||
FailAlert(e);
|
|
||||||
} finally {
|
|
||||||
busy.set(branch.braname, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onAddWhitelist(branch: AnyBranch) {
|
|
||||||
const account = whitelistInput[branch.braname];
|
|
||||||
if (!account) return;
|
|
||||||
busy.set(branch.braname, true);
|
|
||||||
try {
|
|
||||||
await addBranchWhitelist({ coopname: system.info.coopname, braname: branch.braname, account });
|
|
||||||
whitelistInput[branch.braname] = '';
|
|
||||||
SuccessAlert('Пайщик добавлен в белый список участка');
|
|
||||||
} catch (e: unknown) {
|
|
||||||
FailAlert(e);
|
|
||||||
} finally {
|
|
||||||
busy.set(branch.braname, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onRemoveWhitelist(branch: AnyBranch, account: string) {
|
|
||||||
busy.set(branch.braname, true);
|
|
||||||
try {
|
|
||||||
await deleteBranchWhitelist({ coopname: system.info.coopname, braname: branch.braname, account });
|
|
||||||
SuccessAlert('Пайщик удалён из белого списка участка');
|
|
||||||
} catch (e: unknown) {
|
|
||||||
FailAlert(e);
|
|
||||||
} finally {
|
|
||||||
busy.set(branch.braname, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
if (isChairman.value) {
|
await branchStore.loadPublicBranches({ coopname: system.info.coopname });
|
||||||
await branchStore.loadBranches({ coopname: system.info.coopname });
|
|
||||||
} else {
|
|
||||||
await branchStore.loadPublicBranches({ coopname: system.info.coopname });
|
|
||||||
}
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
FailAlert(e);
|
FailAlert(e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -266,55 +145,4 @@ onMounted(async () => {
|
|||||||
width: 1%;
|
width: 1%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* колонка со стрелкой разворота — узкая */
|
|
||||||
.col-expand {
|
|
||||||
width: 1%;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* строка управления приватностью под участком */
|
|
||||||
.expand-row > td {
|
|
||||||
background: var(--p-surface-2);
|
|
||||||
padding: var(--p-4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--p-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin__subtitle {
|
|
||||||
margin-top: var(--p-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin__add {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--p-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin__search {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
max-width: 420px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin__list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--p-2);
|
|
||||||
max-width: 420px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.branch-admin__member {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: var(--p-2);
|
|
||||||
padding: var(--p-2) var(--p-3);
|
|
||||||
background: var(--p-surface-1);
|
|
||||||
border: 1px solid var(--p-line);
|
|
||||||
border-radius: var(--p-r-sm);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user