feat(localization): Add en/vi language

This commit is contained in:
Tran Anh Tuan
2025-11-20 16:21:17 +07:00
parent dea435a4ec
commit 216e865ca5
37 changed files with 2356 additions and 455 deletions

View File

@@ -1,3 +1,4 @@
import useTranslation from '@/hooks/useTranslation';
import {
deleteSos,
getSos,
@@ -20,23 +21,22 @@ interface SosButtonProps {
}
const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
const { t } = useTranslation();
const [form] = Form.useForm<{ message: string; messageOther?: string }>();
const [sosData, setSosData] = useState<API.SosResponse>();
const screens = Grid.useBreakpoint();
useEffect(() => {
getSosData();
}, []);
const getSosData = async () => {
try {
const sosData = await getSos();
console.log('SOS Data: ', sosData);
setSosData(sosData);
} catch (error) {
console.error('Failed to fetch SOS data:', error);
}
};
useEffect(() => {
getSosData();
}, []);
// map width cho từng breakpoint
const getWidth = () => {
if (screens.xs) return '95%'; // mobile
@@ -50,33 +50,33 @@ const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
if (messageData) {
try {
await sendSosMessage(messageData);
message.success('Gửi tín hiệu SOS thành công!');
message.success(t('sos.sendSuccess'));
getSosData(); // Cập nhật lại trạng thái SOS
onRefresh?.(true);
} catch (error) {
console.error('Failed to send SOS:', error);
message.error('Gửi tín hiệu SOS thất bại!');
message.error(t('sos.sendError'));
}
} else {
try {
await deleteSos();
message.success('Huỷ tín hiệu SOS thành công!');
message.success(t('sos.cancelSuccess'));
getSosData(); // Cập nhật lại trạng thái SOS
onRefresh?.(true);
} catch (error) {
console.error('Failed to delete SOS:', error);
message.error('Huỷ tín hiệu SOS thất bại!');
message.error(t('sos.cancelError'));
}
console.log('Sending SOS without message');
}
};
return sosData && sosData.active == true ? (
return sosData && sosData.active === true ? (
<div className=" flex flex-col sm:flex-row sm:justify-between sm:items-center bg-red-500 px-4 py-3 gap-3 rounded-xl animate-pulse">
<div className="flex items-center gap-2">
<WarningOutlined style={{ color: 'white', fontSize: '20px' }} />
<Typography.Text className="text-white text-sm sm:text-base">
Đang trong trạng thái khẩn cấp
{t('sos.status')}
</Typography.Text>
</div>
@@ -86,13 +86,13 @@ const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
className="self-end sm:self-auto"
onClick={async () => await handleSos()}
>
Kết thúc
{t('sos.end')}
</Button>
</div>
) : (
<ModalForm
title="Thông báo khẩn cấp"
initialValues={{ message: 'Tình huống khẩn cấp, không kịp chọn !!!' }}
title={t('sos.title')}
initialValues={{ message: t('sos.defaultMessage') }}
form={form}
width={getWidth()}
modalProps={{
@@ -112,7 +112,7 @@ const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
danger
shape="round"
>
Khẩn cấp
{t('sos.button')}
</Button>
}
onFinish={async (values) => {
@@ -129,16 +129,16 @@ const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
>
<ProFormSelect
options={[
{ value: 'other', label: 'Khác' },
{ value: 'other', label: t('sos.other') },
...sosMessage.map((item) => ({
value: item.moTa,
label: item.moTa,
})),
]}
name="message"
rules={[{ required: true, message: 'Vui lòng chọn hoặc nhập lý do!' }]}
placeholder="Chọn hoặc nhập lý do..."
label="Nội dung:"
rules={[{ required: true, message: t('sos.validationError') }]}
placeholder={t('sos.placeholder')}
label={t('sos.label')}
/>
<ProFormDependency name={['message']}>
@@ -146,9 +146,11 @@ const SosButton: React.FC<SosButtonProps> = ({ onRefresh }) => {
message === 'other' ? (
<ProFormText
name="messageOther"
placeholder="Nhập lý do khác..."
rules={[{ required: true, message: 'Vui lòng nhập lý do khác!' }]}
label="Lý do khác"
placeholder={t('sos.otherPlaceholder')}
rules={[
{ required: true, message: t('sos.otherValidationError') },
]}
label={t('sos.otherLabel')}
/>
) : null
}