;;;; user.lisp (in-package :vampire) ;;; CLIENT UI (defun create-new-playlist-form (parent) (with-clog-create parent (form () (section (:h3 :content "Create New Playlist")) (label (:content "Playlist Title:")) (form-element (:text :bind pl-title)) (button (:content "Create" :bind btn))) (set-on-click btn (thunk* (new-playlist (session-user parent) :title (value pl-title)) (reload (location (connection-body parent))))))) (defun url-to-playlist (pl) (format nil "/playlist/~a" (key pl))) (defun create-playlist-listing (parent &optional user) (dolist (pl (user-playlists (or user (session-user parent)))) (with-clog-create parent (div (:bind pl-item) (div () (playlist-explore-card (pl)) (button (:content "delete" :bind btn)))) (cond ((eq user (session-user parent)) (set-on-click btn (thunk* (destroy-playlist pl) (destroy pl-item)))) (t (destroy btn)))))) (defun create-invite-list-item (invite-list invite) (with-clog-create invite-list (list-item (:bind item) (button (:bind delbtn :content "delete")) (p () (span (:content "Code: ")) (span (:content (key invite)))) (p () (span (:content "Uses Remaining: ")) (span (:content (format nil "~a" (or (uses-remaining invite) "unlimited")))))) (set-on-click delbtn (thunk* (destroy-invite invite) (destroy item))))) (defun create-invite-control (parent) (let* ((user (session-user parent)) (container (create-div parent)) (invite-list (create-unordered-list parent))) (place-after (create-section container :h3 :content "Your Invites") invite-list) ;; list invites (dolist (invite (invites-by-maker user)) (create-invite-list-item invite-list invite)) (with-clog-create container (form () (button (:bind createbtn :content "Create Invite")) (form-element (:number :bind count)) (p (:bind invite-explainer :content "Share invite codes with friends to invite them to this server. Optinally say how many times an invite code can be used by setting the Uses count before clicking the Create Invite button."))) (setf (maximum-width invite-explainer) "500px" (minimum count) 0 (place-holder count) "Uses" (width count) 70) (set-on-click createbtn (thunk* (let ((invite (make-invite user (parse-integer (value count) :junk-allowed t)))) (create-invite-list-item invite-list invite))))))) (defun create-password-reset (parent) (with-clog-create parent (div () (button (:content "Password Reset" :bind pw-reset-toggle)) (form (:hidden t :bind pw-reset-form) (form-element (:password :bind pw-input)) (br ()) (form-element (:password :bind pw-repeated)) (br ()) (button (:content "Change password" :bind pw-update))) (p (:bind notice-area))) (setf (place-holder pw-input) "New Password" (place-holder pw-repeated) "Repeat New Password" (disabledp pw-update) t) (set-on-key-down pw-repeated (thunk* (when (equal (value pw-input) (value pw-repeated)) (setf (disabledp pw-update) nil)))) (flet ((toggle-form () (cond ((visiblep pw-reset-form) (setf (visiblep pw-reset-form) nil (text pw-reset-toggle) "Password Reset" (text notice-area) "" (disabledp pw-update) t (value pw-input) "" (value pw-repeated) "")) (t (setf (visiblep pw-reset-form) t (text notice-area) "" (text pw-reset-toggle) "Nevermind"))))) (set-on-click pw-update (thunk* ;; assumes pw-input and pw-repeat are equal (set-new-password (session-user parent) (value pw-input)) (toggle-form) (setf (text notice-area) "Password updated!"))) (set-on-click pw-reset-toggle (thunk* (toggle-form)))))) (defun user-home-page (body) (include-style body) (with-clog-create body (div () (navigation-header ()) (div (:class "row") (p (:content "ANNOUNCEMENT: Vampire Sucks (ha ha). No really. It has been regularly refusing connections. You may have noticed a White Screen Of Death. I (colin) have been (very slowly) working on an improved application. Stay tuned: IMPROVEMENTS LAND IN OCTOBER 2024. Forthcoming new features: Comments! Search! Exploration!"))) (div (:class "row") (div () (section (:pre :content (format nil "Welcome ~a" (user-name (session-user body))))) (section (:h3 :content "Your Playlists")) (div (:class "row") (playlist-listing ())) (new-playlist-form ()) (invite-control ()) (password-reset ())))))) (defun user-key-from-url (url) (first (last (ppcre:split "/" (nth 4 (multiple-value-list (quri:parse-uri url))))))) (defun user-listing-page (body) (when-let* ((user-id (user-key-from-url (url (location body)))) (user (object-with-key user-id))) (include-style body) (with-clog-create body (div () (navigation-header ()) (div (:class "row") (div () (section (:h3 :content (format nil "Playlists by ~a" (user-name user)))) (div (:class "row") (playlist-listing (user)))))))))