Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion app/composables/api/profile/useProfile.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import type {
ProfileDTO,
EditProfileDTO,
DeleteProfileDTO,
ChangePasswordDTO,
} from '@/types'

const loadingGetItemById = ref(false)
const loadingEditItem = ref(false)
const loadingDeleteItem = ref(false)
const loadingCancelDeleteItem = ref(false)
const loadingChangeGroup = ref(false)
const loadingChangePassword = ref(false)
const NAME = 'Profile'

export const useProfile = () => {
const { $toast } = useNuxtApp()
const auth = useAuth()
const { handleApiResponseError, handleApiCatchError, createApiFailure } = useApiErrorHandler()

const getItemById = async (id: string) => {
loadingGetItemById.value = true
Expand Down Expand Up @@ -304,7 +307,33 @@ export const useProfile = () => {
}
}

const changePassword = async (item: ChangePasswordDTO) => {
try {
loadingChangePassword.value = true
const response = await useApiService.put<
ApiResult<boolean>
>('/api/v1/users/password', { ...item })

if (response.status == 1) {
$toast.success('Password changed successfully')
}
else {
handleApiResponseError(response)
}

return response
}
catch (err: unknown) {
handleApiCatchError(err)

return createApiFailure<boolean>(err, false)
}
finally {
loadingChangePassword.value = false
}
}

return {
getItemById, loadingGetItemById, editItem, loadingEditItem, deleteItem, loadingDeleteItem, cancelDeleteItem, loadingCancelDeleteItem, changeGroup, loadingChangeGroup,
getItemById, loadingGetItemById, editItem, loadingEditItem, deleteItem, loadingDeleteItem, cancelDeleteItem, loadingCancelDeleteItem, changeGroup, loadingChangeGroup, changePassword, loadingChangePassword,
}
}
4 changes: 2 additions & 2 deletions app/composables/useValidationRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ export const useValidationRules = () => {
|| 'Password must contain uppercase, lowercase, number and special character'

// Confirmation validation
const matches = (target: Ref<string> | string, fieldName = 'field') =>
const matches = (target: Ref<string> | string, fieldName = 'field', message?: string) =>
(v: string) => {
const targetValue
= typeof target === 'string' ? target : target.value
return v === targetValue || `Must match ${fieldName}`
return v === targetValue || message || `Must match ${fieldName}`
}

// Array validation
Expand Down
72 changes: 27 additions & 45 deletions app/pages/user/edit-pass.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<v-row>
<v-col
cols="12"
class="pl-5 text-h4 teal--text"
class="pl-5 text-h4 text-grey700"
>
<v-icon
large
Expand All @@ -25,7 +25,7 @@
label="Current password"
outlined
rounded="lg"
color="#FFB600"
color="primary"
:append-inner-icon="
showCurrentPassword ? 'md:visibility' : 'md:visibility_off'
"
Expand All @@ -46,7 +46,7 @@
label="New password"
outlined
rounded="lg"
color="#FFB600"
color="primary"
:append-inner-icon="
showNewPassword ? 'md:visibility' : 'md:visibility_off'
"
Expand All @@ -67,7 +67,7 @@
label="Repeat new password"
outlined
rounded="lg"
color="#FFB600"
color="primary"
:append-inner-icon="
showRepeatNewPassword ? 'md:visibility' : 'md:visibility_off'
"
Expand All @@ -91,7 +91,7 @@
class="text-h5 font-weight-bold"
color="success"
:disabled="!isFormValid"
:loading="loading"
:loading="loadingChangePassword"
@click="updatePassword"
>
Submit
Expand Down Expand Up @@ -146,17 +146,6 @@
</template>

<script setup lang="ts">
interface ApiError {
response?: {
status?: number
data?: {
message?: string
[key: string]: unknown
}
}
message?: string
[key: string]: unknown
}
definePageMeta({
layout: 'dashboard-layout',
})
Expand All @@ -165,9 +154,16 @@ useSeoMeta({
title: 'Change Password',
})

const { $dayjs, $toast } = useNuxtApp()
const { $dayjs } = useNuxtApp()
const router = useRouter()
const { user } = useUser()
const { changePassword, loadingChangePassword } = useProfile()
const {
required,
minLength,
pattern,
matches,
} = useValidationRules()

const showCurrentPassword = ref(false)
const currentPassword = ref('')
Expand All @@ -178,23 +174,19 @@ const newPassword = ref('')
const showRepeatNewPassword = ref(false)
const repeatNewPassword = ref('')

const loading = ref(false)

const requiredRule = (v: string) => !!v || 'This field is required'
const requiredRule = required

const passwordRules = [
(v: string) => !!v || 'Password is required',
(v: string) => v.length >= 8 || 'Minimum 8 characters',
(v: string) =>
/[A-Z]/.test(v) || 'Must include at least one uppercase letter',
(v: string) =>
/[a-z]/.test(v) || 'Must include at least one lowercase letter',
(v: string) => /\d/.test(v) || 'Must include at least one number',
required,
minLength(8),
pattern(/[A-Z]/, 'Must include at least one uppercase letter'),
pattern(/[a-z]/, 'Must include at least one lowercase letter'),
pattern(/\d/, 'Must include at least one number'),
]

const repeatPasswordRules = [
(v: string) => !!v || 'Repeat password is required',
(v: string) => v === newPassword.value || 'Passwords do not match',
required,
matches(newPassword, 'passwords', 'Passwords do not match'),
]

const currentTime = ref($dayjs())
Expand Down Expand Up @@ -236,25 +228,15 @@ const isFormValid = computed(() => {
const updatePassword = async () => {
if (!isFormValid.value) return

try {
loading.value = true
const response = await changePassword({
oldpass: currentPassword.value,
newpass: newPassword.value,
repeat_newpass: repeatNewPassword.value,
})

const payload = {
oldpass: currentPassword.value,
newpass: newPassword.value,
repeat_newpass: repeatNewPassword.value,
}
await useApiService.put('/api/v1/users/password', payload)
$toast.success('Password changed successfully')
if (response?.succeeded) {
router.push('/user')
}
catch (err: unknown) {
const error = err as ApiError
$toast.error(error?.response?.data?.message || 'Failed to change password')
}
finally {
loading.value = false
}
}
</script>

Expand Down
Loading