Я никогда не беру свой компьютер с собой в отпуск.

Я вижу в этом способ отключиться и избежать соблазна исследовать идеи, которые неизбежно ведут не только к работе, но и к неоплачиваемой работе.

Во время перерывов я более чем счастлив использовать свой телефон в качестве основного источника указаний и мемов.

Но на этот раз я принесла свой компьютер на наше 3-х дневное пребывание в общежитии, где вообще не было интернета. Интернет-провайдеры, даже по нашим телефонным данным, просто не доходили до дома.

Место находится на полуострове Каикоура и в 15 минутах езды от города. Но из-за окружающих гор и прочего интернета там просто нет.

Какое-то время у меня была идея создать веб-приложение, которое позволило бы пользователям делать следующее:

  1. Создавайте и сохраняйте тренировки HIIT с упражнениями, временем и повторениями для них, а также временем восстановления.
  2. Воспроизвести эти тренировки. Пользователь нажимает кнопку начать тренировку, и приложение проведет его через тренировку, переключаясь с одного упражнения на другое, показывая, что пользователю нужно будет выполнить.
  3. Один или несколько пользователей могут тренироваться вместе удаленно, выполняя одну и ту же тренировку в одно и то же время, при этом приложение синхронизирует все устройства.

У меня было четкое представление о том, что мне нужно, и у меня было время. Мне просто не хватало Интернета и большинства вещей, на которые я обычно полагаюсь при создании приложения.

С npx create-react-app workouts-app и даже самим npm со стола я взял все, что у меня было в наличии, составил очень быстрый план и использовал то, что я могу сделать сам с моими умопомрачительными способностями и без какого-либо руководства из интернетов.

Теперь, когда я в Эрроутауне и снова в паутине, я хотел бы рассказать вам, как я его обошёл и как далеко продвинулся.

что мне было нужно

Глядя на то, на что я нацелен, вот что мне нужно на высоком уровне:

  1. Бэкенд-сервер Node для (фиктивного) API и широковещания сокетов.
  2. React интерфейс для веб-приложения.
  3. WebSockets для поддержания актуальности приложения во внешнем интерфейсе.

Серверная часть Node будет генерировать и извлекать имитированный список тренировок и генерировать широковещательное событие, когда пользователь запускает новую тренировку.

Внешний интерфейс будет отображать список доступных тренировок, позволять детализировать их детали и воспроизводить их (показывая пошаговые инструкции с указанием времени, чтобы пользователь мог следовать им).

Во внешнем интерфейсе WebSockets будет обрабатывать событие, сгенерированное сервером, а React соответствующим образом обновит внешний интерфейс, чтобы пользователи знали, что тренировка была запущена другим пользователем.

Но без yarn install…. Что делать, о, что делать?

Основы

Мой последний проект — это приложение React для Министерства здравоохранения Новой Зеландии, которое использует WebSockets для синхронизации устройств в тестовом центре RAT.

Это монорепозиторий с бэкендом (сервер Node Express) и внешним интерфейсом (CRA).

Это приложение было запущено пару недель назад (начало января 2022 года), поэтому я с уверенностью могу предположить, что это будет достойная сборка CRA и современный сервер Express.

По сути, я взял это приложение и урезал его до самых основ, которые мне были нужны.

  1. Удалены конечные точки с сервера Express.
  2. Удалено все, что связано с приложением RAT во внешнем интерфейсе.
  3. Оставил его в состоянии, когда соединение WebSockets работало, и приложение просто отображало страницу с надписью Socketsconnected.

Это было отличное начало, и я использовал только то, что было на моем компьютере.

Но что еще более важно, я получил стартовое приложение для любого другого веб-сокета, которое хотел бы создать в будущем.

Итак, чистый лист с работающим сервером WebSocket. Теперь приступим к осколкам.

Бэкэнд

Глядя на то, что намеревается сделать MVP, у нас в основном есть две конечные точки:

  1. GET /workouts: для получения списка тренировок.
  2. POST /workout/:id/start: Чтобы сообщить бэкэнду, что новая тренировка началась, и чтобы бэкэнд транслировал ее на все подключенные сокеты.

Конечная точка GET /workouts вернет пробные тренировки.

Но что такое workout? Как это представлено в контексте приложения и где я могу получить его список?

С faker.js вне поля зрения (без Интернета и не включенного в мой стартовый проект), мне нужно было немного смоделировать список тренировок вручную.

Итак, я просто следовал концепции приложения:

  1. Нацельтесь на HIIT, поэтому должны быть циклы.
  2. В цепях есть интервальные упражнения, восстановление и раунды.
  3. Упражнения также могут иметь repetitions.

Итак, я создал типы.

Одни и те же можно повторно использовать во внешнем интерфейсе, что является отличной новостью.

Итак, с этого момента это стало просто большим упражнением по рандомизации, поэтому имитации могут быть (вроде) реальными сценариями.

Это то, на что я нацелился с помощью моков:

  1. Создайте три тренировки.
  2. Каждая тренировка будет иметь случайное количество схем со случайным количеством раундов.
  3. Каждая схема будет иметь случайное количество упражнений и периодов восстановления.
  4. Каждому упражнению и восстановлению будет назначено случайное время.
  5. Некоторые упражнения будут иметь случайные числа повторений.

Итак, вот что из этого вышло.

Ничего сумасшедшего, а просто пара утилит, которые рандомизируют нужные мне числа, и нужно ли добавлять повторения или нет.

Далее мне нужно было подключить моки с помощью API. Итак, учитывая прошлый проект и ожидая выхода за пределы MVP, я последовал соглашению, которое использовал для этого проекта RAT, и создал модуль workout.ts следующим образом.

Последним шагом было добавление конечной точки к маршрутизатору Express с новым обработчиком запроса списка тренировок и тестирование этого API с помощью Postman, чтобы убедиться, что я получаю три тренировки, как имитированные.

Так оно и было. Теперь о фронтенд-стороне реализации.

Фронтенд

Интерфейс будет работать следующим образом:

  1. Пользователь переходит на страницу, и приложение запрашивает тренировки из API.
  2. Пользователь нажимает на тренировку, и сведения о ней отображаются с помощью кнопки Начать тренировку.
  3. Пользователь нажимает Начать тренировку, и приложение воспроизводит тренировку, показывая упражнения, время, повторения и текущий раунд для циклов или просто время для восстановления.
  4. Другие пользователи, просматривающие приложение, смогут увидеть, что кто-то еще выполняет определенную тренировку.

Для этого у приложения должен быть способ использовать данные о тренировках из API для отображения упражнений и восстановления и переключения с одного на другое в соответствии с установленным для них временем.

Подход к приложениям React в настоящее время в значительной степени основан на хуках. Хуки представляют собой функциональный способ написания функций, которые не обязательно принадлежат конкретному компоненту, но которые можно использовать для введения state в чистые компоненты.

Мои хуки в основном выглядели бы следующим образом:

  1. useWorkouts: Хук, который будет полагаться на response-query и axios (оба доступны в моем RAT-ловце) для запроса тренировок из API.
  2. useWorkoutTimer: Хук, который будет уменьшать время начала на единицу с интервалом в 1 секунду и вызывать обратный вызов, когда время достигает 0.

Таким образом, я могу проверить визуализацию списка тренировок, детализировать тренировку и функция воспроизведения тренировки в зависимости от времени выполнения упражнений и восстановления.

Веб-сокеты

А теперь самое интересное: уведомление других пользователей о начале новой тренировки.

Это в основном означает, что мне нужно:

  1. Внешний интерфейс для уведомления внутреннего интерфейса о начале новой тренировки.
  2. Бэкэнд для трансляции начала тренировки остальным пользователям, подключенным к серверу WebSockets.

Чтобы уведомить серверную часть о начале новой тренировки, я использовал конечную точку POST workout/:id/start.

Для этого MVP запрос работает только с пустым телом (на данный момент см. Куда сейчас ниже), а серверная часть идентифицирует начатую тренировку через id в пути.

Чтобы транслировать начало тренировки на остальные подключенные сокеты, сервер emits отправляет событие с идентификатором тренировки как часть полезной нагрузки, отправляемой во внешний интерфейс.

Чтобы сделать сервер WebSockets доступным для обработчиков emit, для этой версии достаточно export в server.js и импорта оттуда, откуда должна происходить трансляция.

Где я приземлился

Я в восторге от того, что мне удалось доказать то, что я хотел, не прибегая к помощи Интернета, а просто полагаясь на прошлое меня в том, что мне было нужно.

Приложение отображает три различных имитационных тренировки, созданных при запуске сервера, пользователи могут углубиться в тренировку, чтобы увидеть все ее схемы, упражнения и восстановление с их временем, и пользователи могут начать тренировку.

И самое интересное… Когда начинается новая тренировка, другие пользователи видят ее в списке тренировок.

Действительно хороший прогресс, используя только то, что у меня было под рукой, и определенно то, из чего я могу продолжать строить.

Где сейчас

Это определенно MVP, но я считаю, что это полезный прототип.

Мне удалось сохранить кодовую базу на достойном уровне, и те детали, которые мне нужно улучшить, потребуют помощи от сообщества, также известного как Интернет.

Проект находится в Github. Я перешел к ответвлению MVP без подключения, чтобы сохранить результаты этих трех дней отдельно и в качестве отправной точки для подпитываемых Интернетом последующих действий.

Итак, теперь, когда Интернет доступен, я предприму следующие шаги:

  1. Сделайте его способным создавать тренировки через приложение.
  2. Пригласите tailwind-css в проект! Как вы могли заметить, я не дизайнер (и не силен в CSS). Итак, моему MVP нужна помощь, чтобы выглядеть достойно.
  3. Перенесите useWebSocketsс hook на context, чтобы соединение WebSocket устанавливалось на уровне приложения.
  4. Сделайте так, чтобы приложение позволяло пользователям переходить в тренировку, в которую играет другой пользователь, с той точки, в которой они находятся, и синхронизировало их. ЭТО БУДЕТ ИНТЕРЕСНО, но мне не терпится поучаствовать в этом.

Заключение

Я рассматриваю этот опыт как способ показать, что чего бы вы ни хотели достичь, вы либо уже это сделали, либо у вас где-то есть что-то, что можно настроить для того, что вам нужно.

В этом случае я поставил перед собой задачу создать работающий пример того, что я себе представлял, сосредоточившись на вещах, которые я мог решить сам, используя то, что у меня было в моем компьютере, чтобы заставить его работать.

Что удивительно, так это то, что если я сравниваю результаты с развитием в обычных обстоятельствах, результат, даже если он не идеален, все же является чем-то, на чем я могу основываться.

Попробуйте игнорировать Интернет в своем следующем проекте и посмотрите, как далеко вы сможете продвинуться.

Выберите то, что может быть основано на прошлом опыте, составьте список того, что требуется, и определите действия, которые вы можете предпринять, когда VS Code является единственным открытым приложением на вашем компьютере.

Вы будете удивлены тем, как много из тех вещей, для которых вы обычно просто загуглили / установили еще один пакет, вы можете просто подумать и разобраться в них, опираясь на собственные знания и размышления.