feat: changed folder structure for the secod dev

This commit is contained in:
Тимур Городецкий
2026-08-03 12:06:48 +05:00
parent bc91c9861d
commit 788e046ebe
11 changed files with 367 additions and 104 deletions
@@ -0,0 +1,33 @@
@import '../../../../styles/design-tokens';
// Постоянная боковая панель (всегда открыта). Раскладку колонок задаёт корень;
// здесь — только внутреннее оформление панели.
.panel {
display: flex;
flex-direction: column;
height: 100%;
background: $white;
border: 1px solid $gray-200;
border-radius: $r-lg;
box-shadow: $sh-1;
overflow: hidden;
}
.header {
padding: $sp-4 $sp-5;
border-bottom: 1px solid $gray-200;
}
.title {
font-family: $font-serif;
font-size: 18px;
color: $navy-900;
}
.body {
flex: 1;
overflow-y: auto;
padding: $sp-5;
color: $gray-500;
font-size: $fs-sm;
}
@@ -0,0 +1,26 @@
import * as React from 'react';
import type { WebPartContext } from '@microsoft/sp-webpart-base';
import styles from './MyRequestsPanel.module.scss';
export interface IMyRequestsPanelProps {
context: WebPartContext;
}
// Постоянная боковая панель «Мои заявки»: пользователь видит, что он отправлял
// и согласовывал. Всегда открыта (без кнопки/оверлея).
// Владелец: второй разработчик. Вся логика/данные — внутри этой папки.
// Общий UI-кит (shared/ui), pnpjs и config можно импортировать, но НЕ менять.
const MyRequestsPanel: React.FC<IMyRequestsPanelProps> = (/* { context } */) => {
return (
<aside className={styles.panel} aria-label="Мои заявки">
<div className={styles.header}>
<span className={styles.title}>Мои заявки</span>
</div>
<div className={styles.body}>
Раздел в разработке: здесь будут заявки пользователя, статусы и согласования.
</div>
</aside>
);
};
export default MyRequestsPanel;
@@ -0,0 +1,52 @@
@import '../../../../styles/design-tokens';
// Центрированная колонка контента. 1080px — ширина контента из дизайн-системы
// (как .sec в референсе): форма и плитки читаются аккуратно, не растягиваясь.
.content {
width: 100%;
max-width: 1080px;
margin: 0 auto;
}
// ── Заглушка формы (до появления реальных форм) ──
.formPlaceholder {
margin-top: $sp-6;
padding: $sp-8;
background: $white;
border: 1px solid $gray-200;
border-radius: $r-lg;
box-shadow: $sh-1;
}
.backButton {
display: inline-flex;
align-items: center;
gap: $sp-2;
margin-bottom: $sp-4;
padding: 0;
border: 0;
background: transparent;
color: $navy-700;
font-family: $font-sans;
font-size: $fs-sm;
cursor: pointer;
transition: color .18s;
&:hover {
color: $gold-600;
}
}
.placeholderText {
font-family: $font-serif;
font-size: 18px;
color: $navy-900;
}
.loading {
margin-top: $sp-6;
padding: $sp-8;
color: $gray-500;
font-size: $fs-sm;
text-align: center;
}
@@ -0,0 +1,73 @@
import * as React from 'react';
import { useState } from 'react';
import type { WebPartContext } from '@microsoft/sp-webpart-base';
import styles from './SubmitFeature.module.scss';
import { Icon } from '../../shared/ui/Icon/Icon';
import { CategoryTabs } from '../../components/CategoryTabs/CategoryTabs';
import { RequestGrid } from '../../components/RequestGrid/RequestGrid';
import { CATEGORIES, DEFAULT_CATEGORY_ID } from '../../data/categories';
import { getRequestsByCategory } from '../../data/requests';
import { getFormComponent } from '../../forms/registry';
import { IRequestType } from '../../models/types';
export interface ISubmitFeatureProps {
context: WebPartContext;
}
// Фича «Подать заявку»: категории → плитки → беспоук-форма.
// Владелец: автор портала. Живёт целиком в features/submit/**.
const SubmitFeature: React.FC<ISubmitFeatureProps> = ({ context }) => {
const [activeCategoryId, setActiveCategoryId] = useState<string>(DEFAULT_CATEGORY_ID);
const [selectedRequest, setSelectedRequest] = useState<IRequestType | null>(null);
const requests = getRequestsByCategory(activeCategoryId);
const handleCategoryChange = (categoryId: string): void => {
setActiveCategoryId(categoryId);
setSelectedRequest(null); // при смене категории возвращаемся к списку плиток
};
const handleBack = (): void => setSelectedRequest(null);
const renderSelected = (request: IRequestType): React.ReactNode => {
const FormComponent = getFormComponent(request.id);
// Форма ещё не реализована — показываем заглушку.
if (!FormComponent) {
return (
<div className={styles.formPlaceholder}>
<button type="button" className={styles.backButton} onClick={handleBack}>
<Icon name="arrow-left" size="sm" />
<span>К списку заявок</span>
</button>
<p className={styles.placeholderText}>Форма «{request.title}» ещё в разработке.</p>
</div>
);
}
// Ленивый рендер формы: её код подтягивается только сейчас, при открытии.
return (
<React.Suspense fallback={<div className={styles.loading}>Загрузка формы…</div>}>
<FormComponent requestType={request} context={context} onCancel={handleBack} />
</React.Suspense>
);
};
return (
<div className={styles.content}>
<CategoryTabs
categories={CATEGORIES}
activeId={activeCategoryId}
onChange={handleCategoryChange}
/>
{selectedRequest ? (
renderSelected(selectedRequest)
) : (
<RequestGrid requests={requests} onSelect={setSelectedRequest} />
)}
</div>
);
};
export default SubmitFeature;