summaryrefslogtreecommitdiff
path: root/app/views/recipes/show.html.erb
blob: 180fdae6a1fd13c235f6f6d1344fb283a2736285 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!-- app/views/recipes/show.html.erb -->
<%# Controls header %>
<div class="card shadow my-4">
    <div class="card-header d-flex flex-wrap gap-2 justify-content-between align-items-center">
	<h5 class="mb-0">Ferti© Recipe</h5>

	<div class="d-flex flex-wrap gap-2 align-items-center">
	    <%= form_with url: ferti_recipe_path, method: :get, local: true, class: "d-flex flex-wrap gap-2 align-items-center", id: "recipe-form" do %>
		<div class="d-flex align-items-center gap-2">
		    <label class="mb-0 small text-nowrap" for="volume_select">Volume</label>
		    <select id="volume_select" name="volume" class="form-select form-select-sm">
			<% options = [["100 000 L", 100_000], ["200 000 L", 200_000], ["300 000 L", 300_000]] %>
			<% current_volume = (params[:volume].presence || 100_000).to_i %>
			<% options.each do |label, val| %>
			    <option value="<%= val %>" <%= 'selected' if val == current_volume %>><%= label %></option>
			<% end %>
		    </select>
		</div>

		<div class="vr" style="height: 24px;"></div>

		<div class="d-flex align-items-center gap-2">
		    <label class="mb-0 small text-nowrap" for="portions_input">Portions</label>
		    <input id="portions_input" type="number" min="2" max="10" step="1"
			   class="form-control form-control-sm" value="<%= params[:portions].presence || 2 %>">
		</div>
	    <% end %>

	    <%= link_to "Back", root_path, class: "btn btn-sm btn-secondary" %>
	</div>
    </div>

    <div class="table-responsive">
	<table class="table table-sm align-middle mb-0" id="recipe-table">
	    <thead class="table-light">
		<tr>
		    <th>Product</th>
		    <th class="text-muted">Fertilizer</th>
		    <th class="text-end">Qty (kg)</th>
		    <th class="text-end">Per portion (kg)</th>
		</tr>
	    </thead>
	    <tbody>
		<% @recipe.each do |component, kg| %>
		    <% prod_name = commercial_name_for(component) %>
		    <tr data-total-kg="<%= kg %>">
			<td><strong><%= prod_name %></strong></td>
			<td class="text-muted"><small><%= component.name %></small></td>
			<td class="text-end fw-semibold"><%= fmt_kg(kg) %></td>
			<td class="text-end per-portion-cell"><%= fmt_kg(kg / (params[:portions].presence || 2).to_f) %></td>
		    </tr>
		<% end %>
		<% if @recipe.blank? %>
		    <tr><td colspan="4" class="text-center text-muted">No supplementation required.</td></tr>
		<% end %>
	    </tbody>
	</table>
    </div>

    <div class="card-footer small text-muted">
	Recipe based on latest measurement: <%= @latest.measured_on %>
    </div>
</div>

<%# Tiny vanilla JS: auto-submit on volume change; live per-portion update %>
<script>
 (function() {
     const form = document.getElementById('recipe-form');
     const volumeSelect = document.getElementById('volume_select');
     const portionsInput = document.getElementById('portions_input');
     const rows = document.querySelectorAll('#recipe-table tbody tr[data-total-kg]');

     function clampPortions(n) {
	 n = parseInt(n || 2, 10);
	 if (isNaN(n)) n = 2;
	 return Math.min(10, Math.max(2, n));
     }

     function updatePerPortion() {
	 const n = clampPortions(portionsInput.value);
	 portionsInput.value = n;
	 rows.forEach(row => {
             const total = parseFloat(row.getAttribute('data-total-kg') || '0');
             const cell = row.querySelector('.per-portion-cell');
             const per = (n > 0) ? (total / n) : 0;
             cell.textContent = formatKg(per);
	 });
     }

     function formatKg(v) {
	 // match Rails number_with_precision(... precision: 2, strip zeros-ish)
	 const s = (Math.round(v * 100) / 100).toFixed(2);
	 return s.replace(/\.00$/, '').replace(/(\.\d)0$/, '$1');
     }

     volumeSelect.addEventListener('change', () => {
	 // submit with selected volume, keeping portions as a query param
	 const portions = clampPortions(portionsInput.value);
	 const url = new URL(form.action, window.location.origin);
	 url.searchParams.set('volume', volumeSelect.value);
	 url.searchParams.set('portions', portions);
	 window.location.assign(url.toString());
     });

     portionsInput.addEventListener('input', updatePerPortion);
     updatePerPortion();
 })();
</script>
Copyright 2019--2025 Marius PETER