Навыки
То, во что вкладывают годы. Семнадцать ступеней от первого часа до пятнадцати тысяч. Вкладка появляется, только когда модуль включён.

Зачем этот экран
Приоритеты отвечают на вопрос «как прошла неделя». Навыки отвечают на вопрос «сколько я в этом всего» — и меряются не сутками, а годами. Поэтому переключателя периода здесь нет: на такой шкале выбор окна менял бы только пару мелких чисел. Вместо него — темп за 30 дней и прогноз следующей ступени: он отвечает на второй вопрос, «двигаюсь ли я вообще».
Главное отличие от приоритетов: у навыка есть стартовый капитал — часы, накопленные до появления приложения. Их вписывают руками, и лестница начинается не с нуля.
Что на экране
- Счётчик в шапке — сколько навыков из двенадцати занято.
- Итог — всего часов во всех навыках и сколько из них прибавилось за последние 30 дней.
- «Дописать прошлый день» — раскрывает ленту из четырнадцати дней, ту же, что и на главной.
- Строка навыка: название, текущая ступень, полоса до следующей ступени (не относительно других навыков — у навыка нет соперников), полоса дней за две недели, накопленные часы, прибавка за 30 дней цветом и порог следующей ступени.
- «+» — добавить блок. У привязанного навыка этот «+» пишет в приоритет.
- «Добавить навык», ниже — архив удалённых навыков с их часами.
Как этим пользоваться
Отметить блок и снять отметку
«+» в строке добавляет блок за сегодня — или за тот день, который выбран в ленте. Чтобы снять лишний, нажмите на строку — наверху шторки стоит счётчик с «−» и «+», и подпись под ним всегда называет день. Это тот же счётчик, что и у приоритетов: промахнуться по «+» одинаково легко и там, и там, и способ исправиться один и тот же.

У привязанного навыка обе кнопки работают с приоритетом — время там и там одно, поэтому на главной блоков тоже станет на один меньше. Запасной путь есть для навыка, который копил сам и получил привязку позже: собственные блоки этого дня у него никуда не делись, и «−» снимет их.
Понять, занимался ли сегодня
Под полосой прогресса в каждой строке стоит полоса дней: столбик на день, высота — сколько блоков. Крайний правый столбик — сегодня, и он обведён всегда, даже пустой. Пустая рамка у правого края и есть ответ «сегодня ещё нет» — его видно, не читая ни одной цифры.
Глубина полосы — четырнадцать дней, ровно столько же, сколько у ленты дописывания. Видно только те пропуски, которые ещё можно закрыть: показывать дыру, до которой не дотянуться, значит дразнить.
Высота столбиков считается от собственного максимума навыка, а не от общего на экране. У гитары и у английского разный обычный день, и общая шкала прижала бы меньший навык к нулю. Сравнивать навыки между собой полоса и не должна — у каждого свой порог впереди.
В шторке та же полоса, но крупная и с подписями дней недели: нажмите на столбик, и под ним появится этот день с часами. Без нажатия там стоит сегодняшний день.
Дописать блок за прошедший день

Нажмите «Дописать прошлый день» и выберите число в ленте. Точка под числом означает, что в этот день у навыков уже что-то есть: у привязанного — блоки его приоритета, у самостоятельного — свои.
Дальше всё как обычно: «+» в строке и счётчик в шторке пишут в выбранный день, а не в сегодня. Об этом напоминает жёлтая плашка с кнопкой «К сегодня» — она же и выход из режима. Режим не переживает перезапуск приложения и сбрасывается в полночь: забыть, что пишешь во вчера, — главный риск, и он стоил бы целых суток.
Это единственный способ дописать время самостоятельному навыку задним числом. У привязанного тот же блок можно дописать и с главной — время там и там одно, и разницы между двумя путями нет.
Посмотреть темп и прогноз
Под накопленными часами в шторке стоит строка вида «Темп за 30 дней — 4,5 ч в неделю. Следующая ступень при таком темпе — через 7 месяцев».
Окно всегда одно и то же — тридцать дней. Недели мало: одна поездка обнулила бы темп. Прогноз линейный, поэтому округляется до дней, недель, месяцев и лет — «через 4,3 месяца» обещало бы точность, которой здесь нет. Дальше десяти лет прогноз не считается вовсе: там уже не темп, а случайность.
Если за месяц не набралось ни блока, строка говорит об этом прямо, а прогноза нет — считать не от чего.
Добавить навык

Название берётся либо из списка (полсотни готовых, сгруппированных по темам), либо своё. Уже занятые названия в списке заблокированы.
Поле «Уже накоплено, часов» — самое важное. Считайте честно и приблизительно: точность здесь никому не нужна, а порядок величины меняет ступень. Эти часы — факт, а не клики, поэтому смена цены блока их не пересчитывает.
Посмотреть лестницу
Всё в той же шторке, под счётчиком.
По умолчанию видна окрестность текущей ступени: одна назад, две вперёд. Этого хватает, чтобы понять, где вы и что дальше.

Кнопка «Все 17 ступеней» разворачивает лестницу целиком. Полное описание рангов и порогов — на странице «Лестница навыков».
Связать навык с приоритетом

Если вы уже отмечаете «Работу» на главной, а навык называется «Программирование» — свяжите их. Тогда одно нажатие «+» на главной засчитается и туда, и сюда, а «+» у навыка начнёт писать в приоритет.
Правила связи:
- Один приоритет кормит только один навык. Привязка к занятому приоритету переспросит и снимет предыдущую.
- Связь ничего не переписывает. Часы приоритета просто прибавляются к часам навыка. Отвязали — навык вернулся ровно к прежнему числу.
- Если приоритет ушёл в архив, новое время идёт в собственный журнал навыка, а старые часы приоритета продолжают считаться. Об этом сообщает отдельная строка в шторке.
Настроить или удалить навык
Всё в той же шторке: название, цвет, стартовые часы, дата начала («В этом уже 7 лет») и кнопка удаления. Удалённый навык уходит в архив вместе с часами — добавьте навык с тем же названием, и они вернутся.
Пустое состояние

Ни итога, ни ленты дней нет: складывать и дописывать нечего. Вместо объяснения словами — размытый пример: три настоящие строки навыка с лестницей, часами и полосой дней, и кнопка поверх них. Пример собирается тем же компонентом, что и живой список, поэтому разойтись с ним не может.
Пределы и предупреждения
- 12 навыков и 12 в архиве, название — до 24 знаков. Это не вкусовое ограничение, а объём хранилища: см. «Пределы и лимиты».
- Стартовые часы — от 0 до 100 000.
- Прибавка за 30 дней не включает стартовый капитал и часы, свёрнутые из истёкших месяцев: у них нет даты, и приписать их к месяцу нельзя.
- Дописать можно четырнадцать дней назад, не глубже: дальше уже не вспомнить.
- Часы навыка, набранные кликами, переоцениваются при смене цены блока. Вписанные руками — нет.
Чего здесь нельзя
- Посмотреть итоги дня или недели. Переключателя периода здесь нет намеренно: навык меряется годами, и окно на этой шкале ничего не меняет. Лента дней — это выбор дня для записи, а не для просмотра.
- Отметить час, а не блок. Единица та же, что на главной.
- Связать два навыка с одним приоритетом. Приложение молча снимет старую связь — но предупредит об этом до, а не после.
- Получить достижение за конкретный навык. Достижения формулируются глобально («любой навык дошёл до 100 часов»): см. справочник.
Рядом
Лестница навыков · Модули · Приоритеты · Пределы и лимиты
Как это работает внутри
- Экран —
src/screens/SkillsScreen.tsx, строка —src/skills/SkillRow.tsx, шторка —src/skills/SkillSheet.tsx. - Часы навыка складываются из трёх источников (
src/skills/total.ts):baseMinutes + (carryBlocks + свои клики + клики привязанного приоритета) × цена блока. Формула аддитивная, поэтому привязка ничего не записывает и полностью обратима. - Куда уходит «+», решает
targetOf(skill, activePriorityIds): при живой связи — в приоритет, иначе — в собственный журнал навыка. Иначе одно и то же время считалось бы дважды. «−» зеркалит это решение и откатывается на собственный журнал, если в приоритете за выбранный день блоков нет. - Лента дней и всё её обрамление —
src/components/DayPicker.tsx: сама лента, кнопкаDayPickerToggleи плашкаPastDayNotice. Их делят главная и навыки, поэтому они живут рядом с лентой, а не на экранах. - Полоса дней —
src/skills/SkillHistory.tsx, один компонент на строку и на шторку: в строке без нажатия и подписей, в шторке с ними (detailed). Собрана наspan, хотя раскладка блочная: в строке она лежит внутри кнопки, а кнопка принимает только строчное содержимое — и кнопка в кнопке невалидна, поэтому там дни не нажимаются. Глубина берётся изBACK_DAYSсамой ленты, чтобы два горизонта не разъехались, а окно — это хвост тех же тридцати дней, что считают темп. Данные даётskillBlocksByDay(src/skills/total.ts). - Темп и прогноз —
src/skills/pace.ts, окноPACE_DAYS = 30. Прогноз линейный и намеренно грубый;formatEtaукрупняет единицу вместе со сроком. Границы подобраны так, чтобы недель никогда не вышло ровно одна: «через 1 неделя» требовало бы винительного падежа отдельной таблицей. Покрытоpace.test.ts. - Счётчик в шторке — общий
src/components/BlockTuner.tsx, тот же, что и в шторке приоритета. Инлайновую пару кнопок в самой строке пробовали и убрали: она отъедала у названия сорок с лишним пикселей на каждой строке. - Инвариант «один приоритет — один навык» чинится и при чтении из хранилища (
sanitizeSkillsвsrc/skills/types.ts), а не только в интерфейсе. carryBlocks— блоки, свёрнутые из месяцев, вышедших за глубину хранения (foldExpiredMonths). Без этого навык на 400 часов через год просел бы до 380. МеткаfoldedThroughедет в облаке, чтобы второе устройство не свернуло те же месяцы повторно.- Список названий —
src/skills/catalogue.ts; ступени —src/skills/levels.ts. Поведение покрытоsrc/skills/total.test.ts,src/skills/levels.test.tsиsrc/skills/pace.test.ts. - Модуль включается в настройках; при включении сначала дочитывается история навыков и только потом поднимается флаг, иначе клик, сделанный в этот промежуток, затёрся бы приехавшей картой (
src/store/useStore.tsx).