refactor: натравил форматтер на весь фронт
This commit is contained in:
@@ -503,8 +503,8 @@ onMounted(() => {
|
||||
{{ syncError || visibleSyncResult.error }}
|
||||
</template>
|
||||
<template v-else>
|
||||
Создано: {{ visibleSyncResult.created }} / обновлено:
|
||||
{{ visibleSyncResult.updated }} / пропущено: {{ visibleSyncResult.skipped }}
|
||||
Создано: {{ visibleSyncResult.created }} / обновлено: {{ visibleSyncResult.updated }} /
|
||||
пропущено: {{ visibleSyncResult.skipped }}
|
||||
</template>
|
||||
</div>
|
||||
<div v-else-if="syncError" class="sync-result failed">
|
||||
@@ -694,7 +694,9 @@ onMounted(() => {
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 12px;
|
||||
background: var(--color-white-a82);
|
||||
box-shadow: 0 8px 22px var(--color-black-a04), inset 0 1px 0 var(--color-white-a90);
|
||||
box-shadow:
|
||||
0 8px 22px var(--color-black-a04),
|
||||
inset 0 1px 0 var(--color-white-a90);
|
||||
}
|
||||
.sync-advanced-fields .glass-input {
|
||||
background: var(--color-white-a96);
|
||||
|
||||
@@ -359,7 +359,9 @@ onMounted(() => {
|
||||
></textarea>
|
||||
<div class="prompt-footer">
|
||||
<div class="prompt-messages">
|
||||
<span class="prompt-hint">Обязательные плейсхолдеры: {lectureContext}, {reviewText}</span>
|
||||
<span class="prompt-hint"
|
||||
>Обязательные плейсхолдеры: {lectureContext}, {reviewText}</span
|
||||
>
|
||||
<span v-if="promptError" class="prompt-error">{{ promptError }}</span>
|
||||
<span v-else-if="promptSuccess" class="prompt-success">{{ promptSuccess }}</span>
|
||||
</div>
|
||||
|
||||
@@ -33,11 +33,11 @@ const roleBadgeClasses: Record<ApiUserRole, string> = {
|
||||
}
|
||||
|
||||
const rows = computed(() =>
|
||||
users.value.map(user => ({
|
||||
users.value.map((user) => ({
|
||||
id: user.id,
|
||||
name: user.displayName || user.email,
|
||||
email: user.email,
|
||||
role: user.roles.map(role => roleLabels[role]).join(', '),
|
||||
role: user.roles.map((role) => roleLabels[role]).join(', '),
|
||||
apiRoles: user.roles,
|
||||
institute: 'ЮФУ',
|
||||
activity: user.isActive ? 'Активен' : 'Заблокирован',
|
||||
@@ -52,7 +52,10 @@ async function fetchUsers() {
|
||||
try {
|
||||
users.value = await usersApi.list({
|
||||
Search: search.value || undefined,
|
||||
Role: roleFilter.value === 'Все роли' ? undefined : roleApi[roleFilter.value as keyof typeof roleApi],
|
||||
Role:
|
||||
roleFilter.value === 'Все роли'
|
||||
? undefined
|
||||
: roleApi[roleFilter.value as keyof typeof roleApi],
|
||||
PageSize: 100,
|
||||
})
|
||||
} catch (err) {
|
||||
@@ -81,14 +84,16 @@ function hasRole(row: Record<string, unknown>, role: ApiUserRole) {
|
||||
}
|
||||
|
||||
function getRoleChipClass(row: Record<string, unknown>, role: ApiUserRole) {
|
||||
return hasRole(row, role) ? ['badge', roleBadgeClasses[role]] : ['btn-ghost', 'role-chip-inactive']
|
||||
return hasRole(row, role)
|
||||
? ['badge', roleBadgeClasses[role]]
|
||||
: ['btn-ghost', 'role-chip-inactive']
|
||||
}
|
||||
|
||||
async function toggleRole(row: Record<string, unknown>, role: ApiUserRole) {
|
||||
const id = Number(row.id)
|
||||
const currentRoles = getRowRoles(row)
|
||||
const nextRoles = currentRoles.includes(role)
|
||||
? currentRoles.filter(currentRole => currentRole !== role)
|
||||
? currentRoles.filter((currentRole) => currentRole !== role)
|
||||
: [...currentRoles, role]
|
||||
|
||||
if (!nextRoles.length) return
|
||||
@@ -125,7 +130,11 @@ onMounted(fetchUsers)
|
||||
</div>
|
||||
|
||||
<EmptyState v-if="error" title="Не удалось загрузить пользователей" :subtitle="error" />
|
||||
<EmptyState v-else-if="!rows.length && !loading" title="Пользователей не найдено" subtitle="Попробуйте изменить фильтры." />
|
||||
<EmptyState
|
||||
v-else-if="!rows.length && !loading"
|
||||
title="Пользователей не найдено"
|
||||
subtitle="Попробуйте изменить фильтры."
|
||||
/>
|
||||
<DataTable :columns="columns" :rows="rows">
|
||||
<template #role="{ row }">
|
||||
<div class="role-chips">
|
||||
@@ -142,11 +151,15 @@ onMounted(fetchUsers)
|
||||
</div>
|
||||
</template>
|
||||
<template #activity="{ value }">
|
||||
<span class="badge" :class="value === 'Активен' ? 'badge-green' : 'badge-orange'">{{ value }}</span>
|
||||
<span class="badge" :class="value === 'Активен' ? 'badge-green' : 'badge-orange'">{{
|
||||
value
|
||||
}}</span>
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<div class="actions">
|
||||
<button class="btn-ghost" @click="toggleActive(row)">{{ row.isActive ? 'Заблокировать' : 'Активировать' }}</button>
|
||||
<button class="btn-ghost" @click="toggleActive(row)">
|
||||
{{ row.isActive ? 'Заблокировать' : 'Активировать' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</DataTable>
|
||||
@@ -155,13 +168,53 @@ onMounted(fetchUsers)
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.admin-users { display: flex; flex-direction: column; gap: 16px; }
|
||||
.header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
||||
.filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 12px; }
|
||||
.actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }
|
||||
.role-chips { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; }
|
||||
.role-chip { cursor: pointer; border: 0; transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease; }
|
||||
.role-chip:hover { transform: translateY(-1px); box-shadow: 0 4px 12px var(--color-primary-a15); }
|
||||
.role-chip:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
|
||||
.role-chip-inactive { opacity: 0.75; }
|
||||
.admin-users {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.filters {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.role-chips {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.role-chip {
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
transition:
|
||||
transform 0.15s ease,
|
||||
box-shadow 0.15s ease,
|
||||
opacity 0.15s ease;
|
||||
}
|
||||
.role-chip:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px var(--color-primary-a15);
|
||||
}
|
||||
.role-chip:focus-visible {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.role-chip-inactive {
|
||||
opacity: 0.75;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user