/
Cybran65
/
Project_0
Обзор
Документация
Войти
/
Cybran65
/
Project_0
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/components/Notes/NotesSection.tsx
139 строк
5 KB
Cybran65
style: выравнивание модели, масштаб ленты и векторные иконки
09 авг 2026, 01:10
09 авг 2026, 01:10
9ead2b4
Код
Авторство
О чём код?
import { useState } from 'react'; import styles from './NotesSection.module.css'; import type { Note, NoteKind } from '../../types'; interface Props { notes: Note[]; targetLabel: string; onAdd: (text: string, kind: NoteKind) => void; onToggleDone: (id: string) => void; onDelete: (id: string) => void; } export const NOTE_KIND_LABELS: Record<NoteKind, string> = { comment: 'Замечание', question: 'Вопрос', issue: 'Ошибка', }; /** Заметки к выбранному объекту. */ export default function NotesSection({ notes, targetLabel, onAdd, onToggleDone, onDelete }: Props) { const [text, setText] = useState(''); const [kind, setKind] = useState<NoteKind>('comment'); const [open, setOpen] = useState(false); const submit = () => { const value = text.trim(); if (!value) return; onAdd(value, kind); setText(''); setOpen(false); }; if (!open) { return ( <div className={styles.wrap}> <button type="button" className={styles.add} onClick={() => setOpen(true)}> Добавить заметку </button> {notes.length > 0 && ( <ul className={styles.list}> {notes.map((note) => ( <li key={note.id} className={note.done ? styles.itemDone : styles.item}> <div className={styles.head}> <span className={styles[note.kind]}>{NOTE_KIND_LABELS[note.kind]}</span> <span className={styles.meta}> {note.author} · {note.time} </span> <button type="button" className={styles.action} title={note.done ? 'Вернуть в работу' : 'Отметить решённой'} onClick={() => onToggleDone(note.id)} > {note.done ? '↺' : '✓'} </button> <button type="button" className={styles.action} title="Удалить заметку" onClick={() => onDelete(note.id)} > ✕ </button> </div> <div className={styles.text}>{note.text}</div> </li> ))} </ul> )} </div> ); } return ( <div className={styles.wrap}> <div className={styles.form}> <select value={kind} onChange={(event) => setKind(event.target.value as NoteKind)}> {(Object.keys(NOTE_KIND_LABELS) as NoteKind[]).map((value) => ( <option key={value} value={value}> {NOTE_KIND_LABELS[value]} </option> ))} </select> <textarea className={styles.input} rows={2} value={text} placeholder={`Заметка к объекту «${targetLabel}»`} onChange={(event) => setText(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) submit(); }} /> <div className={styles.formActions}> <button type="button" className={styles.cancel} onClick={() => setOpen(false)}> Отмена </button> <button type="button" className={styles.add} onClick={submit} disabled={!text.trim()}> Добавить </button> </div> </div> {notes.length === 0 ? ( <div className={styles.empty}>Заметок нет</div> ) : ( <ul className={styles.list}> {notes.map((note) => ( <li key={note.id} className={note.done ? styles.itemDone : styles.item}> <div className={styles.head}> <span className={styles[note.kind]}>{NOTE_KIND_LABELS[note.kind]}</span> <span className={styles.meta}> {note.author} · {note.time} </span> <button type="button" className={styles.action} title={note.done ? 'Вернуть в работу' : 'Отметить решённой'} onClick={() => onToggleDone(note.id)} > {note.done ? '↺' : '✓'} </button> <button type="button" className={styles.action} title="Удалить заметку" onClick={() => onDelete(note.id)} > ✕ </button> </div> <div className={styles.text}>{note.text}</div> </li> ))} </ul> )} </div> ); }