WIP: account info modal prototype with a little bit of pinia state mgmt.

This commit is contained in:
Cindy Chang
2024-06-20 12:13:39 +08:00
parent d6a79687da
commit 26441d3979
9 changed files with 183 additions and 47 deletions

View File

@@ -1,12 +1,41 @@
export const PRIME_VUE_TICKS_LIMIT = 6; export const PRIME_VUE_TICKS_LIMIT = 6;
export const GRID_COLOR = '#64748b'; export const GRID_COLOR = '#64748b';
export const MODAL_CREATE_NEW = 'MODAL_CREATE_NEW';
export const MODAL_ACCT_EDIT = 'MODAL_ACCT_EDIT';
export const MODAL_ACCT_INFO = 'MODAL_ACCT_INFO';
export const knownLayoutChartOption = { export const knownLayoutChartOption = {
padding: { padding: {
top: 16, top: 16,
left: 8, left: 8,
right: 8, right: 8,
} }
}; };
export const accountList = [
{
id: 12345,
account: "REDACTED-USER1",
fullName: "Alice Zheng",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
{
id: 345,
account: "REDACTED-USER2",
fullName: "Mike Chen",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
{
id: 88,
account: "REDACTED-USER3",
fullName: "Tory Cheng",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
];
export const knownScaleLineChartOptions = { export const knownScaleLineChartOptions = {
x: { x: {
type: 'time', type: 'time',

View File

@@ -20,7 +20,8 @@
"AccountActivation": "Account Activation", "AccountActivation": "Account Activation",
"Detail": "Detail", "Detail": "Detail",
"Edit": "Edit", "Edit": "Edit",
"AccountEdit": "Account Edit" "AccountEdit": "Account Edit",
"AccountInformation": "Account Information"
}, },
"Compare": { "Compare": {
"timeUsage": "Time Usage", "timeUsage": "Time Usage",

View File

@@ -1,8 +1,17 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { accountList, } from "@/constants/constants.js";
export default defineStore('acctMgmtStore', { export default defineStore('acctMgmtStore', {
state: () => ({ state: () => ({
isAcctMenuOpen: false, isAcctMenuOpen: false,
currentViewingUser: {
id: 12345,
account: "REDACTED-USER1",
fullName: "Alice Zheng",
adminRights: true,
accountActivation: true,
detail: "abcde",
}
}), }),
getters: { getters: {
}, },
@@ -22,5 +31,13 @@ export default defineStore('acctMgmtStore', {
toggleIsAcctMenuOpen() { toggleIsAcctMenuOpen() {
this.isAcctMenuOpen = !this.isAcctMenuOpen; this.isAcctMenuOpen = !this.isAcctMenuOpen;
}, },
/**
* For convenience, set current viewing data according to unique user ID.
* @param {number} userId
*/
setCurrentViewingUser(userId) {
const userFind = accountList.find(user => user.id === userId);
this.currentViewingUser = userFind ? userFind : {};
},
}, },
}) })

View File

@@ -1,12 +1,14 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { MODAL_ACCT_INFO, } from '@/constants/constants.js';
export const useModalStore = defineStore('modalStore', { export const useModalStore = defineStore('modalStore', {
state: () => ({ state: () => ({
isModalOpen: false, isModalOpen: false,
whichModal: MODAL_ACCT_INFO,
}), }),
actions: { actions: {
openModal() { openModal(whichModal) {
this.isModalOpen = true; this.isModalOpen = true;
this.whichModal = whichModal;
}, },
closeModal() { closeModal() {
this.isModalOpen = false; this.isModalOpen = false;

View File

@@ -54,8 +54,15 @@
import { storeToRefs, mapState, mapActions, } from 'pinia'; import { storeToRefs, mapState, mapActions, } from 'pinia';
import LoadingStore from '@/stores/loading.js'; import LoadingStore from '@/stores/loading.js';
import { useModalStore } from '@/stores/modal.js'; import { useModalStore } from '@/stores/modal.js';
import useAcctMgmtStore from '@/stores/acctMgmt.js';
import SearchBar from '../../../components/AccountMenu/SearchBar.vue'; import SearchBar from '../../../components/AccountMenu/SearchBar.vue';
import i18next from '@/i18n/i18n.js'; import i18next from '@/i18n/i18n.js';
import {
MODAL_CREATE_NEW,
MODAL_ACCT_EDIT,
MODAL_ACCT_INFO,
accountList,
} from "@/constants/constants.js";
const ONCE_RENDER_NUM_OF_DATA = 9; const ONCE_RENDER_NUM_OF_DATA = 9;
@@ -74,33 +81,6 @@ function repeatAccountList(accountList, N) {
return repeatedList; return repeatedList;
} }
const accountList = [
{
id: 12345,
account: "REDACTED-USER1",
fullName: "Alice Zheng",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
{
id: 345,
account: "REDACTED-USER2",
fullName: "Mike Chen",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
{
id: 88,
account: "REDACTED-USER3",
fullName: "Tory Cheng",
adminRights: true,
accountActivation: true,
detail: "abcde",
},
];
const repeatedAccountList = repeatAccountList(accountList, 20); const repeatedAccountList = repeatAccountList(accountList, 20);
export default { export default {
setup() { setup() {
@@ -166,12 +146,14 @@ export default {
}, },
onDetailBtnClick(dataId){ onDetailBtnClick(dataId){
this.openModal(); this.openModal(MODAL_ACCT_INFO);
this.setCurrentViewingUser(dataId);
}, },
onEditBtnClick(dataId){ onEditBtnClick(dataId){
this.openModal(); this.openModal(MODAL_ACCT_EDIT);
}, },
...mapActions(useModalStore, ['openModal']), ...mapActions(useModalStore, ['openModal']),
...mapActions(useAcctMgmtStore, ['setCurrentViewingUser']),
}, },
created() { created() {

View File

@@ -1,14 +1,7 @@
<template> <template>
<div id="modal_account_edit" class="w-[600px] h-[296px] bg-[#FFFFFF] rounded <div id="modal_account_edit" class="w-[600px] h-[296px] bg-[#FFFFFF] rounded
shadow-lg flex flex-col"> shadow-lg flex flex-col">
<header class="w-full flex h-[64px] justify-between pr-[22px] pl-[16px] items-center <ModalHeader :headerText="i18next.t('AcctMgmt.AccountEdit')"/>
border-b border-b-[1px] border-[#CBD5E1]
">
<h1 class="flex text-base font-bold"> {{ i18next.t("AcctMgmt.AccountEdit") }}</h1>
<img src="@/assets/icon-x.svg" alt="X" class="flex cursor-pointer"
@click="onCloseBtnClick"
/>
</header>
<main class="flex row h-[96px] my-[32px] flex-col px-8"> <main class="flex row h-[96px] my-[32px] flex-col px-8">
<div class="input-row w-full flex py-3"> <div class="input-row w-full flex py-3">
@@ -38,21 +31,25 @@
</template> </template>
<script> <script>
import { defineComponent } from 'vue';
import i18next from "@/i18n/i18n.js"; import i18next from "@/i18n/i18n.js";
import { mapActions, } from 'pinia'; import { mapActions, } from 'pinia';
import { useModalStore } from '@/stores/modal.js'; import { useModalStore } from '@/stores/modal.js';
import ModalHeader from "./ModalHeader.vue";
export default { export default defineComponent({
setup() { setup() {
return { return {
};
};
}, },
data() { data() {
return { return {
i18next: i18next, i18next: i18next,
}; };
}, },
components: {
ModalHeader,
},
methods: { methods: {
onConfirmBtnClick(){ onConfirmBtnClick(){
//TODO: //TODO:
@@ -65,7 +62,7 @@ export default {
}, },
...mapActions(useModalStore, ['closeModal']), ...mapActions(useModalStore, ['closeModal']),
} }
}; });
</script> </script>
<style> <style>

View File

@@ -0,0 +1,56 @@
<template>
<div id="modal_account_edit" class="w-[600px] h-[536px] bg-[#FFFFFF] rounded
shadow-lg flex flex-col">
<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 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>
</main>
<main class="flex main-part flex-col px-6 py-4">
<ul class="leading-[21px] list-disc list-inside">
<li>[2023-01-01 08:30:25] Account created by Lorrie Cheng.</li>
<li>[2023-01-01 08:30:25] Account created by Lorrie Cheng.</li>
<li>[2023-01-01 08:30:25] Account created by Lorrie Cheng.</li>
<li>[2023-01-01 08:30:25] Account created by Lorrie Cheng.</li>
</ul>
</main>
</div>
</template>
<script>
import i18next from '@/i18n/i18n.js';
import ModalHeader from './ModalHeader.vue';
import useAcctMgmtStore from '@/stores/acctMgmt.js';
export default {
setup(){
const acctMgmtStore = useAcctMgmtStore();
const visitTiime = 23;
const { currentViewingUser } = acctMgmtStore;
const {
id,
account,
fullName,
adminRights,
accountActivation,
detail
} = currentViewingUser;
return {
i18next,
visitTiime,
id,
account,
fullName,
adminRights,
accountActivation,
detail
};
},
components: {
ModalHeader,
}
}
</script>

View File

@@ -3,23 +3,43 @@
flex justify-center items-center"> flex justify-center items-center">
<div class="flex"> <div class="flex">
<ModalAccountEdit/> <ModalAccountEdit v-if="whichModal === MODAL_ACCT_EDIT"/>
<ModalAccountInfo v-if="whichModal === MODAL_ACCT_INFO"/>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { watch, computed, } from 'vue';
import { useModalStore } from '@/stores/modal.js'; import { useModalStore } from '@/stores/modal.js';
import ModalAccountEdit from './ModalAccountEdit.vue'; import ModalAccountEdit from './ModalAccountEdit.vue';
import ModalAccountInfo from './ModalAccountInfo.vue';
import {
MODAL_CREATE_NEW,
MODAL_ACCT_EDIT,
MODAL_ACCT_INFO,
} from "@/constants/constants.js";
export default { export default {
setup() { setup() {
const modalStore = useModalStore(); const modalStore = useModalStore();
const whichModal = computed(() => modalStore.whichModal);
watch(() => whichModal, (newVal, oldVal) => {
// (`whichModal changed from ${oldVal} to ${newVal}`);
});
return { return {
modalStore, modalStore,
whichModal,
MODAL_CREATE_NEW,
MODAL_ACCT_EDIT,
MODAL_ACCT_INFO,
}; };
}, },
components: { components: {
ModalAccountEdit, ModalAccountEdit,
ModalAccountInfo,
} }
}; };
</script> </script>

View File

@@ -0,0 +1,32 @@
<template>
<header class="w-full flex h-[64px] justify-between pr-[22px] pl-[16px] items-center
border-b border-b-[1px] border-[#CBD5E1]
">
<h1 class="flex text-base font-bold"> {{ headerText }}</h1>
<img src="@/assets/icon-x.svg" alt="X" class="flex cursor-pointer"
@click="closeModal"
/>
</header>
</template>
<script>
import { useModalStore } from '@/stores/modal.js';
export default {
props: {
headerText: {
type: String,
required: true // 确保 headerText 是必填的
}
},
setup(props) {
const modalStore = useModalStore();
const { headerText, } = props;
const { closeModal } = modalStore;
return {
headerText,
closeModal,
};
}
}
</script>