refactor: move component and routes to dashboard

This commit is contained in:
Shivam Mishra
2023-12-18 15:41:52 +05:30
parent cea740ceb7
commit 693cc29339
11 changed files with 25 additions and 25 deletions
@@ -1,88 +0,0 @@
<template>
<with-label
:label="label"
:name="name"
:has-error="hasError"
:error-message="errorMessage"
>
<template #label> {{ label }} <slot /> </template>
<input
:id="name"
:name="name"
:type="type"
autocomplete="off"
:required="required"
:placeholder="placeholder"
:data-testid="dataTestid"
:value="value"
:class="{
'focus:ring-red-600 ring-red-600': hasError,
'dark:ring-slate-600 dark:focus:ring-woot-500 ring-slate-200':
!hasError,
'px-3 py-3': spacing === 'base',
'px-3 py-2': spacing === 'compact',
}"
class="block w-full border-0 rounded-md shadow-sm outline-none appearance-none ring-1 ring-inset text-slate-900 dark:text-slate-100 placeholder:text-slate-400 focus:ring-2 focus:ring-inset focus:ring-woot-500 sm:text-sm sm:leading-6 dark:bg-slate-700"
@input="onInput"
@blur="$emit('blur')"
/>
</with-label>
</template>
<script>
import WithLabel from './WithLabel.vue';
export default {
components: {
WithLabel,
},
props: {
label: {
type: String,
default: '',
},
name: {
type: String,
required: true,
},
type: {
type: String,
default: 'text',
},
required: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '',
},
value: {
type: [String, Number],
default: '',
},
hasError: {
type: Boolean,
default: false,
},
errorMessage: {
type: String,
default: '',
},
dataTestid: {
type: String,
default: '',
},
spacing: {
type: String,
default: 'base',
validator: value => ['base', 'compact'].includes(value),
},
},
methods: {
onInput(e) {
this.$emit('input', e.target.value);
},
},
};
</script>
@@ -1,88 +0,0 @@
<template>
<with-label
:label="label"
:name="name"
:has-error="hasError"
:error-message="errorMessage"
>
<select
:id="id"
:selected="value"
:name="name"
:class="{
'text-slate-400': !value,
'text-slate-900 dark:text-slate-100': value,
}"
class="block w-full px-3 py-2 pr-6 border-0 rounded-md shadow-sm outline-none appearance-none select-caret ring-1 ring-inset placeholder:text-slate-400 focus:ring-2 focus:ring-inset focus:ring-woot-500 sm:text-sm sm:leading-6 dark:bg-slate-700 dark:ring-slate-600 dark:focus:ring-woot-500 ring-slate-200"
@input="onInput"
>
<option value="" disabled selected class="hidden">
{{ placeholder }}
</option>
<slot>
<option v-for="opt in options" :key="opt.value" :value="opt.value">
{{ opt.label }}
</option>
</slot>
</select>
</with-label>
</template>
<script>
import WithLabel from './WithLabel.vue';
export default {
components: {
WithLabel,
},
props: {
id: {
type: String,
default: '',
},
options: {
type: Array,
default: () => [],
},
placeholder: {
type: String,
default: '',
},
name: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
value: {
type: String,
default: '',
},
hasError: {
type: Boolean,
default: false,
},
errorMessage: {
type: String,
default: '',
},
},
methods: {
onInput(e) {
this.$emit('input', e.target.value);
},
},
};
</script>
<style scoped>
.select-caret {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='32' height='24' viewBox='0 0 32 24'><polygon points='0,0 32,0 16,24' style='fill: rgb%28110, 111, 115%29'></polygon></svg>");
background-origin: content-box;
background-position: right -1rem center;
background-repeat: no-repeat;
background-size: 9px 6px;
}
</style>
@@ -1,93 +0,0 @@
<template>
<with-label
:label="label"
:name="name"
:has-error="hasError"
:error-message="errorMessage"
>
<template #label> {{ label }} <slot /> </template>
<textarea
:id="name"
:name="name"
autocomplete="off"
:required="required"
:placeholder="placeholder"
:data-testid="dataTestid"
:value="value"
:rows="rows"
:class="{
'focus:ring-red-600 ring-red-600': hasError,
'dark:ring-slate-600 dark:focus:ring-woot-500 ring-slate-200':
!hasError,
'px-3 py-3': spacing === 'base',
'px-3 py-2': spacing === 'compact',
'resize-none': !allowResize,
}"
class="block w-full border-0 rounded-md shadow-sm outline-none appearance-none ring-1 ring-inset text-slate-900 dark:text-slate-100 placeholder:text-slate-400 focus:ring-2 focus:ring-inset focus:ring-woot-500 sm:text-sm sm:leading-6 dark:bg-slate-700"
@input="onInput"
@blur="$emit('blur')"
/>
</with-label>
</template>
<script>
import WithLabel from './WithLabel.vue';
export default {
components: {
WithLabel,
},
props: {
label: {
type: String,
default: '',
},
name: {
type: String,
required: true,
},
required: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '',
},
value: {
type: [String, Number],
default: '',
},
rows: {
type: Number,
default: 3,
},
allowResize: {
type: Boolean,
default: true,
},
hasError: {
type: Boolean,
default: false,
},
errorMessage: {
type: String,
default: '',
},
dataTestid: {
type: String,
default: '',
},
spacing: {
type: String,
default: 'base',
validator: value => ['base', 'compact'].includes(value),
},
},
methods: {
onInput(e) {
this.$emit('input', e.target.value);
},
},
};
</script>
@@ -1,45 +0,0 @@
<template>
<div>
<label
v-if="label"
:for="name"
class="flex justify-between text-sm font-medium leading-6 text-slate-900 dark:text-white"
:class="{ 'text-red-500': hasError }"
>
<slot name="label">
{{ label }}
</slot>
</label>
<div class="mt-1">
<slot />
<span
v-if="errorMessage && hasError"
class="text-xs text-red-400 leading-2"
>
{{ errorMessage }}
</span>
</div>
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
default: '',
},
name: {
type: String,
required: true,
},
hasError: {
type: Boolean,
default: false,
},
errorMessage: {
type: String,
default: '',
},
},
};
</script>
@@ -1,56 +0,0 @@
<template>
<modal-layout
:title="$t('ONBOARDING.FOUNDERS_NOTE.TITLE')"
current-step="founders-note"
>
<template #body>
<section class="mt-4 space-y-3 text-sm leading-relaxed">
<p>👋 Hey {{ user.name }},</p>
<p>
I'm Pranav, one of the co-founders at Chatwoot. Thanks for checking
out Chatwoot. We're eager to understand your needs and expectations.
</p>
<p>
If you are facing trouble using the app or achieving your use case, we
want to help you as quickly as possible.
</p>
<p>
Feel free to schedule a call with our team. We are open to your
feedback. Talk soon!
</p>
</section>
<figure class="mt-5 text-sm leading-relaxed">
<thumbnail
src="https://www.chatwoot.com/images/team/pranav.jpg"
username="Pranav"
/>
<p class="mt-2">Pranav, <br />Co-founder & CEO, Chatwoot</p>
</figure>
</template>
<submit-button
button-class="text-sm"
:button-text="$t('ONBOARDING.FOUNDERS_NOTE.SUBMIT')"
/>
</modal-layout>
</template>
<script>
import ModalLayout from './components/ModalLayout.vue';
import Thumbnail from '../../../../dashboard/components/widgets/Thumbnail.vue';
import SubmitButton from '../../../components/Button/SubmitButton';
export default {
components: {
ModalLayout,
Thumbnail,
SubmitButton,
},
data() {
return {
user: {
name: 'Shivam',
},
};
},
};
</script>
@@ -1,103 +0,0 @@
<template>
<modal-layout
:title="$t('ONBOARDING.COMPANY.TITLE')"
:body="$t('ONBOARDING.COMPANY.BODY')"
current-step="company"
>
<form class="space-y-8">
<div class="space-y-3">
<form-input
v-model="companyName"
name="companyName"
spacing="compact"
:label="$t('ONBOARDING.COMPANY.COMPANY_NAME.LABEL')"
:placeholder="$t('ONBOARDING.COMPANY.COMPANY_NAME.PLACEHOLDER')"
:error-message="$t('ONBOARDING.COMPANY.COMPANY_NAME.ERROR')"
/>
<form-input
v-model="industry"
name="industry"
spacing="compact"
:label="$t('ONBOARDING.COMPANY.INDUSTRY.LABEL')"
:placeholder="$t('ONBOARDING.COMPANY.INDUSTRY.PLACEHOLDER')"
/>
<form-input
v-model="timezone"
name="timezone"
spacing="compact"
:label="$t('ONBOARDING.COMPANY.TIMEZONE.LABEL')"
:placeholder="$t('ONBOARDING.COMPANY.TIMEZONE.PLACEHOLDER')"
/>
<form-select
v-model="locale"
name="locale"
:label="$t('ONBOARDING.COMPANY.LOCALE.LABEL')"
:placeholder="$t('ONBOARDING.COMPANY.LOCALE.PLACEHOLDER')"
>
<option
v-for="lang in languagesSortedByCode"
:key="lang.iso_639_1_code"
:value="lang.iso_639_1_code"
>
{{ lang.name }}
</option>
</form-select>
<form-select
v-model="companySize"
name="companySize"
:label="$t('ONBOARDING.COMPANY.SIZE.LABEL')"
:placeholder="$t('ONBOARDING.COMPANY.SIZE.PLACEHOLDER')"
:options="companySizeOptions"
/>
</div>
<submit-button
button-class="text-sm"
:button-text="$t('ONBOARDING.COMPANY.SUBMIT')"
/>
</form>
</modal-layout>
</template>
<script>
import FormInput from '../../../components/Form/Input.vue';
import FormSelect from '../../../components/Form/Select.vue';
import SubmitButton from '../../../components/Button/SubmitButton';
import ModalLayout from './components/ModalLayout.vue';
import configMixin from 'shared/mixins/configMixin';
export default {
components: {
FormInput,
SubmitButton,
ModalLayout,
FormSelect,
},
mixins: [configMixin],
data() {
return {
companyName: '',
timezone: '',
locale: '',
companySize: '',
industry: '',
companySizeOptions: [
{ value: '1-10', label: '1-10' },
{ value: '11-50', label: '11-50' },
{ value: '51-200', label: '51-200' },
{ value: '201-500', label: '201-500' },
{ value: '501-1000', label: '501-1000' },
{ value: '1001-5000', label: '1001-5000' },
{ value: '5001+', label: 'Over 5000' },
],
};
},
computed: {
languagesSortedByCode() {
const enabledLanguages = [...this.enabledLanguages];
return enabledLanguages.sort((l1, l2) =>
l1.iso_639_1_code.localeCompare(l2.iso_639_1_code)
);
},
},
};
</script>
@@ -1,70 +0,0 @@
<template>
<modal-layout
:title="$t('ONBOARDING.PROFILE.TITLE')"
:body="$t('ONBOARDING.PROFILE.BODY')"
current-step="profile"
>
<form class="mt-8 space-y-8">
<div class="space-y-3">
<form-input
v-model="fullName"
name="full_name"
spacing="compact"
:label="$t('ONBOARDING.PROFILE.FULL_NAME.LABEL')"
:placeholder="$t('ONBOARDING.PROFILE.FULL_NAME.PLACEHOLDER')"
:error-message="$t('ONBOARDING.PROFILE.FULL_NAME.ERROR')"
/>
<form-input
v-model="displayName"
name="display_name"
spacing="compact"
:label="$t('ONBOARDING.PROFILE.DISPLAY_NAME.LABEL')"
:placeholder="$t('ONBOARDING.PROFILE.DISPLAY_NAME.PLACEHOLDER')"
/>
<form-input
v-model="phoneNumber"
name="phone_number"
spacing="compact"
:label="$t('ONBOARDING.PROFILE.PHONE_NUMBER.LABEL')"
:placeholder="$t('ONBOARDING.PROFILE.PHONE_NUMBER.PLACEHOLDER')"
/>
<form-text-area
v-model="signature"
name="signature"
spacing="compact"
:allow-resize="false"
:label="$t('ONBOARDING.PROFILE.SIGNATURE.LABEL')"
:placeholder="$t('ONBOARDING.PROFILE.SIGNATURE.PLACEHOLDER')"
/>
</div>
<submit-button
button-class="text-sm"
:button-text="$t('ONBOARDING.PROFILE.SUBMIT')"
/>
</form>
</modal-layout>
</template>
<script>
import FormInput from '../../../components/Form/Input.vue';
import FormTextArea from '../../../components/Form/TextArea.vue';
import SubmitButton from '../../../components/Button/SubmitButton';
import ModalLayout from './components/ModalLayout.vue';
export default {
components: {
FormInput,
SubmitButton,
ModalLayout,
FormTextArea,
},
data() {
return {
fullName: '',
displayName: '',
phoneNumber: '',
signature: '',
};
},
};
</script>
@@ -1,116 +0,0 @@
<template>
<section
class="relative h-screen px-8 py-20 dark:text-white bg-woot-25 dark:bg-slate-900"
>
<img
id="bg-grad"
src="/onboarding/bg-gradient.png"
class="absolute inset-0 w-full opacity-50 dark:mix-blend-color"
/>
<div class="relative max-w-lg mx-auto">
<div
id="steps"
class="rounded-md w-48 -left-52 dark:shadow-[#000] p-1 border shadow-sm border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 absolute grid gap-1"
>
<h6
class="px-2 pt-1 font-bold tracking-widest uppercase text-xxs text-slate-500"
>
Get Started
</h6>
<modal-step
v-for="(step, index) in steps"
:key="step.name"
v-bind="step"
:step-number="index + 1"
/>
</div>
<div
id="modal-body"
class="dark:shadow-[#000] rounded-md mx-auto p-9 border shadow border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900"
>
<h2 class="text-lg font-bold tracking-tight">
<slot name="title">
{{ title }}
</slot>
</h2>
<slot name="body">
<p class="mt-2 text-sm dark:text-slate-200">
{{ body }}
</p>
</slot>
<div class="mt-8">
<slot />
</div>
</div>
</div>
</section>
</template>
<script>
import ModalStep from './ModalStep.vue';
const UISteps = [
{
name: 'profile',
title: 'Setup Profile',
isActive: false,
isComplete: false,
},
{
name: 'company',
title: 'Setup Company',
isActive: false,
isComplete: false,
},
{
name: 'invite',
title: 'Invite your team',
isActive: false,
isComplete: false,
},
{
name: 'founders-note',
title: "Founder's Note",
hidden: true,
isActive: false,
isComplete: false,
},
];
export default {
components: {
ModalStep,
},
props: {
title: {
type: String,
default: '',
},
body: {
type: String,
default: '',
},
currentStep: {
type: String,
required: true,
},
},
computed: {
steps() {
let foundCurrentStep = false;
return UISteps.map(step => {
if (step.name === this.currentStep) {
foundCurrentStep = true;
}
return {
...step,
isActive: step.name === this.currentStep,
isComplete: !foundCurrentStep,
};
});
},
},
};
</script>
@@ -1,65 +0,0 @@
<template>
<div
v-if="!hidden"
class="flex items-center gap-2 p-2 text-sm rounded"
:class="{
'text-slate-800 dark:text-slate-100 bg-slate-50 dark:bg-slate-800':
isActive,
'opacity-50': !isActive && !isComplete,
hidden: hidden,
}"
>
<div
class="grid w-4 h-4 font-bold rounded-full text-xxs place-content-center"
:class="{
'bg-slate-200 dark:bg-slate-600': !isComplete,
'bg-green-500': isComplete,
}"
>
<fluent-icon
v-if="isComplete"
size="13"
class="text-white"
icon="checkmark"
/>
<template v-else>
{{ stepNumber }}
</template>
</div>
<span
:class="{
'line-through': isComplete,
}"
>
{{ title }}
</span>
</div>
</template>
<script>
export default {
name: 'ModalStep',
props: {
title: {
type: String,
required: true,
},
stepNumber: {
type: Number,
required: true,
},
isActive: {
type: Boolean,
default: false,
},
hidden: {
type: Boolean,
default: false,
},
isComplete: {
type: Boolean,
default: false,
},
},
};
</script>
-18
View File
@@ -5,9 +5,6 @@ const Signup = () => import('./auth/signup/Index.vue');
const ResetPassword = () => import('./auth/reset/password/Index.vue');
const Confirmation = () => import('./auth/confirmation/Index.vue');
const PasswordEdit = () => import('./auth/password/Edit.vue');
const SetupProfile = () => import('./auth/start/SetupProfile.vue');
const SetupCompany = () => import('./auth/start/SetupCompany.vue');
const FounderNote = () => import('./auth/start/FounderNote.vue');
export default [
{
@@ -56,19 +53,4 @@ export default [
name: 'auth_reset_password',
component: ResetPassword,
},
{
path: frontendURL('start/setup-profile'),
name: 'onboarding_setup_profile',
component: SetupProfile,
},
{
path: frontendURL('start/setup-company'),
name: 'onboarding_setup_company',
component: SetupCompany,
},
{
path: frontendURL('start/founders-note'),
name: 'onboarding_founders_note',
component: FounderNote,
},
];