From 0f061d784763b86fb6c76faf772b6c6021eeaae0 Mon Sep 17 00:00:00 2001 From: Charly Bernard Date: Thu, 21 Jul 2022 14:41:58 +0200 Subject: [PATCH 1/3] feat(): Onboarding Checklist --- src/components/TimelineOnboarding.vue | 95 +++++++++++++++++++++++ src/composables/useOnboardingChecklist.ts | 85 ++++++++++++++++++++ src/locales/default.json | 10 +++ src/locales/fr-FR.json | 10 +++ src/views/TimelineView.vue | 3 + 5 files changed, 203 insertions(+) create mode 100644 src/components/TimelineOnboarding.vue create mode 100644 src/composables/useOnboardingChecklist.ts diff --git a/src/components/TimelineOnboarding.vue b/src/components/TimelineOnboarding.vue new file mode 100644 index 00000000000..9ec7e79a1be --- /dev/null +++ b/src/components/TimelineOnboarding.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/composables/useOnboardingChecklist.ts b/src/composables/useOnboardingChecklist.ts new file mode 100644 index 00000000000..e7031f73310 --- /dev/null +++ b/src/composables/useOnboardingChecklist.ts @@ -0,0 +1,85 @@ +import { computed, ref, watch } from 'vue'; +import { useProfiles } from '@/composables/useProfiles'; +import { useWeb3 } from '@/composables/useWeb3'; +import { useI18n } from '@/composables/useI18n'; +import { useApolloQuery } from '@/composables/useApolloQuery'; +import { PROPOSALS_QUERY } from '@/helpers/queries'; +import { ACTIVITY_VOTES_QUERY } from '@/helpers/queries'; +import { useFollowSpace } from '@/composables/useFollowSpace'; + +const { t } = useI18n(); + +const { apolloQuery } = useApolloQuery(); +const { profiles } = useProfiles(); +const { web3Account } = useWeb3(); +const { followingSpaces } = useFollowSpace(); + +const profile = computed(() => profiles.value[web3Account.value]); + +const hasSetPublicProfile = computed(() => + profile.value?.name ? true : false +); +const hasFollowedSpace = computed(() => followingSpaces.value.length); +const hasVoted = ref(false); +const hasCreatedProposal = ref(false); + +const onboardingChecklist = ref([ + { + checked: hasSetPublicProfile, + name: t('onboarding.profile') + }, + { + checked: hasFollowedSpace, + name: t('onboarding.space') + }, + { + checked: hasVoted, + name: t('onboarding.vote') + }, + { + checked: hasCreatedProposal, + name: t('onboarding.proposal') + } +]); + +async function loadVotes() { + const votes = await apolloQuery( + { + query: ACTIVITY_VOTES_QUERY, + variables: { + voter: profile.value.id + } + }, + 'votes' + ); + + hasVoted.value = votes.length ? true : false; +} + +async function loadProposals() { + const proposals = await apolloQuery( + { + query: PROPOSALS_QUERY, + variables: { + first: 1, + skip: 0, + state: 'all', + author_in: [profile.value.id] + } + }, + 'proposals' + ); + + hasCreatedProposal.value = proposals.length ? true : false; +} + +watch(profiles, p => { + if (profile.value) { + loadVotes(); + loadProposals(); + } +}); + +export function useOnboardingChecklist() { + return { onboardingChecklist }; +} diff --git a/src/locales/default.json b/src/locales/default.json index a545d6e41a6..ccfe8ca9a2d 100644 --- a/src/locales/default.json +++ b/src/locales/default.json @@ -612,5 +612,15 @@ "empty": "There are no assets in this contract" }, "24hChange": "24h change" + }, + "onboarding": { + "title": "New to Snapshot?", + "subtitle": "Here is a quick check list to get started:", + "close": "Hide onboarding cheklist", + "profile": "Set your public profile", + "space": "Join your favorite space", + "vote": "Cast your first vote", + "proposal": "Create a proposal", + "congratulations": "Congratulations" } } diff --git a/src/locales/fr-FR.json b/src/locales/fr-FR.json index 39cd31cd132..ab648858b67 100644 --- a/src/locales/fr-FR.json +++ b/src/locales/fr-FR.json @@ -602,5 +602,15 @@ "empty": "There are no assets in this contract" }, "24hChange": "24h change" + }, + "onboarding": { + "title": "Nouveau sur Snapshot ?", + "subtitle": "Voici une checklist rapide pour commencer :", + "close": "Cacher la checklist", + "profile": "Définir votre profil public", + "space": "Rejoindre votre espace préféré", + "vote": "Votre premier vote", + "proposal": "Créer une proposition", + "congratulations": "Félicitations" } } diff --git a/src/views/TimelineView.vue b/src/views/TimelineView.vue index 5107b685365..07cb63fe989 100644 --- a/src/views/TimelineView.vue +++ b/src/views/TimelineView.vue @@ -176,6 +176,9 @@ function selectState(e) { + + +
-import { ref, computed, watch } from 'vue'; +import { computed, watch } from 'vue'; import { useI18n } from '@/composables/useI18n'; import { useOnboardingChecklist } from '@/composables/useOnboardingChecklist'; -import { lsSet, lsGet } from '@/helpers/utils'; +import { useStorage } from '@vueuse/core'; -const { t } = useI18n(); +const props = defineProps<{ + web3Account: string; +}>(); +const { t } = useI18n(); const { onboardingChecklist } = useOnboardingChecklist(); -const showOnboarding = ref(true); +const hideOnboarding = useStorage( + `snapshot.hideOnboarding.${props.web3Account.slice(0, 8).toLowerCase()}`, + false +); const checkListCompleted = computed(() => { let completed = true; @@ -23,48 +29,37 @@ const checkListCompleted = computed(() => { return completed; }); -if (lsGet('timelineOnboarding') == 'hidden') { - showOnboarding.value = false; -} - watch(checkListCompleted, completed => { - if (completed) lsSet('timelineOnboarding', 'hidden'); + if (completed) { + setTimeout(() => { + hideOnboarding.value = true; + }, 2000); + } }); function closeOnboarding() { - lsSet('timelineOnboarding', 'hidden'); - showOnboarding.value = false; + hideOnboarding.value = true; }