M src/Text/HTML/Form/WebApp.hs => src/Text/HTML/Form/WebApp.hs +19 -15
@@ 32,24 32,28 @@ renderPage form [] _ = return $ Just $ Right $ Txt.concat [
     "<a href='/0/?", Txt.pack $ renderQueryString form, "'>Start!</a>"]
 renderPage _ _ _ = return Nothing
 
+isCalType :: Text -> Bool
+isCalType = flip L.elem ["date", "datetime-local", "datetime", "month", "time"]
 renderInput :: Form -> Int -> Input -> [Text] -> [(ByteString, Maybe ByteString)] ->
     IO (Maybe (Either Query Text))
 renderInput form ix input [""] qs = renderInput form ix input [] qs
-renderInput form ix input@Input { inputType = "date", inputName = name } ["year", p] qs
-    | Just t <- modifyTime' (Txt.pack $ "year/" ++ Txt.unpack p) $ get name qs = do
+renderInput form ix input@Input { inputType = ty, inputName = name } ["year", p] qs
+    | isCalType ty,
+      Just t <- modifyTime' (Txt.pack $ "year/" ++ Txt.unpack p) $ get name qs = do
         t' <- timeParseOrNow t
         template' "cal/year-numpad.html" form ix input (set name (Txt.pack t) qs) $
             \prop -> case prop of
                 "T" -> timeData t'
                 _ -> toGVal ()
-renderInput form ix input@Input { inputType = "date", inputName = name } ["zone", p] qs = do
-    t <- timeParseOrNow $ get name qs
-    let Elapsed (Seconds t') = timeGetElapsed $ localTimeToGlobal t
-    template' "cal/timezone.html" form ix input qs $ \prop -> case prop of
-        "T" -> timeData t
-        "zones" -> tzdata t' $ unEscapeString $ Txt.unpack p
-        "continents" -> continents
-        _ -> toGVal ()
+renderInput form ix input@Input { inputType = ty, inputName = name } ["zone", p] qs
+    | isCalType ty = do
+        t <- timeParseOrNow $ get name qs
+        let Elapsed (Seconds t') = timeGetElapsed $ localTimeToGlobal t
+        template' "cal/timezone.html" form ix input qs $ \prop -> case prop of
+            "T" -> timeData t
+            "zones" -> tzdata t' $ unEscapeString $ Txt.unpack p
+            "continents" -> continents
+            _ -> toGVal ()
 renderInput form ix input@Input { multiple = True } [p] qs
     | '=':v' <- Txt.unpack p,
             (utf8 $ inputName input, Just $ utf8' v') `Prelude.elem` qs =
@@ 141,8 145,8 @@ renderInput form ix input@Input { inputType = "number" } [] qs =
     template "number.html" form ix input qs
 renderInput form ix input@Input { inputType = "range" } [] qs =
     template "number.html" form ix input qs
-renderInput form ix input@Input { inputType = "date", inputName = n } [op] qs
-    | Just v <- modifyTime' op $ get n qs = do
+renderInput form ix input@Input { inputType = ty, inputName = n } [op] qs
+    | isCalType ty, Just v <- modifyTime' op $ get n qs = do
         -- TODO: Support other calendars
         v' <- timeParseOrNow v
         template' "gregorian.html" form ix input (set n (Txt.pack v) qs) $
@@ 151,10 155,10 @@ renderInput form ix input@Input { inputType = "date", inputName = n } [op] qs
                 "seqTo" -> fromFunction $ return . gSeqTo
                 "pad2" -> fromFunction $ return . gPad2
                 _ -> toGVal ()
-    | otherwise = return Nothing
-renderInput form ix input@Input { inputType = "date", inputName = n } [] qs = do
+    | isCalType ty = return Nothing
+renderInput f ix input@Input { inputType = ty, inputName = n } [] qs | isCalType ty = do
     v' <- timeParseOrNow $ get n qs
-    template' "gregorian.html" form ix input qs $ \x -> case x of -- TODO: Ditto
+    template' "gregorian.html" f ix input qs $ \x -> case x of -- TODO: Ditto
         "T" -> timeData v'
         "seqTo" -> fromFunction $ return . gSeqTo
         "pad2" -> fromFunction $ return . gPad2
 
M src/Text/HTML/Form/WebApp/Ginger/Hourglass.hs => src/Text/HTML/Form/WebApp/Ginger/Hourglass.hs +2 -1
@@ 21,7 21,8 @@ timeData datetime = orderedDict [
         _ -> "PM",
     ("hour", enumG $ case todHour $ dtTime $ localTimeUnwrap datetime of
         x | x <= 12 -> x
-        x -> x - 12),
+        24 -> 12
+        x -> x - 11),
     ("minute", enumG $ todMin $ dtTime $ localTimeUnwrap datetime),
     ("second", enumG $ todSec $ dtTime $ localTimeUnwrap datetime),
     ("nano", showG unwrapNanos $ todNSec $ dtTime $ localTimeUnwrap datetime),
 
M tpl/gregorian.html => tpl/gregorian.html +18 -0
@@ 12,17 12,23 @@
     </style>
 
     <p><a href="-year{{Q}}" title="Past year">↓</a>
+        {% if input.inputType != "time" %}
         <a href="year/{{Q}}" title="Edit year">{{ T.year }}</a>
         <a href="+year{{Q}}" title="Next year">↑</a>
 
         <a href="-month{{Q}}" title="Past month">↓</a>
         {{ T.month }}
         <a href="+month{{Q}}" title="Next month">↑</a>
+        {% endif %}
 
+        {% if input.inputType != "month" %}
+        {% if input.inputType != "time" %}
         <a href="-date{{Q}}" title="Past day">↓</a>
         {{ T.date }}
         <a href="+date{{Q}}" title="Next day">↑</a>
+        {% endif %}
 
+        {% if input.inputType != "date" %}
         <a href="-hour{{Q}}" title="Past hour">↓</a>
         {{ T.hour|pad2 }}
         <a href="+hour{{Q}}" title="Next hour">↑</a>
@@ 32,12 38,17 @@
         <a href="+minute{{Q}}" title="Next minute">↑</a>
         <a href="meridiem{{Q}}" title="Toggle AM/PM">{{ T.meridiem }}</a>
 
+        {% if input.inputType != "datetime-local" && input.inputType != "time" %}
         <a href="-zone{{Q}}" title="Previous timezone">↓</a>
         <a href="zone/{{Q}}">{{ T.zone }}</a>
         <a href="+zone{{Q}}" title="Next zone">↑</a></p>
+        {% endif %}
+        {% endif %}
+        {% endif %}
     <p><a href="now{{Q}}" title="Select current date & time">Now</a></a>
 
     <div class="multi">
+      {% if input.inputType != "time" %}
       <ul>
         <li><a href="month=0{{Q}}">January</a></li>
         <li><a href="month=1{{Q}}">Febuary</a></li>
@@ 52,7 63,10 @@
         <li><a href="month=10{{Q}}">November</a></li>
         <li><a href="month=11{{Q}}">December</a></li>
       </ul>
+      {% endif %}
 
+      {% if input.inputType != "month" %}
+      {% if input.inputType != "time" %}
       <ul style="grid-template-columns: repeat(7, min-content)">
         {% for i in 1|seqTo(T.daysInMonth) %}
           <li {% if i == 1 %}style="grid-column: {{ T.monthStart }}"{% endif %}>
@@ 60,12 74,16 @@
           </li>
         {% endfor %}
       </ul>
+      {% endif %}
 
+      {% if input.inputType != "date" %}
       <ul>{% for i in 1|seqTo(12) %}
         <li><a href="hour={{ i }}{{Q}}">{{ i|pad2 }}:{{ T.minute|pad2 }}</a></li>
       {% endfor %}</ul>
       <ul>{% for i in 0|seqTo(5, 55) %}
         <li><a href="minute={{ i }}{{Q}}">{{ T.hour|pad2 }}:{{ i|pad2 }}</a></li>
       {% endfor %}</ul>
+      {% endif %}
+      {% endif %}
     </div>
 </section>{%- endblock -%}