-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(): Onboarding Checklist #2863
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<script setup lang="ts"> | ||
import { computed, watch } from 'vue'; | ||
import { useI18n } from '@/composables/useI18n'; | ||
import { useOnboardingChecklist } from '@/composables/useOnboardingChecklist'; | ||
import { useStorage } from '@vueuse/core'; | ||
|
||
const props = defineProps<{ | ||
web3Account: string; | ||
}>(); | ||
|
||
const { t } = useI18n(); | ||
const { onboardingChecklist } = useOnboardingChecklist(); | ||
|
||
const hideOnboarding = useStorage( | ||
`snapshot.hideOnboarding.${props.web3Account.slice(0, 8).toLowerCase()}`, | ||
false | ||
); | ||
|
||
const checkListCompleted = computed(() => { | ||
let completed = true; | ||
|
||
onboardingChecklist.value.forEach(checkListItem => { | ||
if (!checkListItem.checked) { | ||
completed = false; | ||
return; | ||
} | ||
}); | ||
|
||
return completed; | ||
}); | ||
|
||
watch(checkListCompleted, completed => { | ||
if (completed) { | ||
setTimeout(() => { | ||
hideOnboarding.value = true; | ||
}, 2000); | ||
} | ||
}); | ||
|
||
function closeOnboarding() { | ||
hideOnboarding.value = true; | ||
} | ||
</script> | ||
|
||
<template> | ||
<transition name="fade"> | ||
<div | ||
v-if="!hideOnboarding" | ||
class="border-skin-border bg-skin-block-bg text-white md:rounded-lg md:border" | ||
> | ||
<div class="p-4"> | ||
<div class="flex"> | ||
<div class="flex-grow"> | ||
<h3 class="text-bold mt-0"> | ||
{{ t('onboarding.title') }} | ||
</h3> | ||
<p>{{ t('onboarding.subtitle') }}</p> | ||
</div> | ||
<div> | ||
<BaseButtonIcon @click="closeOnboarding"> | ||
<i-ho-x class="text-base" /> | ||
</BaseButtonIcon> | ||
</div> | ||
</div> | ||
|
||
<ul class="mt-4 flex-col space-y-2"> | ||
<li | ||
v-for="checkListItem in onboardingChecklist" | ||
:key="checkListItem.name" | ||
class="flex items-center" | ||
> | ||
<div class="w-4"> | ||
<i-ho-check | ||
v-if="checkListItem.checked" | ||
class="text-[17px] text-green" | ||
/> | ||
<div v-else class="h-3 w-3 border"></div> | ||
</div> | ||
{{ checkListItem.name }} | ||
</li> | ||
</ul> | ||
<transition name="fade"> | ||
<div v-if="checkListCompleted" class="mt-4"> | ||
<h3>🎉 {{ t('onboarding.congratulations') }}</h3> | ||
</div> | ||
</transition> | ||
</div> | ||
</div> | ||
</transition> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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([ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be hard for new users figuring out how to complete each list item. Maybe each item should be collapsable with additional links and information. @ManuBernard do you have a designer with who we could try some things out? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have followed the design provided by @bonustrack : Not sure how to move forward, maybe you should talk together and see if we want to improve this in this PR or create a new one later? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see. Yeah I wasn't aware of this design sorry for the confusion :) |
||
{ | ||
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 }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of auto hiding it on completion we could have a share on twitter button
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could be a good idea. I think it should be also discussed with @bonustrack.
It will ask some UX thinking about how to handle the closing of this panel.