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
|
(import-macros {:compile-html HTML} :macros)
(local lib (require :lib))
(local shop (require :shop))
(local dicts (require :dicts))
(local templates (require :templates))
(fn all-products [db authenticated?]
(local where
(if (not authenticated?)
"WHERE products.published = true"
""))
(_G.must
(luna.db.query-assoc db
(..
"SELECT products.name,
products.title,
products.published,
products.short_description as \"short-description\",
products.price_per AS \"price-per\",
products.volume,
products.stock,
products.packaging,
products.type,
products.region,
products.image1,
products.image2,
products.image3,
products.image4,
products.image5
FROM products "
where
" ORDER BY products.position") [])))
(fn item-template [product basket]
(local item-url (.. "/shop/" product.name))
(local images [])
(for [i 2 5]
(table.insert images (. product (.. "image" i))))
(HTML
[:section {:class (.. "shop-item"
(if (not product.published)
" shop-item-not-published" ""))}
[:a {:href item-url}
[:div {:class "shop-item-imgs"}
[:img {:class "shop-item-img"
:src (.. "/static/files/" (. product.image1) "-thumbnail.jpg")}]
(table.concat
(let [without-videos
(icollect [_ v (ipairs images)]
(if (lib.ends-with? (_G.must (luna.utf8.lower v)) ".webm")
nil
v))]
(icollect [idx image (ipairs without-videos)]
(HTML
[:img {:class "shop-item-img" :src (.. "/static/files/" image "-thumbnail.jpg")
:loading "lazy"
:style (.. "z-index: " (+ idx 2) ";"
"width: calc(100% / " (# without-videos) ");"
"left: calc(100% / " (# without-videos) " * " (- idx 1) ")")}]))))]]
[:a {:href item-url}
[:h3 {:class "shop-item-title"} product.title]]
[:div {:class "shop-item-price"}
(templates.add-to-basket-form product basket "" "/shop")]
(templates.product-overview product "mb-0-25 font-size-0-875")
[:div {} product.short-description]]))
(fn content [db basket authenticated?]
[(HTML
[:aside {}
(templates.header "/shop" authenticated?)
(if (< 0 (# basket)) (templates.basket basket "/shop") "")
[:section {}
[:h2 {} "Условия"]
[:p {} ""]]])
(HTML
[:div {:class "content"}
[:div {:class "back"} [:a {:href "/"} "⟵ Обратно на главную"]]
[:h2 {:class "product-page-title"} "Магазин"]
(if authenticated?
(HTML
[:div {:class "mb-1" :style "margin-top: -0.5rem"}
[:a {:style "white-space: nowrap"
:href (.. "/shop/add")} "+ Добавить"]
[:a {:style "white-space: nowrap; margin-left: 1rem;"
:href (.. "/shop/order/list")} "☰ Список заказов"]])
"")
[:div {:class "shop-items"}
(let [products (all-products db authenticated?)]
(if (< 0 (# products))
(table.concat
(icollect [_ v (ipairs products)]
(item-template v basket)))
(HTML [:em {} "Пока что здесь ничего нет!"])))]])])
(fn render [request db authenticated?]
(let [order-id (shop.order-id request)
basket (if order-id (shop.basket db order-id) [])]
(values 200 {} (templates.base (content db basket authenticated?)))))
{: render}
|