blob: 6f6d6f3585ae60bcfb197f6acbcf0f5ab2f79dde (
plain) (
tree)
|
|
(ns bbbg.handlers.events
(:require
[bbbg.db :as db]
[bbbg.db.attendee :as db.attendee]
[bbbg.db.event :as db.event]
[bbbg.event :as event]
[bbbg.handlers.core :refer [*authenticated?* page-response]]
[bbbg.meetup.import :refer [import-attendees!]]
[bbbg.util.display :refer [format-date pluralize]]
[bbbg.util.time :as t]
[bbbg.views.flash :as flash]
[compojure.coercions :refer [as-uuid]]
[compojure.core :refer [context GET POST]]
[java-time :refer [local-date]]
[ring.util.response :refer [not-found redirect]]
[bbbg.attendee :as attendee]
[bbbg.event-attendee :as event-attendee]
[bbbg.db.attendee-check :as db.attendee-check]
[bbbg.attendee-check :as attendee-check]
[bbbg.user :as user])
(:import
java.time.format.FormatStyle))
(defn- num-attendees [event]
(str
(:num-attendees event)
(if (= (t/->LocalDate (::event/date event))
(local-date))
" Signed In"
(str " Attendee" (when-not (= 1 (:num-attendees event)) "s")))))
(def index-type->label
{:upcoming "Upcoming"
:past "Past"})
(def other-index-type
{:upcoming :past
:past :upcoming})
(defn events-index
[{:keys [events num-events type]}]
[:div.page
[:div.page-header
[:h1
(pluralize
num-events
(str (index-type->label type) " Event"))]
[:a {:href (str "/events"
(when (= :upcoming type)
"/past"))}
"View "
(index-type->label (other-index-type type))
" Events"]]
(when *authenticated?*
[:a.button {:href "/events/new"}
"Create New Event"])
[:ul.events-list
(for [event (sort-by
::event/date
(comp - compare)
events)]
[:li
[:p
[:a {:href (str "/events/" (::event/id event))}
(format-date (::event/date event)
FormatStyle/FULL)]]
[:p
(pluralize (:num-rsvps event) "RSVP")
", "
(num-attendees event)]])]])
(defn- import-attendee-list-form-group []
[:div.form-group
[:label "Import Attendee List"
[:br]
[:input {:type :file
:name :attendees}]]])
(defn import-attendees-form [event]
[:form {:method :post
:action (str "/events/" (::event/id event) "/attendees")
:enctype "multipart/form-data"}
(import-attendee-list-form-group)
[:div.form-group
[:input {:type :submit
:value "Import"}]]])
(defn event-page [{:keys [event attendees]}]
[:div.page
[:div.page-header
[:h1 (format-date (::event/date event)
FormatStyle/FULL)]
[:div.spacer]
[:a.button {:href (str "/signup-forms/" (::event/id event) )}
"Go to Signup Form"]
[:form#delete-event
{:method :post
:action (str "/events/" (::event/id event) "/delete")
:data-confirm "Are you sure you want to delete this event?"}
[:input.error {:type "submit"
:value "Delete Event"}]]]
[:div.stats
[:p (pluralize (:num-rsvps event) "RSVP")]
[:p (num-attendees event)]]
[:div
(import-attendees-form event)]
[:div
[:table.attendees
[:thead
[:th "Meetup Name"]
[:th "Discord Name"]
[:th "RSVP"]
[:th "Signed In"]
[:th "Last Vaccination Check"]]
[:tbody
(for [attendee (sort-by (juxt (comp not ::event-attendee/rsvpd-attending?)
(comp not ::event-attendee/attended?)
(comp some? :last-check)
::attendee/meetup-name)
attendees)]
[:tr
[:td.attendee-name (::attendee/meetup-name attendee)]
[:td
[:label.mobile-label "Discord Name: "]
(or (not-empty (::attendee/discord-name attendee))
"—")]
[:td
[:label.mobile-label "RSVP: "]
(if (::event-attendee/rsvpd-attending? attendee)
[:span {:title "Yes"} "✔️"]
[:span {:title "No"} "❌"])]
[:td
[:label.mobile-label "Signed In: "]
(if (::event-attendee/attended? attendee)
[:span {:title "Yes"} "✔️"]
[:span {:title "No"} "❌"])]
[:td
[:label.mobile-label "Last Vaccination Check: "]
(if-let [last-check (:last-check attendee)]
(str "✔️ "(-> last-check
::attendee-check/checked-at
format-date)
", by "
(get-in last-check [:user ::user/username]))
(list
[:span {:title "Not Checked"}
"❌"]
" "
[:a {:href (str "/attendees/"
(::attendee/id attendee)
"/checks/edit")}
"Edit"]))]])]]]])
(defn import-attendees-page [{:keys [event]}]
[:div.page
[:h1 "Import Attendees for " (format-date (::event/date event))]
(import-attendees-form event)])
(defn event-form
([] (event-form {}))
([event]
[:div.page
[:div.page-header
[:h1 "Create New Event"]]
[:form {:method "POST"
:action "/events"
:enctype "multipart/form-data"}
[:div.form-group
[:label "Date"
[:input {:type "date"
:id "date"
:name "date"
:value (str (::event/date event))}]]]
(import-attendee-list-form-group)
[:div.form-group
[:input {:type "submit"
:value "Create Event"}]]]]))
(defn- events-list-handler [db query type]
(let [events (db/list db (db.event/with-stats query))
num-events (db/count db query)]
(page-response
(events-index {:events events
:num-events num-events
:type type}))))
(defn events-routes [{:keys [db]}]
(context "/events" []
(GET "/" []
(events-list-handler db (db.event/upcoming) :upcoming))
(GET "/past" []
(events-list-handler db (db.event/past) :past))
(GET "/new" [date]
(page-response
{:title "New Event"}
(event-form {::event/date date})))
(POST "/" [date attendees]
(let [event (db.event/create! db {::event/date date})
message
(if attendees
(let [num-attendees
(import-attendees! db
(::event/id event)
(:tempfile attendees))]
(format "Event created with %d attendees"
num-attendees))
"Event created")]
(-> (str "/signup-forms/" (::event/id event))
redirect
(flash/add-flash {:flash/type :success
:flash/message message}))))
(context "/:id" [id :<< as-uuid]
(GET "/" []
(if-let [event (db/fetch db
(-> {:select [:event.*]
:from [:event]
:where [:= :event.id id]}
(db.event/with-stats)))]
(let [attendees (db.attendee-check/attendees-with-last-checks
db
(db/list db (db.attendee/for-event id)))]
(page-response
(event-page {:event event
:attendees attendees})))
(not-found "Event Not Found")))
(POST "/delete" []
(db/delete! db :event_attendee [:= :event-id id])
(db/delete! db :event [:= :id id])
(-> (redirect "/events")
(flash/add-flash
#:flash {:type :success
:message "Successfully deleted event"})))
(GET "/attendees/import" []
(if-let [event (db/get db :event id)]
(page-response
(import-attendees-page {:event event}))
(not-found "Event Not Found")))
(POST "/attendees" [attendees]
(let [num-imported (import-attendees! db id (:tempfile attendees))]
(-> (redirect (str "/events/" id))
(flash/add-flash
#:flash{:type :success
:message (format "Successfully imported %d attendees"
num-imported)})))))))
(comment
(def db (:db bbbg.core/system))
(-> (db/list db :event)
first
::event/date
format-date)
)
|