Files
FE-DEVICE-SGW/src/pages/Home/components/SosButton.tsx
2025-11-21 14:27:00 +07:00

163 lines
4.5 KiB
TypeScript

import useTranslation from '@/hooks/useTranslation';
import {
deleteSos,
getSos,
sendSosMessage,
} from '@/services/controller/DeviceController';
import { sosMessage } from '@/utils/sosUtil';
import { InfoCircleOutlined, WarningOutlined } from '@ant-design/icons';
import {
ModalForm,
ProFormDependency,
ProFormSelect,
ProFormText,
} from '@ant-design/pro-components';
import { Button, Form, Grid, message, Typography } from 'antd';
import { useEffect, useState } from 'react';
import './index.less';
interface SosButtonProps {
onRefresh?: (isTrue: boolean) => void;
}
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();
const getSosData = async () => {
try {
const sosData = await getSos();
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
if (screens.sm) return '30%';
if (screens.md) return '30%';
if (screens.lg) return '30%';
return '40%'; // xl, xxl
};
const handleSos = async (messageData?: string) => {
if (messageData) {
try {
await sendSosMessage(messageData);
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(t('sos.sendError'));
}
} else {
try {
await deleteSos();
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(t('sos.cancelError'));
}
// console.log('Sending SOS without message');
}
};
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">
{t('sos.status')}
</Typography.Text>
</div>
<Button
color="danger"
variant="outlined"
className="self-end sm:self-auto"
onClick={async () => await handleSos()}
>
{t('sos.end')}
</Button>
</div>
) : (
<ModalForm
title={t('sos.title')}
initialValues={{ message: t('sos.defaultMessage') }}
form={form}
width={getWidth()}
modalProps={{
destroyOnHidden: true,
onCancel: () => console.log('run'),
}}
onOpenChange={(open) => {
if (open) {
form.resetFields();
}
}}
trigger={
<Button
icon={<InfoCircleOutlined />}
size="large"
type="primary"
danger
shape="round"
>
{t('sos.button')}
</Button>
}
onFinish={async (values) => {
// console.log('Form Values: ', values);
// Nếu chọn "Khác" thì lấy messageOther, ngược lại lấy message
const finalMessage =
values.message === 'other' ? values.messageOther : values.message;
await handleSos(finalMessage);
return true;
}}
>
<ProFormSelect
options={[
{ value: 'other', label: t('sos.other') },
...sosMessage.map((item) => ({
value: item.moTa,
label: item.moTa,
})),
]}
name="message"
rules={[{ required: true, message: t('sos.validationError') }]}
placeholder={t('sos.placeholder')}
label={t('sos.label')}
/>
<ProFormDependency name={['message']}>
{({ message }) =>
message === 'other' ? (
<ProFormText
name="messageOther"
placeholder={t('sos.otherPlaceholder')}
rules={[
{ required: true, message: t('sos.otherValidationError') },
]}
label={t('sos.otherLabel')}
/>
) : null
}
</ProFormDependency>
</ModalForm>
);
};
export default SosButton;