import React, { useState, useEffect, useCallback } from 'react'; import { Card, Typography, Form, Input, Button, Avatar, Space, Upload, message, Row, Col, Modal, Image, Popconfirm } from 'antd'; import { UserOutlined, LockOutlined, PhoneOutlined, MailOutlined, UploadOutlined, EyeOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons'; import { useAuthStore } from '../store/authStore'; import { useLanguageStore } from '../store/languageStore'; import apiClient from '../utils/request'; const { Title, Paragraph, Text } = Typography; const ProfilePage: React.FC = () => { const { user, setUser } = useAuthStore(); const { t, currentLanguage } = useLanguageStore(); const [form] = Form.useForm(); const [passwordForm] = Form.useForm(); const [loading, setLoading] = useState(false); const [passwordModalVisible, setPasswordModalVisible] = useState(false); const [avatarUrl, setAvatarUrl] = useState(user?.avatar); const [passportUrl, setPassportUrl] = useState(user?.passport); const [driverLicenseUrl, setDriverLicenseUrl] = useState(user?.driverLicense); const [uploading, setUploading] = useState(null); const [previewVisible, setPreviewVisible] = useState(false); const [previewTitle, setPreviewTitle] = useState(''); const [previewUrl, setPreviewUrl] = useState(''); const [isMobile, setIsMobile] = useState(false); useEffect(() => { const checkMobile = () => setIsMobile(window.innerWidth <= 768); checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); useEffect(() => { if (user) { form.setFieldsValue({ name: user.name, phone: user.phone, email: user.email }); setAvatarUrl(user.avatar); setPassportUrl(user.passport); setDriverLicenseUrl(user.driverLicense); } const fetchProfile = async () => { try { const res = await apiClient.get('/users/me'); if (res.data.success) { const d = res.data.data; form.setFieldsValue({ name: d.name, phone: d.phone, email: d.email }); setAvatarUrl(d.avatar); setPassportUrl(d.passport); setDriverLicenseUrl(d.driverLicense); if (user) { setUser({ ...user, name: d.name, email: d.email, phone: d.phone, avatar: d.avatar, passport: d.passport, driverLicense: d.driverLicense }); } } } catch (e) {} }; fetchProfile(); }, [user, form]); const uploadToCos = async (file: File): Promise => { try { const formData = new FormData(); formData.append('file', file); const res = await apiClient.post('/upload/single', formData); if (res.data.success) return res.data.data.url; message.error(t('user.uploadFailed')); return null; } catch (e) { message.error(t('user.uploadFailed')); return null; } }; const handleSubmit = async () => { try { const values = await form.validateFields(); setLoading(true); const response = await apiClient.put(`/users/${user?.id}/profile`, { ...values, avatar: avatarUrl, passport: passportUrl, driver_license: driverLicenseUrl }); const data = response.data; if (data.success) { message.success(t('user.profileUpdated')); if (user) { setUser({ ...user, name: values.name, email: values.email, phone: values.phone, avatar: avatarUrl, passport: passportUrl, driverLicense: driverLicenseUrl }); } } else { message.error(data.message || t('user.updateFailed')); } } catch (error) { message.error(t('user.updateRetry')); } finally { setLoading(false); } }; const handlePasswordSubmit = async () => { try { const values = await passwordForm.validateFields(); const response = await apiClient.put(`/users/${user?.id}/password`, { currentPassword: values.currentPassword, newPassword: values.newPassword }); const data = response.data; if (data.success) { message.success(t('user.passwordUpdated')); setPasswordModalVisible(false); passwordForm.resetFields(); } else { message.error(data.message || t('user.passwordUpdateFailed')); } } catch (error) { message.error(t('user.passwordUpdateRetry')); } }; const handleAvatarUpload = async (options: any) => { setUploading('avatar'); const url = await uploadToCos(options.file); if (url) setAvatarUrl(url); setUploading(null); }; const handlePassportUpload = async (options: any) => { setUploading('passport'); const url = await uploadToCos(options.file); if (url) setPassportUrl(url); setUploading(null); }; const handleDriverLicenseUpload = async (options: any) => { setUploading('driverLicense'); const url = await uploadToCos(options.file); if (url) setDriverLicenseUrl(url); setUploading(null); }; const showPreview = (title: string, url: string) => { setPreviewTitle(title); setPreviewUrl(url); setPreviewVisible(true); }; const colSpan = isMobile ? 24 : 12; return (
{t('user.profile')} {t('user.managingProfile')}
{avatarUrl ? ( ) : ( } style={{ cursor: 'pointer' }} /> )} {t('user.clickToChangeAvatar')} {user?.name || user?.username} {user?.role === 'admin' ? t('user.admin') : user?.role === 'manager' ? t('user.manager') : t('user.employee')}
} /> } />
{t('user.idDocument')} {t('user.idDocTip')}
setPassportUrl(undefined)}> ) : null} style={{ marginBottom: 16 }} > {passportUrl ? (
showPreview(t('user.passport'), passportUrl)}> {t('user.passport')}
) : (
{t('user.uploadPassport')}
)}
setDriverLicenseUrl(undefined)}> ) : null} style={{ marginBottom: 16 }} > {driverLicenseUrl ? (
showPreview(t('user.driverLicense'), driverLicenseUrl)}> {t('user.driverLicense')}
) : (
{t('user.uploadDriverLicense')}
)}
setPasswordModalVisible(false)} onOk={handlePasswordSubmit} width={400} >
} /> } /> ({ validator(_, value) { if (!value || getFieldValue('newPassword') === value) return Promise.resolve(); return Promise.reject(new Error(t('user.passwordMismatch'))); } })]}> } />
setPreviewVisible(false)} width={isMobile ? '95%' : 600} centered >
{previewTitle}
); }; export default ProfilePage;