diff --git a/frontend/src/app/departments/[id]/page.tsx b/frontend/src/app/departments/[id]/page.tsx index f3a35744..459f8e1c 100644 --- a/frontend/src/app/departments/[id]/page.tsx +++ b/frontend/src/app/departments/[id]/page.tsx @@ -1,6 +1,7 @@ "use client"; import Link from "next/link"; +import dynamic from "next/dynamic"; import { useParams, useRouter } from "next/navigation"; import { useEffect, useMemo, useRef, useState, type ReactNode, type RefObject } from "react"; import { @@ -51,6 +52,13 @@ import { displayUserName, formatDate, loadAllPages, userProfileLink } from "@/li import type { DepartmentMemberLink, DepartmentPermissionChoice, DepartmentRole, Document, User } from "@/types/api"; import { toast } from "sonner"; +const RegulationCreateForm = dynamic( + () => import("@/components/documents/DocumentUploadForm").then((mod) => ({ + default: mod.RegulationCreateForm, + })), + { ssr: false }, +); + type DepartmentMemberModalMode = "add" | "assignRole"; type DepartmentRoleDraft = { id: number | null; @@ -995,6 +1003,9 @@ export default function DepartmentDetailPage() { const [membersExpanded, setMembersExpanded] = useState(false); const [regulationsExpanded, setRegulationsExpanded] = useState(false); const [departmentRegulations, setDepartmentRegulations] = useState([]); + const [departmentRegulationsLoading, setDepartmentRegulationsLoading] = useState(true); + const [regulationsRefreshKey, setRegulationsRefreshKey] = useState(0); + const [createRegulationOpen, setCreateRegulationOpen] = useState(false); const [selectedRegulation, setSelectedRegulation] = useState(null); const [roleMenuOpenForId, setRoleMenuOpenForId] = useState(null); const roleMenuRef = useRef(null); @@ -1023,9 +1034,9 @@ export default function DepartmentDetailPage() { if (!Number.isFinite(departmentId)) return; let cancelled = false; - setRegulationsExpanded(false); const loadDepartmentRegulations = async () => { + setDepartmentRegulationsLoading(true); try { const regulations = await loadAllPages((pageParams) => ( apiClient.getDocuments({ ...pageParams, is_regulation: true }) @@ -1046,6 +1057,8 @@ export default function DepartmentDetailPage() { } catch (error) { console.error("Не удалось загрузить регламенты отдела:", error); if (!cancelled) setDepartmentRegulations([]); + } finally { + if (!cancelled) setDepartmentRegulationsLoading(false); } }; @@ -1053,6 +1066,10 @@ export default function DepartmentDetailPage() { return () => { cancelled = true; }; + }, [departmentId, regulationsRefreshKey]); + + useEffect(() => { + setRegulationsExpanded(false); }, [departmentId]); const refreshSelectedRegulation = async () => { @@ -1425,62 +1442,93 @@ export default function DepartmentDetailPage() { - {departmentRegulations.length > 0 ? ( -
-
-
-
-

- Регламенты отдела -

- {departmentRegulations.length} -
-

- Документы, требующие ознакомления сотрудников отдела. +

+
+
+
+

+ Регламенты отдела

+ + {departmentRegulationsLoading ? "…" : departmentRegulations.length} +
+

+ Документы, требующие ознакомления сотрудников отдела. +

+
+
+ {departmentRegulations.length > 0 ? ( + + ) : null}
+
- {regulationsExpanded ? ( -
- {departmentRegulations.map((document) => ( - - ))} -
- ) : null} -
- ) : null} + + + + ))} +
+ ) : null} +
+ + setCreateRegulationOpen(false)} + title="Создать регламент отдела" + size="xl" + > + setCreateRegulationOpen(false)} + onSuccess={() => { + setCreateRegulationOpen(false); + setRegulationsExpanded(true); + setRegulationsRefreshKey((current) => current + 1); + }} + /> + ); } diff --git a/frontend/src/app/documents/page.tsx b/frontend/src/app/documents/page.tsx index e839ee5d..7739f71f 100644 --- a/frontend/src/app/documents/page.tsx +++ b/frontend/src/app/documents/page.tsx @@ -1549,7 +1549,7 @@ function DocumentsPageContent() { })} {/* Document Cards */} - {filteredDocuments.map((doc) => { + {filteredDocuments.map((doc, documentIndex) => { const authorName = doc.created_by ? `${doc.created_by.last_name || ''} ${doc.created_by.first_name || ''}`.trim() : null; @@ -1602,16 +1602,25 @@ function DocumentsPageContent() {
- - {doc.is_regulation ? ( - - ) : ( - - )} - {doc.is_regulation ? "Регламент" : "Документ"} - + {activeSection === "regulations" ? ( + + {documentIndex + 1} + + ) : ( + + {doc.is_regulation ? ( + + ) : ( + + )} + {doc.is_regulation ? "Регламент" : "Документ"} + + )} {doc.tags?.slice(0, 3).map((tag) => ( void; onFolderCreated?: () => void; currentFolderId?: number | null; + initialDepartmentId?: number | null; mode?: "document" | "regulation"; } @@ -122,9 +123,11 @@ export function DocumentUploadForm({ onCancel, onFolderCreated, currentFolderId, + initialDepartmentId, mode = "document", }: DocumentUploadFormProps) { const isDedicatedRegulation = mode === "regulation"; + const initialDepartmentIds = initialDepartmentId ? [initialDepartmentId] : []; const [isRegulation, setIsRegulation] = useState(isDedicatedRegulation); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); @@ -137,10 +140,14 @@ export function DocumentUploadForm({ // New fields for extended functionality const [sentToAll, setSentToAll] = useState(true); - const [acknowledgementMode, setAcknowledgementMode] = useState("all"); + const [acknowledgementMode, setAcknowledgementMode] = useState( + initialDepartmentIds.length > 0 ? "restricted" : "all", + ); const [selectedDepartments, setSelectedDepartments] = useState([]); const [selectedRecipients, setSelectedRecipients] = useState([]); - const [acknowledgementDepartments, setAcknowledgementDepartments] = useState([]); + const [acknowledgementDepartments, setAcknowledgementDepartments] = useState( + initialDepartmentIds, + ); const [acknowledgementRecipients, setAcknowledgementRecipients] = useState([]); // Metadata fields @@ -527,10 +534,10 @@ export function DocumentUploadForm({ setFolderCreateError(null); setSentToAll(true); setIsRegulation(isDedicatedRegulation); - setAcknowledgementMode("all"); + setAcknowledgementMode(initialDepartmentIds.length > 0 ? "restricted" : "all"); setSelectedDepartments([]); setSelectedRecipients([]); - setAcknowledgementDepartments([]); + setAcknowledgementDepartments(initialDepartmentIds); setAcknowledgementRecipients([]); setSelectedTags([]); diff --git a/frontend/src/components/feed/FeedRegulationCard.tsx b/frontend/src/components/feed/FeedRegulationCard.tsx index f9479bb5..eda41a53 100644 --- a/frontend/src/components/feed/FeedRegulationCard.tsx +++ b/frontend/src/components/feed/FeedRegulationCard.tsx @@ -320,11 +320,12 @@ export function FeedRegulationCard({ type="button" onClick={() => onAcknowledge(document)} disabled={isAcknowledging} - className="app-action-ghost inline-flex h-9 w-9 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-60" + className="app-action-ghost inline-flex h-9 items-center justify-center gap-2 rounded-lg px-3 text-sm font-medium disabled:cursor-not-allowed disabled:opacity-60" title="Ознакомился(лась)" aria-label="Ознакомился(лась)" > {isAcknowledging ? : } + {isAcknowledging ? "Подтверждение..." : "Ознакомился(лась)"} ) : null} {document.file_url ? (