diff --git a/src/app/(admin)/dashboard/page.tsx b/src/app/(admin)/dashboard/page.tsx index 40ad72d..2f255d0 100644 --- a/src/app/(admin)/dashboard/page.tsx +++ b/src/app/(admin)/dashboard/page.tsx @@ -1,6 +1,6 @@ import { redirect } from "next/navigation"; import { getCurrentSession } from "@/lib/auth/session"; -import { listTickets } from "@/lib/tickets/service"; +import { listTickets, listTags } from "@/lib/tickets/service"; import { TicketBoard } from "./ticket-board"; export default async function DashboardPage() { @@ -8,6 +8,6 @@ export default async function DashboardPage() { if (!session) redirect("/login"); const currentUser = { id: session.user.id, role: session.user.role }; - const tickets = await listTickets(undefined, currentUser); - return ; + const [tickets, tags] = await Promise.all([listTickets(undefined, currentUser), listTags()]); + return ; } diff --git a/src/app/(admin)/dashboard/ticket-board.tsx b/src/app/(admin)/dashboard/ticket-board.tsx index 1f3de5b..006e5c1 100644 --- a/src/app/(admin)/dashboard/ticket-board.tsx +++ b/src/app/(admin)/dashboard/ticket-board.tsx @@ -6,7 +6,7 @@ import { AnimatePresence, motion } from "framer-motion"; import { Send, Globe, UserRound, Mail, MessageSquare, Plus, Inbox, Search, X } from "lucide-react"; import { useTicketEvents } from "@/lib/events/use-ticket-events"; import { formatRelativeTime } from "@/lib/format"; -import type { TicketDTO, TicketStatus } from "@/lib/tickets/types"; +import type { TicketDTO, TicketStatus, TagDTO } from "@/lib/tickets/types"; import { isTicketVisibleTo } from "@/lib/tickets/visibility"; import { NewTicketModal } from "./new-ticket-modal"; import { Avatar } from "@/components/avatar"; @@ -45,9 +45,11 @@ const PRIORITY_COLOR: Record = { export function TicketBoard({ initialTickets, + allTags, currentUser, }: { initialTickets: TicketDTO[]; + allTags: TagDTO[]; currentUser: { id: string; role: "admin" | "agent" }; }) { const [tickets, setTickets] = useState(initialTickets); @@ -100,13 +102,11 @@ export function TicketBoard({ const baseTickets = query.trim() ? (searchResults ?? tickets) : tickets; - const availableTags = useMemo(() => { - const map = new Map(); - for (const ticket of baseTickets) { - for (const tag of ticket.tags) map.set(tag.id, tag); - } - return [...map.values()].sort((a, b) => a.name.localeCompare(b.name)); - }, [baseTickets]); + // Every tag that exists, not just ones already applied to a currently + // loaded ticket — otherwise a freshly created tag has nothing to filter + // by until someone happens to tag a ticket with it. allTags is already + // name-sorted server-side (listTags orders by tagsTable.name). + const availableTags = allTags; const filteredTickets = useMemo(() => { if (!activeTagId) return baseTickets; diff --git a/src/app/(admin)/settings/tags/tags-manager.tsx b/src/app/(admin)/settings/tags/tags-manager.tsx index f5a1aaf..b8136a4 100644 --- a/src/app/(admin)/settings/tags/tags-manager.tsx +++ b/src/app/(admin)/settings/tags/tags-manager.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Plus, Trash2 } from "lucide-react"; +import { Plus, Star, Trash2 } from "lucide-react"; import { TAG_COLOR_CLASSES, TAG_COLORS, TAG_COLOR_LABELS } from "@/lib/tags/colors"; import type { TagDTO, TagColor } from "@/lib/tickets/types"; @@ -40,6 +40,18 @@ export function TagsManager({ initialTags }: { initialTags: TagDTO[] }) { setTags((prev) => prev.filter((t) => t.id !== id)); } + async function handleToggleDefault(tag: TagDTO) { + const nextIsDefault = !tag.isDefault; + const res = await fetch(`/api/tags/${tag.id}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ isDefault: nextIsDefault }), + }); + if (!res.ok) return; + const { tags: updated } = await res.json(); + setTags(updated); + } + return (
@@ -77,12 +89,23 @@ export function TagsManager({ initialTags }: { initialTags: TagDTO[] }) { {tags.length === 0 &&

Тегов пока нет.

} +

+ Тег по умолчанию отмечается звёздочкой — он автоматически ставится на каждую новую заявку. +

+
{tags.map((tag) => ( + {tag.name}