From 5cf21fcb8c91896bb2b889dd4a90cc0b2ef3e9e5 Mon Sep 17 00:00:00 2001 From: unwox Date: Mon, 13 Oct 2025 21:04:15 +0600 Subject: finishing touches for shop functionality --- pages/shop/_product/index.fnl | 2 +- pages/shop/cart/add.fnl | 3 ++- pages/shop/index.fnl | 6 ++--- pages/shop/order/index.fnl | 4 ++-- run.sh | 1 + shop.fnl | 16 ++++++++++++- templates.fnl | 54 +++++++++++++++++++++++++------------------ 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/pages/shop/_product/index.fnl b/pages/shop/_product/index.fnl index f8b38f7..0dd5ff9 100644 --- a/pages/shop/_product/index.fnl +++ b/pages/shop/_product/index.fnl @@ -64,7 +64,7 @@ [:a {:href (.. "/shop/" product.name "/edit")} "% Редактировать"]]) "") - (templates.add-to-basket-form product "mb-0-5" redirect-url) + (templates.add-to-basket-form product basket "mb-0-5" redirect-url) (templates.product-overview product "mb-0-5") [:div {:class "mb-1" :style "font-style: italic;"} diff --git a/pages/shop/cart/add.fnl b/pages/shop/cart/add.fnl index 53366b4..b276608 100644 --- a/pages/shop/cart/add.fnl +++ b/pages/shop/cart/add.fnl @@ -19,7 +19,8 @@ (let [body-values (lib.parse-values request.body)] (if (and order-id request.body - (< 0 (tonumber body-values.quantity))) + (< 0 (tonumber body-values.quantity)) + (not (shop.in-basket? db order-id body-values.name))) (do (shop.create-order-line db order-id body-values.name body-values.quantity) diff --git a/pages/shop/index.fnl b/pages/shop/index.fnl index dff486c..da83114 100644 --- a/pages/shop/index.fnl +++ b/pages/shop/index.fnl @@ -31,7 +31,7 @@ where " ORDER BY products.position") []))) -(fn item-template [product] +(fn item-template [product basket] (local item-url (.. "/shop/" product.name)) (local images []) (for [i 2 5] @@ -61,7 +61,7 @@ [:a {:href item-url} [:h3 {:class "shop-item-title"} product.title]] [:div {:class "shop-item-price"} - (templates.add-to-basket-form product "" "/shop")] + (templates.add-to-basket-form product basket "" "/shop")] (templates.product-overview product "mb-0-25 font-size-0-875") [:div {} product.short-description]])) @@ -90,7 +90,7 @@ (if (< 0 (# products)) (table.concat (icollect [_ v (ipairs products)] - (item-template v))) + (item-template v basket))) (HTML [:em {} "Пока что здесь ничего нет!"])))]])]) (fn render [request db authenticated?] diff --git a/pages/shop/order/index.fnl b/pages/shop/order/index.fnl index 7d25a40..019b61a 100644 --- a/pages/shop/order/index.fnl +++ b/pages/shop/order/index.fnl @@ -8,11 +8,11 @@ [{:title "" :fields [ (forms.text-input "name" "Как к вам обращаться?" true) - (forms.text-input "contact" "Телеграм или E-mail для связи" true) + (forms.text-input "contact" "Telegram, Whatsapp или E-mail для связи" true) (forms.checkbox-input "correct-order" "Данные заказа верны" true) (forms.checkbox-input "consent" (.. - "Я даю согласие ИП «Горенкин Владислав Константинович» (ИНН ...)" + "Я даю согласие " ;; "ИП «Горенкин Владислав Константинович» (ИНН ...)") " на хранение и обработку предоставленных персональных данных для уточнения деталей заказа.") true)]}]) diff --git a/run.sh b/run.sh index f8231b8..235fcd6 100755 --- a/run.sh +++ b/run.sh @@ -29,6 +29,7 @@ deploy () { scp macros.fnl root@everytea.ru:~/whitetoad.ru/ scp dicts.fnl root@everytea.ru:~/whitetoad.ru/ scp templates.fnl root@everytea.ru:~/whitetoad.ru/ + scp shop.fnl root@everytea.ru:~/whitetoad.ru/ ssh root@everytea.ru -- systemctl restart whitetoad git stash pop } diff --git a/shop.fnl b/shop.fnl index fea398e..9711095 100644 --- a/shop.fnl +++ b/shop.fnl @@ -111,6 +111,19 @@ ORDER BY order_lines.creation_time ASC" [order-id]))) +(fn in-basket? [db order-id product-name] + (= 1 + (# + (_G.must + (luna.db.query + db + "SELECT id + FROM order_lines + WHERE order_lines.order_id = ? + AND order_lines.product_name = ? + LIMIT 1" + [order-id product-name]))))) + {: create-order : place-order : finish-order @@ -118,4 +131,5 @@ : order-id : create-order-line : delete-order-line - : basket} + : basket + : in-basket?} diff --git a/templates.fnl b/templates.fnl index 53b5c0c..b80576c 100644 --- a/templates.fnl +++ b/templates.fnl @@ -110,7 +110,7 @@ [:NO-ESCAPE "(" (lib.format-price product.price-per) "₽ за 1 грамм)"]]))])) -(fn add-to-basket-form [product classes redirect-url] +(fn add-to-basket-form [product basket classes redirect-url] (fn quantity-steps [stock step] (assert (< 0 step) "step must be greater than 0") (var result []) @@ -120,27 +120,37 @@ (set first (+ first step))) result) - (var quantity-options []) - (var no-stock? false) - (let [piece? (= product.packaging :piece)] - (if (< 0 product.stock) - (each [_ q (ipairs (quantity-steps product.stock (if piece? 1 50)))] - (table.insert - quantity-options - (HTML - [:option {:value (tostring q)} - (.. (lib.format-price (* product.price-per q)) - "₽ за " q (if piece? " шт." " гр."))]))) - (do - (table.insert quantity-options (HTML [:option {:value "0"} "Товар закончился"])) - (set no-stock? true)))) - - (HTML - [:form {:method "POST" :action "/shop/cart/add" :class classes} - [:input {:type "hidden" :name "name" :value product.name}] - [:input {:type "hidden" :name "redirect-url" :value redirect-url}] - [:select {:name "quantity"} (table.concat quantity-options)] - (if no-stock? "" (HTML [:button {:type "submit"} "Добавить"]))])) + (var in-basket-quantity nil) + (each [_ basket-item (pairs basket) &until in-basket-quantity] + (when (= product.name basket-item.name) + (set in-basket-quantity basket-item.quantity))) + + (var quantity-options []) + (var out-of-stock? false) + (let [piece? (= product.packaging :piece)] + (if (< 0 product.stock) + (each [_ q (ipairs (quantity-steps product.stock (if piece? 1 50)))] + (table.insert + quantity-options + (HTML + [:option (fn [] {:value q + :selected (= in-basket-quantity q)}) + (.. (lib.format-price (* product.price-per q)) + "₽ за " q (if piece? " шт." " гр."))]))) + (do + (table.insert quantity-options (HTML [:option {:value "0"} "Товар закончился"])) + (set out-of-stock? true)))) + + (local disabled (or out-of-stock? in-basket-quantity)) + + (HTML + [:form {:method "POST" :action "/shop/cart/add" :class classes} + [:input {:type "hidden" :name "name" :value product.name}] + [:input {:type "hidden" :name "redirect-url" :value redirect-url}] + [:select (fn [] {:name "quantity" :disabled disabled}) + (table.concat quantity-options)] + [:button (fn [] {:type "submit" :disabled disabled}) + (if in-basket-quantity "В корзине" "Добавить")]])) (fn order-lines [order-lines] (HTML -- cgit v1.2.3