WIP my account page

This commit is contained in:
Cindy Chang
2024-08-28 15:52:12 +08:00
parent 4b56130278
commit b76c432386
3 changed files with 148 additions and 6 deletions

View File

@@ -9,7 +9,9 @@
"Cancel": "Cancel", "Cancel": "Cancel",
"Clear": "Clear", "Clear": "Clear",
"Save": "Save", "Save": "Save",
"Confirm": "Confirm" "Confirm": "Confirm",
"Edit": "Edit",
"Reset": "Reset"
}, },
"Map":{ "Map":{
"FileName": "File Name", "FileName": "File Name",

View File

@@ -30,8 +30,7 @@
{{ i18next.t("AcctMgmt.AccountNotUnique") }} {{ i18next.t("AcctMgmt.AccountNotUnique") }}
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="input-row w-full flex py-2 h-[40px] mb-4 items-center <div class="input-row w-full flex py-2 h-[40px] mb-4 items-center

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="general my-account flex justify-center w-full h-full p-8"> <div class="general my-account flex flex-col items-center w-full h-full p-8">
<main class="flex main-part flex-col px-6 mt-6 w-[536px]"> <main class="flex main-part flex-col px-6 mt-6 w-[536px]">
<h1 id="general_acct_info_user_name" class="text-[32px] leading-[64px] font-medium mb-2"> <h1 id="general_acct_info_user_name" class="text-[32px] leading-[64px] font-medium mb-2">
{{ name }} {{ name }}
@@ -15,20 +15,115 @@
</span> times. </span> times.
</div> </div>
</main> </main>
<main class="flex flex-col pt-6 px-6 w-[536px]">
<h1 class="text-[20px] font-medium mb-4">
{{ i18next.t("AcctMgmt.UserInfo") }}
</h1>
<div class="row w-full flex py-2 h-[40px] mb-4 items-center">
<div class="field-label text-sm flex items-center font-medium mr-4">
<span class="align-right-span flex w-[80px]">
{{ i18next.t("AcctMgmt.Account") }}
</span>
</div>
<div class="account flex flex-col">
<span class="flex text-[#0F172A] text-[14px]">{{ username }}</span>
<div v-show="false" class="error-wrapper my-2">
<div 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.AccountNotUnique") }}
</span>
</div>
</div>
</div>
</div>
<div class="row w-full flex py-2 h-[40px] mb-4 items-center">
<div class="field-label text-sm flex items-center font-medium mr-4">
<span class="align-right-span flex w-[80px]">
{{ i18next.t("AcctMgmt.FullName") }}
</span>
</div>
<input v-if='isNameEditable' id="input_name_field"
class="w-[280px] h-[40px] rounded p-1 border border-[1px] border-[#64748B] flex items-center outline-none"
v-model="inputName" :readonly="!isNameEditable"
autocomplete="off"
/>
<span v-else class="not-editable displayable name w-[280px]">
{{ name }}
</span>
<button v-if='isNameEditable' class="flex save-btn rounded-full text-[#FFFFFF] h-[40px] w-[80px] items-center
bg-[#0099FF] justify-center cursor-pointer ml-20
">
{{ i18next.t("Global.Save") }}
</button>
<button v-else class="flex save-btn rounded-full text-[#666666] h-[40px] w-[80px] items-center
bg-[#FFFFFF] justify-center cursor-pointer ml-20 border border-[#666666]"
@click="onEditNameClick"
>
{{ i18next.t("Global.Edit") }}
</button>
</div>
<div class="row w-full flex py-2 mb-4">
<div class="field-label flex flex-col text-sm font-medium mr-4">
<span class="flex h-[40px] w-[80px] items-center">
{{ i18next.t("AcctMgmt.Password") }}
</span>
<div class="flex dummy-cell"></div>
</div>
<div class="flex input-and-error-msg flex-col w-[242px]">
<!-- 280 扣掉 24 眼睛的寬度 256 還要扣掉留白的寬度 -->
<div v-if='isPwdEditable' class="input-and-eye flex items-center h-[40px] relative border-[1px] rounded"
:class="{'border-[#FF3366]': !isPwdLengthValid, 'border-[#64748B]': isPwdLengthValid,}"
>
<input class="outline-none p-1 w-[242px]" :type="isPwdEyeOn ? 'text' : 'password'"
v-model="inputPwd"
autocomplete="off" :class="{'color-[#FF3366]': !isPwdLengthValid,
'color-[#64748B]': isPwdLengthValid,}"/>
<img id='eye_button' v-if="isPwdEyeOn" src='@/assets/icon-eye-open.svg' class="absolute right-[8px] cursor-pointer"
@mousedown="togglePwdEyeBtn(true)" @mouseup="togglePwdEyeBtn(false)" alt=""/>
<img v-else src='@/assets/icon-eye-hide.svg' class="absolute right-[8px] cursor-pointer"
@mousedown="togglePwdEyeBtn(true)" @mouseup="togglePwdEyeBtn(false)" alt="eye"/>
</div>
<div class="error-msg-section flex justify-start mt-4">
<img v-show="!isPwdLengthValid" src="@/assets/icon-alert.svg" alt="!" class="exclamation-img flex mr-2">
<span class="error-msg-text flex text-[#FF3366] h-[24px]">
{{ isPwdLengthValid ? "" : i18next.t("AcctMgmt.PwdLengthNotEnough") }}
</span>
</div>
</div>
<div class="button-column flex flex-col">
<button v-if='isPwdEditable' class="flex save-btn rounded-full text-[#FFFFFF] h-[40px] w-[80px] items-center
bg-[#0099FF] justify-center cursor-pointer ml-20"
@click="onSavePwdClick">
{{ i18next.t("Global.Save") }}
</button>
<button v-else class="flex reset-btn rounded-full text-[#666666] h-[40px] w-[80px] items-center
bg-[#FFFFFF] justify-center cursor-pointer ml-20 border border-[#666666]"
@click="onResetPwdClick"
>
{{ i18next.t("Global.Reset") }}
</button>
<div class="flex dummy-cell h-[40px]"></div>
</div>
</div>
</main>
</div> </div>
</template> </template>
<script> <script>
import { onMounted, onBeforeMount, computed, ref } from 'vue'; import { onMounted, computed, ref, onBeforeMount, } from 'vue';
import i18next from '@/i18n/i18n.js'; import i18next from '@/i18n/i18n.js';
import LoginStore from '@/stores/login';
import useAcctMgmtStore from '@/stores/acctMgmt.ts'; import useAcctMgmtStore from '@/stores/acctMgmt.ts';
import ModalHeader from './ModalHeader.vue';
import Badge from '../../components/Badge.vue'; import Badge from '../../components/Badge.vue';
import LoadingStore from '@/stores/loading.js'; import LoadingStore from '@/stores/loading.js';
import { PWD_VALID_LENGTH } from '@/constants/constants.js';
export default { export default {
setup() { setup() {
const loadingStore = LoadingStore(); const loadingStore = LoadingStore();
const loginStore = LoginStore();
const acctMgmtStore = useAcctMgmtStore(); const acctMgmtStore = useAcctMgmtStore();
const visitTime = ref(0); const visitTime = ref(0);
const currentViewingUser = computed(() => acctMgmtStore.currentViewingUser); const currentViewingUser = computed(() => acctMgmtStore.currentViewingUser);
@@ -39,6 +134,42 @@ export default {
is_active, is_active,
} = currentViewingUser.value; } = currentViewingUser.value;
const inputName = ref(name);
const inputPwd = ref('');
const isNameEditable = ref(false);
const isPwdEditable = ref(false);
const isPwdEyeOn = ref(false);
const isPwdLengthValid = ref(true);
const onEditNameClick = () => {
isNameEditable.value = true;
}
const onResetPwdClick = () => {
isPwdEditable.value = true;
}
const onSavePwdClick = () => {
validatePwdLength();
if (isPwdLengthValid.value) {
isPwdEditable.value = false;
inputPwd.value = '';
}
}
const togglePwdEyeBtn = (toBeOpen) => {
isPwdEyeOn.value = toBeOpen;
};
const validatePwdLength = () => {
isPwdLengthValid.value = inputPwd.value.length >= PWD_VALID_LENGTH;
}
onBeforeMount(async() => {
// 在此設定 current viewing user 的來源是登入者的身分
await acctMgmtStore.getUserDetail(loginStore.userData.username);
});
onMounted(() => { onMounted(() => {
loadingStore.setIsLoading(false); loadingStore.setIsLoading(false);
}); });
@@ -50,6 +181,16 @@ export default {
is_admin, is_admin,
is_active, is_active,
visitTime, visitTime,
inputName,
inputPwd,
isNameEditable,
isPwdEditable,
isPwdEyeOn,
isPwdLengthValid,
onEditNameClick,
onResetPwdClick,
onSavePwdClick,
togglePwdEyeBtn,
}; };
}, },
components: { components: {