/
Cybran65
/
Project_0
Обзор
Документация
Войти
/
Cybran65
/
Project_0
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/components/AppHeader/AppHeader.tsx
154 строки
5 KB
Cybran65
@
09 авг 2026, 20:30
09 авг 2026, 20:30
98a9bb5
Код
Авторство
О чём код?
import { useState } from 'react'; import styles from './AppHeader.module.css'; import type { Role } from '../../types'; interface MenuItem { id: string; label: string; } /** Пункты главного меню приложения. Большинство — заглушки. */ const MENU: Array<{ id: string; label: string; items: MenuItem[] }> = [ { id: 'file', label: 'Файл', items: [ { id: 'new', label: 'Создать проект…' }, { id: 'open', label: 'Открыть…' }, { id: 'save', label: 'Сохранить' }, { id: 'export', label: 'Экспорт…' }, { id: 'role', label: 'Выбрать роль…' }, ], }, ]; /** Кнопки панели быстрого доступа (в макете — ряд иконок слева). */ const QUICK_ACCESS: Array<{ id: string; label: string; glyph: string }> = [ { id: 'new', label: 'Создать', glyph: '🗋' }, { id: 'open', label: 'Открыть', glyph: '🗀' }, { id: 'save', label: 'Сохранить', glyph: '🖫' }, { id: 'undo', label: 'Отменить', glyph: '↶' }, { id: 'redo', label: 'Повторить', glyph: '↷' }, { id: 'print', label: 'Печать', glyph: '⎙' }, { id: 'checks', label: 'Проверки', glyph: '✓' }, { id: 'help', label: 'Справка', glyph: '?' }, ]; interface Props { projectName: string; role: Role; leftOpen: boolean; rightOpen: boolean; serviceOpen: boolean; onMenuAction: (id: string, label: string) => void; onOpenRoles: () => void; onToggleLeft: () => void; onToggleRight: () => void; onToggleService: () => void; } /** Верхняя строка приложения: панель быстрого доступа, имя проекта, роль. */ export default function AppHeader({ projectName, role, leftOpen, rightOpen, serviceOpen, onMenuAction, onOpenRoles, onToggleLeft, onToggleRight, onToggleService, }: Props) { const [openMenu, setOpenMenu] = useState<string | null>(null); return ( <header className={styles.header}> <div className={styles.left}> <span className={styles.mark}>МС</span> {MENU.map((menu) => ( <div key={menu.id} className={styles.menuItem}> <button type="button" className={openMenu === menu.id ? styles.menuButtonActive : styles.menuButton} onClick={() => setOpenMenu(openMenu === menu.id ? null : menu.id)} > {menu.label} </button> {openMenu === menu.id && ( <> <div className={styles.backdrop} onClick={() => setOpenMenu(null)} /> <ul className={styles.dropdown}> {menu.items.map((item) => ( <li key={item.id}> <button type="button" onClick={() => { setOpenMenu(null); onMenuAction(item.id, item.label); }} > {item.label} </button> </li> ))} </ul> </> )} </div> ))} <div className={styles.quick}> {QUICK_ACCESS.map((item) => ( <button key={item.id} type="button" className={styles.quickButton} title={item.label} onClick={() => onMenuAction(item.id, item.label)} > {item.glyph} </button> ))} </div> </div> <div className={styles.title}>МИСИ-САПР — {projectName}</div> <div className={styles.right}> <button type="button" className={styles.role} onClick={onOpenRoles} title="Сменить роль"> <span className={styles.roleMark}>{role.label.charAt(0)}</span> <span className={styles.roleText}>Роль: {role.label}</span> </button> <div className={styles.panelToggles} role="group" aria-label="Панели"> <button type="button" className={leftOpen ? styles.panelOn : styles.panelOff} title="Панель свойств" onClick={onToggleLeft} > ▤ </button> <button type="button" className={serviceOpen ? styles.panelOn : styles.panelOff} title="Служебная информация" onClick={onToggleService} > ▭ </button> <button type="button" className={rightOpen ? styles.panelOn : styles.panelOff} title="Структура проекта" onClick={onToggleRight} > ▥ </button> </div> </div> </header> ); }