♻️ refactor(personal-settings): Break down PersonalSetting.js into modular components

- Split the 1554-line PersonalSetting.js file into smaller, maintainable components
- Created organized folder structure under personal/:
  - components/: UserInfoHeader for shared user info display
  - tabs/: ModelsList, AccountBinding, SecuritySettings, NotificationSettings
  - modals/: EmailBindModal, WeChatBindModal, AccountDeleteModal, ChangePasswordModal
- Refactored main PersonalSetting component to use composition pattern
- Improved code maintainability and separation of concerns
- Added collapsible prop to ModelsList tabs for better UX
- Fixed import path for TwoFASetting component in SecuritySettings
- Preserved all existing functionality and user interactions

This refactoring reduces the main file from 1554 to 484 lines and makes
the codebase more modular, testable, and easier to maintain.
This commit is contained in:
t0ng7u
2025-08-17 00:49:54 +08:00
parent 6ce92b9e19
commit 66289f7991
11 changed files with 1629 additions and 1266 deletions
@@ -0,0 +1,106 @@
/*
Copyright (C) 2025 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import React from 'react';
import { Button, Input, Modal } from '@douyinfe/semi-ui';
import { IconMail, IconKey } from '@douyinfe/semi-icons';
import Turnstile from 'react-turnstile';
const EmailBindModal = ({
t,
showEmailBindModal,
setShowEmailBindModal,
inputs,
handleInputChange,
sendVerificationCode,
bindEmail,
disableButton,
loading,
countdown,
turnstileEnabled,
turnstileSiteKey,
setTurnstileToken
}) => {
return (
<Modal
title={
<div className="flex items-center">
<IconMail className="mr-2 text-blue-500" />
{t('绑定邮箱地址')}
</div>
}
visible={showEmailBindModal}
onCancel={() => setShowEmailBindModal(false)}
onOk={bindEmail}
size={'small'}
centered={true}
maskClosable={false}
className="modern-modal"
>
<div className="space-y-4 py-4">
<div className="flex gap-3">
<Input
placeholder={t('输入邮箱地址')}
onChange={(value) => handleInputChange('email', value)}
name='email'
type='email'
size="large"
className="!rounded-lg flex-1"
prefix={<IconMail />}
/>
<Button
onClick={sendVerificationCode}
disabled={disableButton || loading}
className="!rounded-lg"
type="primary"
theme="outline"
size='large'
>
{disableButton ? `${t('重新发送')} (${countdown})` : t('获取验证码')}
</Button>
</div>
<Input
placeholder={t('验证码')}
name='email_verification_code'
value={inputs.email_verification_code}
onChange={(value) =>
handleInputChange('email_verification_code', value)
}
size="large"
className="!rounded-lg"
prefix={<IconKey />}
/>
{turnstileEnabled && (
<div className="flex justify-center">
<Turnstile
sitekey={turnstileSiteKey}
onVerify={(token) => {
setTurnstileToken(token);
}}
/>
</div>
)}
</div>
</Modal>
);
};
export default EmailBindModal;