Initial commit MKD fixes

This commit is contained in:
Arsen
2026-02-04 00:17:04 +05:00
commit de94ad707b
312 changed files with 138754 additions and 0 deletions

103
components/DevelopmentModule.tsx Executable file
View File

@@ -0,0 +1,103 @@
import React, { useState, useEffect, useMemo } from 'react';
import {
Briefcase,
Target,
Vote,
Calculator,
Plus,
Megaphone,
Printer,
ChevronRight
} from 'lucide-react';
// Modular Imports
import { DevSummary } from './development/DevSummary';
import { PipelineRegistry } from './development/PipelineRegistry';
import { OSSMaster } from './development/OSSMaster';
import { TechnicalAudit } from './development/TechnicalAudit';
import { MarketingCampaigns } from './development/MarketingCampaigns';
import { allowedSubsForSection } from '../constants/permissions';
type Tab = 'summary' | 'pipeline' | 'oss' | 'audit' | 'marketing';
const DEV_TABS: Tab[] = ['summary', 'pipeline', 'oss', 'audit', 'marketing'];
const SUBTAB_KEY = 'mkd_subTab_development';
interface DevelopmentModuleProps {
allowedPermissions?: string[] | null;
}
export const DevelopmentModule: React.FC<DevelopmentModuleProps> = ({ allowedPermissions }) => {
const visibleTabs = useMemo(() => {
const allowed = allowedSubsForSection(allowedPermissions ?? [], 'development');
if (allowed === 'all') return DEV_TABS;
return DEV_TABS.filter((t) => allowed.includes(t));
}, [allowedPermissions]);
const [activeTab, setActiveTab] = useState<Tab>(() => {
const s = localStorage.getItem(SUBTAB_KEY);
return (s && DEV_TABS.includes(s as Tab)) ? s as Tab : 'summary';
});
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]);
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="Печать отчетов"
onClick={() => {
// Печать отчетов - можно реализовать генерацию PDF
window.print();
}}
>
<Printer 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: 'summary', label: 'Сводка', icon: Target },
{ id: 'pipeline', label: 'Воронка', icon: Briefcase },
{ id: 'oss', label: 'ОСС', icon: Vote },
{ id: 'audit', label: 'Аудит', icon: Calculator },
{ id: 'marketing', label: 'Поле', icon: Megaphone },
].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]">
{activeTab === 'summary' && <DevSummary onNavigate={setActiveTab} />}
{activeTab === 'pipeline' && <PipelineRegistry />}
{activeTab === 'oss' && <OSSMaster />}
{activeTab === 'audit' && <TechnicalAudit onNavigate={setActiveTab} />}
{activeTab === 'marketing' && <MarketingCampaigns />}
</div>
</div>
);
};