feature: create POST api done.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
export const PRIME_VUE_TICKS_LIMIT = 6;
|
export const PRIME_VUE_TICKS_LIMIT = 6;
|
||||||
export const ONCE_RENDER_NUM_OF_DATA = 6;
|
export const ONCE_RENDER_NUM_OF_DATA = 9;
|
||||||
|
|
||||||
export const GRID_COLOR = '#64748b';
|
export const GRID_COLOR = '#64748b';
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,28 @@ export default defineStore('acctMgmtStore', {
|
|||||||
isEditHovered: false,
|
isEditHovered: false,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Create new user in database.
|
||||||
|
* @param {object} userToCreate
|
||||||
|
* userToCreate {
|
||||||
|
* "username": "string",
|
||||||
|
* "password": "string",
|
||||||
|
* "name": "string",
|
||||||
|
* "is_admin": boolean,
|
||||||
|
* "is_active": boolean,
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
async createNewAccount(userToCreate) {
|
||||||
|
const apiCreateAccount = `/api/users`;
|
||||||
|
|
||||||
|
try{
|
||||||
|
const response = await this.$axios.post(apiCreateAccount, userToCreate);
|
||||||
|
console.log('TODO: response:', response, response.status);
|
||||||
|
}
|
||||||
|
catch(error) {
|
||||||
|
apiError(error, 'Failed to add a new account');
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* According to mouseover or mouseleave status, change the bool value.
|
* According to mouseover or mouseleave status, change the bool value.
|
||||||
* @param {string} username
|
* @param {string} username
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ import {
|
|||||||
import iconDetailOn from '@/assets/icon-detail-on.svg';
|
import iconDetailOn from '@/assets/icon-detail-on.svg';
|
||||||
import iconDetailOff from '@/assets/icon-detail-card.svg';
|
import iconDetailOff from '@/assets/icon-detail-card.svg';
|
||||||
|
|
||||||
|
// 這是製作假資料,在正式環境不會用到
|
||||||
function repeatAccountList(accountList, N) {
|
function repeatAccountList(accountList, N) {
|
||||||
const repeatedList = [];
|
const repeatedList = [];
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ function repeatAccountList(accountList, N) {
|
|||||||
const repeatedAccountList = repeatAccountList(accountList, 20);
|
const repeatedAccountList = repeatAccountList(accountList, 20);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup(props) {
|
setup() {
|
||||||
const acctMgmtStore = useAcctMgmtStore();
|
const acctMgmtStore = useAcctMgmtStore();
|
||||||
const loadingStore = LoadingStore();
|
const loadingStore = LoadingStore();
|
||||||
const modalStore = useModalStore();
|
const modalStore = useModalStore();
|
||||||
@@ -182,6 +182,8 @@ export default {
|
|||||||
internalInfiniteAcctData.value = allUserAccoutList.value.slice(0, ONCE_RENDER_NUM_OF_DATA)
|
internalInfiniteAcctData.value = allUserAccoutList.value.slice(0, ONCE_RENDER_NUM_OF_DATA)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isInfiniteFinish = ref(true);
|
||||||
|
|
||||||
const handleDeleteMouseOver = (username) => {
|
const handleDeleteMouseOver = (username) => {
|
||||||
acctMgmtStore.changeIsDeleteHoveredByUser(username, true);
|
acctMgmtStore.changeIsDeleteHoveredByUser(username, true);
|
||||||
};
|
};
|
||||||
@@ -229,12 +231,39 @@ export default {
|
|||||||
moveCurrentLoginUserToFirstRow();
|
moveCurrentLoginUserToFirstRow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 無限滾動: 監聽 scroll 有沒有滾到底部
|
||||||
|
* @param {element} event 滾動傳入的事件
|
||||||
|
*/
|
||||||
|
const handleScroll = (event) => {
|
||||||
|
if(internalInfiniteAcctData.value.length < ONCE_RENDER_NUM_OF_DATA || isInfiniteFinish.value === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = event.target;
|
||||||
|
const smallValue = 4;
|
||||||
|
|
||||||
|
const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight - smallValue;
|
||||||
|
|
||||||
|
if(overScrollHeight){
|
||||||
|
fetchMoreDataVue3();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchMoreDataVue3 = () => {
|
||||||
|
infiniteStart.value += ONCE_RENDER_NUM_OF_DATA;
|
||||||
|
internalInfiniteAcctData.value = [internalInfiniteAcctData.value, acctMgmtStore.allUserAccoutList.slice(
|
||||||
|
infiniteStart.value, this.infiniteStart + ONCE_RENDER_NUM_OF_DATA)];
|
||||||
|
isInfiniteFinish.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isLoading,
|
isLoading,
|
||||||
modalStore,
|
modalStore,
|
||||||
loginUserData,
|
loginUserData,
|
||||||
internalInfiniteAcctData,
|
internalInfiniteAcctData,
|
||||||
onCreateNewClick,
|
onCreateNewClick,
|
||||||
|
handleScroll,
|
||||||
getRowClass,
|
getRowClass,
|
||||||
onDeleteBtnClick,
|
onDeleteBtnClick,
|
||||||
handleDeleteMouseOver,
|
handleDeleteMouseOver,
|
||||||
@@ -276,11 +305,12 @@ export default {
|
|||||||
onAdminRightsBtnClick(isOn){
|
onAdminRightsBtnClick(isOn){
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 無限滾動: 監聽 scroll 有沒有滾到底部
|
* 無限滾動: 監聽 scroll 有沒有滾到底部
|
||||||
* @param {element} event 滾動傳入的事件
|
* @param {element} event 滾動傳入的事件
|
||||||
*/
|
*/
|
||||||
handleScroll(event) {
|
handleScrollVue2(event) {
|
||||||
if(this.infinitMaxItems || this.infiniteAcctData.length < ONCE_RENDER_NUM_OF_DATA || this.isInfiniteFinish === false) {
|
if(this.infinitMaxItems || this.infiniteAcctData.length < ONCE_RENDER_NUM_OF_DATA || this.isInfiniteFinish === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -291,13 +321,13 @@ export default {
|
|||||||
const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight - smallValue;
|
const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight - smallValue;
|
||||||
|
|
||||||
if(overScrollHeight){
|
if(overScrollHeight){
|
||||||
this.fetchMoreData();
|
this.fetchMoreDataVue2();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 無限滾動: 滾到底後,要載入數據
|
* 無限滾動: 滾到底後,要載入數據
|
||||||
*/
|
*/
|
||||||
async fetchMoreData() {
|
async fetchMoreDataVue2() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.infiniteFinish = false;
|
this.infiniteFinish = false;
|
||||||
this.infiniteStart += ONCE_RENDER_NUM_OF_DATA;
|
this.infiniteStart += ONCE_RENDER_NUM_OF_DATA;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<input id="input_account_field"
|
<input id="input_account_field"
|
||||||
class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
|
class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
|
||||||
:value="username"/>
|
v-model="inputUserAccount"/>
|
||||||
</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
|
||||||
justify-between">
|
justify-between">
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<input class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
|
<input class="w-[454px] rounded p-1 border border-[1px] border-[#64748B] flex items-center h-[40px] outline-none"
|
||||||
:value="name"/>
|
v-model="inputName"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!isSSO" class="input-row w-full flex py-2 h-[40px] mb-4 items-center
|
<div v-show="!isSSO" class="input-row w-full flex py-2 h-[40px] mb-4 items-center
|
||||||
justify-between">
|
justify-between">
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, computed, ref, } from 'vue';
|
import { defineComponent, computed, ref, watch, } 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';
|
||||||
@@ -133,8 +133,7 @@ export default defineComponent({
|
|||||||
const isPwdEyeOn = ref(false);
|
const isPwdEyeOn = ref(false);
|
||||||
const isPwdConfirmEyeOn = ref(false);
|
const isPwdConfirmEyeOn = ref(false);
|
||||||
const isPwdMatched = ref(true);
|
const isPwdMatched = ref(true);
|
||||||
const inputPwd = ref("");
|
|
||||||
const inputConfirmPwd = ref("");
|
|
||||||
const isSetAsAdminChecked = ref(false);
|
const isSetAsAdminChecked = ref(false);
|
||||||
const isSetActivedChecked = ref(true);
|
const isSetActivedChecked = ref(true);
|
||||||
|
|
||||||
@@ -148,6 +147,22 @@ export default defineComponent({
|
|||||||
const username = computed(() => acctMgmtStore.currentViewingUser.username);
|
const username = computed(() => acctMgmtStore.currentViewingUser.username);
|
||||||
const name = computed(() => acctMgmtStore.currentViewingUser.name);
|
const name = computed(() => acctMgmtStore.currentViewingUser.name);
|
||||||
|
|
||||||
|
const inputUserAccount = ref(whichCurrentModal.value === MODAL_CREATE_NEW ? '' : currentViewingUser.value.username);
|
||||||
|
const inputName = ref(whichCurrentModal.value === MODAL_CREATE_NEW ? '' : currentViewingUser.value.name);
|
||||||
|
const inputPwd = ref("");
|
||||||
|
const inputConfirmPwd = ref("");
|
||||||
|
|
||||||
|
// 自從加入這段 watch 之後,填寫密碼欄位之時,就不會胡亂清空掉 account 或是 full name 蘭為了。
|
||||||
|
watch(whichCurrentModal, (newVal) => {
|
||||||
|
if (newVal === MODAL_CREATE_NEW) {
|
||||||
|
inputUserAccount.value = '';
|
||||||
|
inputName.value = '';
|
||||||
|
} else {
|
||||||
|
inputUserAccount.value = currentViewingUser.value.username;
|
||||||
|
inputName.value = currentViewingUser.value.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const modalTitle = computed(() => {
|
const modalTitle = computed(() => {
|
||||||
return modalStore.whichModal === MODAL_CREATE_NEW ? i18next.t('AcctMgmt.CreateNew') : i18next.t('AcctMgmt.AccountEdit');
|
return modalStore.whichModal === MODAL_CREATE_NEW ? i18next.t('AcctMgmt.CreateNew') : i18next.t('AcctMgmt.AccountEdit');
|
||||||
});
|
});
|
||||||
@@ -164,13 +179,40 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const validateConfirmPwd = () => {
|
const validateConfirmPwd = () => {
|
||||||
|
let validateResult = true;
|
||||||
isPwdMatched.value = inputPwd.value === inputConfirmPwd.value;
|
isPwdMatched.value = inputPwd.value === inputConfirmPwd.value;
|
||||||
console.log('isPwdMatched.value',isPwdMatched.value );
|
return validateResult && isPwdMatched.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onConfirmBtnClick = () => {
|
const onConfirmBtnClick = () => {
|
||||||
validateConfirmPwd();
|
const validateResult = validateConfirmPwd();
|
||||||
|
if(!validateResult){
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
//TODO: 這邊要記得回來加一個判斷帳號是否已經存在的邏輯
|
||||||
|
checkAccountIsUnique();
|
||||||
|
console.log('input content to feed in',
|
||||||
|
inputUserAccount.value,
|
||||||
|
inputPwd.value,
|
||||||
|
inputName.value,
|
||||||
|
isSetAsAdminChecked.value,
|
||||||
|
isSetActivedChecked.value,
|
||||||
|
);
|
||||||
|
acctMgmtStore.createNewAccount({
|
||||||
|
username: inputUserAccount.value,
|
||||||
|
password: inputPwd.value,
|
||||||
|
name: inputName.value,
|
||||||
|
is_admin: isSetAsAdminChecked.value,
|
||||||
|
is_active: isSetActivedChecked.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAccountIsUnique = async() => {
|
||||||
|
let isAccountUnique = false;
|
||||||
|
//TODO: call pinia store to call backend API
|
||||||
|
return isAccountUnique;
|
||||||
|
};
|
||||||
|
|
||||||
const toggleIsAdmin = () => {
|
const toggleIsAdmin = () => {
|
||||||
isSetAsAdminChecked.value = !isSetAsAdminChecked.value;
|
isSetAsAdminChecked.value = !isSetAsAdminChecked.value;
|
||||||
@@ -190,6 +232,8 @@ export default defineComponent({
|
|||||||
togglePwdEyeBtn,
|
togglePwdEyeBtn,
|
||||||
togglePwdConfirmEyeBtn,
|
togglePwdConfirmEyeBtn,
|
||||||
isPwdMatched,
|
isPwdMatched,
|
||||||
|
inputUserAccount,
|
||||||
|
inputName,
|
||||||
inputPwd,
|
inputPwd,
|
||||||
inputConfirmPwd,
|
inputConfirmPwd,
|
||||||
onConfirmBtnClick,
|
onConfirmBtnClick,
|
||||||
|
|||||||
Reference in New Issue
Block a user