first commit
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

This commit is contained in:
brusnitsyn
2026-04-06 00:06:00 +09:00
commit fb2e6c58e3
409 changed files with 42953 additions and 0 deletions

View File

@@ -0,0 +1,297 @@
<script setup lang="ts">
import { Form, Head } from '@inertiajs/vue3';
import { Building2, FolderPlus, Plus } from 'lucide-vue-next';
import InputError from '@/components/InputError.vue';
import Heading from '@/components/Heading.vue';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { index, store as storeDepartment } from '@/routes/references/departments';
import { store as storeDepartmentProfile } from '@/routes/references/department-profiles';
import type { Department, DepartmentProfile, Team } from '@/types';
type Props = {
currentTeam?: Team | null;
departmentProfiles: DepartmentProfile[];
departments: Department[];
};
const props = defineProps<Props>();
defineOptions({
layout: (props: { currentTeam?: Team | null }) => ({
breadcrumbs: [
{
title: 'Справочники',
href: props.currentTeam ? index(props.currentTeam.slug) : '/',
},
{
title: 'Отделения',
href: props.currentTeam ? index(props.currentTeam.slug) : '/',
},
],
}),
});
</script>
<template>
<Head title="Отделения" />
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-2">
<Heading
title="Отделения"
description="Управляйте профилями отделений и создавайте сами отделения в одном разделе."
/>
</div>
<div class="grid gap-6 xl:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)]">
<Card class="border-sidebar-border/70">
<CardHeader>
<CardTitle class="flex items-center gap-2 text-base">
<FolderPlus class="h-4 w-4" />
Создать профиль отделения
</CardTitle>
<CardDescription>
Профиль используется как категория, к которой
привязывается отделение.
</CardDescription>
</CardHeader>
<CardContent>
<Form
v-bind="
props.currentTeam
? storeDepartmentProfile.form(
props.currentTeam.slug,
)
: undefined
"
class="space-y-4"
v-slot="{ errors, processing }"
>
<div class="grid gap-2">
<Label for="department-profile-name">
Название профиля
</Label>
<Input
id="department-profile-name"
name="name"
data-test="department-profile-name"
placeholder="Например, Клинический профиль"
required
/>
<InputError :message="errors.name" />
</div>
<Button
type="submit"
data-test="department-profile-submit"
:disabled="processing"
class="w-full sm:w-auto"
>
<Plus class="h-4 w-4" />
Создать профиль
</Button>
</Form>
</CardContent>
</Card>
<Card class="border-sidebar-border/70">
<CardHeader>
<CardTitle class="flex items-center gap-2 text-base">
<Building2 class="h-4 w-4" />
Создать отделение
</CardTitle>
<CardDescription>
Укажите название, профиль и статус активности для
нового отделения.
</CardDescription>
</CardHeader>
<CardContent>
<Form
v-bind="
props.currentTeam
? storeDepartment.form(props.currentTeam.slug)
: undefined
"
class="space-y-4"
v-slot="{ errors, processing }"
>
<div class="grid gap-2">
<Label for="department-name">Название отделения</Label>
<Input
id="department-name"
name="name"
data-test="department-name"
placeholder="Например, Приемное отделение"
required
/>
<InputError :message="errors.name" />
</div>
<div class="grid gap-2">
<Label for="department-profile">Профиль</Label>
<Select
name="department_profile_id"
data-test="department-profile-id"
>
<SelectTrigger
id="department-profile"
class="w-full"
>
<SelectValue
placeholder="Выберите профиль отделения"
/>
</SelectTrigger>
<SelectContent>
<SelectItem
v-for="departmentProfile in departmentProfiles"
:key="departmentProfile.id"
:value="String(departmentProfile.id)"
>
{{ departmentProfile.name }}
</SelectItem>
</SelectContent>
</Select>
<InputError
:message="errors.department_profile_id"
/>
</div>
<div class="grid gap-2">
<Label for="department-status">Статус</Label>
<Select
name="is_active"
default-value="1"
data-test="department-is-active"
>
<SelectTrigger
id="department-status"
class="w-full"
>
<SelectValue placeholder="Выберите статус" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Активно</SelectItem>
<SelectItem value="0">Неактивно</SelectItem>
</SelectContent>
</Select>
<InputError :message="errors.is_active" />
</div>
<Button
type="submit"
data-test="department-submit"
:disabled="processing || departmentProfiles.length === 0"
class="w-full sm:w-auto"
>
<Plus class="h-4 w-4" />
Создать отделение
</Button>
</Form>
<p
v-if="departmentProfiles.length === 0"
class="mt-3 text-sm text-muted-foreground"
>
Сначала создайте хотя бы один профиль отделения.
</p>
</CardContent>
</Card>
</div>
<div class="grid gap-6 xl:grid-cols-2">
<Card class="border-sidebar-border/70">
<CardHeader>
<CardTitle>Профили отделений</CardTitle>
<CardDescription>
Всего профилей: {{ departmentProfiles.length }}
</CardDescription>
</CardHeader>
<CardContent class="space-y-3">
<div
v-for="departmentProfile in departmentProfiles"
:key="departmentProfile.id"
class="flex items-center justify-between rounded-lg border px-4 py-3"
>
<div>
<p class="font-medium">
{{ departmentProfile.name }}
</p>
<p class="text-sm text-muted-foreground">
Отделений: {{
departmentProfile.departmentsCount
}}
</p>
</div>
</div>
<p
v-if="departmentProfiles.length === 0"
class="py-6 text-center text-sm text-muted-foreground"
>
Профили отделений пока не созданы.
</p>
</CardContent>
</Card>
<Card class="border-sidebar-border/70">
<CardHeader>
<CardTitle>Список отделений</CardTitle>
<CardDescription>
Всего отделений: {{ departments.length }}
</CardDescription>
</CardHeader>
<CardContent class="space-y-3">
<div
v-for="department in departments"
:key="department.id"
class="flex items-center justify-between rounded-lg border px-4 py-3"
>
<div>
<p class="font-medium">{{ department.name }}</p>
<p class="text-sm text-muted-foreground">
Профиль:
{{ department.departmentProfile.name }}
</p>
</div>
<Badge
:variant="
department.isActive ? 'default' : 'secondary'
"
>
{{
department.isActive
? 'Активно'
: 'Неактивно'
}}
</Badge>
</div>
<p
v-if="departments.length === 0"
class="py-6 text-center text-sm text-muted-foreground"
>
Отделения пока не созданы.
</p>
</CardContent>
</Card>
</div>
</div>
</template>