WIP: can hover icon-delete. can have self on the first row on list.

API get all users done
This commit is contained in:
Cindy Chang
2024-06-21 11:14:49 +08:00
parent 193bc315ca
commit 1b8c8629a9
6 changed files with 204 additions and 57 deletions

View File

@@ -5,20 +5,31 @@
<SearchBar/>
</div>
<div id="acct_mgmt_data_grid" class="flex w-full overflow-y-auto h-[570px]" @scroll="handleScroll">
<DataTable :value="infiniteAcctData" dataKey="id" tableClass="w-full mt-4 text-sm relative table-fixed"
<DataTable :value="internalInfiniteAcctData" dataKey="username" tableClass="w-full mt-4 text-sm relative table-fixed"
>
<Column field="account" :header="i18next.t('AcctMgmt.Account')" bodyClass="font-medium" sortable>
<template #body="slotProps">
<div class="flex w-full h-full whole-row"
:class="{
'hover:bg-[#CBD5E1]': slotProps.data.isRowHovered,
}"
@mouseover="handleRowMouseOver(slotProps.data.username)"
@mouseout="handleRowMouseOut(slotProps.data.username)"
> <!--處理一整列的互動監聽-->
</div>
</template>
<Column field="username" :header="i18next.t('AcctMgmt.Account')" bodyClass="font-medium" sortable>
<template #body="slotProps">
<div @dblclick="onAcctDoubleClick()" class="cursor-pointer">
{{ slotProps.data.account }}
{{ slotProps.data.username }}
</div>
</template>
</Column>
<Column field="fullName" :header="i18next.t('AcctMgmt.FullName')" bodyClass="text-neutral-500" sortable></Column>
<Column field="adminRights" :header="i18next.t('AcctMgmt.AdminRights')" bodyClass="text-neutral-500 flex justify-center"
<Column field="name" :header="i18next.t('AcctMgmt.FullName')" bodyClass="text-neutral-500" sortable></Column>
<Column field="is_admin" :header="i18next.t('AcctMgmt.AdminRights')" bodyClass="text-neutral-500 flex justify-center"
headerClass="header-center">
<template #body="slotProps">
<img v-if="slotProps.data.adminRights" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"
<img v-if="slotProps.data.is_admin" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"
@click="onAdminRightsBtnClick(true)"
/>
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex"
@@ -26,24 +37,36 @@
/>
</template>
</Column>
<Column field="accountActivation" :header="i18next.t('AcctMgmt.AccountActivation')" bodyClass="text-neutral-500"
<Column field="is_active" :header="i18next.t('AcctMgmt.AccountActivation')" bodyClass="text-neutral-500"
headerClass="header-center">
<template #body="slotProps">
<div class="w-full flex justify-center">
<img v-if="slotProps.data.accountActivation" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"/>
<img v-if="slotProps.data.is_active" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"/>
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex"/>
</div>
</template>
</Column>
<Column field="detail" :header="i18next.t('AcctMgmt.Detail')" bodyClass="text-neutral-500">
<Column :header="i18next.t('AcctMgmt.Detail')" bodyClass="text-neutral-500">
<template #body="slotProps">
<img src="@/assets/icon-detail-card.svg" alt="Detail" class="cursor-pointer" @click="onDetailBtnClick(slotProps.data.id)"/>
<img src="@/assets/icon-detail-card.svg" alt="Detail" class="cursor-pointer" @click="onDetailBtnClick(slotProps.data.username)"/>
</template>
</Column>
<Column field="edit" :header="i18next.t('AcctMgmt.Edit')" bodyClass="text-neutral-500">
<Column :header="i18next.t('AcctMgmt.Edit')" bodyClass="text-neutral-500">
<template #body="slotProps">
<img src="@/assets/icon-edit.svg" alt="Edit" class="cursor-pointer" @click="onEditBtnClick(slotProps.data.id)"/>
</template></Column>
<img src="@/assets/icon-edit.svg" alt="Edit" class="cursor-pointer" @click="onEditBtnClick(slotProps.data.username)"/>
</template>
</Column>
<Column :header="i18next.t('AcctMgmt.Delete')" bodyClass="text-neutral-500">
<template #body="slotProps">
<img :src="slotProps.data.isDeleteHovered ? iconDeleteRed : iconDeleteGray"
:alt="slotProps.data.isDeleteHovered ? 'hovered' : 'not-hovered'"
class="cursor-pointer"
@mouseover="handleDeleteMouseOver(slotProps.data.username)"
@mouseout="handleDeleteMouseOut(slotProps.data.username)"
@click="onDeleteBtnClick(slotProps.data.username)"
>
</template>
</Column>
</DataTable>
</div>
</div>
@@ -51,10 +74,12 @@
</template>
<script>
import { ref, computed, onBeforeMount, watch, } from 'vue';
import { storeToRefs, mapState, mapActions, } from 'pinia';
import LoadingStore from '@/stores/loading.js';
import { useModalStore } from '@/stores/modal.js';
import useAcctMgmtStore from '@/stores/acctMgmt.js';
import piniaLoginStore from '@/stores/login.js';
import SearchBar from '../../../components/AccountMenu/SearchBar.vue';
import i18next from '@/i18n/i18n.js';
import {
@@ -63,6 +88,8 @@ import {
MODAL_ACCT_INFO,
accountList,
} from "@/constants/constants.js";
import iconDeleteGray from '@/assets/icon-delete-gray.svg';
import iconDeleteRed from '@/assets/icon-delete-red.svg';
const ONCE_RENDER_NUM_OF_DATA = 9;
@@ -81,23 +108,90 @@ function repeatAccountList(accountList, N) {
return repeatedList;
}
// 這是製作假資料,在正式環境不會用到
const repeatedAccountList = repeatAccountList(accountList, 20);
export default {
setup() {
setup(props) {
const acctMgmtStore = useAcctMgmtStore();
const loadingStore = LoadingStore();
const modalStore = useModalStore();
const { isLoading } = storeToRefs(loadingStore);
const loginStore = piniaLoginStore();
const internalInfiniteAcctData = ref([]);
const loginUserData = ref(null);
const allUserAccoutList = computed(() => acctMgmtStore.allUserAccoutList);
const fetchLoginUserData = async () => {
await loginStore.getUserData();
loginUserData.value = loginStore.userData;
};
const moveCurrentLoginUserToFirstRow = () => {
const currentLoginUsername = loginUserData.value.username;
if(internalInfiniteAcctData.value && internalInfiniteAcctData.value.length){
const index = internalInfiniteAcctData.value.findIndex(user => user.username === currentLoginUsername);
if (index !== -1) {
// 移除匹配的對象(現正登入的使用者)並將其插入到陣列的第一位"
const [user] = internalInfiniteAcctData.value.splice(index, 1);
internalInfiniteAcctData.value.unshift(user);
}
}
};
const getFirstPageUserData = async() => {
await acctMgmtStore.getAllUserAccounts();
internalInfiniteAcctData.value = allUserAccoutList.value.slice(0, ONCE_RENDER_NUM_OF_DATA)
};
const handleDeleteMouseOver = (username) => {
acctMgmtStore.changeIsDeleteHoveredByUser(username, true);
};
const handleDeleteMouseOut = (username) => {
acctMgmtStore.changeIsDeleteHoveredByUser(username, false);
};
const handleRowMouseOver = (username) => {
acctMgmtStore.changeIsRowHoveredByUser(username, true);
};
const handleRowMouseOut = (username) => {
acctMgmtStore.changeIsRowHoveredByUser(username, false);
};
const onDeleteBtnClick = (usernameToDelete) => {
};
onBeforeMount(async () => {
await fetchLoginUserData();
await getFirstPageUserData();
moveCurrentLoginUserToFirstRow();
});
return {
isLoading,
modalStore,
loginUserData,
internalInfiniteAcctData,
onDeleteBtnClick,
handleDeleteMouseOver,
handleDeleteMouseOut,
handleRowMouseOver,
handleRowMouseOut,
iconDeleteGray,
iconDeleteRed,
};
},
data() {
return {
i18next: i18next,
repeatedAccountList: repeatedAccountList,
infiniteAcctData: repeatedAccountList.slice(0, ONCE_RENDER_NUM_OF_DATA),
infiniteAcctData: [],
infiniteStart: 0,
isInfiniteFinish: true,
isInfinitMaxItemsMet: false,
@@ -106,6 +200,9 @@ export default {
components: {
SearchBar,
},
computed: {
...mapState(useAcctMgmtStore, ['allUserAccoutList']),
},
methods: {
onAcctDoubleClick(){
@@ -139,25 +236,30 @@ export default {
this.infiniteFinish = false;
this.infiniteStart += ONCE_RENDER_NUM_OF_DATA;
// await this.acctMgmtStore.getAccountDetail();
this.infiniteAcctData = await [...this.infiniteAcctData, ...this.repeatedAccountList.slice(
this.infiniteAcctData = await [...this.infiniteAcctData, ...this.allUserAccoutList.slice(
this.infiniteStart, this.infiniteStart + ONCE_RENDER_NUM_OF_DATA)];
this.isInfiniteFinish = true;
this.isLoading = false;
},
onDetailBtnClick(dataId){
onDetailBtnClick(dataKey){
this.openModal(MODAL_ACCT_INFO);
this.setCurrentViewingUser(dataId);
this.setCurrentViewingUser(dataKey);
},
onEditBtnClick(dataId){
onEditBtnClick(dataKey){
this.openModal(MODAL_ACCT_EDIT);
this.setCurrentViewingUser(dataId);
this.setCurrentViewingUser(dataKey);
},
moveCurrentLoginUserToFirstRow(){
},
...mapActions(useModalStore, ['openModal']),
...mapActions(useAcctMgmtStore, ['setCurrentViewingUser']),
...mapActions(useAcctMgmtStore, [
'setCurrentViewingUser',
'getAllUserAccounts',
]),
},
created() {
},
mounted() {
this.isLoading = false; //TODO: