Files
mkd/components/OfficeModule.tsx
2026-02-04 00:17:04 +05:00

139 lines
5.7 KiB
TypeScript
Executable File
Raw Permalink 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.
import React, { useState, useEffect, useMemo } from 'react';
import {
Briefcase,
ShoppingCart,
FileText,
Monitor,
QrCode,
Wrench,
BookOpen,
Calendar,
Newspaper
} from 'lucide-react';
import { MOCK_OFFICE_REQUESTS } from '../constants';
import { OfficeRequest } from '../types';
// Modular Imports
import { OfficeSummary } from './office/OfficeSummary';
import { SupplyRegistry } from './office/SupplyRegistry';
import { DocumentFlow } from './office/DocumentFlow';
import { FacilityManagement } from './office/FacilityManagement';
import { RepairRequests } from './office/RepairRequests';
import { KnowledgeBase } from './office/KnowledgeBase';
import { MeetingsAndRooms } from './office/MeetingsAndRooms';
import { CompanyNewsRegistry } from './office/CompanyNewsRegistry';
import { allowedSubsForSection } from '../constants/permissions';
type Tab = 'dashboard' | 'supply' | 'docs' | 'facility' | 'repair' | 'knowledge' | 'meetings' | 'news';
const OFFICE_TABS: Tab[] = ['dashboard', 'supply', 'docs', 'facility', 'repair', 'knowledge', 'meetings', 'news'];
const SUBTAB_KEY = 'mkd_subTab_office';
interface OfficeModuleProps {
allowedPermissions?: string[] | null;
}
export const OfficeModule: React.FC<OfficeModuleProps> = ({ allowedPermissions }) => {
const visibleTabs = useMemo(() => {
const allowed = allowedSubsForSection(allowedPermissions ?? [], 'office');
if (allowed === 'all') return OFFICE_TABS;
return OFFICE_TABS.filter((t) => allowed.includes(t));
}, [allowedPermissions]);
const [activeTab, setActiveTab] = useState<Tab>(() => {
const s = localStorage.getItem(SUBTAB_KEY);
return (s && OFFICE_TABS.includes(s as Tab)) ? s as Tab : 'dashboard';
});
useEffect(() => {
if (visibleTabs.length > 0 && !visibleTabs.includes(activeTab)) {
setActiveTab(visibleTabs[0]);
}
}, [visibleTabs, activeTab]);
useEffect(() => {
if (visibleTabs.includes(activeTab)) localStorage.setItem(SUBTAB_KEY, activeTab);
}, [activeTab, visibleTabs]);
const [requests, setRequests] = useState<OfficeRequest[]>(MOCK_OFFICE_REQUESTS);
return (
<div className="animate-fade-in pb-20">
<div className="flex justify-between items-center mb-6 px-1">
<div>
<h2 className="text-xl font-bold text-slate-800 leading-none">Офис и Хоз. часть</h2>
<p className="text-[10px] text-slate-400 font-black uppercase tracking-widest mt-1">Внутренняя операционная деятельность</p>
</div>
<div className="flex gap-2">
<button
className="p-2.5 bg-white border border-slate-200 text-slate-400 rounded-xl hover:text-primary-600 transition-all shadow-sm"
title="Сканировать QR"
onClick={() => alert("Камера активирована для инвентаризации")}
>
<QrCode className="w-5 h-5"/>
</button>
</div>
</div>
{/* Sheet Selector */}
<div className="flex p-1 bg-slate-200/50 rounded-2xl mb-6 overflow-x-auto no-scrollbar gap-1">
{[
{ id: 'dashboard', label: 'Сводка', icon: Briefcase },
{ id: 'supply', label: 'Закупки', icon: ShoppingCart },
{ id: 'docs', label: 'Корреспонденция', icon: FileText },
{ id: 'facility', label: 'Имущество', icon: Monitor },
{ id: 'repair', label: 'Ремонт техники', icon: Wrench },
{ id: 'knowledge', label: 'База знаний', icon: BookOpen },
{ id: 'meetings', label: 'Совещания', icon: Calendar },
{ id: 'news', label: 'Новости', icon: Newspaper },
].filter((tab) => visibleTabs.includes(tab.id as Tab)).map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id as Tab)}
className={`flex-shrink-0 min-w-[7rem] flex items-center justify-center gap-2 py-2.5 px-4 text-[10px] font-black uppercase tracking-wider whitespace-nowrap rounded-xl transition-all ${activeTab === tab.id ? 'bg-white text-primary-600 shadow-sm border border-white' : 'text-slate-500 hover:text-slate-700'}`}
>
<tab.icon className="w-3.5 h-3.5"/> {tab.label}
</button>
))}
</div>
{/* Dynamic Sheet Content */}
<div className="min-h-[280px] sm:min-h-[360px] md:min-h-[500px]">
{(() => {
try {
switch (activeTab) {
case 'dashboard':
return <OfficeSummary requests={requests} />;
case 'supply':
return <SupplyRegistry requests={requests} />;
case 'docs':
return <DocumentFlow />;
case 'facility':
return <FacilityManagement />;
case 'repair':
return <RepairRequests />;
case 'knowledge':
return <KnowledgeBase />;
case 'meetings':
return <MeetingsAndRooms />;
case 'news':
return <CompanyNewsRegistry />;
default:
return <OfficeSummary requests={requests} />;
}
} catch (error) {
console.error('Ошибка рендеринга вкладки:', error);
return (
<div className="text-center py-8 text-red-600">
<p className="font-bold">Ошибка загрузки вкладки</p>
<p className="text-sm text-slate-500 mt-2">Попробуйте перезагрузить страницу</p>
</div>
);
}
})()}
</div>
</div>
);
};