From 1bb1734448b4d4efc767524745309e90238617fd Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 14 Jun 2023 14:15:06 +0200 Subject: [PATCH] :bug: Fix some onboarding survey issues --- .../resources/styles/main/partials/forms.scss | 1 + .../src/app/main/ui/components/forms.cljs | 5 +- .../src/app/main/ui/onboarding/questions.cljs | 140 +++++++++++------- 3 files changed, 88 insertions(+), 58 deletions(-) diff --git a/frontend/resources/styles/main/partials/forms.scss b/frontend/resources/styles/main/partials/forms.scss index 6299fe81f..4d42d4c31 100644 --- a/frontend/resources/styles/main/partials/forms.scss +++ b/frontend/resources/styles/main/partials/forms.scss @@ -322,6 +322,7 @@ textarea { flex-grow: 1; display: flex; flex-direction: column; + font-family: "worksans", sans-serif; justify-content: center; padding-top: 6px; padding-bottom: 6px; diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index 015e31b97..be9a8c057 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -220,7 +220,10 @@ :disabled disabled :data-test data-test} (for [item options] - [:option {:key (:value item) :value (:value item)} (:label item)])] + [:> :option (clj->js (cond-> {:key (:value item) :value (:value item)} + (:disabled item) (assoc :disabled "disabled") + (:hidden item) (assoc :style {:display "none"}))) + (:label item)])] [:div.input-container {:class (dom/classnames :disabled disabled :focus @focus?)} [:div.main-content diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index 54c1e97c5..473e4dd4a 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.onboarding.questions "External form for onboarding questions." (:require + [app.common.data.macros :as dm] [app.main.data.users :as du] [app.main.store :as st] [app.main.ui.components.forms :as fm] @@ -36,65 +37,65 @@ (s/keys :req-un [::planning])) (mf/defc step-1 - [{:keys [on-next] :as props}] - - (let [form (fm/use-form - :initial {} - :spec ::questions-form-step-1)] - [:& step-container {:form form :step 1 :on-next on-next} - [:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}] - [:h1 (tr "questions.lets-get-started")] - [:p.intro (tr "questions.your-feedback-will-help-us")] - [:h3 (tr "questions-how-are-you-planning-to-use-penpot")] - [:& fm/select {:options [{:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"} - {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"} - {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"} - {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"} - {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"} - {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"} - {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}] - :label (tr "questions.select-option") - :default nil - :name :planning}]])) + [{:keys [on-next form] :as props}] + [:& step-container {:form form :step 1 :on-next on-next} + [:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}] + [:h1 (tr "questions.lets-get-started")] + [:p.intro (tr "questions.your-feedback-will-help-us")] + [:h3 (tr "questions-how-are-you-planning-to-use-penpot")] + [:& fm/select {:options [{:label (tr "questions-how-are-you-planning-to-use-penpot") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true :hidden true} + {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"} + {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"} + {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"} + {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"} + {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"} + {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"} + {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}] + :label (tr "questions.select-option") + :default "" + :name :planning}]]) (s/def ::questions-form-step-2 (s/keys :req-un [::experience-branding-illustrations-marketing-pieces ::experience-interface-design-visual-assets-design-systems ::experience-interface-wireframes-user-journeys-flows-navigation-trees])) (mf/defc step-2 - [{:keys [on-next on-prev] :as props}] - (let [form (fm/use-form - :initial {} - :spec ::questions-form-step-2)] - [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev} - [:h3 (tr "questions.describe-your-experience-working-on")] + [{:keys [on-next on-prev form] :as props}] + [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev} + [:h3 (tr "questions.describe-your-experience-working-on")] - [:div.section (tr "branding-illustrations-marketing-pieces")] - [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} - {:label (tr "questions.some") :value "some"} - {:label (tr "questions.a-lot") :value "a-lot"}] - :name :experience-branding-illustrations-marketing-pieces}] + [:div.section (tr "branding-illustrations-marketing-pieces")] + [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} + {:label (tr "questions.some") :value "some"} + {:label (tr "questions.a-lot") :value "a-lot"}] + :name :experience-branding-illustrations-marketing-pieces}] - [:div.section (tr "questions.interface-design-visual-assets-design-systems")] - [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} - {:label (tr "questions.some") :value "some"} - {:label (tr "questions.a-lot") :value "a-lot"}] - :name :experience-interface-design-visual-assets-design-systems}] + [:div.section (tr "questions.interface-design-visual-assets-design-systems")] + [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} + {:label (tr "questions.some") :value "some"} + {:label (tr "questions.a-lot") :value "a-lot"}] + :name :experience-interface-design-visual-assets-design-systems}] - [:div.section (tr "questions.wireframes-user-journeys-flows-navigation-trees")] - [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} - {:label (tr "questions.some") :value "some"} - {:label (tr "questions.a-lot") :value "a-lot"}] - :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]])) + [:div.section (tr "questions.wireframes-user-journeys-flows-navigation-trees")] + [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} + {:label (tr "questions.some") :value "some"} + {:label (tr "questions.a-lot") :value "a-lot"}] + :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]]) (s/def ::questions-form-step-3 (s/keys :req-un [::experience-design-tool] :opt-un[::experience-design-tool-other])) +(defn- step-3-form-validator + [errors data] + (let [experience-design-tool (:experience-design-tool data) + experience-design-tool-other (:experience-design-tool-other data)] + (cond-> errors + (and (= experience-design-tool "other") (= 0 (count experience-design-tool-other))) + (assoc :experience-design-tool-other {:code "missing"})))) + (mf/defc step-3 - [{:keys [on-next on-prev] :as props}] - (let [form (fm/use-form - :initial {} - :spec ::questions-form-step-3)] + [{:keys [on-next on-prev form] :as props}] + (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])] [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev} [:h3 (tr "question.design-tool-more-experienced-with")] [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"} @@ -107,17 +108,23 @@ :name :experience-design-tool}] [:div.other [:label (tr "questions.other")] - [:& fm/input {:name :experience-design-tool-other :label (tr "questions.other")}]]])) + [:& fm/input {:name :experience-design-tool-other :label (tr "questions.other") :disabled (not= experience-design-tool "other")}]]])) (s/def ::questions-form-step-4 (s/keys :req-un [::team-size ::role] :opt-un [::role-other])) +(defn- step-4-form-validator + [errors data] + (let [role (:role data) + role-other (:role-other data)] + (cond-> errors + (and (= role "other") (= 0 (count role-other))) + (assoc :role-other {:code "missing"})))) + (mf/defc step-4 - [{:keys [on-next on-prev] :as props}] - (let [form (fm/use-form - :initial {} - :spec ::questions-form-step-4)] + [{:keys [on-next on-prev form] :as props}] + (let [role (dm/get-in @form [:data :role])] [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev} [:h3 (tr "questions.role")] [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"} @@ -130,17 +137,18 @@ :name :role}] [:div.other [:label (tr "questions.other")] - [:& fm/input {:name :role-other :label (tr "questions.other")}]] + [:& fm/input {:name :role-other :label (tr "questions.other") :disabled (not= role "other")}]] [:h3 (tr "questions.team-size")] - [:& fm/select {:options [{:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"} + [:& fm/select {:options [{:label (tr "questions-how-are-you-planning-to-use-penpot") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true :hidden true} + {:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"} {:label (tr "questions.31-50") :value "31-50" :key "31-50"} {:label (tr "questions.11-30") :value "11-30" :key "11-30"} {:label (tr "questions.2-10") :value "2-10" :key "2-10"} {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"} {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}] :label (tr "questions.select-option") - :default nil + :default "" :name :team-size}]])) (mf/defc questions @@ -149,6 +157,24 @@ step (mf/use-state 1) clean-data (mf/use-state {}) + ;; Forms are initialized here because we can go back and forth between the steps + ;; and we want to keep the filled info + step-1-form (fm/use-form + :initial {} + :spec ::questions-form-step-1) + step-2-form (fm/use-form + :initial {} + :spec ::questions-form-step-2) + step-3-form (fm/use-form + :initial {} + :validators [step-3-form-validator] + :spec ::questions-form-step-3) + + step-4-form (fm/use-form + :initial {} + :validators [step-4-form-validator] + :spec ::questions-form-step-4) + on-next (mf/use-fn (fn [form] @@ -175,7 +201,7 @@ [:img.deco.right {:src "images/deco-right.png" :border 0}] [:div.signup-questions (case @step - 1 [:& step-1 {:on-next on-next :on-prev on-prev}] - 2 [:& step-2 {:on-next on-next :on-prev on-prev}] - 3 [:& step-3 {:on-next on-next :on-prev on-prev}] - 4 [:& step-4 {:on-next on-submit :on-prev on-prev}])]]]])) + 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}] + 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}] + 3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}] + 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]]]))