1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

Change code, for build Docker

This commit is contained in:
MoonTestUse1
2024-12-23 22:03:04 +06:00
parent b6608572f2
commit 33c6806c1d
12 changed files with 89 additions and 29 deletions

View File

@@ -4,7 +4,7 @@
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<h3 class="text-sm font-semibold mb-2 flex items-center gap-2">
<PhoneIcon size="16" class="text-blue-400" />
<PhoneIcon :size="16" class="text-blue-400" />
Контактная информация
</h3>
<div class="space-y-1 text-sm text-slate-300">
@@ -14,7 +14,7 @@
</div>
<div>
<h3 class="text-sm font-semibold mb-2 flex items-center gap-2">
<ClockIcon size="16" class="text-blue-400" />
<ClockIcon :size="16" class="text-blue-400" />
Режим работы
</h3>
<div class="space-y-1 text-sm text-slate-300">
@@ -24,7 +24,7 @@
</div>
<div>
<h3 class="text-sm font-semibold mb-2 flex items-center gap-2">
<MailIcon size="16" class="text-blue-400" />
<MailIcon :size="16" class="text-blue-400" />
Техподдержка
</h3>
<div class="space-y-1 text-sm text-slate-300">

View File

@@ -3,14 +3,14 @@
<div class="container mx-auto px-4">
<div class="flex flex-col sm:flex-row justify-between items-center gap-2">
<div class="flex items-center space-x-3">
<Building2Icon size="28" class="text-blue-400" />
<Building2Icon :size="28" class="text-blue-400" />
<div class="text-center sm:text-left">
<h1 class="text-lg sm:text-xl font-semibold">Администрация КАО</h1>
<p class="text-xs sm:text-sm text-slate-300">Портал технической поддержки</p>
</div>
</div>
<div class="flex items-center space-x-2">
<PhoneIcon size="18" class="text-blue-400" />
<PhoneIcon :size="18" class="text-blue-400" />
<div class="text-center sm:text-left">
<p class="text-xs text-slate-300">Поддержка:</p>
<p class="text-sm font-semibold">8 (800) 123-45-67</p>

View File

@@ -6,7 +6,7 @@
<div class="p-2 bg-blue-50 rounded-lg">
<component
:is="employee ? UserIcon : UserPlusIcon"
size="24"
:size="24"
class="text-blue-600"
/>
</div>
@@ -18,7 +18,7 @@
@click="$emit('close')"
class="text-gray-400 hover:text-gray-500 transition-colors"
>
<XIcon size="20" />
<XIcon :size="20" />
</button>
</div>
@@ -30,7 +30,7 @@
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<UserIcon size="18" class="text-gray-400" />
<UserIcon :size="18" class="text-gray-400" />
</div>
<input
v-model="formData.last_name"
@@ -48,7 +48,7 @@
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<UserIcon size="18" class="text-gray-400" />
<UserIcon :size="18" class="text-gray-400" />
</div>
<input
v-model="formData.first_name"
@@ -66,7 +66,7 @@
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<BuildingIcon size="18" class="text-gray-400" />
<BuildingIcon :size="18" class="text-gray-400" />
</div>
<select
v-model="formData.department"
@@ -87,7 +87,7 @@
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<DoorClosedIcon size="18" class="text-gray-400" />
<DoorClosedIcon :size="18" class="text-gray-400" />
</div>
<input
v-model="formData.office"
@@ -105,7 +105,7 @@
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<LockIcon size="18" class="text-gray-400" />
<LockIcon :size="18" class="text-gray-400" />
</div>
<input
v-model="formData.password"
@@ -127,14 +127,14 @@
@click="$emit('close')"
class="px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors flex items-center gap-2"
>
<XIcon size="16" />
<XIcon :size="16" />
Отмена
</button>
<button
type="submit"
class="px-4 py-2 bg-blue-600 text-white rounded-md text-sm font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors flex items-center gap-2"
>
<component :is="employee ? SaveIcon : UserPlusIcon" size="16" />
<component :is="employee ? SaveIcon : UserPlusIcon" :size="16" />
{{ employee ? 'Сохранить' : 'Добавить' }}
</button>
</div>
@@ -147,6 +147,8 @@
import { ref, onMounted } from 'vue';
import { XIcon, UserIcon, BuildingIcon, DoorClosedIcon, LockIcon, UserPlusIcon, SaveIcon } from 'lucide-vue-next';
import { departments } from '@/utils/constants';
import type { EmployeeFormData } from '@/types/employee';
const props = defineProps<{
employee?: any;
@@ -157,7 +159,7 @@ const emit = defineEmits<{
(e: 'submit', data: any): void;
}>();
const formData = ref({
const formData = ref<EmployeeFormData>({
first_name: '',
last_name: '',
department: '',
@@ -165,6 +167,7 @@ const formData = ref({
password: ''
});
onMounted(() => {
if (props.employee) {
formData.value = {
@@ -180,7 +183,7 @@ onMounted(() => {
function handleSubmit() {
const data = { ...formData.value };
if (props.employee && !data.password) {
delete data.password;
delete data.password; // Теперь это безопасно, так как password опциональный
}
emit('submit', data);
}

View File

@@ -1,12 +1,17 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { UserPlusIcon, PencilIcon } from 'lucide-vue-next';
import { departments } from '@/utils/constants';
import EmployeeForm from './EmployeeForm.vue';
import EmployeeFormModal from './employee/EmployeeFormModal.vue';
import Notification from '@/components/ui/Notification.vue';
import type { Employee } from '@/types/employee';
const employees = ref([]);
const employees = ref<Employee[]>([]); // Добавляем типизацию массива сотрудников
const showAddForm = ref(false);
const editingEmployee = ref(null);
const editingEmployee = ref<Employee | null>(null);
const showNotification = ref(false);
const notificationMessage = ref('');
function getDepartmentLabel(value: string) {
return departments.find(d => d.value === value)?.label || value;

View File

@@ -7,7 +7,7 @@
@click="$emit('close')"
class="text-gray-400 hover:text-gray-500"
>
<XIcon size="20" />
<XIcon :size="20" />
</button>
</div>

View File

@@ -105,16 +105,16 @@
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import type { Request } from '@/types/request';
import RequestStatusBadge from './RequestStatusBadge.vue';
import RequestPriorityBadge from './RequestPriorityBadge.vue';
import RequestStatusModal from './RequestStatusModal.vue';
import RequestDescriptionModal from './RequestDescriptionModal.vue';
import Notification from '@/components/ui/Notification.vue';
import { getRequestTypeLabel } from '@/utils/constants';
const requests = ref([]);
const selectedRequest = ref(null);
const selectedDescription = ref(null);
const requests = ref<Request[]>([]); // Типизируем массив запросов
const selectedRequest = ref<Request | null>(null);
const selectedDescription = ref<Request | null>(null);
const showNotification = ref(false);
const filter = ref('all');
const searchQuery = ref('');
@@ -135,6 +135,7 @@ const filteredRequests = computed(() => {
return result;
});
function formatDate(date: string) {
return new Date(date).toLocaleString('ru-RU');
}

View File

@@ -8,7 +8,7 @@
</template>
<script setup lang="ts">
const props = defineProps<{
const { priority } = defineProps<{
priority: 'low' | 'medium' | 'high' | 'critical'
}>();

View File

@@ -46,16 +46,17 @@
<script setup lang="ts">
import RequestStatusBadge from './RequestStatusBadge.vue';
import type { RequestStatus } from '@/types/request';
const props = defineProps<{
currentStatus: string;
currentStatus: RequestStatus;
}>();
const emit = defineEmits(['close', 'update']);
const allStatuses = ['new', 'in_progress', 'resolved', 'closed'] as const;
const allStatuses: RequestStatus[] = ['new', 'in_progress', 'resolved', 'closed'];
function handleStatusSelect(newStatus: string) {
function handleStatusSelect(newStatus: RequestStatus) {
if (newStatus === props.currentStatus) return;
emit('update', newStatus);
emit('close');

View File

@@ -55,7 +55,7 @@
class="w-full bg-blue-600 text-white py-2 px-4 text-sm sm:text-base rounded-md hover:bg-blue-700 transition-colors flex items-center justify-center gap-2 disabled:opacity-50"
>
<component :is="isSubmitting ? LoaderIcon : SendIcon"
size="18"
:size="18"
:class="{ 'animate-spin': isSubmitting }"
/>
{{ isSubmitting ? 'Отправка...' : 'Отправить заявку' }}

View File

@@ -14,4 +14,23 @@ export interface LoginCredentials {
export interface AdminCredentials {
username: string;
password: string;
}
export interface Employee {
id: number;
first_name: string;
last_name: string;
department: string;
office: string;
}
export interface Request {
id: number;
employee_last_name: string;
employee_first_name: string;
employee_office: string;
request_type: string;
priority: 'low' | 'medium' | 'high' | 'critical';
status: 'new' | 'in_progress' | 'resolved' | 'closed';
created_at: string;
}

17
src/types/employee.ts Normal file
View File

@@ -0,0 +1,17 @@
export interface Employee {
id: number;
first_name: string;
last_name: string;
department: string;
office: string;
created_at?: string;
}
export interface EmployeeFormData {
first_name: string;
last_name: string;
department: string;
office: string;
password?: string; // Делаем password опциональным
}

14
src/types/request.ts Normal file
View File

@@ -0,0 +1,14 @@
export type RequestStatus = 'new' | 'in_progress' | 'resolved' | 'closed';
export interface Request {
id: number;
status: RequestStatus;
created_at: string;
employee_last_name: string;
employee_first_name: string;
employee_office: string;
request_type: string;
priority: 'low' | 'medium' | 'high' | 'critical';
description: string;
}