WIP: validate confirm password and show error message

This commit is contained in:
Cindy Chang
2024-06-20 15:54:14 +08:00
parent 26441d3979
commit 05caf819bb
10 changed files with 191 additions and 20 deletions

View File

@@ -151,6 +151,7 @@ export default {
},
onEditBtnClick(dataId){
this.openModal(MODAL_ACCT_EDIT);
this.setCurrentViewingUser(dataId);
},
...mapActions(useModalStore, ['openModal']),
...mapActions(useAcctMgmtStore, ['setCurrentViewingUser']),

View File

@@ -1,28 +1,95 @@
<template>
<div id="modal_account_edit" class="w-[600px] h-[296px] bg-[#FFFFFF] rounded
<div id="modal_account_edit" class="w-[640px] bg-[#FFFFFF] rounded
shadow-lg flex flex-col">
<ModalHeader :headerText="i18next.t('AcctMgmt.AccountEdit')"/>
<main class="flex row h-[96px] my-[32px] flex-col px-8">
<div class="input-row w-full flex py-3">
<span class="field-label w-[68px] text-sm flex items-center font-medium mr-4 justify-end">{{ i18next.t("AcctMgmt.Account") }} </span>
<input class="w-[454px] rounded p-1 btn btn-sm btn-neutralborder border-[1px] border-[#64748B] flex items-center h-[40px]"/>
<main class="flex row min-h-[96px] my-[32px] flex-col px-6">
<div class="input-row w-full flex py-2 h-[40px] mb-4 items-center
justify-between">
<div class="field-label text-sm flex items-center font-medium mr-4 justify-end">
<span class="align-right-span flex w-[100px] justify-end">
{{ i18next.t("AcctMgmt.Account") }}
</span>
</div>
<input id="input_account_field"
class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
:value="account"/>
</div>
<div class="input-row w-full flex py-3 items-center">
<span class="field-label w-[68px] text-sm flex items-center font-medium mr-4 justify-end">{{ i18next.t("AcctMgmt.FullName") }} </span>
<input class="w-[454px] rounded p-1 btn btn-sm btn-neutralborder border-[1px] border-[#64748B] flex items-center h-[40px]"/>
<div class="input-row w-full flex py-2 h-[40px] mb-4 items-center
justify-between">
<div class="field-label text-sm flex items-center font-medium mr-4 justify-end">
<span class="align-right-span flex w-[100px] justify-end">
{{ i18next.t("AcctMgmt.FullName") }}
</span>
</div>
<input class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
:value="fullName"/>
</div>
<div v-show="!isSSO" class="input-row w-full flex py-2 h-[40px] mb-4 items-center
justify-between">
<div class="field-label text-sm flex items-center font-medium mr-4 justify-end">
<span class="align-right-span flex w-[100px] justify-end">
{{ i18next.t("AcctMgmt.Password") }}
</span>
</div>
<div class="w-[454px] rounded border-[1px] border-[#64748B] flex items-center h-[40px] relative">
<input class="outline-none p-1 w-[352px]" :type="isPwdEyeOn ? 'text' : 'password'"
v-model="inputPwd"/>
<img v-if="isPwdEyeOn" src='@/assets/icon-eye-open.svg' class="absolute right-[8px] cursor-pointer"
@click="togglePwdEyeBtn"/>
<img v-else src='@/assets/icon-eye-hide.svg' class="absolute right-[8px] cursor-pointer" @click="togglePwdEyeBtn"/>
</div>
</div>
<div v-show="!isSSO" id="confirm_pwd_row" class="input-row w-full grid grid-cols-2 grid-cols-[122px_1fr] gap-x-4
mb-4 flex items-center"> <!-- 2-by-2 的格子其中左下角是一個dummy格子其沒有內容 -->
<span class="field-label w-[100px] text-sm flex items-center justify-end text-right font-medium mr-4 whitespace-nowrap"
:class="{
'text-[#000000]': isPwdMatched,
'text-[#FF3366]': !isPwdMatched,
}">
{{ i18next.t("AcctMgmt.ConfirmPassword") }}
</span>
<div class="input-and-toggle-btn w-[454px] flex flex-row rounded border border-[1px] relative items-center
h-[40px] mb-4"
:class="{
'border-[#000000]': isPwdMatched,
'border-[#FF3366]': !isPwdMatched,
}">
<input class="outline-none p-1 w-[352px]" :type="isPwdConfirmEyeOn ? 'text' : 'password'"
v-model="inputConfirmPwd"
:class="{
'text-[#000000]': isPwdMatched,
'text-[#FF3366]': !isPwdMatched,
}"/>
<img v-if="isPwdConfirmEyeOn" src='@/assets/icon-eye-open.svg' class="absolute right-[8px] cursor-pointer"
@click="togglePwdConfirmEyeBtn"/>
<img v-else src='@/assets/icon-eye-hide.svg' class="absolute right-[8px] cursor-pointer" @click="togglePwdConfirmEyeBtn"/>
</div>
<div class="dummy-grid h-[24px]"></div> <!-- 透過 dummy-grid 來撐起高度-->
<div v-show="!isPwdMatched" class="error-msg-section flex justify-start">
<img src="@/assets/icon-alert.svg" alt="!" class="exclamation-img flex mr-2">
<span class="error-msg-text flex text-[#FF3366] h-[24px]">
{{ i18next.t("AcctMgmt.PwdNotMatch") }}
</span>
</div>
</div>
</main>
<footer class="flex row footer justify-end pr-[32px]">
<footer class="flex row footer justify-end pr-[32px] pb-8">
<button class="cancel-btn rounded rounded-full w-[92px] h-10 px-2.5 py-6 border border-[1px] border-[#64748B]
flex justify-center items-center text-[#4E5969] font-medium"
@click="onCancelBtnClick"
>
{{ i18next.t("Global.Cancel") }}
</button>
<button class="confirm-btn rounded rounded-full w-[92px] h-10 px-2.5 py-6 bg-[#0099FF]
<button class="confirm-btn rounded rounded-full w-[92px] h-10 px-2.5 py-6
flex justify-center items-center text-[#ffffff] font-medium ml-[16px]"
@click="onConfirmBtnClick"
@click="onConfirmBtnClick" :disabled="isConfirmDisabled"
:class="{
'bg-[#0099FF]': !isConfirmDisabled,
'bg-[#E2E8F0]': isConfirmDisabled,
}"
>
{{ i18next.t("Global.Confirm") }}
</button>
@@ -31,15 +98,65 @@
</template>
<script>
import { defineComponent } from 'vue';
import { defineComponent, computed, ref, } from 'vue';
import i18next from "@/i18n/i18n.js";
import { mapActions, } from 'pinia';
import { useModalStore } from '@/stores/modal.js';
import useAcctMgmtStore from '@/stores/acctMgmt.js';
import ModalHeader from "./ModalHeader.vue";
export default defineComponent({
setup() {
const acctMgmtStore = useAcctMgmtStore();
const currentViewingUser = computed(() => acctMgmtStore.currentViewingUser);
const isPwdEyeOn = ref(false);
const isPwdConfirmEyeOn = ref(false);
const isPwdMatched = ref(true);
const inputPwd = ref("");
const inputConfirmPwd = ref("");
const {
id,
} = currentViewingUser;
const isSSO = computed(() => acctMgmtStore.currentViewingUser.isSSO);
const account = computed(() => acctMgmtStore.currentViewingUser.account);
const fullName = computed(() => acctMgmtStore.currentViewingUser.fullName);
const isConfirmDisabled = computed(() => {
return inputPwd.length && inputConfirmPwd.length;
});
const togglePwdEyeBtn = () => {
isPwdEyeOn.value = !isPwdEyeOn.value;
};
const togglePwdConfirmEyeBtn = () => {
isPwdConfirmEyeOn.value = !isPwdConfirmEyeOn.value;
};
const validateConfirmPwd = () => {
isPwdMatched.value = inputPwd.value === inputConfirmPwd.value;
console.log('isPwdMatched.value',isPwdMatched.value );
}
const onConfirmBtnClick = () => {
validateConfirmPwd();
}
return {
isConfirmDisabled,
account,
id,
fullName,
isSSO,
isPwdEyeOn,
isPwdConfirmEyeOn,
togglePwdEyeBtn,
togglePwdConfirmEyeBtn,
isPwdMatched,
inputPwd,
inputConfirmPwd,
onConfirmBtnClick,
};
},
data() {
@@ -51,9 +168,6 @@ export default defineComponent({
ModalHeader,
},
methods: {
onConfirmBtnClick(){
//TODO:
},
onCloseBtnClick(){
this.closeModal();
},

View File

@@ -4,7 +4,7 @@
<ModalHeader :headerText='i18next.t("AcctMgmt.AccountInformation")'/>
<main class="flex main-part flex-col px-6 mt-6">
<h1 id="acct_info_user_name" class="text-[32px] leading-[64px] font-medium">{{ fullName }}</h1>
<div class="status-container">Admin Suspended</div>
<div class="status-container"><Badge displayText="Admin" isActivated/> <Badge displayText="Suspended" :isActivated="false"/></div>
<div id="account_visit_info" class="border-b border-b-[#CBD5E1] border-b-[1px] pb-4">
Account: <span class="text-[#0099FF]">{{ account }}</span>, total visits <span class="text-[#0099FF]">{{ visitTiime }}</span> times.
</div>
@@ -22,8 +22,9 @@
<script>
import i18next from '@/i18n/i18n.js';
import ModalHeader from './ModalHeader.vue';
import useAcctMgmtStore from '@/stores/acctMgmt.js';
import ModalHeader from './ModalHeader.vue';
import Badge from '../../components/Badge.vue';
export default {
setup(){
@@ -51,6 +52,7 @@ export default {
},
components: {
ModalHeader,
Badge,
}
}
</script>