---
name: getmyboat-listing-workflow
description: Create and manage boat listings on GetMyBoat — login, fill essentials, vessel details, pricing, autocomplete fields, and handle session limits.
---

# GetMyBoat Listing Workflow

Создание и редактирование объявлений на GetMyBoat через браузер.

## Проблемы и решения

### 1. Login и CAPTCHA
- GetMyBoat использует reCAPTCHA на логине
- **Работает:** залогиниться с первой попытки, быстро ввести данные через `browser_type`
- **Не работает:** повторный логин после обнуления сессии — CAPTCHA блокирует
- **Сессию нельзя терять** — страницу не перезагружать без необходимости

### 2. Сессия в админке
- Прямой URL админки: `https://www.getmyboat.com/admin/listings/`
- Если уже залогинен — сразу показывает список лодок
- Если нет — редиректит на `/s/auth/login/`

### 3. Редактор объявления (multi-tab)
URL: `https://www.getmyboat.com/admin/listing/{ID}/`

Tabs (по порядку):
1. **Essentials** — заголовок, описание, категории, капитан
2. **Location** — адрес и точка отбытия
3. **Photos** — загрузка фото (только руками — системный диалог)
4. **Vessel Details** — make, model, year, length, capacity, engines
5. **Pricing** — тарифы, отмена, депозит

### 4. Autocomplete поля (Make / Model)
Эти поля — React Downshift-компоненты с `id="make-input"` / `id="model-input"`. **Не работают** через обычный `browser_type` по ref — нужно через JS.

**Как заполнить Make (проверено):**
1. Сфокусироваться на поле (через браузер нажать на combobox)
2. Ввести название через JavaScript, диспатча `input` event:
```javascript
const input = document.getElementById('make-input');
input.value = 'Fountaine';
input.dispatchEvent(new Event('input', {bubbles: true}));
// Затем дописать полное имя
input.value = 'Fountaine Pajot';
input.dispatchEvent(new Event('input', {bubbles: true}));
```
3. Подождать ~500ms пока API подгрузит options в `#make-menu`
4. Проверить наличие "Fountaine Pajot" в меню:
```javascript
const items = document.querySelectorAll('#make-menu [role="option"]');
// items ~659 штук, алфавитный порядок
```
5. Найти нужный option и кликнуть:
```javascript
items.forEach(item => {
  if(item.textContent.trim() === 'Fountaine Pajot') item.click();
});
```
6. После выбора Make — Model combobox разблокируется (disabled снимается)

**Как заполнить Model:**
- Аналогично Make, но id = `#model-input`, меню = `#model-menu`
- Input value = 'Lipari', меню покажет модели конкретного производителя

**Важно:** Просто установить `input.value` недостаточно — нужно `dispatchEvent(new Event('input', {bubbles: true}))` чтобы Downshift подхватил изменения.

### 5. Spinbutton поля (Year, Length, Capacity, Engines)
Эти поля — кастомные компоненты. Использовать `browser_type` с ref ID из snapshot:
- Year: spinbutton, ref обычно рядом с "Year Please enter a year."
- Length (ft): ref рядом с "Length (ft)"
- Capacity: ref рядом с "Capacity"
- Number of Engines
- Engine Horsepower

### 6. Engine Maker / Model
Обычные текстовые поля (`textbox` в snapshot). Заполнять через `browser_type`.

### 7. Сохранение прогресса
Из-за лимита итераций — сохранять промежуточные результаты в файл:
```markdown
~/hermes/session_progress/getmyboat_lipari41.md
```
Структура: ✅ заполненные секции, ❌ что осталось, URL листинга.

### 8. Кнопка Save
Внизу каждой вкладки: `@e85` = Discard Changes, `@e86` = Save.
Нажать Save перед переключением вкладок.

### 9. Особенности Pricing\n\n- **Авто-расчёт:** Поле "Total starting at €" = Trip rate × Min trip duration. Например: €194 × 8h = €1,552.\n- **Multi-Day Options** — секция есть, но кнопка разворачивания **не срабатывает** через обычный клик (вероятно JS-обработчик не зарегистрирован или ошибка). Для дневных чартеров достаточно настроить Hourly Options с min duration 8-12h.\n- **Display Price** показывает €/hour, но при min=8h это адекватная цена за день.\n- **Cancellation Policy:** Refund % и Prior to Rental Days заполняются как spinbutton.\n- **Security Allowance:** опционально, spinbutton.\n\n### 10. Publish
Кнопка в дропдауне статуса (Unpublished → Publish).
Либо на странице списка листингов через Actions.

## Pitfalls

- **Не использовать `form.submit()`** — GetMyBoat использует AJAX, form.submit() уходит как GET (405 error)
- **Скролл сбрасывает сессию** — бот-детекция GetMyBoat отслеживает скролл. После `browser_scroll()` страница может стать пустой (`(empty page)`) — сессия убита, нужно логиниться заново через CAPTCHA. Не скроллить без крайней необходимости.
- **После выбора Make** — Model combobox разблокируется, но options в `#model-menu` загружаются ~500ms. Проверять наличие искомой модели через querySelectorAll перед кликом.
- **Save после каждой вкладки** — данные не сохраняются автоматически при переключении табов. Нажимать Save (ref=e86) перед переходом на другую вкладку, иначе введённые данные пропадают.
- **Photos** — только ручная загрузка, браузерный системный диалог не контролируется
- **Тип цены:** GetMyBoat показывает €/hour, но можно установить min duration 8h чтобы получить цену за день
- **Multi-Day Options не раскрывается** — кнопка есть, но клик по ней (browser_click) не срабатывает. Возможно JS-баг или компонент не подключён. Использовать Hourly Options с min duration ≥8h как обход.

## Структура данных для Lipari 41

```yaml
title: "Comfortable Business Class Catamaran - Fountaine Pajot Lipari 41"
short_name: "Lipari 41 Catamaran"
make: "Fountaine Pajot"
model: "Lipari 41"
year: 2015
length_ft: 41
capacity: 12
engines: 2
horsepower: 30
engine_maker: "Volvo Penta"
engine_model: "D2-30"
captain: included
categories:
  - Sailing -> Cruising Catamaran
  - Luxury, Events & Large groups
  - Tours, Lessons, and Diving
location: "Tivat, Montenegro"
price_per_hour: 194
min_hours: 8
total_starting: 1552
cancellation_refund: 100
cancellation_days: 5
```
