Files
econom/resources/js/pages/references/departments/Index.vue
brusnitsyn fb2e6c58e3
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
first commit
2026-04-06 00:06:00 +09:00

298 lines
12 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.

<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>