Merge pull request #3302 from penpot/superalex-fix-survey-issues

🐛 Fix some onboarding survey issues
This commit is contained in:
Alejandro 2023-06-15 07:38:47 +02:00 committed by GitHub
commit 28b1c9c6d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 58 deletions

View file

@ -322,6 +322,7 @@ textarea {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-family: "worksans", sans-serif;
justify-content: center; justify-content: center;
padding-top: 6px; padding-top: 6px;
padding-bottom: 6px; padding-bottom: 6px;

View file

@ -220,7 +220,10 @@
:disabled disabled :disabled disabled
:data-test data-test} :data-test data-test}
(for [item options] (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.input-container {:class (dom/classnames :disabled disabled :focus @focus?)}
[:div.main-content [:div.main-content

View file

@ -7,6 +7,7 @@
(ns app.main.ui.onboarding.questions (ns app.main.ui.onboarding.questions
"External form for onboarding questions." "External form for onboarding questions."
(:require (:require
[app.common.data.macros :as dm]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
@ -36,65 +37,65 @@
(s/keys :req-un [::planning])) (s/keys :req-un [::planning]))
(mf/defc step-1 (mf/defc step-1
[{:keys [on-next] :as props}] [{:keys [on-next form] :as props}]
[:& step-container {:form form :step 1 :on-next on-next}
(let [form (fm/use-form [:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
:initial {} [:h1 (tr "questions.lets-get-started")]
:spec ::questions-form-step-1)] [:p.intro (tr "questions.your-feedback-will-help-us")]
[:& step-container {:form form :step 1 :on-next on-next} [:h3 (tr "questions-how-are-you-planning-to-use-penpot")]
[:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}] [:& 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}
[:h1 (tr "questions.lets-get-started")] {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
[:p.intro (tr "questions.your-feedback-will-help-us")] {: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"}
[:h3 (tr "questions-how-are-you-planning-to-use-penpot")] {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
[:& fm/select {:options [{:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"} {: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.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.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
{: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.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
{: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.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.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"} :label (tr "questions.select-option")
{:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"} :default ""
{: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"}] :name :planning}]])
:label (tr "questions.select-option")
:default nil
:name :planning}]]))
(s/def ::questions-form-step-2 (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])) (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 (mf/defc step-2
[{:keys [on-next on-prev] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [form (fm/use-form [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
:initial {} [:h3 (tr "questions.describe-your-experience-working-on")]
: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")]
[:div.section (tr "branding-illustrations-marketing-pieces")] [:div.section (tr "branding-illustrations-marketing-pieces")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-branding-illustrations-marketing-pieces}] :name :experience-branding-illustrations-marketing-pieces}]
[:div.section (tr "questions.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"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-design-visual-assets-design-systems}] :name :experience-interface-design-visual-assets-design-systems}]
[:div.section (tr "questions.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"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]])) :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]])
(s/def ::questions-form-step-3 (s/def ::questions-form-step-3
(s/keys :req-un [::experience-design-tool] (s/keys :req-un [::experience-design-tool]
:opt-un[::experience-design-tool-other])) :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 (mf/defc step-3
[{:keys [on-next on-prev] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [form (fm/use-form (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
:initial {}
:spec ::questions-form-step-3)]
[:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev} [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
[:h3 (tr "question.design-tool-more-experienced-with")] [:h3 (tr "question.design-tool-more-experienced-with")]
[:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"} [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
@ -107,17 +108,23 @@
:name :experience-design-tool}] :name :experience-design-tool}]
[:div.other [:div.other
[:label (tr "questions.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/def ::questions-form-step-4
(s/keys :req-un [::team-size ::role] (s/keys :req-un [::team-size ::role]
:opt-un [::role-other])) :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 (mf/defc step-4
[{:keys [on-next on-prev] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [form (fm/use-form (let [role (dm/get-in @form [:data :role])]
:initial {}
:spec ::questions-form-step-4)]
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev} [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
[:h3 (tr "questions.role")] [:h3 (tr "questions.role")]
[:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"} [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
@ -130,17 +137,18 @@
:name :role}] :name :role}]
[:div.other [:div.other
[:label (tr "questions.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")] [: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.31-50") :value "31-50" :key "31-50"}
{:label (tr "questions.11-30") :value "11-30" :key "11-30"} {: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.2-10") :value "2-10" :key "2-10"}
{:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"} {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
{:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}] {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
:label (tr "questions.select-option") :label (tr "questions.select-option")
:default nil :default ""
:name :team-size}]])) :name :team-size}]]))
(mf/defc questions (mf/defc questions
@ -149,6 +157,24 @@
step (mf/use-state 1) step (mf/use-state 1)
clean-data (mf/use-state {}) 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 on-next
(mf/use-fn (mf/use-fn
(fn [form] (fn [form]
@ -175,7 +201,7 @@
[:img.deco.right {:src "images/deco-right.png" :border 0}] [:img.deco.right {:src "images/deco-right.png" :border 0}]
[:div.signup-questions [:div.signup-questions
(case @step (case @step
1 [:& step-1 {:on-next on-next :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}] 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}] 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}])]]]])) 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]]]))