feat: Update Signup screen (#6002)
* feat: Update Signup page designs * feat: Update the signup page with dynamic testimonials * Remove the images * chore: Minor UI fixes * chore: Form aligned to centre * Update app/javascript/dashboard/routes/auth/components/Signup/Form.vue * Design improvements * Update company name key * Revert "chore: Minor UI fixes" This reverts commit 1556f4ca835d9aa0d9620fd6a3d52d259f0d7d65. * Revert "Design improvements This reverts commit dfb2364cf2f0cc93123698fde92e5f9e00536cc2. * Remove footer * Fix spacing * Update app/views/installation/onboarding/index.html.erb Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
This commit is contained in:
parent
6064aad38f
commit
779bcf5e0d
17 changed files with 840 additions and 261 deletions
6
app/javascript/dashboard/api/testimonials.js
Normal file
6
app/javascript/dashboard/api/testimonials.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* global axios */
|
||||
import wootConstants from 'dashboard/constants';
|
||||
|
||||
export const getTestimonialContent = () => {
|
||||
return axios.get(wootConstants.TESTIMONIAL_URL);
|
||||
};
|
|
@ -22,5 +22,6 @@ export default {
|
|||
EXPANDED: 'expanded',
|
||||
},
|
||||
DOCS_URL: '//www.chatwoot.com/docs/product/',
|
||||
TESTIMONIAL_URL: 'https://testimonials.cdn.chatwoot.com/content.json',
|
||||
};
|
||||
export const DEFAULT_REDIRECT_URL = '/app/';
|
||||
|
|
|
@ -99,11 +99,7 @@
|
|||
},
|
||||
"AVAILABILITY": {
|
||||
"LABEL": "Availability",
|
||||
"STATUSES_LIST": [
|
||||
"Online",
|
||||
"Busy",
|
||||
"Offline"
|
||||
]
|
||||
"STATUSES_LIST": ["Online", "Busy", "Offline"]
|
||||
},
|
||||
"EMAIL": {
|
||||
"LABEL": "Your email address",
|
||||
|
@ -257,7 +253,7 @@
|
|||
},
|
||||
"FORM": {
|
||||
"NAME": {
|
||||
"LABEL": "Account Name",
|
||||
"LABEL": "Company Name",
|
||||
"PLACEHOLDER": "Wayne Enterprises"
|
||||
},
|
||||
"SUBMIT": "Submit"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"REGISTER": {
|
||||
"TRY_WOOT": "Register an account",
|
||||
"TITLE": "Register",
|
||||
"TESTIMONIAL_HEADER": "All it takes is one step to move forward",
|
||||
"TESTIMONIAL_CONTENT": "You're one step away from engaging your customers, retaining them and finding new ones.",
|
||||
"TERMS_ACCEPT": "By signing up, you agree to our <a href=\"https://www.chatwoot.com/terms\">T & C</a> and <a href=\"https://www.chatwoot.com/privacy-policy\">Privacy policy</a>",
|
||||
"COMPANY_NAME": {
|
||||
"LABEL": "Company name",
|
||||
|
|
|
@ -1,283 +1,133 @@
|
|||
<template>
|
||||
<div class="medium-10 column signup">
|
||||
<div class="text-center medium-12 signup--hero">
|
||||
<img
|
||||
:src="globalConfig.logo"
|
||||
:alt="globalConfig.installationName"
|
||||
class="hero--logo"
|
||||
/>
|
||||
<h2 class="hero--title">
|
||||
{{ $t('REGISTER.TRY_WOOT') }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row align-center">
|
||||
<div class="small-12 medium-6 large-5 column">
|
||||
<form class="signup--box login-box" @submit.prevent="submit">
|
||||
<woot-input
|
||||
v-model="credentials.fullName"
|
||||
:class="{ error: $v.credentials.fullName.$error }"
|
||||
:label="$t('REGISTER.FULL_NAME.LABEL')"
|
||||
:placeholder="$t('REGISTER.FULL_NAME.PLACEHOLDER')"
|
||||
:error="
|
||||
$v.credentials.fullName.$error
|
||||
? $t('REGISTER.FULL_NAME.ERROR')
|
||||
: ''
|
||||
"
|
||||
@blur="$v.credentials.fullName.$touch"
|
||||
/>
|
||||
<woot-input
|
||||
v-model.trim="credentials.email"
|
||||
type="email"
|
||||
:class="{ error: $v.credentials.email.$error }"
|
||||
:label="$t('REGISTER.EMAIL.LABEL')"
|
||||
:placeholder="$t('REGISTER.EMAIL.PLACEHOLDER')"
|
||||
:error="
|
||||
$v.credentials.email.$error ? $t('REGISTER.EMAIL.ERROR') : ''
|
||||
"
|
||||
@blur="$v.credentials.email.$touch"
|
||||
/>
|
||||
<woot-input
|
||||
v-model="credentials.accountName"
|
||||
:class="{ error: $v.credentials.accountName.$error }"
|
||||
:label="$t('REGISTER.COMPANY_NAME.LABEL')"
|
||||
:placeholder="$t('REGISTER.COMPANY_NAME.PLACEHOLDER')"
|
||||
:error="
|
||||
$v.credentials.accountName.$error
|
||||
? $t('REGISTER.COMPANY_NAME.ERROR')
|
||||
: ''
|
||||
"
|
||||
@blur="$v.credentials.accountName.$touch"
|
||||
/>
|
||||
<woot-input
|
||||
v-model.trim="credentials.password"
|
||||
type="password"
|
||||
:class="{ error: $v.credentials.password.$error }"
|
||||
:label="$t('LOGIN.PASSWORD.LABEL')"
|
||||
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
||||
:error="passwordErrorText"
|
||||
@blur="$v.credentials.password.$touch"
|
||||
/>
|
||||
<div v-if="globalConfig.hCaptchaSiteKey" class="h-captcha--box">
|
||||
<vue-hcaptcha
|
||||
ref="hCaptcha"
|
||||
:class="{ error: !hasAValidCaptcha && didCaptchaReset }"
|
||||
:sitekey="globalConfig.hCaptchaSiteKey"
|
||||
@verify="onRecaptchaVerified"
|
||||
<div class="h-full w-full">
|
||||
<div v-show="!isLoading" class="row h-full">
|
||||
<div
|
||||
:class="
|
||||
`${showTestimonials ? 'large-6' : 'large-12'} signup-form--container`
|
||||
"
|
||||
>
|
||||
<div class="signup-form--content">
|
||||
<div class="signup--hero">
|
||||
<img
|
||||
:src="globalConfig.logo"
|
||||
:alt="globalConfig.installationName"
|
||||
class="hero--logo"
|
||||
/>
|
||||
<span
|
||||
v-if="!hasAValidCaptcha && didCaptchaReset"
|
||||
class="captcha-error"
|
||||
>
|
||||
{{ $t('SET_NEW_PASSWORD.CAPTCHA.ERROR') }}
|
||||
</span>
|
||||
<h2 class="hero--title">
|
||||
{{ $t('REGISTER.TRY_WOOT') }}
|
||||
</h2>
|
||||
</div>
|
||||
<signup-form />
|
||||
<div class="auth-screen--footer">
|
||||
<span>{{ $t('REGISTER.HAVE_AN_ACCOUNT') }}</span>
|
||||
<router-link to="/app/login">
|
||||
{{
|
||||
useInstallationName(
|
||||
$t('LOGIN.TITLE'),
|
||||
globalConfig.installationName
|
||||
)
|
||||
}}
|
||||
</router-link>
|
||||
</div>
|
||||
<woot-submit-button
|
||||
:disabled="isSignupInProgress || !hasAValidCaptcha"
|
||||
:button-text="$t('REGISTER.SUBMIT')"
|
||||
:loading="isSignupInProgress"
|
||||
button-class="large expanded"
|
||||
/>
|
||||
<p v-dompurify-html="termsLink" class="accept--terms" />
|
||||
</form>
|
||||
<div class="column text-center sigin--footer">
|
||||
<span>{{ $t('REGISTER.HAVE_AN_ACCOUNT') }}</span>
|
||||
<router-link to="/app/login">
|
||||
{{
|
||||
useInstallationName(
|
||||
$t('LOGIN.TITLE'),
|
||||
globalConfig.installationName
|
||||
)
|
||||
}}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<testimonials
|
||||
v-if="isAChatwootInstance"
|
||||
class="medium-6 testimonial--container"
|
||||
@resize-containers="resizeContainers"
|
||||
/>
|
||||
</div>
|
||||
<div v-show="isLoading" class="spinner--container">
|
||||
<spinner size="" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||
import Auth from '../../api/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { DEFAULT_REDIRECT_URL } from '../../constants';
|
||||
import VueHcaptcha from '@hcaptcha/vue-hcaptcha';
|
||||
import { isValidPassword } from 'shared/helpers/Validators';
|
||||
|
||||
const CompanyEmailValidator = require('company-email-validator');
|
||||
import SignupForm from './components/Signup/Form.vue';
|
||||
import Testimonials from './components/Testimonials/Index.vue';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VueHcaptcha,
|
||||
SignupForm,
|
||||
Spinner,
|
||||
Testimonials,
|
||||
},
|
||||
mixins: [globalConfigMixin, alertMixin],
|
||||
mixins: [globalConfigMixin],
|
||||
data() {
|
||||
return {
|
||||
credentials: {
|
||||
accountName: '',
|
||||
fullName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
hCaptchaClientResponse: '',
|
||||
},
|
||||
didCaptchaReset: false,
|
||||
isSignupInProgress: false,
|
||||
error: '',
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
credentials: {
|
||||
accountName: {
|
||||
required,
|
||||
minLength: minLength(2),
|
||||
},
|
||||
fullName: {
|
||||
required,
|
||||
minLength: minLength(2),
|
||||
},
|
||||
email: {
|
||||
required,
|
||||
email,
|
||||
businessEmailValidator(value) {
|
||||
return CompanyEmailValidator.isCompanyEmail(value);
|
||||
},
|
||||
},
|
||||
password: {
|
||||
required,
|
||||
isValidPassword,
|
||||
minLength: minLength(6),
|
||||
},
|
||||
},
|
||||
return { showTestimonials: false, isLoading: false };
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({ globalConfig: 'globalConfig/get' }),
|
||||
termsLink() {
|
||||
return this.$t('REGISTER.TERMS_ACCEPT')
|
||||
.replace('https://www.chatwoot.com/terms', this.globalConfig.termsURL)
|
||||
.replace(
|
||||
'https://www.chatwoot.com/privacy-policy',
|
||||
this.globalConfig.privacyURL
|
||||
);
|
||||
},
|
||||
hasAValidCaptcha() {
|
||||
if (this.globalConfig.hCaptchaSiteKey) {
|
||||
return !!this.credentials.hCaptchaClientResponse;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
passwordErrorText() {
|
||||
const { password } = this.$v.credentials;
|
||||
if (!password.$error) {
|
||||
return '';
|
||||
}
|
||||
if (!password.minLength) {
|
||||
return this.$t('REGISTER.PASSWORD.ERROR');
|
||||
}
|
||||
if (!password.isValidPassword) {
|
||||
return this.$t('REGISTER.PASSWORD.IS_INVALID_PASSWORD');
|
||||
}
|
||||
return '';
|
||||
isAChatwootInstance() {
|
||||
return this.globalConfig.installationName === 'Chatwoot';
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
this.isLoading = this.isAChatwootInstance;
|
||||
},
|
||||
methods: {
|
||||
async submit() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
this.resetCaptcha();
|
||||
return;
|
||||
}
|
||||
this.isSignupInProgress = true;
|
||||
try {
|
||||
const response = await Auth.register(this.credentials);
|
||||
if (response.status === 200) {
|
||||
window.location = DEFAULT_REDIRECT_URL;
|
||||
}
|
||||
} catch (error) {
|
||||
let errorMessage = this.$t('REGISTER.API.ERROR_MESSAGE');
|
||||
if (error.response && error.response.data.message) {
|
||||
this.resetCaptcha();
|
||||
errorMessage = error.response.data.message;
|
||||
}
|
||||
this.showAlert(errorMessage);
|
||||
} finally {
|
||||
this.isSignupInProgress = false;
|
||||
}
|
||||
},
|
||||
onRecaptchaVerified(token) {
|
||||
this.credentials.hCaptchaClientResponse = token;
|
||||
this.didCaptchaReset = false;
|
||||
},
|
||||
resetCaptcha() {
|
||||
if (!this.globalConfig.hCaptchaSiteKey) {
|
||||
return;
|
||||
}
|
||||
this.$refs.hCaptcha.reset();
|
||||
this.credentials.hCaptchaClientResponse = '';
|
||||
this.didCaptchaReset = true;
|
||||
resizeContainers(hasTestimonials) {
|
||||
this.showTestimonials = hasTestimonials;
|
||||
this.isLoading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.signup {
|
||||
.signup--hero {
|
||||
margin-bottom: var(--space-larger);
|
||||
.signup-form--container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
min-height: 640px;
|
||||
overflow: auto;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.hero--logo {
|
||||
width: 180px;
|
||||
}
|
||||
.signup-form--content {
|
||||
padding: var(--space-jumbo);
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hero--title {
|
||||
margin-top: var(--space-large);
|
||||
font-weight: var(--font-weight-light);
|
||||
}
|
||||
.signup--hero {
|
||||
margin-bottom: var(--space-normal);
|
||||
|
||||
.hero--logo {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.signup--box {
|
||||
padding: var(--space-large);
|
||||
|
||||
label {
|
||||
font-size: var(--font-size-default);
|
||||
color: var(--b-600);
|
||||
|
||||
input {
|
||||
padding: var(--space-slab);
|
||||
height: var(--space-larger);
|
||||
font-size: var(--font-size-default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sigin--footer {
|
||||
padding: var(--space-medium);
|
||||
font-size: var(--font-size-default);
|
||||
|
||||
> a {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
}
|
||||
|
||||
.accept--terms {
|
||||
font-size: var(--font-size-small);
|
||||
text-align: center;
|
||||
margin: var(--space-normal) 0 0 0;
|
||||
}
|
||||
|
||||
.h-captcha--box {
|
||||
margin-bottom: var(--space-one);
|
||||
|
||||
.captcha-error {
|
||||
color: var(--r-400);
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
&::v-deep .error {
|
||||
iframe {
|
||||
border: 1px solid var(--r-500);
|
||||
border-radius: var(--border-radius-normal);
|
||||
}
|
||||
}
|
||||
.hero--title {
|
||||
margin-top: var(--space-medium);
|
||||
font-weight: var(--font-weight-light);
|
||||
}
|
||||
}
|
||||
|
||||
.auth-screen--footer {
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.testimonial--container {
|
||||
display: none;
|
||||
}
|
||||
.signup-form--container {
|
||||
width: 100%;
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.signup-form--content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.spinner--container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,6 +8,12 @@ const Signup = () => import('./Signup');
|
|||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('auth/signup'),
|
||||
name: 'auth_signup',
|
||||
component: Signup,
|
||||
meta: { requireSignupEnabled: true },
|
||||
},
|
||||
{
|
||||
path: frontendURL('auth'),
|
||||
name: 'auth',
|
||||
|
@ -33,12 +39,6 @@ export default {
|
|||
redirectUrl: route.query.route_url,
|
||||
}),
|
||||
},
|
||||
{
|
||||
path: 'signup',
|
||||
name: 'auth_signup',
|
||||
component: Signup,
|
||||
meta: { requireSignupEnabled: true },
|
||||
},
|
||||
{
|
||||
path: 'reset/password',
|
||||
name: 'auth_reset_password',
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<label class="auth-input--wrap">
|
||||
<div class="label-wrap">
|
||||
<fluent-icon v-if="iconName" :icon="iconName" size="16" />
|
||||
<span v-if="label">{{ label }}</span>
|
||||
</div>
|
||||
<div class="input--wrap">
|
||||
<input
|
||||
class="auth-input"
|
||||
:value="value"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
:readonly="readonly"
|
||||
@input="onChange"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
<p v-if="helpText" class="help-text" />
|
||||
<span v-if="error" class="message">
|
||||
{{ error }}
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
helpText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
error: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onChange(e) {
|
||||
this.$emit('input', e.target.value);
|
||||
},
|
||||
onBlur(e) {
|
||||
this.$emit('blur', e.target.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.auth-input--wrap {
|
||||
.label-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--s-900);
|
||||
margin-bottom: var(--space-smaller);
|
||||
|
||||
span {
|
||||
margin-left: var(--space-smaller);
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
}
|
||||
|
||||
.auth-input {
|
||||
font-size: var(--font-size-small) !important;
|
||||
height: 4rem !important;
|
||||
padding: var(--space-small) !important;
|
||||
width: 100% !important;
|
||||
background: var(--s-50) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<woot-button
|
||||
size="expanded"
|
||||
color-scheme="primary"
|
||||
class-names="submit--button"
|
||||
:is-disabled="isDisabled"
|
||||
:is-loading="isLoading"
|
||||
@click="onClick"
|
||||
>
|
||||
{{ label }}
|
||||
<fluent-icon :icon="icon" size="18" />
|
||||
</woot-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.submit--button {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin: 0 0 var(--space-normal) 0;
|
||||
|
||||
&::v-deep .button__content {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
218
app/javascript/dashboard/routes/auth/components/Signup/Form.vue
Normal file
218
app/javascript/dashboard/routes/auth/components/Signup/Form.vue
Normal file
|
@ -0,0 +1,218 @@
|
|||
<template>
|
||||
<form @submit.prevent="submit">
|
||||
<div class="input-wrap">
|
||||
<auth-input
|
||||
v-model="credentials.fullName"
|
||||
:class="{ error: $v.credentials.fullName.$error }"
|
||||
:label="$t('REGISTER.FULL_NAME.LABEL')"
|
||||
icon-name="person"
|
||||
:placeholder="$t('REGISTER.FULL_NAME.PLACEHOLDER')"
|
||||
:error="
|
||||
$v.credentials.fullName.$error ? $t('REGISTER.FULL_NAME.ERROR') : ''
|
||||
"
|
||||
@blur="$v.credentials.fullName.$touch"
|
||||
/>
|
||||
<auth-input
|
||||
v-model.trim="credentials.email"
|
||||
type="email"
|
||||
:class="{ error: $v.credentials.email.$error }"
|
||||
icon-name="mail"
|
||||
:label="$t('REGISTER.EMAIL.LABEL')"
|
||||
:placeholder="$t('REGISTER.EMAIL.PLACEHOLDER')"
|
||||
:error="$v.credentials.email.$error ? $t('REGISTER.EMAIL.ERROR') : ''"
|
||||
@blur="$v.credentials.email.$touch"
|
||||
/>
|
||||
<auth-input
|
||||
v-model="credentials.accountName"
|
||||
:class="{ error: $v.credentials.accountName.$error }"
|
||||
icon-name="building-bank"
|
||||
:label="$t('REGISTER.COMPANY_NAME.LABEL')"
|
||||
:placeholder="$t('REGISTER.COMPANY_NAME.PLACEHOLDER')"
|
||||
:error="
|
||||
$v.credentials.accountName.$error
|
||||
? $t('REGISTER.COMPANY_NAME.ERROR')
|
||||
: ''
|
||||
"
|
||||
@blur="$v.credentials.accountName.$touch"
|
||||
/>
|
||||
<auth-input
|
||||
v-model.trim="credentials.password"
|
||||
type="password"
|
||||
:class="{ error: $v.credentials.password.$error }"
|
||||
icon-name="lock-closed"
|
||||
:label="$t('LOGIN.PASSWORD.LABEL')"
|
||||
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
||||
:error="passwordErrorText"
|
||||
@blur="$v.credentials.password.$touch"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="globalConfig.hCaptchaSiteKey" class="h-captcha--box">
|
||||
<vue-hcaptcha
|
||||
ref="hCaptcha"
|
||||
:class="{ error: !hasAValidCaptcha && didCaptchaReset }"
|
||||
:sitekey="globalConfig.hCaptchaSiteKey"
|
||||
@verify="onRecaptchaVerified"
|
||||
/>
|
||||
<span v-if="!hasAValidCaptcha && didCaptchaReset" class="captcha-error">
|
||||
{{ $t('SET_NEW_PASSWORD.CAPTCHA.ERROR') }}
|
||||
</span>
|
||||
</div>
|
||||
<auth-submit-button
|
||||
:label="$t('REGISTER.SUBMIT')"
|
||||
:is-disabled="isSignupInProgress || !hasAValidCaptcha"
|
||||
:is-loading="isSignupInProgress"
|
||||
icon="arrow-chevron-right"
|
||||
@click="submit"
|
||||
/>
|
||||
<p v-dompurify-html="termsLink" class="accept--terms" />
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||
import Auth from '../../../../api/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { DEFAULT_REDIRECT_URL } from '../../../../constants';
|
||||
import VueHcaptcha from '@hcaptcha/vue-hcaptcha';
|
||||
import AuthInput from '../AuthInput.vue';
|
||||
import AuthSubmitButton from '../AuthSubmitButton.vue';
|
||||
import { isValidPassword } from 'shared/helpers/Validators';
|
||||
var CompanyEmailValidator = require('company-email-validator');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AuthInput,
|
||||
AuthSubmitButton,
|
||||
VueHcaptcha,
|
||||
},
|
||||
mixins: [globalConfigMixin, alertMixin],
|
||||
data() {
|
||||
return {
|
||||
credentials: {
|
||||
accountName: '',
|
||||
fullName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
hCaptchaClientResponse: '',
|
||||
},
|
||||
didCaptchaReset: false,
|
||||
isSignupInProgress: false,
|
||||
error: '',
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
credentials: {
|
||||
accountName: {
|
||||
required,
|
||||
minLength: minLength(2),
|
||||
},
|
||||
fullName: {
|
||||
required,
|
||||
minLength: minLength(2),
|
||||
},
|
||||
email: {
|
||||
required,
|
||||
email,
|
||||
businessEmailValidator(value) {
|
||||
return CompanyEmailValidator.isCompanyEmail(value);
|
||||
},
|
||||
},
|
||||
password: {
|
||||
required,
|
||||
isValidPassword,
|
||||
minLength: minLength(6),
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({ globalConfig: 'globalConfig/get' }),
|
||||
termsLink() {
|
||||
return this.$t('REGISTER.TERMS_ACCEPT')
|
||||
.replace('https://www.chatwoot.com/terms', this.globalConfig.termsURL)
|
||||
.replace(
|
||||
'https://www.chatwoot.com/privacy-policy',
|
||||
this.globalConfig.privacyURL
|
||||
);
|
||||
},
|
||||
hasAValidCaptcha() {
|
||||
if (this.globalConfig.hCaptchaSiteKey) {
|
||||
return !!this.credentials.hCaptchaClientResponse;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
passwordErrorText() {
|
||||
const { password } = this.$v.credentials;
|
||||
if (!password.$error) {
|
||||
return '';
|
||||
}
|
||||
if (!password.minLength) {
|
||||
return this.$t('REGISTER.PASSWORD.ERROR');
|
||||
}
|
||||
if (!password.isValidPassword) {
|
||||
return this.$t('REGISTER.PASSWORD.IS_INVALID_PASSWORD');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async submit() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
this.resetCaptcha();
|
||||
return;
|
||||
}
|
||||
this.isSignupInProgress = true;
|
||||
try {
|
||||
const response = await Auth.register(this.credentials);
|
||||
if (response.status === 200) {
|
||||
window.location = DEFAULT_REDIRECT_URL;
|
||||
}
|
||||
} catch (error) {
|
||||
let errorMessage = this.$t('REGISTER.API.ERROR_MESSAGE');
|
||||
if (error.response && error.response.data.message) {
|
||||
this.resetCaptcha();
|
||||
errorMessage = error.response.data.message;
|
||||
}
|
||||
this.showAlert(errorMessage);
|
||||
} finally {
|
||||
this.isSignupInProgress = false;
|
||||
}
|
||||
},
|
||||
onRecaptchaVerified(token) {
|
||||
this.credentials.hCaptchaClientResponse = token;
|
||||
this.didCaptchaReset = false;
|
||||
},
|
||||
resetCaptcha() {
|
||||
if (!this.globalConfig.hCaptchaSiteKey) {
|
||||
return;
|
||||
}
|
||||
this.$refs.hCaptcha.reset();
|
||||
this.credentials.hCaptchaClientResponse = '';
|
||||
this.didCaptchaReset = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.h-captcha--box {
|
||||
margin-bottom: var(--space-small);
|
||||
|
||||
.captcha-error {
|
||||
color: var(--r-400);
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
&::v-deep .error {
|
||||
iframe {
|
||||
border: 1px solid var(--r-500);
|
||||
border-radius: var(--border-radius-normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accept--terms {
|
||||
margin: var(--space-normal) 0 var(--space-smaller) 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,119 @@
|
|||
<template>
|
||||
<div v-if="testimonials.length" class="testimonial--section">
|
||||
<img src="/assets/images/auth/top-left.svg" class="top-left--img" />
|
||||
<img src="/assets/images/auth/bottom-right.svg" class="bottom-right--img" />
|
||||
<img src="/assets/images/auth/auth--bg.svg" class="center--img" />
|
||||
<div class="testimonial--content">
|
||||
<div class="testimonial--content-card">
|
||||
<testimonial-card
|
||||
v-for="(testimonial, index) in testimonials"
|
||||
:key="testimonial.id"
|
||||
:review-content="testimonial.authorReview"
|
||||
:author-image="testimonial.authorImage"
|
||||
:author-name="testimonial.authorName"
|
||||
:author-designation="testimonial.authorCompany"
|
||||
:class="`testimonial-${index ? 'right' : 'left'}--card`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TestimonialCard from './TestimonialCard.vue';
|
||||
import { getTestimonialContent } from 'dashboard/api/testimonials';
|
||||
export default {
|
||||
components: {
|
||||
TestimonialCard,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
testimonials: [],
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.fetchTestimonials();
|
||||
},
|
||||
methods: {
|
||||
async fetchTestimonials() {
|
||||
try {
|
||||
const { data } = await getTestimonialContent();
|
||||
this.testimonials = data;
|
||||
} catch (error) {
|
||||
// Ignoring the error as the UI wouldn't break
|
||||
} finally {
|
||||
this.$emit('resize-containers', !!this.testimonials.length);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~dashboard/assets/scss/woot';
|
||||
|
||||
.top-left--img {
|
||||
left: 0;
|
||||
height: 16rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 16rem;
|
||||
}
|
||||
|
||||
.bottom-right--img {
|
||||
bottom: 0;
|
||||
height: 16rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 16rem;
|
||||
}
|
||||
|
||||
.center--img {
|
||||
left: 5%;
|
||||
max-height: 86%;
|
||||
max-width: 90%;
|
||||
position: absolute;
|
||||
top: 2%;
|
||||
}
|
||||
|
||||
.center-container {
|
||||
padding: var(--space-medium) 0;
|
||||
}
|
||||
|
||||
.testimonial--section {
|
||||
background: var(--w-400);
|
||||
display: flex;
|
||||
flex: 1 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.testimonial--content {
|
||||
align-content: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.testimonial--content-card {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: var(--space-larger);
|
||||
}
|
||||
|
||||
.testimonial-left--card {
|
||||
--signup-testimonial-top: 20%;
|
||||
margin-top: var(--signup-testimonial-top);
|
||||
margin-right: var(--space-minus-normal);
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.testimonial--section {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<div class="testimonial-card">
|
||||
<div class="left-card--wrap absolute">
|
||||
<div class="left-card--content">
|
||||
<p class="card-content">
|
||||
{{ reviewContent }}
|
||||
</p>
|
||||
<div class="content-author--details row">
|
||||
<div class="author-image--wrap">
|
||||
<img :src="authorImage" class="author-image" />
|
||||
</div>
|
||||
<div class="author-name-company--details">
|
||||
<div class="author-name">{{ authorName }}</div>
|
||||
<div class="author-company">{{ authorDesignation }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
reviewContent: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
authorImage: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
authorName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
authorDesignation: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.testimonial-card {
|
||||
align-items: center;
|
||||
background: var(--white);
|
||||
border-radius: var(--border-radius-normal);
|
||||
box-shadow: var(--shadow-large);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: var(--space-medium) var(--space-large);
|
||||
width: 32rem;
|
||||
}
|
||||
|
||||
.content-author--details {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: var(--space-small);
|
||||
|
||||
.author-image--wrap {
|
||||
background: white;
|
||||
border-radius: var(--border-radius-rounded);
|
||||
padding: var(--space-smaller);
|
||||
|
||||
.author-image {
|
||||
border-radius: var(--border-radius-rounded);
|
||||
height: calc(var(--space-two) + var(--space-two));
|
||||
width: calc(var(--space-two) + var(--space-two));
|
||||
}
|
||||
}
|
||||
|
||||
.author-name-company--details {
|
||||
margin-left: var(--space-small);
|
||||
|
||||
.author-name {
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
.author-company {
|
||||
font-size: var(--font-size-mini);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
color: var(--s-600);
|
||||
// font-size: var(--font-size-default);
|
||||
line-height: 1.7;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div class="testimonial--footer">
|
||||
<h2 class="heading">
|
||||
{{ title }}
|
||||
</h2>
|
||||
<span class="sub-block-title sub-heading">
|
||||
{{ subTitle }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.testimonial--footer {
|
||||
align-items: center;
|
||||
bottom: var(--space-jumbo);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--space-jumbo);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
.heading {
|
||||
color: var(--white);
|
||||
font-size: var(--font-size-bigger);
|
||||
}
|
||||
|
||||
.sub-heading {
|
||||
color: var(--white);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -94,6 +94,7 @@
|
|||
"list-outline": "M2.75 18h12.5a.75.75 0 0 1 .102 1.493l-.102.007H2.75a.75.75 0 0 1-.102-1.494L2.75 18h12.5-12.5Zm0-6.5h18.5a.75.75 0 0 1 .102 1.493L21.25 13H2.75a.75.75 0 0 1-.102-1.493l.102-.007h18.5-18.5Zm0-6.497h15.5a.75.75 0 0 1 .102 1.493l-.102.007H2.75a.75.75 0 0 1-.102-1.493l.102-.007h15.5-15.5Z",
|
||||
"location-outline": "M5.843 4.568a8.707 8.707 0 1 1 12.314 12.314l-1.187 1.174c-.875.858-2.01 1.962-3.406 3.312a2.25 2.25 0 0 1-3.128 0l-3.491-3.396c-.439-.431-.806-.794-1.102-1.09a8.707 8.707 0 0 1 0-12.314Zm11.253 1.06A7.207 7.207 0 1 0 6.904 15.822L8.39 17.29a753.98 753.98 0 0 0 3.088 3 .75.75 0 0 0 1.043 0l3.394-3.3c.47-.461.863-.85 1.18-1.168a7.207 7.207 0 0 0 0-10.192ZM12 7.999a3.002 3.002 0 1 1 0 6.004 3.002 3.002 0 0 1 0-6.003Zm0 1.5a1.501 1.501 0 1 0 0 3.004 1.501 1.501 0 0 0 0-3.003Z",
|
||||
"lock-closed-outline": "M12 2a4 4 0 0 1 4 4v2h1.75A2.25 2.25 0 0 1 20 10.25v9.5A2.25 2.25 0 0 1 17.75 22H6.25A2.25 2.25 0 0 1 4 19.75v-9.5A2.25 2.25 0 0 1 6.25 8H8V6a4 4 0 0 1 4-4Zm5.75 7.5H6.25a.75.75 0 0 0-.75.75v9.5c0 .414.336.75.75.75h11.5a.75.75 0 0 0 .75-.75v-9.5a.75.75 0 0 0-.75-.75Zm-5.75 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm0-10A2.5 2.5 0 0 0 9.5 6v2h5V6A2.5 2.5 0 0 0 12 3.5Z",
|
||||
"lock-shield-outline": "M10 2a4 4 0 0 1 4 4v2h1.75A2.25 2.25 0 0 1 18 10.25V11c-.319 0-.637.11-.896.329l-.107.1c-.164.17-.33.323-.496.457L16.5 10.25a.75.75 0 0 0-.75-.75H4.25a.75.75 0 0 0-.75.75v9.5c0 .414.336.75.75.75h9.888a6.024 6.024 0 0 0 1.54 1.5H4.25A2.25 2.25 0 0 1 2 19.75v-9.5A2.25 2.25 0 0 1 4.25 8H6V6a4 4 0 0 1 4-4Zm8.284 10.122c.992 1.036 2.091 1.545 3.316 1.545.193 0 .355.143.392.332l.008.084v2.501c0 2.682-1.313 4.506-3.873 5.395a.385.385 0 0 1-.253 0c-2.476-.86-3.785-2.592-3.87-5.13L14 16.585v-2.5c0-.23.18-.417.4-.417 1.223 0 2.323-.51 3.318-1.545a.389.389 0 0 1 .566 0ZM10 13.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm0-10A2.5 2.5 0 0 0 7.5 6v2h5V6A2.5 2.5 0 0 0 10 3.5Z",
|
||||
"mail-inbox-all-outline": "M6.25 3h11.5a3.25 3.25 0 0 1 3.245 3.066L21 6.25v11.5a3.25 3.25 0 0 1-3.066 3.245L17.75 21H6.25a3.25 3.25 0 0 1-3.245-3.066L3 17.75V6.25a3.25 3.25 0 0 1 3.066-3.245L6.25 3Zm2.075 11.5H4.5v3.25a1.75 1.75 0 0 0 1.606 1.744l.144.006h11.5a1.75 1.75 0 0 0 1.744-1.607l.006-.143V14.5h-3.825a3.752 3.752 0 0 1-3.475 2.995l-.2.005a3.752 3.752 0 0 1-3.632-2.812l-.043-.188Zm9.425-10H6.25a1.75 1.75 0 0 0-1.744 1.606L4.5 6.25V13H9a.75.75 0 0 1 .743.648l.007.102a2.25 2.25 0 0 0 4.495.154l.005-.154a.75.75 0 0 1 .648-.743L15 13h4.5V6.25a1.75 1.75 0 0 0-1.607-1.744L17.75 4.5Zm-11 5h10.5a.75.75 0 0 1 .102 1.493L17.25 11H6.75a.75.75 0 0 1-.102-1.493L6.75 9.5h10.5-10.5Zm0-3h10.5a.75.75 0 0 1 .102 1.493L17.25 8H6.75a.75.75 0 0 1-.102-1.493L6.75 6.5h10.5-10.5Z",
|
||||
"mail-unread-outline": "M16 6.5H5.25a1.75 1.75 0 0 0-1.744 1.606l-.004.1L11 12.153l6.03-3.174a3.489 3.489 0 0 0 2.97.985v6.786a3.25 3.25 0 0 1-3.066 3.245L16.75 20H5.25a3.25 3.25 0 0 1-3.245-3.066L2 16.75v-8.5a3.25 3.25 0 0 1 3.066-3.245L5.25 5h11.087A3.487 3.487 0 0 0 16 6.5Zm2.5 3.399-7.15 3.765a.75.75 0 0 1-.603.042l-.096-.042L3.5 9.9v6.85a1.75 1.75 0 0 0 1.606 1.744l.144.006h11.5a1.75 1.75 0 0 0 1.744-1.607l.006-.143V9.899ZM19.5 4a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z",
|
||||
"mail-outline": "M5.25 4h13.5a3.25 3.25 0 0 1 3.245 3.066L22 7.25v9.5a3.25 3.25 0 0 1-3.066 3.245L18.75 20H5.25a3.25 3.25 0 0 1-3.245-3.066L2 16.75v-9.5a3.25 3.25 0 0 1 3.066-3.245L5.25 4h13.5-13.5ZM20.5 9.373l-8.15 4.29a.75.75 0 0 1-.603.043l-.096-.042L3.5 9.374v7.376a1.75 1.75 0 0 0 1.606 1.744l.144.006h13.5a1.75 1.75 0 0 0 1.744-1.607l.006-.143V9.373ZM18.75 5.5H5.25a1.75 1.75 0 0 0-1.744 1.606L3.5 7.25v.429l8.5 4.473 8.5-4.474V7.25a1.75 1.75 0 0 0-1.607-1.744L18.75 5.5Z",
|
||||
|
@ -117,6 +118,7 @@
|
|||
"people-outline": "M4 13.999 13 14a2 2 0 0 1 1.995 1.85L15 16v1.5C14.999 21 11.284 22 8.5 22c-2.722 0-6.335-.956-6.495-4.27L2 17.5v-1.501c0-1.054.816-1.918 1.85-1.995L4 14ZM15.22 14H20c1.054 0 1.918.816 1.994 1.85L22 16v1c-.001 3.062-2.858 4-5 4a7.16 7.16 0 0 1-2.14-.322c.336-.386.607-.827.802-1.327A6.19 6.19 0 0 0 17 19.5l.267-.006c.985-.043 3.086-.363 3.226-2.289L20.5 17v-1a.501.501 0 0 0-.41-.492L20 15.5h-4.051a2.957 2.957 0 0 0-.595-1.34L15.22 14H20h-4.78ZM4 15.499l-.1.01a.51.51 0 0 0-.254.136.506.506 0 0 0-.136.253l-.01.101V17.5c0 1.009.45 1.722 1.417 2.242.826.445 2.003.714 3.266.753l.317.005.317-.005c1.263-.039 2.439-.308 3.266-.753.906-.488 1.359-1.145 1.412-2.057l.005-.186V16a.501.501 0 0 0-.41-.492L13 15.5l-9-.001ZM8.5 3a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9Zm9 2a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Zm-9-.5c-1.654 0-3 1.346-3 3s1.346 3 3 3 3-1.346 3-3-1.346-3-3-3Zm9 2c-1.103 0-2 .897-2 2s.897 2 2 2 2-.897 2-2-.897-2-2-2Z",
|
||||
"people-team-add-outline": "M17.5 12a5.5 5.5 0 1 1 0 11a5.5 5.5 0 0 1 0-11Zm0 2l-.09.007a.5.5 0 0 0-.402.402L17 14.5V17h-2.502l-.09.008a.5.5 0 0 0-.402.402l-.008.09l.008.09a.5.5 0 0 0 .402.402l.09.008H17v2.503l.008.09a.5.5 0 0 0 .402.402l.09.008l.09-.008a.5.5 0 0 0 .402-.402l.008-.09V18l2.504.001l.09-.008a.5.5 0 0 0 .402-.402l.008-.09l-.008-.09a.5.5 0 0 0-.403-.402l-.09-.008H18v-2.5l-.008-.09a.5.5 0 0 0-.402-.403L17.5 14Zm-3.246-4c.835 0 1.563.454 1.951 1.13a6.44 6.44 0 0 0-1.518.509a.736.736 0 0 0-.433-.139H9.752a.75.75 0 0 0-.75.75v4.249c0 1.41.974 2.594 2.286 2.915a6.42 6.42 0 0 0 .735 1.587l-.02-.001a4.501 4.501 0 0 1-4.501-4.501V12.25A2.25 2.25 0 0 1 9.752 10h4.502Zm-6.848 0a3.243 3.243 0 0 0-.817 1.5H4.25a.75.75 0 0 0-.75.75v2.749a2.501 2.501 0 0 0 3.082 2.433c.085.504.24.985.453 1.432A4.001 4.001 0 0 1 2 14.999V12.25a2.25 2.25 0 0 1 2.096-2.245L4.25 10h3.156Zm12.344 0A2.25 2.25 0 0 1 22 12.25v.56A6.478 6.478 0 0 0 17.5 11l-.245.005A3.21 3.21 0 0 0 16.6 10h3.15ZM18.5 4a2.5 2.5 0 1 1 0 5a2.5 2.5 0 0 1 0-5ZM12 3a3 3 0 1 1 0 6a3 3 0 0 1 0-6ZM5.5 4a2.5 2.5 0 1 1 0 5a2.5 2.5 0 0 1 0-5Zm13 1.5a1 1 0 1 0 0 2a1 1 0 0 0 0-2Zm-6.5-1a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3Zm-6.5 1a1 1 0 1 0 0 2a1 1 0 0 0 0-2Z",
|
||||
"people-team-outline": "M14.754 10c.966 0 1.75.784 1.75 1.75v4.749a4.501 4.501 0 0 1-9.002 0V11.75c0-.966.783-1.75 1.75-1.75h5.502Zm0 1.5H9.252a.25.25 0 0 0-.25.25v4.749a3.001 3.001 0 0 0 6.002 0V11.75a.25.25 0 0 0-.25-.25ZM3.75 10h3.381a2.738 2.738 0 0 0-.618 1.5H3.75a.25.25 0 0 0-.25.25v3.249a2.501 2.501 0 0 0 3.082 2.433c.085.504.24.985.453 1.432A4.001 4.001 0 0 1 2 14.999V11.75c0-.966.784-1.75 1.75-1.75Zm13.125 0h3.375c.966 0 1.75.784 1.75 1.75V15a4 4 0 0 1-5.03 3.866c.214-.448.369-.929.455-1.433A2.5 2.5 0 0 0 20.5 15v-3.25a.25.25 0 0 0-.25-.25h-2.757a2.738 2.738 0 0 0-.618-1.5ZM12 3a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm6.5 1a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm-13 0a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm6.5.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Zm6.5 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm-13 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2Z",
|
||||
"person-account-outline": "M11 15c0-.35.06-.687.17-1H4.253a2.249 2.249 0 0 0-2.249 2.249v.578c0 .892.319 1.756.899 2.435 1.566 1.834 3.952 2.74 7.098 2.74.397 0 .783-.015 1.156-.044A2.998 2.998 0 0 1 11 21v-.535c-.321.024-.655.036-1 .036-2.738 0-4.704-.746-5.958-2.213a2.25 2.25 0 0 1-.539-1.462v-.577c0-.414.336-.75.75-.75H11V15ZM10 2.005a5 5 0 1 1 0 10 5 5 0 0 1 0-10Zm0 1.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7ZM12 15a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-7a2 2 0 0 1-2-2v-6Zm2.5 1a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6Zm0 3a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6Z",
|
||||
"person-add-outline": "M17.5 12a5.5 5.5 0 1 1 0 11a5.5 5.5 0 0 1 0-11zm-5.477 2a6.47 6.47 0 0 0-.709 1.5H4.253a.749.749 0 0 0-.75.75v.577c0 .535.192 1.053.54 1.46c1.253 1.469 3.22 2.214 5.957 2.214c.597 0 1.157-.035 1.68-.106c.246.495.553.954.912 1.367c-.795.16-1.66.24-2.592.24c-3.146 0-5.532-.906-7.098-2.74a3.75 3.75 0 0 1-.898-2.435v-.578A2.249 2.249 0 0 1 4.253 14h7.77zm5.477 0l-.09.008a.5.5 0 0 0-.402.402L17 14.5V17h-2.496l-.09.008a.5.5 0 0 0-.402.402l-.008.09l.008.09a.5.5 0 0 0 .402.402l.09.008H17L17 20.5l.008.09a.5.5 0 0 0 .402.402l.09.008l.09-.008a.5.5 0 0 0 .402-.402L18 20.5V18h2.504l.09-.008a.5.5 0 0 0 .402-.402l.008-.09l-.008-.09a.5.5 0 0 0-.402-.402l-.09-.008H18L18 14.5l-.008-.09a.5.5 0 0 0-.402-.402L17.5 14zM10 2.005a5 5 0 1 1 0 10a5 5 0 0 1 0-10zm0 1.5a3.5 3.5 0 1 0 0 7a3.5 3.5 0 0 0 0-7z",
|
||||
"person-assign-outline": "M11.313 15.5a6.471 6.471 0 0 1 .709-1.5h-7.77a2.249 2.249 0 0 0-2.249 2.25v.577c0 .892.319 1.756.899 2.435c1.566 1.834 3.952 2.74 7.098 2.74c.931 0 1.796-.08 2.592-.24a6.51 6.51 0 0 1-.913-1.366c-.524.07-1.083.105-1.68.105c-2.737 0-4.703-.745-5.957-2.213a2.25 2.25 0 0 1-.539-1.461v-.578a.75.75 0 0 1 .75-.749h7.06ZM10 2.005a5 5 0 1 1 0 10a5 5 0 0 1 0-10Zm0 1.5a3.5 3.5 0 1 0 0 7a3.5 3.5 0 0 0 0-7ZM23 17.5a5.5 5.5 0 1 1-11 0a5.5 5.5 0 0 1 11 0Zm-4.647-2.853a.5.5 0 0 0-.707.707L19.293 17H15a.5.5 0 1 0 0 1h4.293l-1.647 1.647a.5.5 0 0 0 .707.707l2.5-2.5a.497.497 0 0 0 .147-.345V17.5a.498.498 0 0 0-.15-.357l-2.497-2.496Z",
|
||||
"person-outline": "M17.754 14a2.249 2.249 0 0 1 2.25 2.249v.575c0 .894-.32 1.76-.902 2.438-1.57 1.834-3.957 2.739-7.102 2.739-3.146 0-5.532-.905-7.098-2.74a3.75 3.75 0 0 1-.898-2.435v-.577a2.249 2.249 0 0 1 2.249-2.25h11.501Zm0 1.5H6.253a.749.749 0 0 0-.75.749v.577c0 .536.192 1.054.54 1.461 1.253 1.468 3.219 2.214 5.957 2.214s4.706-.746 5.962-2.214a2.25 2.25 0 0 0 .541-1.463v-.575a.749.749 0 0 0-.749-.75ZM12 2.004a5 5 0 1 1 0 10 5 5 0 0 1 0-10Zm0 1.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</label>
|
||||
<label>
|
||||
<span>Company Name</span>
|
||||
<%= text_field :user, :company, placeholder: "Enter an account name. eg: Wayne Enterprises", required: true %>
|
||||
<%= text_field :user, :company, placeholder: "Enter your company name. eg: Wayne Enterprises", required: true %>
|
||||
</label>
|
||||
<label>
|
||||
<span>Work Email</span>
|
||||
|
|
91
public/assets/images/auth/auth--bg.svg
Normal file
91
public/assets/images/auth/auth--bg.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 76 KiB |
3
public/assets/images/auth/bottom-right.svg
Normal file
3
public/assets/images/auth/bottom-right.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M800 0H600V200H400V400H200V600H0V800H200H400H600H800V600V400V200V0Z" fill="#2773E4" fill-opacity="0.42"/>
|
||||
</svg>
|
After Width: | Height: | Size: 262 B |
3
public/assets/images/auth/top-left.svg
Normal file
3
public/assets/images/auth/top-left.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M200 0H0V200V400V600H200V400H400V200H600V0H400H200Z" fill="#2773E4" fill-opacity="0.42"/>
|
||||
</svg>
|
After Width: | Height: | Size: 246 B |
Loading…
Reference in a new issue