This commit is contained in:
brusnitsyn
2026-02-20 17:28:16 +09:00
parent 94e374c32b
commit 52a80ccd3b
41 changed files with 2555 additions and 206 deletions

View File

@@ -0,0 +1,47 @@
<script setup>
import {NH1, NFlex, NSpace, NP} from 'naive-ui'
import {TbUsers} from "vue-icons-plus/tb";
import AppLayout from "../../Layouts/AppLayout.vue";
import {Link} from "@inertiajs/vue3";
import {computed} from "vue";
import {format} from "date-fns";
import {useNow} from "@vueuse/core";
import {ru} from "date-fns/locale";
import StartButton from "../../Components/StartButton.vue";
const currentDate = computed(() => {
const formatted = format(useNow().value, 'PPPPpp', {
locale: ru
})
return formatted.charAt(0).toUpperCase() + formatted.slice(1)
})
</script>
<template>
<AppLayout>
<div class="flex flex-col justify-start items-center mt-12">
<NFlex vertical align="center" justify="center" class="max-w-xl w-full">
<NSpace vertical align="center">
<NH1 class="mb-0!">
Панель администратора
</NH1>
<NP class="mb-4!">
{{ currentDate }}
</NP>
</NSpace>
<StartButton title="Учетные записи"
description="Создание и редактирование учетных записей"
href="/admin/users"
:tag="Link"
:icon="TbUsers"
/>
</NFlex>
</div>
</AppLayout>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,61 @@
<script setup>
import {NButton, NFlex, NGi, NGrid, NH2, NForm, NFormItem, NInput} from "naive-ui";
import AppLayout from "../../../Layouts/AppLayout.vue";
import AppContainer from "../../../Components/AppContainer.vue";
import AppPanel from "../../../Components/AppPanel.vue";
import {useForm} from "@inertiajs/vue3";
import {ref} from "vue";
const props = defineProps({
departments: {
type: Array,
default: []
},
roles: {
type: Array,
default: []
}
})
const form = ref({
'name': '',
'login': '',
'password': '',
'is_active': true,
})
</script>
<template>
<AppLayout>
<template #header>
<NFlex align="center" justify="space-between" class="max-w-6xl mx-auto mt-6 mb-4 w-full">
<NH2>
Создание нового пользователя
</NH2>
</NFlex>
</template>
<AppContainer>
<AppPanel>
<NForm v-model:model="form">
<NFormItem label="Имя">
<NInput v-model:value="form.name" />
</NFormItem>
<NFormItem label="Логин">
<NInput v-model:value="form.login" />
</NFormItem>
<NFormItem label="Логин">
<NInput v-model:value="form.password" />
</NFormItem>
<NFormItem label="Логин">
<NInput v-model:value="form.password" />
</NFormItem>
</NForm>
</AppPanel>
</AppContainer>
</AppLayout>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,81 @@
<script setup>
import AppLayout from "../../../Layouts/AppLayout.vue";
import {NFlex, NH2, NSpace, NButton, NDataTable} from 'naive-ui'
import {h, ref} from "vue";
import {Link} from "@inertiajs/vue3";
const props = defineProps({
users: {
type: Array,
default: []
}
})
const columns = ref([
{
title: 'Имя',
key: 'name'
},
{
title: 'Логин',
key: 'login'
},
{
title: 'Активен',
key: 'is_active',
render: (row) => {
return row.is_active ? 'Да' : 'Нет'
}
},
{
title: 'Дата создания',
key: 'created_at'
},
{
title: 'Дата изменения',
key: 'updated_at'
},
{
title: 'Действия',
key: 'actions',
render: (row) => {
return h(NButton, {
text: true,
size: 'small',
tag: Link,
href: `/admin/users/${row.id}`
}, 'Редактировать')
}
},
])
</script>
<template>
<AppLayout>
<template #header>
<NFlex align="center" justify="space-between" class="max-w-6xl mx-auto mt-6 mb-4 w-full">
<NH2>
Учетные записи
</NH2>
<NSpace>
<NButton :tag="Link" href="/admin/users/new" type="primary">
Создать учетную запись
</NButton>
</NSpace>
</NFlex>
</template>
<NDataTable class="max-w-6xl mx-auto mb-4 w-full" :columns="columns" :data="users" />
</AppLayout>
</template>
<style scoped>
:deep(.n-h) {
margin: 0;
}
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
font-size: var(--n-font-size);
}
</style>

View File

@@ -0,0 +1,120 @@
<script setup>
import {NButton, NDataTable, NScrollbar, NList, NListItem, NGrid, NGi, NFlex, NH2, NSpace} from "naive-ui";
import AppLayout from "../../../Layouts/AppLayout.vue";
import AppPanel from "../../../Components/AppPanel.vue";
import AppContainer from "../../../Components/AppContainer.vue";
const props = defineProps({
userData: {
type: Object,
default: {}
},
roles: {
type: Array,
default: []
},
departments: {
type: Array,
default: []
}
})
</script>
<template>
<AppLayout>
<template #header>
<NFlex align="center" justify="space-between" class="max-w-6xl mx-auto mt-6 mb-4 w-full">
<NH2>
{{ userData.name }}
</NH2>
<NSpace>
<NButton type="primary">
Создать учетную запись
</NButton>
</NSpace>
</NFlex>
</template>
<AppContainer>
<NGrid cols="2" x-gap="12" y-gap="12">
<NGi>
<AppPanel header="Информация о пользователе" min-h="148px" max-h="148px">
<NSpace vertical>
<NFlex align="center" justify="space-between">
<div>
Имя
</div>
<div>
{{ userData.name }}
</div>
</NFlex>
<NFlex align="center" justify="space-between">
<div>
Логин
</div>
<div>
{{ userData.login }}
</div>
</NFlex>
<NFlex align="center" justify="space-between">
<div>
Активен
</div>
<div>
{{ userData.is_active ? 'Да' : 'Нет' }}
</div>
</NFlex>
<NFlex align="center" justify="space-between">
<div>
Дата создания
</div>
<div>
{{ userData.created_at }}
</div>
</NFlex>
<NFlex align="center" justify="space-between">
<div>
Дата обновления
</div>
<div>
{{ userData.updated_at }}
</div>
</NFlex>
</NSpace>
</AppPanel>
</NGi>
<NGi>
</NGi>
<NGi>
<AppPanel :header="`Доступные отделения (${departments.length})`" min-h="148px" max-h="148px">
<NList>
<NListItem v-for="department in departments">
{{ department.name_full }}
</NListItem>
</NList>
</AppPanel>
</NGi>
<NGi>
<AppPanel :header="`Доступные роли (${roles.length})`" min-h="148px" max-h="148px">
<NList>
<NListItem v-for="role in roles">
{{ role.name }}
</NListItem>
</NList>
</AppPanel>
</NGi>
</NGrid>
</AppContainer>
</AppLayout>
</template>
<style scoped>
:deep(.n-h) {
margin: 0;
}
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
font-size: var(--n-font-size);
}
</style>