Restructure manager navigation and views

This commit is contained in:
Ruslan Bakiev
2026-04-04 09:29:16 +07:00
parent 264b88bcee
commit ecd92ef7e4
12 changed files with 569 additions and 118 deletions

View File

@@ -1,5 +1,8 @@
<script setup lang="ts">
import { useQuery } from '@vue/apollo-composable';
import FullCalendar from '@fullcalendar/vue3';
import dayGridPlugin from '@fullcalendar/daygrid';
import ruLocale from '@fullcalendar/core/locales/ru';
import OrderStatusBadge from '~/components/orders/OrderStatusBadge.vue';
import {
ManagerOrdersDocument,
@@ -12,6 +15,9 @@ definePageMeta({
type ManagerOrderItem = ManagerOrdersQuery['managerOrders'][number];
const route = useRoute();
const router = useRouter();
const ACTIVE_STATUSES = new Set(['NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CONFIRMED', 'IN_PROGRESS']);
const CLOSED_STATUSES = new Set(['COMPLETED', 'CLIENT_REJECTED', 'MANAGER_REJECTED', 'MANAGER_BLOCKED']);
@@ -19,6 +25,19 @@ const ordersQuery = useQuery(ManagerOrdersDocument, { status: null });
const search = ref('');
const statusFilter = ref<'ALL' | 'WAITING' | 'ACTIVE' | 'CLOSED'>('ALL');
const viewMode = computed<'cards' | 'calendar'>(() => (
route.query.view === 'calendar' ? 'calendar' : 'cards'
));
function setViewMode(view: 'cards' | 'calendar') {
void router.replace({
query: {
...route.query,
view,
},
});
}
function matchesFilter(order: ManagerOrderItem) {
if (statusFilter.value === 'ALL') {
return true;
@@ -50,22 +69,59 @@ const filteredOrders = computed(() => {
return matchesSearch && matchesFilter(order);
});
});
const calendarOptions = computed(() => ({
plugins: [dayGridPlugin],
locale: ruLocale,
initialView: 'dayGridMonth',
height: 'auto',
fixedWeekCount: false,
firstDay: 1,
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: '',
},
buttonText: {
today: 'Сегодня',
},
events: filteredOrders.value.map((order) => ({
id: order.id,
title: `${order.code}${order.customerId}`,
start: new Date(order.createdAt).toISOString(),
allDay: true,
})),
eventClick: ({ event }: { event: { id: string } }) => {
void router.push(`/client-orders/${event.id}`);
},
}));
</script>
<template>
<section class="space-y-6">
<UiSectionSearchHero
v-model="search"
title="Заказы клиентов"
title="Заказы"
search-placeholder="Номер заказа, клиент, адрес или товар"
>
<template #controls>
<select v-model="statusFilter" class="select select-bordered w-full rounded-full bg-white md:w-64">
<option value="ALL">Все заказы</option>
<option value="WAITING">Ожидают подтверждения</option>
<option value="ACTIVE">Активные</option>
<option value="CLOSED">Закрытые</option>
</select>
<div class="flex w-full flex-col gap-3 md:w-auto md:flex-row">
<select v-model="statusFilter" class="select select-bordered w-full rounded-full bg-white md:w-64">
<option value="ALL">Все заказы</option>
<option value="WAITING">Ожидают подтверждения</option>
<option value="ACTIVE">Активные</option>
<option value="CLOSED">Закрытые</option>
</select>
<div class="tabs tabs-boxed w-fit bg-white">
<button class="tab" :class="{ 'tab-active': viewMode === 'cards' }" @click="setViewMode('cards')">
Карточки
</button>
<button class="tab" :class="{ 'tab-active': viewMode === 'calendar' }" @click="setViewMode('calendar')">
Календарь
</button>
</div>
</div>
</template>
</UiSectionSearchHero>
@@ -76,6 +132,10 @@ const filteredOrders = computed(() => {
Заказы по текущим условиям не найдены.
</div>
<div v-else-if="viewMode === 'calendar'" class="surface-card rounded-3xl p-4 md:p-5">
<FullCalendar :options="calendarOptions" />
</div>
<div v-else class="space-y-4">
<NuxtLink
v-for="order in filteredOrders"