initial commit

This commit is contained in:
Daniel Kauss Serna 2026-01-26 13:19:50 +01:00
commit 6667a969b7
10 changed files with 1340 additions and 0 deletions

224
src/Render.hs Normal file
View file

@ -0,0 +1,224 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Render (renderFrontpage, renderMonthview) where
import Control.Monad (forM_)
import Data.Maybe (fromMaybe)
import Data.Text qualified as T
import Data.Time (Day, MonthOfYear, Year, addDays, addGregorianMonthsClip, dayOfWeek, defaultTimeLocale, formatTime, fromGregorian, toGregorian)
import Ical
import Lucid
import Text.Printf (printf)
renderHead :: Html ()
renderHead = do
doctype_
head_ $ do
meta_ [charset_ "UTF-8"]
meta_
[ name_ "viewport",
content_ "width=device-width, initial-scale=1.0"
]
meta_
[ name_ "description",
content_ "Chipburners home page"
]
title_ "Chipburners"
link_ [rel_ "stylesheet", href_ "/style.css"]
renderHeader :: Int -> Html ()
renderHeader active =
header_ [class_ "site-header"] $ do
nav_ [] $ do
ul_ [class_ "nav-list"] $ do
li_ $ a_ [href_ "/", getActive 0] "Chip"
li_ $ a_ [href_ "/monthView", getActive 1] "Eventos"
li_ $ a_ [href_ "/wiki", getActive 2] "Wiki"
li_ $ a_ [href_ "/contact", getActive 3] "Contacto"
where
getActive cur = if cur == active then class_ "active" else class_ "inactive"
renderImage :: T.Text -> T.Text -> T.Text -> Html ()
renderImage url caption alt =
figure_ $ do
img_
[ src_ url,
alt_ alt,
loading_ "lazy"
]
figcaption_ $ toHtml caption
renderSideEvent :: Event -> Html ()
renderSideEvent e =
li_ $ do
span_ [class_ "event-time"] $
toHtml (formatTime defaultTimeLocale "%H:%M" (dtStart e))
span_ [class_ "event-title"] $ do
let uid = euid e
a_ [href_ ("/monthView#" <> uid), class_ "event-link"] $ toHtml (summary e)
renderDayGroup :: (Day, [Event]) -> Html ()
renderDayGroup (day, events) =
li_ [class_ "event-group"] $ do
time_
[ datetime_ $ T.pack (formatTime defaultTimeLocale "%Y-%m-%d" day),
class_ "date-header"
]
$ toHtml
$ T.pack (formatTime defaultTimeLocale "%A %d.%m.%y" day)
ul_ [class_ "daily-events"] $
mapM_ renderSideEvent events
renderEventList :: [Event] -> Html ()
-- mapM_ only cares about the monad I think? So it throws away the () part
-- mapM applies the monad to everz element of the list and returns monad with a list?
renderEventList events = mapM_ renderDayGroup (groupEvents events)
renderFrontpage :: [Event] -> Html ()
renderFrontpage events = do
doctype_
html_ [lang_ "es"] $ do
renderHead
body_ $ do
renderHeader 0
div_ [class_ "wrapper"] $ do
div_ [class_ "layout"] $ do
main_ [id_ "main-content", class_ "content"] $ do
section_ [class_ "intro"] $ do
h1_ "Chipburners_"
p_ [class_ "lead"] $
"Frase motivadora aqui"
p_ $ do
"Buenos dias, "
br_ []
"Somos un grupo d personas y entidades interesados en infromatica y \
\las technologias relacionadas. "
br_ []
"Este hackerspace ha sido creado como manera d juntar gente con intereses \
\similares y compartir conocimientos. "
br_ []
"Contactanos en "
a_ [href_ "/contact"] "signal"
"!"
section_ [class_ "image-gallery"] $ do
renderImage "example.com" "Imagen sobre algo" "Imagen interesante"
aside_ [class_ "sidebar"] $ do
section_ [class_ "events-panel"] $ do
h2_ "Eventos"
renderEventList events
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs =
let (ys, zs) = splitAt n xs
in ys : chunksOf n zs
padZero :: Int -> String
padZero n = if n < 10 then "0" ++ show n else show n
renderCalendarEvent :: Event -> Html ()
renderCalendarEvent e = do
let uid = euid e
li_ [class_ "event-item"] $ do
-- (toHtml $ summary e)
a_ [href_ ("#" <> uid), class_ "event-link"] $ toHtml (summary e)
div_ [class_ "event-popup", id_ uid] $ do
h1_ [] $ do
(toHtml $ summary e)
a_
[ href_ ("#None"),
class_ "close-btn"
]
"×"
p_ [class_ "lead"] $
toHtml $
T.pack $
printf
"%s -> %s - %s"
(formatTime defaultTimeLocale "%A %d.%m.%y" $ dtStart e)
(formatTime defaultTimeLocale "%H:%M" $ dtStart e)
(formatTime defaultTimeLocale "%H:%M" $ dtEnd e)
p_ [] $
toHtml $
description e
renderMonthview :: (Year, MonthOfYear) -> Day -> [(Day, [Event])] -> Html ()
renderMonthview (year, month) today groupedEvents = do
let firstOfMonth = fromGregorian year month 1
wd = dayOfWeek firstOfMonth
daysToSubtract = fromEnum wd - 1
startOfGrid = addDays (fromIntegral (-daysToSubtract)) firstOfMonth
gridDays = [addDays i startOfGrid | i <- [0 .. 41]]
weeks = chunksOf 7 gridDays
prevMonthDay = addGregorianMonthsClip (-1) firstOfMonth
nextMonthDay = addGregorianMonthsClip 1 firstOfMonth
(py, pm, _) = toGregorian prevMonthDay
(cy, cm, _) = toGregorian today
(ny, nm, _) = toGregorian nextMonthDay
mkLink y m label =
a_
[ href_ $ T.pack $ printf "/monthView/%s/%s" (show y) (padZero m),
class_ "nav-link"
]
label
renderHead
renderHeader 1
div_ [class_ "calendar-wrapper"] $ do
header_ [class_ "calendar-header"] $ do
h1_ [class_ "view-title"] "Vista mensual"
nav_ [class_ "calendar-nav"] $ do
mkLink py pm "« Mes pasado"
mkLink cy cm "Este mes"
mkLink ny nm "Mes siguiente »"
h2_ [class_ "month-name"] $
toHtml $
formatTime defaultTimeLocale "%B %Y" $
fromGregorian year month 1
table_ [class_ "calendar-table"] $ do
thead_ $ do
tr_ $ do
th_ "Lunes"
th_ "Martes"
th_ "Miercoles"
th_ "Jueves"
th_ "Viernes"
th_ "Sabado"
th_ "Domingo"
tbody_ $ do
forM_ weeks $ \week -> do
tr_ $ do
forM_ week $ \d -> do
let (_, dM, dD) = toGregorian d
isCurrentMonth = dM == month
isToday = d == today
baseClasses = []
monthClass = if isCurrentMonth then [] else ["other-month"]
todayClass = if isToday then ["current-day"] else []
finalClass = T.intercalate " " (baseClasses ++ monthClass ++ todayClass)
-- TODO: lookup very slow :(
dayEvents = fromMaybe [] (lookup d groupedEvents)
-- cool
td_ ([class_ finalClass | not (T.null finalClass)]) $ do
span_ [class_ "day-number"] (toHtml $ show dD)
if null dayEvents
then return ()
else ul_ [class_ "event-list"] $ do
forM_ dayEvents $ \e ->
renderCalendarEvent e