- Book-styled UI with parchment aesthetic and Russian navigation - Characters model with Konva.js 2D canvas drawing (draggable shapes) - StoryPages model with character association and page navigation - Stimulus controllers: canvas (editor) + canvas-preview (read-only) - Full Russian interface: all labels, buttons, flash messages in Russian
70 lines
3.5 KiB
Plaintext
70 lines
3.5 KiB
Plaintext
<%= form_with model: character do |f| %>
|
||
<% if character.errors.any? %>
|
||
<div class="error-messages">
|
||
<strong>Исправьте ошибки:</strong>
|
||
<ul>
|
||
<% character.errors.full_messages.each do |msg| %>
|
||
<li><%= msg %></li>
|
||
<% end %>
|
||
</ul>
|
||
</div>
|
||
<% end %>
|
||
|
||
<div class="form-group">
|
||
<%= f.label :name, "Имя персонажа", class: "form-label" %>
|
||
<%= f.text_field :name, class: "form-input", placeholder: "Иван Царевич", autofocus: true %>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<%= f.label :description, "Описание", class: "form-label" %>
|
||
<%= f.text_area :description, class: "form-textarea", rows: 4,
|
||
placeholder: "Храбрый юноша с добрым сердцем..." %>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<%= f.label :color, "Цвет персонажа", class: "form-label" %>
|
||
<div style="display:flex;align-items:center;gap:12px;">
|
||
<%= f.color_field :color, class: "form-input", style: "width:60px;height:40px;padding:2px;cursor:pointer;" %>
|
||
<span style="font-size:0.85rem;color:var(--ink-light);font-style:italic;">Этот цвет будет использоваться для выделения персонажа в книге</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<span class="form-label">Нарисуйте персонажа</span>
|
||
<p style="font-size:0.85rem;color:var(--ink-light);font-style:italic;margin:0 0 12px;">
|
||
Используйте инструменты ниже, чтобы создать портрет персонажа на холсте.
|
||
</p>
|
||
|
||
<div data-controller="canvas"
|
||
data-canvas-initial-value="<%= character.canvas_data.presence || '' %>">
|
||
|
||
<div class="canvas-toolbar">
|
||
<button type="button" class="btn-tool" data-action="canvas#addHead">👤 Голова</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addBody">🟫 Тело</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addEye">👁 Глаз</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addMouth">〰 Рот</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addHair">〰 Волосы</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addArm">💪 Рука</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addLeg">🦵 Нога</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#addAccessory">⚔ Аксессуар</button>
|
||
<button type="button" class="btn-tool" data-action="canvas#clear" style="margin-left:auto;color:#8b1a1a;">✕ Очистить</button>
|
||
</div>
|
||
|
||
<div class="canvas-wrap">
|
||
<div data-canvas-target="container" style="width:380px;height:480px;"></div>
|
||
</div>
|
||
|
||
<p style="font-size:0.78rem;color:var(--ink-light);font-style:italic;margin-top:8px;">
|
||
Нажмите на фигуру, чтобы выделить. Перетащите для перемещения. Клик правой кнопкой — удалить.
|
||
</p>
|
||
|
||
<%= f.hidden_field :canvas_data, data: { canvas_target: "data" } %>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="action-row">
|
||
<%= f.submit "💾 Сохранить персонажа", class: "btn btn-primary" %>
|
||
<%= link_to "Отмена", character.persisted? ? character_path(character) : characters_path, class: "btn btn-secondary" %>
|
||
</div>
|
||
<% end %>
|