/* lk-workcard.jsx — «Карточка работы»: одно окно на одну работу сметы (или точку фотоконтроля) для кабинетов сотрудников.
   Слева — фото сдачи: выбранное крупно, по клику на фото ставится метка и пишется замечание к этому месту, к замечанию можно
   приложить картинку (пример, схему); так к каждому фото. Справа — срок, мастер, этап, чек-лист, общий комментарий, история
   и решение: «Принять» или «Вернуть на доработку» (возврат — с замечаниями к фото и/или общим комментарием).
   Данные — ForemanViews.work(); решение — onAccept / onReturn({ remark, notes }) кабинета (те же функции ProjectStore,
   что и раньше: setTaskStatus / decideGate). Замечание к фото: { url, name, x, y, text, img } — x, y в % от фото (метка) или null.
   Наряд (KSH-184): кто делает работу — выдать, сменить мастера, добавить второго, снять (onAssign → ProjectStore.assign) и ссылка
   мастеру на задание в его кабинете (onLink — адрес, когда у мастера есть доступ в кабинет).
   По комнатам (KSH-504): у работы сметы по комнатам под карточкой — комнаты с шагами: принять, вернуть, отметить сделанным (onRoomStep).
   Exports on window: LKW.WorkCard (дописывает в библиотеку lk-widgets.jsx, грузится после неё). */
(function () {
  'use strict';
  const W = window.LKW;
  const { Ic, Face, FaceSt, Modal, rub, plural, dateR, short } = W;
  // статус в шапке: просрочка и возврат — охрой (как в календаре), остальное — спокойно
  const ST = { todo: ['Впереди', 'pill-d'], progress: ['В работе', 'pill-g'], review: ['На приёмке', 'pill-g'], returned: ['На доработке', 'lw-wst is-late'], done: ['Принята', 'pill-g'] };
  const when = (iso) => (iso ? dateR(String(iso).slice(0, 10), { month: 'short' }) + ', ' + new Date(iso).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }) : '');

  /* фото крупно с метками замечаний; клик по фото — новая метка (только когда можно вернуть) */
  function PhotoNotes({ photo, notes, draft, onPin, onZoom, editable }) {
    const box = React.useRef(null);
    const pin = (e) => {
      if (!editable || !box.current) return;
      const r = box.current.getBoundingClientRect();
      onPin({ x: Math.round((e.clientX - r.left) / r.width * 1000) / 10, y: Math.round((e.clientY - r.top) / r.height * 1000) / 10 });
    };
    return (
      <div className={'lw-wph' + (editable ? ' is-edit' : '')}>
        <div className="lw-wimg" ref={box} onClick={pin} role={editable ? 'button' : undefined} aria-label={editable ? 'Отметить место на фото' : undefined}>
          <img src={photo.url} alt={photo.name || ''} draggable={false} />
          {notes.map((n, i) => n.x != null ? <b key={i} className="lw-pin" style={{ left: n.x + '%', top: n.y + '%' }}>{n.no}</b> : null)}
          {draft && draft.x != null ? <b className="lw-pin is-draft" style={{ left: draft.x + '%', top: draft.y + '%' }}>{draft.no}</b> : null}
        </div>
        <button type="button" className="lw-wzoom" onClick={onZoom} aria-label="Открыть фото на весь экран"><Ic n="ne" s={16} /></button>
      </div>);
  }

  /* составление замечания к выбранному фото: текст и картинка (необязательно) */
  function NoteForm({ draft, setDraft, onAdd, upload }) {
    const file = React.useRef(null);
    const [busy, setBusy] = React.useState(false);
    const pick = async (e) => {
      const f = e.target.files && e.target.files[0]; e.target.value = '';
      if (!f) return;
      setBusy(true);
      try { const r = await upload(f); setDraft((d) => ({ ...d, img: { url: r.url, name: r.name || f.name } })); } finally { setBusy(false); }
    };
    return (
      <div className="lw-wnote">
        <textarea value={draft.text} onChange={(e) => { const v = e.target.value; setDraft((d) => ({ ...d, text: v })); }} rows={2}
          placeholder={draft.x != null ? 'Что не так в отмеченном месте' : 'Замечание к этому фото — или нажмите на фото, чтобы отметить место'} aria-label="Замечание к фото" />
        <div className="lw-wnote-f">
          {draft.img ? <span className="lw-watt"><img src={draft.img.url} alt="" /><button type="button" aria-label="Убрать картинку" onClick={() => setDraft((d) => ({ ...d, img: null }))}><Ic n="x" s={12} /></button></span> : null}
          <input ref={file} type="file" accept="image/*" hidden onChange={pick} />
          <button type="button" className="lw-btn-l" disabled={busy} onClick={() => file.current && file.current.click()}><Ic n="camera" s={15} />{busy ? 'Загружаю…' : draft.img ? 'Заменить картинку' : 'Приложить картинку'}</button>
          {draft.x != null ? <button type="button" className="lw-lnk lab" onClick={() => setDraft((d) => ({ ...d, x: null, y: null }))}>убрать метку</button> : null}
          <button type="button" className="lw-btn-k lw-wadd" disabled={!draft.text.trim()} onClick={onAdd}>Добавить замечание</button>
        </div>
      </div>);
  }

  /* наряд: мастера работы и выбор из бригады объекта — по специальности первыми; занятые на эти даты — с объектом, где заняты;
     кто не берёт новые работы (пауза, ушёл из команды) — неактивны. Все мастера работы ушли из команды — «Передать другому».
     Принятую работу и офисную (дизайн, закупка) не переназначаем */
  // согласие мастера с нарядом (KSH-519): до старта работы мастер отвечает «Согласен» или «Есть вопросы»
  const AGR = { pending: 'ещё не ответил на наряд', agreed: 'согласен с нарядом', question: 'есть вопрос' };
  function Crew({ w, onAssign, canLink, onLink, note }) {
    const [pick, setPick] = React.useState(null); // 'replace' | 'add'
    const [copied, setCopied] = React.useState(null);
    const [err, setErr] = React.useState('');
    const can = !!onAssign && w.status !== 'done' && !w.office && !w.sub;
    const free = w.crew.filter((c) => !c.on);
    const go = (id, mode) => { const r = onAssign(id, mode) || {}; setErr(r.error || ''); if (!r.error) { setPick(null); setCopied(null); } };
    const copy = (m) => {
      const url = onLink(m.id); if (!url) return;
      try { const pr = navigator.clipboard && navigator.clipboard.writeText(url); if (pr && pr.catch) pr.catch(() => {}); } catch (e) { /* без буфера — ссылка видна ниже */ }
      setCopied({ url });
    };
    const gone = w.who.length > 0 && w.who.every((m) => m.st && m.st.k === 'left');
    // отсутствие на дни работы (KSH-524): «отпуск по 12.11», «больничный без даты выхода»
    const awL = (a) => a.l + (a.to ? ' по ' + a.to.slice(8) + '.' + a.to.slice(5, 7) : ' без даты выхода');
    const off = !gone && w.who.length > 0 && w.who.every((m) => m.away) ? w.who[0].away : null;
    const offL = (c) => (c.away ? awL(c.away) + ', на эти дни наряд не выдать' : !c.st ? 'не берёт новые работы' : c.st.k === 'no_new' ? 'на паузе, новые наряды не выдаются' : c.st.l);
    const busyL = (c) => (!c.active ? offL(c) : c.busy.length ? 'в эти дни занят: ' + short(c.busy[0].obj) + (c.busy.length > 1 ? ' и ещё ' + (c.busy.length - 1) : '') : 'свободен в эти дни');
    return (
      <React.Fragment>
        <div className="lw-wsh">Наряд</div>
        {w.who.length ? w.who.map((m) => (
          <span key={m.id || m.name} className="lw-wwho"><FaceSt m={m} size={32} /><span className="tx"><span className="t">{m.name}</span><span className={'lab' + (m.st ? ' lw-tst is-' + m.st.k : m.away ? ' lw-tst is-away' : '')}>{(m.trade || 'мастер') + (m.st ? ' · ' + m.st.l : m.away ? ' · ' + awL(m.away) : '')}</span>
              {m.agree ? <span className={'lab lw-tst lw-agr is-' + m.agree.status}>{AGR[m.agree.status]}{m.agree.status === 'question' && m.agree.question ? ': «' + m.agree.question + '»' : ''}</span> : null}</span>
            {can && canLink && canLink(m.id) ? <button type="button" className="cv-arrow-btn lw-wln" onClick={() => copy(m)} title="Скопировать ссылку на задание в кабинете мастера">Ссылка<Ic n="ne" s={13} /></button> : null}
            {can ? <button type="button" className="lw-lnk lab lw-wrm" onClick={() => go(m.id, 'remove')} aria-label={'Снять с работы: ' + m.name} title="Снять с работы"><Ic n="x" s={14} /></button> : null}
          </span>)) : <span className="lab">{can ? 'Наряд никому не выдан. Нужен ' + w.need.toLowerCase() + '.' : 'Мастер не назначен'}</span>}
        {gone && can && <div className="lab is-late lw-wcopied">{w.who.length > 1 ? 'Мастера ушли' : 'Мастер ушёл'} из команды, работа без исполнителя. Передайте её мастеру из бригады объекта.</div>}
        {off && can && <div className="lab lw-wcopied">{w.who.length > 1 ? 'Мастера отсутствуют' : 'Мастер отсутствует'} в дни работы: {awL(off)}. Передайте работу мастеру из бригады объекта или сдвиньте сроки.</div>}
        {w.sub && <div className="lab lw-wcopied">Работа подрядчика {w.sub.name}: счёт, заказ, поставка и ссылка подрядчику — в окне «Подрядчики».</div>}
        {copied && <div className="lab lw-wcopied">Ссылка на задание скопирована, отправьте её мастеру в мессенджер. <a href={copied.url} target="_blank" rel="noopener">Открыть</a>{note ? <React.Fragment><br />{note}.</React.Fragment> : null}</div>}
        {can && !pick && <span className="lw-wcrew">
          {gone || off ? <button type="button" className="lw-btn-k" onClick={() => setPick('replace')}>Передать другому</button>
            : w.who.length ? <button type="button" className="lw-btn-l" onClick={() => setPick('replace')}>Сменить мастера</button> : <button type="button" className="lw-btn-k" onClick={() => setPick('replace')}>Выдать наряд</button>}
          {w.who.length > 0 && !gone && free.length > 0 && <button type="button" className="cv-arrow-btn" onClick={() => setPick('add')}>Добавить второго</button>}</span>}
        {pick && <div className="lw-wpick">
          <div className="lab">{pick === 'add' ? 'Второй мастер на эту работу' : w.who.length ? 'Кому передать работу' : 'Кому выдать наряд'} · бригада объекта</div>
          {free.map((c) => (
            <button type="button" key={c.id} className={'lw-wpc' + (c.match ? ' is-match' : '') + (c.busy.length ? ' is-busy' : '')} disabled={!c.active} onClick={() => go(c.id, pick)}>
              <span className="t">{c.name}</span><span className="lab">{c.trade}{c.kind === 'guest' ? ', приходящий' : ''} · {busyL(c)}</span></button>))}
          {!free.length && <span className="lab">В бригаде объекта больше никого нет.</span>}
          <button type="button" className="lw-lnk lab" onClick={() => setPick(null)}>Отмена</button>
        </div>}
        {err && <div className="lab is-late" role="alert">{err}</div>}
      </React.Fragment>);
  }

  /* по комнатам (KSH-504): работа сметы по комнатам — в каждой комнате шаги работы (пункты чек-листа); мастер сдаёт шаг, прораб принимает
     сданный, возвращает (замечание — необязательно) или отмечает сделанным сам (сдать и принять разом). Готовность — по принятым шагам.
     onRoomStep(kind, roomId, stepId, comment) — kind: accept | return | close; вернуть { error } при ошибке. Задачу шаги не закрывают */
  const RST = { open: ['Не сдано', 'pill-d'], submitted: ['Сдано, ждёт проверки', 'lw-wst is-soon'], accepted: ['Принято', 'pill-g'] };
  const num = (n) => String(Math.round(n * 100) / 100).replace('.', ',');
  const roomQty = (r) => (r.qty != null ? num(r.qty) + (r.unit ? ' ' + r.unit : '') : r.share ? 'доля ' + Math.round(r.share * 100) + ' %' : '');
  function RoomSteps({ v, onRoomStep }) {
    const [ret, setRet] = React.useState(null); // { roomId, stepId, text }
    const [err, setErr] = React.useState('');
    const go = (kind, roomId, stepId, comment) => { const r = onRoomStep(kind, roomId, stepId, comment) || {}; setErr(r.error || ''); if (!r.error) setRet(null); };
    const acceptAll = (room) => {
      for (const s of room.steps.filter((x) => x.state === 'submitted')) { const r = onRoomStep('accept', room.roomId, s.id) || {}; if (r.error) { setErr(r.error); return; } }
      setErr('');
    };
    return (
      <section className="lw-wrooms" aria-labelledby="lw-wr-h">
        <div className="lw-sech"><h3 className="lw-h3" id="lw-wr-h">По комнатам</h3>
          <span className="lab">{v.accepted} из {v.total} {plural(v.total, 'шага', 'шагов', 'шагов')} принято{v.submitted ? ' · сдано, ждёт проверки: ' + v.submitted : ''}</span></div>
        {v.allAccepted && <div className="lw-wrdone"><span className="pill-g"><span className="dot" />Все комнаты приняты</span><span className="lab">Работу можно принять целиком — статус работы шаги не меняют.</span></div>}
        {err && <div className="lab is-late" role="alert">{err}</div>}
        <div className="lw-wrg">{v.rooms.map((room) => (
          <div key={room.roomId} className="cv-w lw-wr">
            <div className="hd"><span className="tx"><span className="t">{room.name}</span>{roomQty(room) ? <span className="lab">{roomQty(room)}</span> : null}</span>
              <b className="pct">{room.pct} %</b></div>
            <div className="lw-wrbar" aria-hidden="true"><i style={{ width: room.pct + '%' }} /></div>
            {room.submitted > 1 && <button type="button" className="cv-arrow-btn lw-wrall" onClick={() => acceptAll(room)}>Принять всё сданное · {room.submitted}</button>}
            {room.steps.map((s) => {
              const [l, c] = RST[s.state] || RST.open;
              const open = ret && ret.roomId === room.roomId && ret.stepId === s.id;
              return (
                <div key={s.id} className={'lw-wrs is-' + s.state}>
                  <span className="tx"><span className="t">{s.label}</span>
                    {s.state !== 'open' && (s.by || s.at) ? <span className="lab">{(s.state === 'accepted' ? 'принял ' : 'сдал ') + [s.by, s.at ? when(s.at) : ''].filter(Boolean).join(' · ')}</span> : null}
                    {s.state === 'open' && s.comment ? <span className="lab is-late">Вернули: {s.comment}</span> : null}</span>
                  <span className={c}>{l}</span>
                  {s.state === 'submitted' && !open && <span className="lw-racts">
                    <button type="button" className="lw-btn-l" onClick={() => setRet({ roomId: room.roomId, stepId: s.id, text: '' })}>Вернуть</button>
                    <button type="button" className="lw-btn-k" onClick={() => go('accept', room.roomId, s.id)}><Ic n="check" s={14} />Принять</button></span>}
                  {s.state === 'open' && <span className="lw-racts"><button type="button" className="lw-btn-l" onClick={() => go('close', room.roomId, s.id)} title="Сдать и принять разом — прораб закрывает шаг сам">Отметить сделанным</button></span>}
                  {open && <div className="lw-wrret">
                    <textarea rows={2} value={ret.text} onChange={(e) => { const t = e.target.value; setRet((x) => ({ ...x, text: t })); }} placeholder="Что исправить — необязательно" aria-label={'Замечание: ' + room.name + ', ' + s.label} />
                    <span className="lw-racts"><button type="button" className="lw-lnk lab" onClick={() => setRet(null)}>Отмена</button>
                      <button type="button" className="lw-btn-l" onClick={() => go('return', room.roomId, s.id, ret.text)}>Вернуть на доработку</button></span>
                  </div>}
                </div>);
            })}
          </div>))}</div>
      </section>);
  }

  /* просьба мастера о переносе сроков (KSH-528): было → стало, причина, чьи работы в тех же комнатах окажутся внутри новых дат.
     «Перенести» двигает только эту работу; соседей прораб двигает сам. Отказ — с причиной для мастера */
  const dd = (x) => (x ? x.slice(8, 10) + '.' + x.slice(5, 7) : '');
  function ShiftReq({ r, onShift }) {
    const [no, setNo] = React.useState(false);
    const [note, setNote] = React.useState('');
    const [err, setErr] = React.useState('');
    if (!r) return null;
    const go = (ok) => { const x = onShift(ok, note) || {}; setErr(x.error || ''); };
    if (r.status !== 'pending') return <div className="lab lw-wcopied">{r.status === 'approved' ? 'Перенос согласован: ' + dd(r.from.start) + ' → ' + dd(r.start) : 'Перенос не согласован' + (r.note ? ': ' + r.note : '')}{r.decidedBy ? ' · ' + r.decidedBy : ''}</div>;
    return (
      <div className="lw-wshift">
        <div className="lw-wsh">{r.byName || 'Мастер'} просит перенести сроки</div>
        <div className="lw-wsh-d"><span className="lab">Было</span><b>{dd(r.from.start)}–{dd(r.from.end)}</b><span className="lab">Стало</span><b>{dd(r.start)}–{dd(r.end)}</b></div>
        <p className="lab">«{r.reason}»</p>
        {r.impact && r.impact.length ? <div className="lab is-late">Заденет в тех же комнатах: {r.impact.map((x) => '«' + x.name + '»' + (x.who ? ', ' + x.who : '') + ' ' + dd(x.start) + '–' + dd(x.end)).join('; ')}. Их сроки не изменятся сами.</div>
          : <div className="lab">Чужие работы в тех же комнатах не задевает.</div>}
        {onShift ? (no ? <div className="lw-wdec"><textarea rows={2} value={note} onChange={(e) => setNote(e.target.value)} placeholder="Почему не переносим — увидит мастер" />
          <div className="lw-wbtns"><button type="button" className="lw-btn-l" onClick={() => { setNo(false); setErr(''); }}>Отмена</button><button type="button" className="lw-btn-k" disabled={!note.trim()} onClick={() => go(false)}>Отправить отказ</button></div></div>
          : <div className="lw-wbtns"><button type="button" className="lw-btn-l" onClick={() => setNo(true)}>Отказать</button><button type="button" className="lw-btn-k" onClick={() => go(true)}>Перенести</button></div>) : null}
        {err && <div className="lab is-late" role="alert">{err}</div>}
      </div>);
  }

  function WorkCard({ w, onClose, onAccept, onReturn, onChat, onObject, view, upload, onAssign, canLink, onLink, linkNote, onRoomStep, onShift }) {
    const [sel, setSel] = React.useState(Math.min(w.at || 0, Math.max(0, w.photos.length - 1)));
    const [notes, setNotes] = React.useState([]);
    const [draft, setDraft] = React.useState({ x: null, y: null, text: '', img: null });
    const [general, setGeneral] = React.useState('');
    const [err, setErr] = React.useState('');
    const photo = w.photos[sel] || null;
    const edit = w.decide;
    // прошлые замечания (работа уже возвращалась) — метками на фото, без правки
    const old = (w.notes || []).map((n, i) => ({ ...n, no: i + 1 }));
    const mine = notes.map((n, i) => ({ ...n, no: i + 1 }));
    const shown = (edit ? mine : old).filter((n) => photo && n.url === photo.url);
    const add = () => {
      if (!photo || !draft.text.trim()) return;
      setNotes(notes.concat({ url: photo.url, name: photo.name || '', x: draft.x, y: draft.y, text: draft.text.trim(), img: draft.img }));
      setDraft({ x: null, y: null, text: '', img: null });
    };
    const ret = () => {
      setErr('');
      const r = onReturn({ remark: general.trim(), notes });
      if (r && r.error) setErr(r.error);
    };
    const acc = () => { setErr(''); const r = onAccept(); if (r && r.error) setErr(r.error); };
    const canReturn = notes.length > 0 || general.trim().length > 0;
    const [stL, stC] = w.late ? ['Просрочено на ' + w.late + ' ' + plural(w.late, 'день', 'дня', 'дней'), 'lw-wst is-late'] : (ST[w.status] || ST.todo);
    return (
      <Modal size="wide" className="lw-work" sub={[short(w.obj), w.phase, w.stage].filter(Boolean).join(' · ')} title={w.title + (w.pointName ? ' · ' + w.pointName : '')} onClose={onClose}
        head={<span className={stC}>{stL}</span>}>
        <div className="lw-wg">
          <div className="lw-wmain">
            {photo ? <React.Fragment>
              <PhotoNotes photo={photo} notes={shown} draft={edit && draft.x != null ? { ...draft, no: mine.length + 1 } : null} editable={edit}
                onPin={(pt) => setDraft((d) => ({ ...d, ...pt }))} onZoom={() => view(w.photos.map((x) => ({ kind: 'image', url: x.url, name: x.name || w.title })), sel)} />
              {w.photos.length > 1 && <div className="lw-wstrip" role="tablist" aria-label="Фото работы">{w.photos.map((x, i) => {
                const n = (edit ? mine : old).filter((y) => y.url === x.url).length;
                return <button type="button" role="tab" key={x.url + i} aria-selected={i === sel} className={i === sel ? 'on' : ''} onClick={() => { setSel(i); setDraft({ x: null, y: null, text: '', img: null }); }} aria-label={'Фото ' + (i + 1) + (n ? ', замечаний: ' + n : '')}>
                  <img src={x.url} alt="" loading="lazy" />{n ? <span>{n}</span> : null}</button>;
              })}</div>}
              {edit && <NoteForm draft={draft} setDraft={setDraft} onAdd={add} upload={upload} />}
              {shown.length > 0 && <div className="lw-wnl">{shown.map((n) => (
                <div key={n.no} className="lw-wn"><b className="lw-pin is-static">{n.no}</b>
                  <span className="t">{n.text}{n.x == null ? <span className="lab"> · ко всему фото</span> : null}</span>
                  {n.img ? <button type="button" className="lw-watt" onClick={() => view([{ kind: 'image', url: n.img.url, name: n.img.name || 'Картинка к замечанию' }], 0)} aria-label="Открыть картинку к замечанию"><img src={n.img.url} alt="" /></button> : null}
                  {edit ? <button type="button" className="lw-lnk lab" onClick={() => setNotes(notes.filter((y, k) => k !== n.no - 1))} aria-label={'Убрать замечание ' + n.no}><Ic n="x" s={14} /></button> : null}
                </div>))}</div>}
            </React.Fragment> : <div className="lw-wempty"><Ic n="camera" s={26} /><span>{w.status === 'review' ? 'Мастер сдал работу без фото.' : 'Фото появятся, когда мастер сдаст работу.'}</span></div>}
          </div>

          <aside className="cv-w lw-wside" aria-label="О работе">
            <div className="lw-wf">
              <span><span className="lab">Срок</span><b className={w.late ? 'is-late' : ''}>{w.end ? dateR(w.end) : '—'}</b>{w.late ? <span className="lab is-late">прошло {w.late} {plural(w.late, 'день', 'дня', 'дней')}</span> : w.start ? <span className="lab">с {dateR(w.start)}</span> : null}</span>
              <span><span className="lab">Стоимость</span><b>{w.price ? rub(w.price) : '—'}</b>{w.submittedAt ? <span className="lab">сдал {when(w.submittedAt)}</span> : null}</span>
            </div>
            <div className="lw-who-l"><Crew w={w} onAssign={onAssign} canLink={canLink} onLink={onLink} note={linkNote} />
              <span className="lw-wlinks">{onChat && !(w.who.length && w.who.every((m) => m.st && m.st.k === 'left')) ? <button type="button" className="cv-arrow-btn" onClick={onChat}>Написать мастеру<Ic n="ne" s={14} /></button> : null}{onObject ? <button type="button" className="cv-arrow-btn" onClick={onObject}>Объект<Ic n="ne" s={14} /></button> : null}</span></div>
            {w.shift ? <ShiftReq r={w.shift} onShift={onShift} /> : null}
            {w.checklist.length > 0 && <div className="lw-wcl"><div className="lw-wsh">Чек-лист сдачи · {w.checklist.filter((c) => c.ok).length} из {w.checklist.length}</div>
              {w.checklist.map((c) => <div key={c.id} className={'lw-wci' + (c.ok ? ' ok' : '')}><Ic n={c.ok ? 'check' : 'clock'} s={14} /><span>{c.label}</span></div>)}</div>}
            {w.remark && w.status === 'returned' && <div className="lw-wret"><div className="lw-wsh">Вернули на доработку{w.returnedAt ? ' · ' + when(w.returnedAt) : ''}</div><p>{w.remark}</p>{old.length ? <span className="lab">{old.length} {plural(old.length, 'замечание', 'замечания', 'замечаний')} к фото — метками на фото</span> : null}</div>}
            {edit && <div className="lw-wdec">
              <label className="lw-wsh" htmlFor="lw-wgen">Общий комментарий</label>
              <textarea id="lw-wgen" rows={3} value={general} onChange={(e) => setGeneral(e.target.value)} placeholder="Если замечание не к конкретному фото" />
              <div className="lab">{notes.length ? notes.length + ' ' + plural(notes.length, 'замечание', 'замечания', 'замечаний') + ' к фото' : 'Замечаний к фото нет'}</div>
              {err && <div className="lab is-late" role="alert">{err}</div>}
              <div className="lw-wbtns">
                <button type="button" className="lw-btn-l" disabled={!canReturn} onClick={ret} title={canReturn ? '' : 'Добавьте замечание к фото или общий комментарий'}>Вернуть на доработку</button>
                <button type="button" className="lw-btn-k" disabled={canReturn} onClick={acc} title={canReturn ? 'Есть замечания — работу можно только вернуть' : ''}><Ic n="check" s={14} />Принять</button>
              </div>
            </div>}
            {w.history.length > 0 && <div className="lw-whist"><div className="lw-wsh">История</div>{w.history.map((h, i) => <div key={i} className="lw-wh"><span className="t">{h.text}</span><span className="lab">{[h.who, when(h.ts)].filter(Boolean).join(' · ')}</span></div>)}</div>}
          </aside>
        </div>
        {w.rooms && onRoomStep ? <RoomSteps v={w.rooms} onRoomStep={onRoomStep} /> : null}
      </Modal>);
  }

  W.WorkCard = WorkCard;
})();
