Update Account

This commit is contained in:
ThienPhamVan
2026-03-30 14:09:41 +07:00
parent e7e8f0b38a
commit e1b9d9c15d
11 changed files with 1029 additions and 280 deletions

115
components/OtpInput.vue Normal file
View File

@@ -0,0 +1,115 @@
<template>
<div class="otp-wrapper">
<input
v-for="(item, index) in length"
:key="index"
ref="inputs"
type="text"
inputmode="numeric"
maxlength="1"
class="otp-input"
v-model="codes[index]"
@input="handleInput(index)"
@keydown.backspace="handleBackspace(index)"
@paste="handlePaste"
/>
</div>
</template>
<script>
export default {
props: {
length: {
type: Number,
default: 9,
},
value: {
type: String,
default: '',
},
},
data() {
return {
codes: Array(this.length).fill(''),
};
},
methods: {
handleInput(index) {
const value = this.codes[index];
// Chỉ cho nhập số
if (!/^[0-9a-zA-Z]?$/.test(value)) {
this.codes[index] = '';
return;
}
// Tự nhảy sang ô tiếp theo
if (value && index < this.length - 1) {
this.$refs.inputs[index + 1].focus();
}
this.emitValue();
},
handleBackspace(index) {
if (!this.codes[index] && index > 0) {
this.$refs.inputs[index - 1].focus();
}
},
handlePaste(event) {
event.preventDefault();
const paste = event.clipboardData.getData('text').trim();
if (!paste) return;
const values = paste
.replace(/[^0-9a-zA-Z]/g, '')
.slice(0, this.length)
.split('');
this.codes = Array(this.length).fill('');
values.forEach((char, i) => {
this.codes[i] = char;
});
this.$nextTick(() => {
const index = Math.min(values.length, this.length - 1);
this.$refs.inputs[index]?.focus();
});
this.emitValue();
},
emitValue() {
const code = this.codes.join('');
this.$emit('input', code);
},
},
};
</script>
<style lang="scss">
.otp-wrapper {
display: flex;
gap: 10px;
justify-content: center;
.otp-input {
width: 42px;
height: 48px;
text-align: center;
font-size: 18px;
border: 1px solid #e5e7eb;
border-radius: 8px;
outline: none;
transition: all 0.2s;
&:focus {
border-color: #16a34a;
box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.2);
}
}
}
</style>

View File

@@ -0,0 +1,182 @@
import { COMPANY } from '~/constants/company';
export default function sendVerificationEmail(
customer,
emailCustomer,
code,
urlVerify,
companyName = COMPANY.name,
office = COMPANY.address,
website = COMPANY.website,
emailCompany = COMPANY.email.support,
hotline = COMPANY.phone.hotline,
) {
return `
<div style="font-family: Arial, Helvetica, sans-serif; line-height: 1.5; background-color: #f0fdf4; font-size: 16px; color: #000; padding: 26px 0;">
<div
style="
max-width: 600px;
margin: 0 auto;
padding: 40px 20px;
border: 1px solid #53b147;
border-radius: 16px;
background-color: #fff;
"
>
<div style="text-align: center">
<img src="https://bigdatatech.cloud/logo.png" alt="Logo" width="150" style="display: block; margin: 0 auto" />
</div>
<div style="margin-top: 1rem">
<h2 style="font-size: 18px; font-weight: 700; text-align: center">Xác thực tài khoản người dùng</h2>
<p style="font-weight: 700">Kính gửi quý khách hàng: ${customer}</p>
<p>${companyName} xin chân thành cảm ơn đến Quý khách đã tin tưởng và sử dụng dịch vụ của chúng tôi.</p>
<p>Hệ thống đã tiếp nhận yêu cầu đăng ký tài khoản từ Quý khách.</p>
<table style="width: 100%; margin-top: 1.5rem; border: 1px solid #53b147;">
<tr style="background-color: #53b147; color: #fff">
<th colspan="2" style="text-align: center; color: #fff; padding: 12px 10px">THÔNG TIN TÀI KHOẢN</th>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Email đăng nhập</td>
<td style="font-weight: 700; padding: 12px 10px">:${emailCustomer}</td>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Mã xác thực</td>
<td style="padding: 12px 10px">:${code}</td>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Link xác nhận đăng ký</td>
<td style="padding: 12px 10px">
:<a
href="${urlVerify}"
target="_blank"
title="Xác nhận đăng ký"
style="
background-color: #1769b2;
border: none;
color: white;
padding: 7px 16px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
border-radius: 5px;
"
>Xác nhận đăng ký</a
>
</td>
</tr>
</table>
<p>
<span style="font-weight: 700; text-decoration: underline; font-style: italic;">Chú ý:</span>
<br />
Các thông tin
<i>${companyName}</i>
đã cung cấp rất quan trọng, Quý khách vui lòng bảo mật nghiêm ngặt các thông tin này.
</p>
<p>
<i> Trân trọng cảm ơn Quý khách! </i>
</p>
</div>
<div style="margin-top: 3rem">
<p style="font-weight: 700; font-size: 20px; text-transform: uppercase">${companyName}</p>
<p><strong>Văn phòng:</strong>${office}</p>
<p>Website: <a href="${website}" target="_blank" rel="noopener noreferrer">${website}</a></p>
<p>Email: <a href="mailto${emailCompany}" target="_blank" rel="noopener noreferrer">${emailCompany}</a></p>
<p>Hotline: ${hotline}</p>
</div>
</div>
</div>
`;
}
export const sendResetPasswordEmail = (
customer,
emailCustomer,
code,
urlVerify,
companyName = COMPANY.name,
office = COMPANY.address,
website = COMPANY.website,
emailCompany = COMPANY.email.support,
hotline = COMPANY.phone.hotline,
) => {
return `
<div style="font-family: Arial, Helvetica, sans-serif; line-height: 1.5; background-color: #f0fdf4; font-size: 16px; color: #000; padding: 26px 0;">
<div
style="
max-width: 600px;
margin: 0 auto;
padding: 40px 20px;
border: 1px solid #53b147;
border-radius: 16px;
background-color: #fff;
"
>
<div style="text-align: center">
<img src="https://bigdatatech.cloud/logo.png" alt="Logo" width="150" style="display: block; margin: 0 auto" />
</div>
<div style="margin-top: 1rem">
<h2 style="font-size: 18px; font-weight: 700; text-align: center">Xác thực đặt lại mật khẩu</h2>
<p style="font-weight: 700">Kính gửi quý khách hàng: ${customer}</p>
<p>${companyName} xin chân thành cảm ơn đến Quý khách đã tin tưởng và sử dụng dịch vụ của chúng tôi.</p>
<p>Hệ thống đã tiếp nhận yêu cầu đặt lại mật khẩu từ Quý khách.</p>
<table style="width: 100%; margin-top: 1.5rem; border: 1px solid #53b147;">
<tr style="background-color: #53b147; color: #fff">
<th colspan="2" style="text-align: center; color: #fff; padding: 12px 10px">THÔNG TIN TÀI KHOẢN</th>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Email đăng nhập</td>
<td style="font-weight: 700; padding: 12px 10px">:${emailCustomer}</td>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Mã xác thực</td>
<td style="padding: 12px 10px">:${code}</td>
</tr>
<tr>
<td style="width: 200px; padding: 12px 10px">Link xác nhận đặt lại mật khẩu</td>
<td style="padding: 12px 10px">
:<a
href="${urlVerify}"
target="_blank"
title="Xác nhận đặt lại mật khẩu"
style="
background-color: #1769b2;
border: none;
color: white;
padding: 7px 16px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
border-radius: 5px;
"
>Xác nhận đặt lại mật khẩu</a
>
</td>
</tr>
</table>
<p>
<span style="font-weight: 700; text-decoration: underline; font-style: italic;">Chú ý:</span>
<br />
Các thông tin
<i>${companyName}</i>
đã cung cấp rất quan trọng, Quý khách vui lòng bảo mật nghiêm ngặt các thông tin này.
</p>
<p>Vui lòng bỏ qua email này nếu Quý khách không yêu cầu đặt lại mật khẩu.</p>
<p>
<i> Trân trọng cảm ơn Quý khách! </i>
</p>
</div>
<div style="margin-top: 3rem">
<p style="font-weight: 700; font-size: 20px; text-transform: uppercase">${companyName}</p>
<p><strong>Văn phòng:</strong>${office}</p>
<p>Website: <a href="${website}" target="_blank" rel="noopener noreferrer">${website}</a></p>
<p>Email: <a href="mailto${emailCompany}" target="_blank" rel="noopener noreferrer">${emailCompany}</a></p>
<p>Hotline: ${hotline}</p>
</div>
</div>
</div>
`;
};