/* eslint-disable */ /* timing-projects.jsx — панель «Проекты»: список сохранённых таймингов с открытием, созданием, переименованием и удалением. Работает через window.TimingAuth.api (с прозрачным офлайн-фолбэком на localStorage в превью). */ (function () { const R = window.React; const { useState, useEffect } = R; const A = window.TimingAuth; function fmtDate(iso) { if (!iso) return '—'; try { const d = new Date(iso); const date = d.toLocaleDateString('ru-RU', { day: '2-digit', month: 'short', year: 'numeric' }); const time = d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }); return date + ', ' + time; } catch (e) { return '—'; } } function ProjectsPanel({ onClose, onOpen, onNew, currentId }) { const [list, setList] = useState(null); const [renaming, setRenaming] = useState(null); const [renameVal, setRenameVal] = useState(''); const [confirmDel, setConfirmDel] = useState(null); const [working, setWorking] = useState(false); async function refresh() { const l = await A.api.list(); setList(Array.isArray(l) ? l : []); } useEffect(() => { refresh(); }, []); async function doOpen(p) { setWorking(true); const full = await A.api.get(p.id); setWorking(false); if (full && full.data) onOpen(full); else alert('Не удалось загрузить проект'); } async function doRename(p) { const t = (renameVal || '').trim(); setRenaming(null); if (!t || t === p.title) return; await A.api.update(p.id, { title: t }); refresh(); } async function doDelete(p) { await A.api.del(p.id); setConfirmDel(null); refresh(); } const iconBtn = (danger) => ({ width: 30, height: 30, borderRadius: 'var(--radius-input)', border: '1px solid var(--color-line-subtle)', background: 'var(--color-surface)', color: danger ? 'var(--color-danger-700)' : 'var(--color-ink-500)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', }); return ReactDOM.createPortal(
{ if (e.target === e.currentTarget) onClose(); }}>
{/* header */}
Проекты
{/* list */}
{list === null && (
)} {list && list.length === 0 && (
Сохранённых проектов пока нет.
Нажмите «Новый проект» или сохраните текущий тайминг.
)} {list && list.map(p => { const isCurrent = p.id === currentId; const isRenaming = renaming === p.id; return (
{isRenaming ? ( setRenameVal(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') doRename(p); if (e.key === 'Escape') setRenaming(null); }} onBlur={() => doRename(p)} style={{ width: '100%', border: '1px solid var(--color-line-strong)', background: 'var(--color-surface)', borderRadius: 5, padding: '4px 7px', fontSize: 13.5, fontWeight: 600, color: 'var(--color-ink-900)', outline: 'none' }} /> ) : (
{p.title || 'Без названия'} {isCurrent && открыт}
)}
{(p.owner_email || '—') + ' · ' + fmtDate(p.updated_at)}
); })}
{A.api.offlineMode && (
Локальный режим: проекты хранятся в этом браузере (нет связи с сервером).
)}
{/* delete confirm */} {confirmDel && (
{ if (e.target === e.currentTarget) setConfirmDel(null); }}>
Удалить проект?
«{confirmDel.title || 'Без названия'}» будет удалён без возможности восстановления.
)}
, document.body ); } window.TimingProjects = { ProjectsPanel }; })();