add new user

parent 8a73e130
......@@ -27,4 +27,5 @@ export enum API_PATHS {
getUserGroupDetail = '/user/group/detail',
updateUserGroupInfo = '/user/group/update',
getListUsers = '/user/list',
addNewUser = '/user/add',
}
const isEmail = (str: string) => {
const email = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return email.test(str);
};
const isMobilePhone = (str: string) => {
const phoneNot84 = /[0]{1}[0-9]{9,11}$/;
const phone84 = /^[84]{2}[0-9]{9,11}$/;
return phoneNot84.test(str) || phone84.test(str);
};
export { isEmail, isMobilePhone };
import { defineComponent } from 'vue';
import { i18n } from 'src/boot/i18n';
import { isEmail } from '../../../boot/functions';
import { isMobilePhone } from '../../../boot/functions';
export default defineComponent({
props: {
showDialog: {
type: Boolean,
required: true,
},
userName: { type: String, required: true },
password: { type: String, required: true },
fullName: { type: String, required: true },
email: { type: String, required: true },
mobileNumber: { type: String, required: true },
address: { type: String, required: true },
phoneNumber: { type: String, required: true },
unit: { type: String, required: true },
sex: { type: Number, required: true },
sexOptions: { type: Array, required: true },
birthday: { type: String, required: true },
group: { type: Number, required: true },
listGroup: { type: Array, required: true },
scheduleAccess: { type: String, required: true },
listScheduleAccess: { type: Array, required: true },
status: { type: Boolean, required: true },
},
setup() {
const userNameRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireUserName'),
];
const passwordRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requirePassword'),
];
const fullNameRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireFullName'),
];
const emailRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireEmail'),
(val: string) =>
isEmail(val) || i18n.global.t('userPage.validateMessages.isEmail'),
];
const mobileNumberRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireMobileNumber'),
(val: string) =>
isMobilePhone(val) ||
i18n.global.t('userPage.validateMessages.isMobilePhone'),
];
const addressRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireAddress'),
];
const unitRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('userPage.validateMessages.requireUnit'),
];
const sexRules = [
(val?: number) =>
val !== undefined ||
i18n.global.t('userPage.validateMessages.requireSex'),
];
const groupRules = [
(val?: number) =>
val !== undefined ||
i18n.global.t('userPage.validateMessages.requiredGroup'),
];
return {
userNameRules,
passwordRules,
fullNameRules,
emailRules,
mobileNumberRules,
addressRules,
unitRules,
sexRules,
groupRules,
};
},
emits: [
'update:showDialog',
'click:CloseBtn',
'update:userName',
'update:password',
'update:fullName',
'update:email',
'update:mobileNumber',
'update:address',
'update:phoneNumber',
'update:unit',
'update:sex',
'update:birthday',
'update:group',
'update:scheduleAccess',
'update:status',
'addNewUser',
],
});
<template>
<q-dialog
persistent
:model-value="showDialog"
@update:model-value="$emit('update:showDialog', $event)"
>
<q-card style="min-width: 900px" bordered>
<q-form greedy @submit.prevent="$emit('addNewUser')">
<q-card-section>
<q-item>
<q-item-section>
<q-item-label class="text-h6 text-weight-regular">{{
$t('userPage.dialogLabel.title.addUser')
}}</q-item-label>
</q-item-section>
</q-item>
</q-card-section>
<q-separator />
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-6">
<q-input
:model-value="userName"
@update:model-value="$emit('update:userName', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.userName')"
:rules="userNameRules"
hide-bottom-space
type="text"
class="q-my-sm"
outlined
></q-input>
<q-input
:model-value="password"
@update:model-value="$emit('update:password', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.password')"
type="password"
class="q-my-sm"
outlined
:rules="passwordRules"
hide-bottom-space
></q-input>
<q-input
:model-value="fullName"
@update:model-value="$emit('update:fullName', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.fullName')"
type="text"
class="q-my-sm"
outlined
:rules="fullNameRules"
hide-bottom-space
></q-input>
<q-input
:model-value="email"
@update:model-value="$emit('update:email', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.email')"
type="text"
class="q-my-sm"
outlined
:rules="emailRules"
hide-bottom-space
></q-input>
<q-input
:model-value="mobileNumber"
@update:model-value="$emit('update:mobileNumber', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.mobileNumber')"
type="number"
class="q-my-sm"
outlined
:rules="mobileNumberRules"
hide-bottom-space
></q-input>
<q-input
:model-value="address"
@update:model-value="$emit('update:address', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.address')"
type="text"
class="q-my-sm"
outlined
:rules="addressRules"
hide-bottom-space
></q-input>
</div>
<div class="col-6">
<q-input
:model-value="phoneNumber"
@update:model-value="$emit('update:phoneNumber', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.phoneNumber')"
type="number"
class="q-my-sm"
outlined
></q-input>
<q-input
:model-value="unit"
@update:model-value="$emit('update:unit', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.unit')"
type="text"
class="q-my-sm"
outlined
:rules="unitRules"
hide-bottom-space
></q-input>
<q-select
:model-value="sex"
emit-value
@update:model-value="$emit('update:sex', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.sex')"
class="q-my-sm"
:options="sexOptions"
option-value="id"
option-label="text"
outlined
map-options
:rules="sexRules"
hide-bottom-space
></q-select>
<q-input
:model-value="birthday"
@update:model-value="$emit('update:birthday', $event)"
type="date"
class="q-my-sm"
outlined
>
<template v-slot:prepend>
<div class="text-body2">
{{ $t('userPage.dialogLabel.fieldLabels.birthday') }}
</div>
</template>
</q-input>
<q-select
:model-value="group"
@update:model-value="$emit('update:group', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.group')"
class="q-my-sm"
outlined
:options="listGroup"
option-value="id"
option-label="groupName"
map-options
emit-value
:rules="groupRules"
hide-bottom-space
></q-select>
<q-select
:model-value="scheduleAccess"
@update:model-value="$emit('update:scheduleAccess', $event)"
:label="$t('userPage.dialogLabel.fieldLabels.scheduleAccess')"
:options="listScheduleAccess"
class="q-my-sm"
outlined
></q-select>
</div>
<q-space></q-space>
<div class="col-6">
<span class="text-body1">{{
$t('userPage.dialogLabel.fieldLabels.status')
}}</span
><q-toggle
:model-value="status"
@update:model-value="$emit('update:status', $event)"
/>
</div>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
type="submit"
color="primary"
:label="$t('userPage.crudActions.save')"
/>
<q-btn
color="black"
:label="$t('userPage.crudActions.cancel')"
@click="$emit('click:CloseBtn')"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<script lang="ts" src="./AddNewUserDialog.ts"></script>
import { defineComponent } from 'vue';
export default defineComponent({});
<template>
<div>My component</div>
</template>
<script lang="ts" src="./UpdateUserDialog.ts"></script>
......@@ -73,5 +73,43 @@ export default {
active: 'Đang hoạt động',
inactive: 'Ngừng hoạt động',
},
dialogLabel: {
title: {
addUser: 'Thêm mới người dùng',
updateUser: 'Cập nhật người dùng',
},
fieldLabels: {
userName: 'Tên đăng nhập *',
password: 'Mật khẩu *',
fullName: 'Họ Tên *',
email: 'Email *',
mobileNumber: 'Số điện thoại *',
address: 'Địa chỉ *',
phoneNumber: 'Số máy bàn',
unit: 'Đơn vị phòng ban *',
sex: 'Giới tính *',
birthday: 'Ngày sinh',
group: 'Thuộc nhóm *',
scheduleAccess: 'Lịch truy cập',
status: 'Trạng thái',
},
},
crudActions: {
save: 'Lưu',
cancel: 'Đóng',
},
validateMessages: {
requireUserName: 'Tên đăng nhập không hợp lệ',
requirePassword: 'Vui lòng nhập mật khẩu',
requireFullName: 'Vui lòng nhập họ tên',
requireEmail: 'Vui lòng nhập Email',
isEmail: 'Email không hợp lệ',
requireMobileNumber: 'Vui lòng nhập số điện thoại',
isMobilePhone: 'Số điện thoại không hợp lệ',
requireAddress: 'Vui lòng nhập địa chỉ',
requireUnit: 'Vui lòng nhập địa chỉ phòng ban',
requireSex: 'Vui lòng chọn giới tính',
requiredGroup: 'Vui lòng chọn nhóm người dùng',
},
},
};
import { AxiosResponse } from 'axios';
import { Notify } from 'quasar';
import { API_PATHS, config } from 'src/assets/configurations';
import { PaginationResponse, UserObject } from 'src/assets/type';
import { api, BaseResponseBody } from 'src/boot/axios';
import { i18n } from 'src/boot/i18n';
import { computed, defineComponent, onMounted, Ref, ref } from 'vue';
import { useStore } from '../../store/index';
import { computed, defineComponent, onMounted, ref, Ref } from 'vue';
import AddNewUserDialogComponent from '../../components/user-management/add-new-user-dialog/index.vue';
import { GroupInfoType } from '../nhom-nguoi-dung/UserGroup';
export default defineComponent({
components: { AddNewUserDialogComponent },
setup() {
const totalPage = ref(0);
const pageIndex = ref(1);
......@@ -70,6 +75,27 @@ export default defineComponent({
];
const userTableRows: Ref<UserObject[]> = ref([]);
const keyword = ref('');
const showDialog = ref(false);
const userName = ref('');
const password = ref('');
const fullName = ref('');
const birthday: Ref<string | undefined> = ref();
const email = ref('');
const phoneNumber = ref('');
const mobileNumber = ref('');
const sex: Ref<number | undefined> = ref();
const sexOptions = ref([
{ id: 1, text: 'Nam' },
{ id: 2, text: 'Nữ' },
]);
const address = ref('');
const unit = ref('');
const status: Ref<boolean> = ref(true);
const listGroup: Ref<{ id: number; groupName: string }[]> = ref([]);
const group: Ref<number | undefined> = ref();
const scheduleAccess = ref('Chưa có lịch truy cập');
const listScheduleAccess = ref(['Chưa có lịch truy cập']);
const getListUsers = async () => {
try {
......@@ -95,8 +121,62 @@ export default defineComponent({
);
});
const $store = useStore();
const getListUserGroup = async () => {
await $store.dispatch('authentication/getListUsers').then((response) => {
const res = response as AxiosResponse<
BaseResponseBody<GroupInfoType[]>
>;
if (!res.data.error.code) {
res.data.data.map((item) => {
listGroup.value.push({ id: item.id, groupName: item.groupName });
});
}
});
};
const addNewUser = async () => {
try {
const response = (await api({
url: API_PATHS.addNewUser,
method: 'POST',
data: {
user: {
id: 2,
userName: userName.value,
password: password.value,
fullName: fullName.value,
birthday: birthday.value,
email: email.value,
phoneNumber: phoneNumber.value,
mobileNumber: mobileNumber.value,
sex: sex.value,
address: address.value,
unit: unit.value,
status: status.value ? 1 : 0,
},
groups: [{ id: group.value }],
pageRoles: [],
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
showDialog.value = false;
Notify.create({
type: 'positive',
message: i18n.global.t(
'userGroupPage.groupInfo.actionMessages.addNewSuccess'
),
});
void getListUsers();
}
} catch (error) {}
};
onMounted(() => {
void getListUsers();
void getListUserGroup();
});
return {
rows: userTableRows,
......@@ -106,6 +186,25 @@ export default defineComponent({
pageSize,
keyword,
filterListUser,
showDialog,
userName,
password,
fullName,
birthday,
email,
phoneNumber,
mobileNumber,
sex,
address,
unit,
status,
group,
scheduleAccess,
sexOptions,
listGroup,
listScheduleAccess,
addNewUser,
getListUserGroup,
};
},
});
......@@ -22,13 +22,17 @@
</div>
<q-space></q-space>
<div class="col-auto flex flex-center">
<q-btn color="primary" :label="$t('crudActions.add')"></q-btn>
<q-btn
@click="showDialog = true"
:label="$t('crudActions.add')"
color="primary"
></q-btn>
</div>
</div>
</q-th>
</template>
<template v-slot:body-cell-status="rowData">
<q-td class="flex flex-center">
<q-td>
<q-chip
:color="rowData.value ? 'positive' : undefined"
text-color="white"
......@@ -42,6 +46,24 @@
</q-chip>
</q-td>
</template>
<template v-slot:body-cell-action>
<q-td style="padding: 0" class="flex flex-center">
<q-btn
flat
round
color="primary"
icon="mdi-account-edit-outline
"
></q-btn>
<q-btn
flat
round
color="primary"
icon="mdi-account-convert-outline"
></q-btn>
<q-btn flat round color="primary" icon="delete"></q-btn>
</q-td>
</template>
</q-table>
</div>
<div class="col-12 q-pa-lg flex flex-center">
......@@ -56,6 +78,28 @@
icon-next="fast_forward"
/>
</div>
<AddNewUserDialogComponent
v-model:show-dialog="showDialog"
v-model:user-name="userName"
v-model:password="password"
v-model:full-name="fullName"
v-model:email="email"
v-model:mobile-number="mobileNumber"
v-model:address="address"
v-model:phone-number="phoneNumber"
v-model:unit="unit"
v-model:sex="sex"
:sex-options="sexOptions"
v-model:birthday="birthday"
v-model:group="group"
:list-group="listGroup"
v-model:schedule-access="scheduleAccess"
:list-schedule-access="listScheduleAccess"
v-model:status="status"
@click:CloseBtn="showDialog = false"
@addNewUser="addNewUser"
></AddNewUserDialogComponent>
</div>
</template>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment