Skip to content

Commit

Permalink
web/satellite: PasswordStrength, NewBillingAddCouponCodeInput compone…
Browse files Browse the repository at this point in the history
…nts migrated to use composition api

Change-Id: I1b878a7bce574c34ec424e7c8b94077c65fa9529
  • Loading branch information
NikolaiYurchenko authored and Storj Robot committed Dec 23, 2022
1 parent af238e2 commit b683f83
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 158 deletions.
Expand Up @@ -28,58 +28,54 @@
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
<script setup lang="ts">
import { ref } from 'vue';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useNotify, useStore } from '@/utils/hooks';
import VInput from '@/components/common/VInput.vue';
import ValidationMessage from '@/components/common/ValidationMessage.vue';
import VButton from '@/components/common/VButton.vue';
// @vue/component
@Component({
components: {
VButton,
VInput,
ValidationMessage,
},
})
export default class NewBillingAddCouponCodeInput extends Vue {
private showValidationMessage = false;
private isCodeValid = false;
private errorMessage = '';
private couponCode = '';
private isLoading = false;
private readonly analytics = new AnalyticsHttpApi();
public setCouponCode(value: string): void {
this.couponCode = value;
}
const store = useStore();
const notify = useNotify();
/**
* Check if coupon code is valid
*/
public async applyCouponCode(): Promise<void> {
if (this.isLoading) return;
this.isLoading = true;
try {
await this.$store.dispatch(PAYMENTS_ACTIONS.APPLY_COUPON_CODE, this.couponCode);
await this.$notify.success('Coupon Added!');
this.$emit('close');
} catch (error) {
this.errorMessage = error.message;
this.isCodeValid = false;
this.showValidationMessage = true;
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
} finally {
this.isLoading = false;
}
const emit = defineEmits(['close']);
const showValidationMessage = ref<boolean>(false);
const isCodeValid = ref<boolean>(false);
const errorMessage = ref<string>('');
const couponCode = ref<string>('');
const isLoading = ref<boolean>(false);
const analytics = new AnalyticsHttpApi();
function setCouponCode(value: string): void {
couponCode.value = value;
}
/**
* Check if coupon code is valid
*/
async function applyCouponCode(): Promise<void> {
if (isLoading.value) return;
isLoading.value = true;
try {
await store.dispatch(PAYMENTS_ACTIONS.APPLY_COUPON_CODE, couponCode.value);
await notify.success('Coupon Added!');
emit('close');
} catch (error) {
errorMessage.value = error.message;
isCodeValid.value = false;
showValidationMessage.value = true;
await analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
} finally {
isLoading.value = false;
}
}
</script>
Expand Down
215 changes: 99 additions & 116 deletions web/satellite/src/components/common/PasswordStrength.vue
Expand Up @@ -34,8 +34,8 @@
</div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
<script setup lang="ts">
import { computed } from 'vue';
import { Validator } from '@/utils/validation';
Expand All @@ -54,141 +54,124 @@ class BarFillStyle {
}
}
const PASSWORD_STRENGTH = {
veryStrong: 'Very Strong',
strong: 'Strong',
good: 'Good',
weak: 'Weak',
};
const PASSWORD_STRENGTH_COLORS = {
[PASSWORD_STRENGTH.good]: '#ffff00',
[PASSWORD_STRENGTH.strong]: '#bfff00',
[PASSWORD_STRENGTH.veryStrong]: '#00ff40',
default: '#e16c58',
};
const BAR_WIDTH = {
[PASSWORD_STRENGTH.weak]: '25%',
[PASSWORD_STRENGTH.good]: '50%',
[PASSWORD_STRENGTH.strong]: '75%',
[PASSWORD_STRENGTH.veryStrong]: '100%',
default: '0px',
};
const props = withDefaults(defineProps<{
passwordString?: string;
isShown?: boolean;
}>(), {
passwordString: '',
isShown: false,
});
const isPasswordLengthAcceptable = computed((): boolean => {
return Validator.password(props.passwordString);
});
/**
* StrengthLabelColor class holds info for StrengthLabelColor entity.
* Returns password strength label depends on score.
*/
class StrengthLabelColor {
color: string;
public constructor(color: string) {
this.color = color;
const passwordStrength = computed((): string => {
if (props.passwordString.length < Validator.PASS_MIN_LENGTH) {
return `Use ${Validator.PASS_MIN_LENGTH} or more characters`;
}
}
// @vue/component
@Component({
components: {
VectorIcon,
},
})
export default class PasswordStrength extends Vue {
@Prop({ default: '' })
private readonly passwordString: string;
/**
* Indicates if component should be rendered.
*/
@Prop({ default: false })
private readonly isShown: boolean;
public get isPasswordLengthAcceptable(): boolean {
return Validator.password(this.passwordString);
if (props.passwordString.length > Validator.PASS_MAX_LENGTH) {
return `Use ${Validator.PASS_MAX_LENGTH} or fewer characters`;
}
/**
* Returns password strength label depends on score.
*/
public get passwordStrength(): string {
if (this.passwordString.length < Validator.PASS_MIN_LENGTH) {
return `Use ${Validator.PASS_MIN_LENGTH} or more characters`;
}
if (this.passwordString.length > Validator.PASS_MAX_LENGTH) {
return `Use ${Validator.PASS_MAX_LENGTH} or fewer characters`;
}
const score = this.scorePassword();
if (score > 90) {
return 'Very Strong';
}
if (score > 70) {
return 'Strong';
}
if (score > 45) {
return 'Good';
}
return 'Weak';
const score = scorePassword();
if (score > 90) {
return PASSWORD_STRENGTH.veryStrong;
}
public get barFillStyle(): BarFillStyle {
return new BarFillStyle(this.passwordStrengthColor, this.barWidth);
if (score > 70) {
return PASSWORD_STRENGTH.strong;
}
public get strengthLabelColor(): StrengthLabelColor {
return new StrengthLabelColor(this.passwordStrengthColor);
if (score > 45) {
return PASSWORD_STRENGTH.good;
}
public get hasLowerAndUpperCaseLetters(): boolean {
return /[a-z]/.test(this.passwordString) && /[A-Z]/.test(this.passwordString);
}
return PASSWORD_STRENGTH.weak;
});
public get hasSpecialCharacter(): boolean {
return /\W/.test(this.passwordString);
}
/**
* Color for indicator between red as weak and green as strong password.
*/
const passwordStrengthColor = computed((): string => {
return PASSWORD_STRENGTH_COLORS[passwordStrength.value] || PASSWORD_STRENGTH_COLORS.default;
});
/**
* Returns password strength score depends on length, case variations and special characters.
*/
private scorePassword(): number {
const password: string = this.passwordString;
let score = 0;
const letters: number[] = [];
for (let i = 0; i < password.length; i++) {
letters[password[i]] = (letters[password[i]] || 0) + 1;
score += 5 / letters[password[i]];
}
/**
* Fills password strength indicator bar.
*/
const barWidth = computed((): string => {
return BAR_WIDTH[passwordStrength.value] || BAR_WIDTH.default;
});
const strengthLabelColor = computed((): { color: string } => {
return { color: passwordStrengthColor.value };
});
const variations: boolean[] = [
/\d/.test(password),
/[a-z]/.test(password),
/[A-Z]/.test(password),
/\W/.test(password),
];
const hasLowerAndUpperCaseLetters = computed((): boolean => {
return /[a-z]/.test(props.passwordString) && /[A-Z]/.test(props.passwordString);
});
let variationCount = 0;
variations.forEach((check) => {
variationCount += check ? 1 : 0;
});
const hasSpecialCharacter = computed((): boolean => {
return /\W/.test(props.passwordString);
});
score += variationCount * 10;
const barFillStyle = computed((): BarFillStyle => {
return new BarFillStyle(passwordStrengthColor.value, barWidth.value);
});
return score;
/**
* Returns password strength score depends on length, case variations and special characters.
*/
function scorePassword(): number {
const password: string = props.passwordString;
let score = 0;
const letters: number[] = [];
for (let i = 0; i < password.length; i++) {
letters[password[i]] = (letters[password[i]] || 0) + 1;
score += 5 / letters[password[i]];
}
/**
* Color for indicator between red as weak and green as strong password.
*/
private get passwordStrengthColor(): string {
switch (this.passwordStrength) {
case 'Good':
return '#ffff00';
case 'Strong':
return '#bfff00';
case 'Very Strong':
return '#00ff40';
}
const variations: boolean[] = [
/\d/.test(password),
/[a-z]/.test(password),
/[A-Z]/.test(password),
/\W/.test(password),
];
return '#e16c58';
}
let variationCount = 0;
variations.forEach((check) => {
variationCount += check ? 1 : 0;
});
/**
* Fills password strength indicator bar.
*/
private get barWidth(): string {
switch (this.passwordStrength) {
case 'Weak':
return '25%';
case 'Good':
return '50%';
case 'Strong':
return '75%';
case 'Very Strong':
return '100%';
}
score += variationCount * 10;
return '0px';
}
return score;
}
</script>

Expand Down

0 comments on commit b683f83

Please sign in to comment.