/
Cybran65
/
Project_0
Обзор
Документация
Войти
/
Cybran65
/
Project_0
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/components/ServicePanel/ServicePanel.tsx
232 строки
8 KB
Cybran65
feat: интерфейс по макету Figma и функции ЛИРА-САПФИР
08 авг 2026, 23:31
08 авг 2026, 23:31
fd3db2b
Код
Авторство
О чём код?
import styles from './ServicePanel.module.css'; import { CHECKS, ESTIMATES, SERVICE_TABS, TASKS } from '../../data/service'; import { NOTE_KIND_LABELS } from '../Notes/NotesSection'; import type { LogRecord, Note, ServiceTabId } from '../../types'; interface Props { open: boolean; activeTab: ServiceTabId; log: LogRecord[]; notes: Note[]; onTabChange: (tab: ServiceTabId) => void; onToggleOpen: () => void; onSelectNote: (targetId: string) => void; onToggleNote: (id: string) => void; } const STATUS_LABELS: Record<LogRecord['status'], string> = { ok: 'Выполнено', warning: 'Внимание', error: 'Ошибка', info: 'Инфо', }; const RESULT_LABELS: Record<'ok' | 'warning' | 'error', string> = { ok: 'Норма', warning: 'Внимание', error: 'Ошибка', }; /** Нижняя служебная панель: журнал, проверки, задачи, сметы. */ export default function ServicePanel({ open, activeTab, log, notes, onTabChange, onToggleOpen, onSelectNote, onToggleNote, }: Props) { return ( <section className={open ? styles.panel : styles.panelCollapsed}> <div className={styles.tabs}> <span className={styles.caption}>Служебная информация</span> {SERVICE_TABS.map((tab) => ( <button key={tab.id} type="button" className={tab.id === activeTab && open ? styles.tabActive : styles.tab} onClick={() => { if (!open) onToggleOpen(); onTabChange(tab.id); }} > {tab.label} {tab.id === 'log' && <span className={styles.badge}>{log.length}</span>} {tab.id === 'notes' && notes.length > 0 && ( <span className={styles.badge}>{notes.length}</span> )} </button> ))} <button type="button" className={styles.collapse} title={open ? 'Свернуть панель' : 'Развернуть панель'} onClick={onToggleOpen} > {open ? '▾' : '▴'} </button> </div> {open && ( <div className={styles.body}> {activeTab === 'log' && ( <table className={styles.table}> <thead> <tr> <th style={{ width: 76 }}>Время</th> <th style={{ width: 150 }}>Пользователь</th> <th style={{ width: 220 }}>Объект</th> <th>Действие</th> <th style={{ width: 110 }}>Статус</th> </tr> </thead> <tbody> {log.map((record) => ( <tr key={record.id}> <td className={styles.mono}>{record.time}</td> <td>{record.user}</td> <td>{record.object}</td> <td>{record.action}</td> <td> <span className={styles[record.status]}>{STATUS_LABELS[record.status]}</span> </td> </tr> ))} </tbody> </table> )} {activeTab === 'notes' && (notes.length === 0 ? ( <div className={styles.empty}> Заметок нет. Выберите объект и добавьте заметку в панели свойств. </div> ) : ( <table className={styles.table}> <thead> <tr> <th style={{ width: 76 }}>Время</th> <th style={{ width: 150 }}>Автор</th> <th style={{ width: 220 }}>Объект</th> <th style={{ width: 110 }}>Тип</th> <th>Текст</th> <th style={{ width: 96 }}>Состояние</th> </tr> </thead> <tbody> {notes.map((note) => ( <tr key={note.id} onClick={() => onSelectNote(note.targetId)}> <td className={styles.mono}>{note.time}</td> <td>{note.author}</td> <td>{note.targetLabel}</td> <td>{NOTE_KIND_LABELS[note.kind]}</td> <td title={note.text}>{note.text}</td> <td> <button type="button" className={styles.rowButton} onClick={(event) => { event.stopPropagation(); onToggleNote(note.id); }} > {note.done ? 'Решена' : 'В работе'} </button> </td> </tr> ))} </tbody> </table> ))} {activeTab === 'checks' && ( <table className={styles.table}> <thead> <tr> <th style={{ width: 260 }}>Правило</th> <th style={{ width: 240 }}>Объект</th> <th style={{ width: 110 }}>Результат</th> <th>Комментарий</th> </tr> </thead> <tbody> {CHECKS.map((check) => ( <tr key={check.id}> <td>{check.rule}</td> <td>{check.object}</td> <td> <span className={styles[check.result]}>{RESULT_LABELS[check.result]}</span> </td> <td className={styles.dim}>{check.comment}</td> </tr> ))} </tbody> </table> )} {activeTab === 'tasks' && ( <table className={styles.table}> <thead> <tr> <th style={{ width: 320 }}>Задача</th> <th style={{ width: 180 }}>Исполнитель</th> <th style={{ width: 110 }}>Срок</th> <th>Состояние</th> </tr> </thead> <tbody> {TASKS.map((task) => ( <tr key={task.id}> <td>{task.title}</td> <td>{task.assignee}</td> <td className={styles.mono}>{task.due}</td> <td>{task.state}</td> </tr> ))} </tbody> </table> )} {activeTab === 'estimates' && ( <table className={styles.table}> <thead> <tr> <th style={{ width: 110 }}>Шифр</th> <th style={{ width: 300 }}>Наименование</th> <th style={{ width: 70 }}>Ед.</th> <th style={{ width: 90 }}>Кол-во</th> <th>Примечание</th> </tr> </thead> <tbody> {ESTIMATES.map((row) => ( <tr key={row.id}> <td className={styles.mono}>{row.code}</td> <td>{row.title}</td> <td>{row.unit}</td> <td className={styles.mono}>{row.amount}</td> <td className={styles.dim}>{row.note}</td> </tr> ))} </tbody> </table> )} </div> )} <div className={styles.subTabs}> <button type="button" className={styles.subTabActive}> Процесс </button> <button type="button" className={styles.subTab} title="Раздел в разработке"> Объёмы </button> <button type="button" className={styles.subTab} title="Раздел в разработке"> Ошибки </button> </div> </section> ); }