[Racket] Ferti hydroponic nutrient solver, redux.
Add active state to Ferti tab bar + make views more orthogonal.
views.rkt
@@ -86,24 +86,28 @@
86
86
87
87
;; Ferti
88
88
89
Removed:
(define (ferti-template body-xexpr)
90
Removed:
(page-template "Ferti" `((h1 ((class "display-1 mb-3")) "Ferti") ,ferti-tabs ,@body-xexpr)))
89
Added:
(define (ferti-template active-tab body-xexpr)
90
Added:
(page-template (format "Ferti — ~a" active-tab) `(,(ferti-tabs-bar active-tab) ,@body-xexpr)))
91
91
92
Added:
(define (ferti-tabs-bar active-tab)
93
Added:
`(ul ((class "nav nav-tabs my-3"))
94
Added:
,@
95
Added:
(for/list ([tab ferti-tabs])
96
Added:
(match-define (cons tab-title tab-action) tab)
97
Added:
`(li ((class "nav-item"))
98
Added:
(a ((class ,(string-append "nav-link" (if (equal? tab-title active-tab) " active" "")))
99
Added:
(aria-current "page")
100
Added:
(href ,tab-action))
101
Added:
,tab-title)))))
102
Added:
92
103
(define ferti-tabs
93
Removed:
'(ul ((class "nav nav-tabs mb-3"))
94
Removed:
(li ((class "nav-item"))
95
Removed:
(a ((class "nav-link") (aria-current "page") (href "/ferti/index")) "Accueil"))
96
Removed:
(li ((class "nav-item"))
97
Removed:
(a ((class "nav-link") (aria-current "page") (href "/ferti/measurements-and-rotations"))
98
Removed:
"Relevés & Assolements"))
99
Removed:
(li ((class "nav-item"))
100
Removed:
(a ((class "nav-link") (aria-current "page") (href "/ferti/fertilizers")) "Intrants"))
101
Removed:
(li ((class "nav-item"))
102
Removed:
(a ((class "nav-link") (aria-current "page") (href "/ferti/crop-requirements"))
103
Removed:
"Cultures"))))
104
Added:
'(("Accueil" . "/ferti/index") ("Relevés et Assolements" . "/ferti/measurements-and-rotations")
105
Added:
("Intrants" . "/ferti/fertilizers")
106
Added:
("Cultures" . "/ferti/crop-requirements")))
104
107
105
108
(define (ferti-index-page)
106
109
(ferti-template
110
Added:
"Accueil"
107
111
`((p "La recette Ferti© est calculée en fonction d'un relevé de nutriments et d'un assolement.")
108
112
(div
109
113
((class "btn-group-vertical"))
@@ -119,47 +123,31 @@
119
123
((class "table"))
120
124
(thead (tr (th "Date du relevé") (th "Relevé") (th "Assolement") (th "Recette")))
121
125
(tbody
122
Removed:
,@
123
Removed:
(for/list ([m measurements])
124
Removed:
(define maybe-rotation (maybe-rotation-for-measurement m))
125
Removed:
`(tr (td ((class "font-monospace align-middle")) ,(normal-date (nutrient-measurement-date m)))
126
Removed:
(td (a ((class "btn btn-outline-secondary btn-sm")
127
Removed:
(href ,(format "/ferti/measurements/~a" (nutrient-measurement-id m))))
128
Removed:
"Voir"))
129
Removed:
(td ,(if maybe-rotation
130
Removed:
`(a ((class "btn btn-outline-secondary btn-sm")
131
Removed:
(href ,(format "/ferti/rotations/~a" (crop-rotation-id maybe-rotation))))
132
Removed:
"Voir")
133
Removed:
`(a ((class "btn btn-outline-primary btn-sm")
134
Removed:
(href ,(format "/ferti/rotations/new/~a" (nutrient-measurement-date m))))
135
Removed:
"Ajouter")))
136
Removed:
(td ,(if maybe-rotation
137
Removed:
`(a ((class "btn btn-outline-secondary btn-sm")
138
Removed:
(href ,(format "/ferti/recipes/~a" (crop-rotation-date maybe-rotation))))
139
Removed:
"Voir")
140
Removed:
"—")))))))
141
Removed:
(ferti-template `((h2 () "Relevés et Assolements")
142
Removed:
(div ((class "btn-group mb-3"))
126
Added:
,@(for/list ([m measurements])
127
Added:
(define maybe-rotation (maybe-rotation-for-measurement m))
128
Added:
`(tr
129
Added:
(td ((class "font-monospace align-middle")) ,(normal-date (nutrient-measurement-date m)))
130
Added:
(td (a ((class "btn btn-outline-secondary btn-sm")
131
Added:
(href ,(format "/ferti/measurements/~a" (nutrient-measurement-id m))))
132
Added:
"Consulter"))
133
Added:
(td ,(if maybe-rotation
134
Added:
`(a ((class "btn btn-outline-secondary btn-sm")
135
Added:
(href ,(format "/ferti/rotations/~a" (crop-rotation-id maybe-rotation))))
136
Added:
"Consulter")
137
Added:
`(a ((class "btn btn-outline-primary btn-sm")
138
Added:
(href ,(format "/ferti/rotations/new/~a" (nutrient-measurement-date m))))
139
Added:
"Ajouter")))
140
Added:
(td ,(if maybe-rotation
141
Added:
`(a ((class "btn btn-outline-secondary btn-sm")
142
Added:
(href ,(format "/ferti/recipes/~a" (crop-rotation-date maybe-rotation))))
143
Added:
"Consulter")
144
Added:
"—")))))))
145
Added:
(ferti-template "Relevés et Assolements"
146
Added:
`((div ((class "btn-group mb-3"))
143
147
(a ((class "btn btn-primary") [href "/ferti/measurements/new"])
144
148
"Ajouter un relevé"))
145
149
,table)))
146
150
147
Removed:
;; TODO: add bar chart for comparing to target concentrations
148
Removed:
(define (ferti-recipe-page recipe-date fertilizer-recipe)
149
Removed:
(define table
150
Removed:
`(table ((class "table"))
151
Removed:
(thead (tr (th "Intrant") (th "Marque") (th ((class "text-end")) "Quantité (g)")))
152
Removed:
(tbody ,@(for/list ([(fertilizer quantity) (in-hash fertilizer-recipe)]
153
Removed:
#:when (not (zero? quantity)))
154
Removed:
(define canonical-name (fertilizer-product-name fertilizer))
155
Removed:
(define brand-name (fertilizer-brand-name fertilizer))
156
Removed:
`(tr (td ,canonical-name)
157
Removed:
(td ,(if (non-empty-string? brand-name) brand-name "—"))
158
Removed:
(td ((class "text-end font-monospace")) ,(round 2 (* 100 quantity))))))))
159
Removed:
(ferti-template `((h2 () ,(format "Recette du ~a" (normal-date recipe-date)))
160
Removed:
(p "Quantités calculées pour 100'000 L.")
161
Removed:
,table)))
162
Removed:
163
151
(define (ferti-fertilizers-page fertilizers)
164
152
(define table
165
153
`(table ((class "table table-striped"))
@@ -169,10 +157,10 @@
169
157
`(tr (td (a ([href ,(format "/ferti/fertilizers/~a" (fertilizer-product-id fp))])
170
158
,(fertilizer-product-name fp)))
171
159
(td ,(if (and brand-name (non-empty-string? brand-name)) brand-name "—"))))))
172
Removed:
(ferti-template `((h2 () "Intrants") (a ((class "btn btn-primary mb-3") [href
173
Removed:
"/ferti/fertilizers/new"])
174
Removed:
"Ajouter un intrant")
175
Removed:
,table)))
160
Added:
(ferti-template "Intrants"
161
Added:
`((a ((class "btn btn-primary mb-3") [href "/ferti/fertilizers/new"])
162
Added:
"Ajouter un intrant")
163
Added:
,table)))
176
164
177
165
(define (ferti-crop-requirements-page crop-requirements)
178
166
(define table
@@ -185,11 +173,32 @@
185
173
(td ,(if crop-id
186
174
(string-titlecase (crop-name (get-crop #:id crop-id)))
187
175
"—"))))))
188
Removed:
(ferti-template `((h2 () "Profils de culture")
189
Removed:
(a ((class "btn btn-primary mb-3") [href "/ferti/crop-requirements/new"])
190
Removed:
"Ajouter un profil")
191
Removed:
,table)))
176
Added:
(define button-group
177
Added:
'(div ((class "btn-group mb-3"))
178
Added:
(a ((class "btn btn-primary") [href "/ferti/crop-requirements/new"]) "Ajouter un profil")
179
Added:
(a ((class "btn btn-secondary") [href "/ferti/crop/new"]) "Ajouter une culture")))
180
Added:
(ferti-template "Cultures" `(,button-group ,table)))
192
181
182
Added:
;; TODO: add bar chart for comparing to target concentrations
183
Added:
(define (ferti-recipe-page recipe-date fertilizer-recipe)
184
Added:
(define normal-recipe-date (normal-date recipe-date))
185
Added:
(define title (format "Recette du ~a" normal-recipe-date))
186
Added:
(define table
187
Added:
`(table ((class "table"))
188
Added:
(thead (tr (th "Intrant") (th "Marque") (th ((class "text-end")) "Quantité (g)")))
189
Added:
(tbody ,@(for/list ([(fertilizer quantity) (in-hash fertilizer-recipe)]
190
Added:
#:when (not (zero? quantity)))
191
Added:
(define canonical-name (fertilizer-product-name fertilizer))
192
Added:
(define brand-name (fertilizer-brand-name fertilizer))
193
Added:
`(tr (td ,canonical-name)
194
Added:
(td ,(if (non-empty-string? brand-name) brand-name "—"))
195
Added:
(td ((class "text-end font-monospace")) ,(round 2 (* 100 quantity))))))))
196
Added:
(page-template title
197
Added:
`((h1 ((class "display-1 mb-3")) "Recette Ferti")
198
Added:
(h5 ((class "display-5 mb-3")) ,normal-recipe-date)
199
Added:
(p "Quantités calculées pour 100'000 L.")
200
Added:
,table)))
201
Added:
193
202
;; New
194
203
195
204
(define (form-page-template title action formlet)
@@ -230,7 +239,8 @@
230
239
;; Show
231
240
232
241
(define (show-measurement-page nm)
233
Removed:
(define title (format "Relevé du ~a" (normal-date (nutrient-measurement-date nm))))
242
Added:
(define id (nutrient-measurement-id nm))
243
Added:
(define measurement-date (normal-date (nutrient-measurement-date nm)))
234
244
(define table
235
245
`(table ((class "table") (style "max-width: 30em"))
236
246
(thead (tr (th "Nutriment") (th ((class "text-end")) "Concentration (mg/L)")))
@@ -240,17 +250,18 @@
240
250
(td ((class "text-end font-monospace")) ,(round 2 nutrient-value)))))))
241
251
(define button-group
242
252
`(div ((class "btn-group mb-3"))
243
Removed:
(a ((class "btn btn-primary")
244
Removed:
[href ,(format "/ferti/measurements/~a/edit" (nutrient-measurement-id nm))])
245
Removed:
"Modifier")
246
Removed:
(a ((class "btn btn-danger")
247
Removed:
[href ,(format "/ferti/measurements/~a/destroy" (nutrient-measurement-id nm))])
253
Added:
(a ((class "btn btn-primary") [href ,(format "/ferti/measurements/~a/edit" id)]) "Modifier")
254
Added:
(a ((class "btn btn-danger") [href ,(format "/ferti/measurements/~a/destroy" id)])
248
255
"Supprimer")))
249
Removed:
(page-template title `((h1 ((class "display-1 mb-3")) ,title) ,button-group ,table)))
256
Added:
(page-template (format "Relevé du ~a" measurement-date)
257
Added:
`((h1 ((class "display-1 mb-3")) "Relevé") (h5 ((class "display-5 mb-3"))
258
Added:
,measurement-date)
259
Added:
,button-group
260
Added:
,table)))
250
261
251
262
(define (show-rotation-page cr)
252
263
(define id (crop-rotation-id cr))
253
Removed:
(define title (format "Assolement du ~a" (normal-date (crop-rotation-date cr))))
264
Added:
(define rotation-date (normal-date (crop-rotation-date cr)))
254
265
(define table
255
266
`(table ((class "table") (style "max-width: 30em"))
256
267
(thead (tr (th "Type de culture") (th ((class "text-end")) "Proportion (%)")))
@@ -266,7 +277,11 @@
266
277
(a ((class "btn btn-danger")
267
278
[href ,(format "/ferti/rotations/~a/destroy" (crop-rotation-id cr))])
268
279
"Supprimer")))
269
Removed:
(page-template title `((h1 ((class "display-1 mb-3")) ,title) ,button-group ,table)))
280
Added:
(page-template (format "Assolement du ~a" rotation-date)
281
Added:
`((h1 ((class "display-1 mb-3")) ,"Assolement") (h5 ((class "display-5 mb-3"))
282
Added:
,rotation-date)
283
Added:
,button-group
284
Added:
,table)))
270
285
271
286
(define (show-fertilizer-page fp)
272
287
(define id (fertilizer-product-id fp))