feat: Redesign onboarding screen (#9939)

Co-authored-by: Pranav <pranavrajs@gmail.com>
This commit is contained in:
Fayaz Ahmed
2024-08-16 13:01:22 +05:30
committed by GitHub
parent 4310a547ca
commit f38101527f
7 changed files with 137 additions and 163 deletions

View File

@@ -0,0 +1,54 @@
<script setup>
defineProps({
imageSrc: {
type: String,
default: '',
},
imageAlt: {
type: String,
default: '',
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
to: {
type: String,
default: '',
},
linkText: {
type: String,
default: '',
},
});
</script>
<template>
<div
class="h-full w-full bg-white dark:bg-slate-900 border border-slate-100 dark:border-white/10 rounded-lg p-4 flex flex-col"
>
<img :src="imageSrc" :alt="imageAlt" class="h-36 w-auto mx-auto" />
<div class="mt-auto">
<p
class="text-base text-slate-800 dark:text-slate-100 font-interDisplay font-semibold tracking-[0.3px]"
>
{{ title }}
</p>
<p class="text-slate-600 dark:text-slate-400 text-sm">
{{ description }}
</p>
<router-link
v-if="to"
:to="{ name: to }"
class="no-underline text-woot-500 text-sm font-medium"
>
<span>{{ linkText }}</span>
<span>{{ `` }}</span>
</router-link>
</div>
</div>
</template>

View File

@@ -1,164 +1,80 @@
<script>
import { mapGetters } from 'vuex';
import { useAccount } from 'dashboard/composables/useAccount';
<script setup>
import OnboardingFeatureCard from './OnboardingFeatureCard.vue';
import { computed } from 'vue';
import { useI18n } from 'dashboard/composables/useI18n';
import { useStoreGetters } from 'dashboard/composables/store';
export default {
setup() {
const { accountScopedUrl } = useAccount();
return {
accountScopedUrl,
};
},
computed: {
...mapGetters({ globalConfig: 'globalConfig/get' }),
newInboxURL() {
return this.accountScopedUrl('settings/inboxes/new');
},
newAgentURL() {
return this.accountScopedUrl('settings/agents/list');
},
newLabelsURL() {
return this.accountScopedUrl('settings/labels/list');
},
},
};
const getters = useStoreGetters();
const { t } = useI18n();
const globalConfig = computed(() => getters['globalConfig/get'].value);
const currentUser = computed(() => getters.getCurrentUser.value);
const greetingMessage = computed(() => {
const hours = new Date().getHours();
let translationKey;
if (hours < 12) {
translationKey = 'ONBOARDING.GREETING_MORNING';
} else if (hours < 18) {
translationKey = 'ONBOARDING.GREETING_AFTERNOON';
} else {
translationKey = 'ONBOARDING.GREETING_EVENING';
}
return t(translationKey, {
name: currentUser.value.name,
installationName: globalConfig.value.installationName,
});
});
</script>
<template>
<div class="onboarding-wrap">
<div class="onboarding">
<div class="scroll-wrap">
<div class="features-item">
<h1 class="text-2xl text-slate-900 dark:text-slate-50">
<span>{{
$t('ONBOARDING.TITLE', {
installationName: globalConfig.installationName,
})
}}</span>
</h1>
<p class="intro-body">
{{
$t('ONBOARDING.DESCRIPTION', {
installationName: globalConfig.installationName,
})
}}
</p>
<p v-if="globalConfig.installationName === 'Chatwoot'">
<a
href="https://www.chatwoot.com/changelog"
target="_blank"
rel="noopener nofollow noreferrer"
class="onboarding--link"
>
{{ $t('ONBOARDING.READ_LATEST_UPDATES') }}
</a>
<span>🎉</span>
</p>
</div>
<div class="features-item">
<h2 class="text-lg text-black-900 dark:text-slate-200">
<span class="emoji">💬</span>
<span class="conversation--title">{{
$t('ONBOARDING.ALL_CONVERSATION.TITLE')
}}</span>
</h2>
<p class="intro-body">
{{ $t('ONBOARDING.ALL_CONVERSATION.DESCRIPTION') }}
</p>
</div>
<div class="features-item">
<h2 class="text-lg text-black-900 dark:text-slate-200">
<span class="emoji">👥</span>
{{ $t('ONBOARDING.TEAM_MEMBERS.TITLE') }}
</h2>
<p class="intro-body">
{{ $t('ONBOARDING.TEAM_MEMBERS.DESCRIPTION') }}
</p>
<router-link :to="newAgentURL" class="onboarding--link">
{{ $t('ONBOARDING.TEAM_MEMBERS.NEW_LINK') }}
</router-link>
</div>
<div class="features-item">
<h2 class="text-lg text-black-900 dark:text-slate-200">
<span class="emoji">📥</span>{{ $t('ONBOARDING.INBOXES.TITLE') }}
</h2>
<p class="intro-body">
{{ $t('ONBOARDING.INBOXES.DESCRIPTION') }}
</p>
<router-link :to="newInboxURL" class="onboarding--link">
{{ $t('ONBOARDING.INBOXES.NEW_LINK') }}
</router-link>
</div>
<div class="features-item">
<h2 class="text-lg text-black-900 dark:text-slate-200">
<span class="emoji">🔖</span>{{ $t('ONBOARDING.LABELS.TITLE') }}
</h2>
<p class="intro-body">
{{ $t('ONBOARDING.LABELS.DESCRIPTION') }}
</p>
<router-link :to="newLabelsURL" class="onboarding--link">
{{ $t('ONBOARDING.LABELS.NEW_LINK') }}
</router-link>
</div>
</div>
<div
class="min-h-screen max-w-4xl mx-auto grid grid-cols-1 xl:grid-cols-2 grid-rows-[auto_1fr_1fr] gap-4 p-8 w-full font-inter overflow-auto"
>
<div class="col-span-full self-start">
<p
class="text-xl font-semibold text-slate-900 dark:text-white font-interDisplay tracking-[0.3px]"
>
{{ greetingMessage }}
</p>
<p class="text-slate-600 dark:text-slate-400 max-w-2xl text-base">
{{
$t('ONBOARDING.DESCRIPTION', {
installationName: globalConfig.installationName,
})
}}
</p>
</div>
<OnboardingFeatureCard
image-src="/dashboard/images/onboarding/omnichannel-inbox.png"
image-alt="Omnichannel"
to="settings_inbox_new"
:title="$t('ONBOARDING.ALL_CONVERSATION.TITLE')"
:description="$t('ONBOARDING.ALL_CONVERSATION.DESCRIPTION')"
:link-text="$t('ONBOARDING.ALL_CONVERSATION.NEW_LINK')"
/>
<OnboardingFeatureCard
image-src="/dashboard/images/onboarding/teams.png"
image-alt="Teams"
to="settings_teams_new"
:title="$t('ONBOARDING.TEAM_MEMBERS.TITLE')"
:description="$t('ONBOARDING.TEAM_MEMBERS.DESCRIPTION')"
:link-text="$t('ONBOARDING.TEAM_MEMBERS.NEW_LINK')"
/>
<OnboardingFeatureCard
image-src="/dashboard/images/onboarding/canned-responses.png"
image-alt="Canned responses"
to="canned_list"
:title="$t('ONBOARDING.CANNED_RESPONSES.TITLE')"
:description="$t('ONBOARDING.CANNED_RESPONSES.DESCRIPTION')"
:link-text="$t('ONBOARDING.CANNED_RESPONSES.NEW_LINK')"
/>
<OnboardingFeatureCard
image-src="/dashboard/images/onboarding/labels.png"
image-alt="Labels"
to="labels_list"
:title="$t('ONBOARDING.LABELS.TITLE')"
:description="$t('ONBOARDING.LABELS.DESCRIPTION')"
:link-text="$t('ONBOARDING.LABELS.NEW_LINK')"
/>
</div>
</template>
<style lang="scss" scoped>
.onboarding-wrap {
display: flex;
font-size: var(--font-size-small);
justify-content: center;
overflow: auto;
text-align: left;
}
.onboarding {
height: 100vh;
overflow: auto;
}
.scroll-wrap {
padding: var(--space-larger) 8.5rem;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
}
.features-item {
margin-bottom: var(--space-large);
}
.conversation--title {
margin-left: var(--space-minus-smaller);
}
.page-title {
font-size: var(--font-size-big);
font-weight: var(--font-weight-bold);
margin-bottom: var(--space-one);
}
.block-title {
font-weight: var(--font-weight-bold);
margin-bottom: var(--space-smaller);
margin-left: var(--space-minus-large);
}
.intro-body {
margin-bottom: var(--space-small);
line-height: 1.5;
}
.onboarding--link {
color: var(--w-500);
font-weight: var(--font-weight-medium);
text-decoration: underline;
}
.emoji {
width: var(--space-large);
display: inline-block;
}
</style>

View File

@@ -241,25 +241,29 @@
"ONBOARDING": {
"TITLE": "Hey 👋, Welcome to %{installationName}!",
"DESCRIPTION": "Thanks for signing up. We want you to get the most out of %{installationName}. Here are a few things you can do in %{installationName} to make the experience delightful.",
"GREETING_MORNING": "👋 Good morning, %{name}. Welcome to %{installationName}.",
"GREETING_AFTERNOON": "👋 Good afternoon, %{name}. Welcome to %{installationName}.",
"GREETING_EVENING": "👋 Good evening, %{name}. Welcome to %{installationName}.",
"READ_LATEST_UPDATES": "Read our latest updates",
"ALL_CONVERSATION": {
"TITLE": "All your conversations in one place",
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status."
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status.",
"NEW_LINK": "Click here to create an inbox"
},
"TEAM_MEMBERS": {
"TITLE": "Invite your team members",
"DESCRIPTION": "Since you are getting ready to talk to your customer, bring in your teammates to assist you. You can invite your teammates by adding their email addresses to the agent list.",
"NEW_LINK": "Click here to invite a team member"
},
"INBOXES": {
"TITLE": "Connect Inboxes",
"DESCRIPTION": "Connect various channels through which your customers would be talking to you. It can be a website live-chat, your Facebook page or even your WhatsApp number.",
"NEW_LINK": "Click here to create an inbox"
},
"LABELS": {
"TITLE": "Organize conversations with labels",
"DESCRIPTION": "Labels provide an easier way to categorize your conversation. Create some labels like #support-enquiry, #billing-question etc., so that you can use them in a conversation later.",
"NEW_LINK": "Click here to create tags"
},
"CANNED_RESPONSES": {
"TITLE": "Create canned responses",
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
"NEW_LINK": "Click here to create a canned response"
}
},
"CONVERSATION_SIDEBAR": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB