/* * @Author: ZhaoYing * @Date: 2026-02-03 16:42:17 * @Last Modified by: ZhaoYing * @Last Modified time: 2026-02-03 16:42:17 */ /** * Member Modal * Modal for inviting new members or editing existing member roles * Generates invitation links for new members */ import { forwardRef, useImperativeHandle, useState } from 'react'; import { Form, Input, Select, Modal, App } from 'antd'; import type { SelectProps } from 'antd'; import { useTranslation } from 'react-i18next'; import copy from 'copy-to-clipboard' import type { MemberModalData, Member, MemberModalRef } from '../types' import RbModal from '@/components/RbModal' import { inviteMember, updateMember } from '@/api/member' const FormItem = Form.Item; const { Option } = Select; type LabelRender = SelectProps['labelRender']; /** * Component props */ interface MemberModalProps { /** Callback to refresh member list */ refreshTable: () => void; } /** * Modal for member invitation and editing */ const MemberModal = forwardRef(({ refreshTable }, ref) => { const { t } = useTranslation(); const { message } = App.useApp() const initialForm = { // role: 'member', } const [visible, setVisible] = useState(false); const [editingUser, setEditingUser] = useState(null); const [form] = Form.useForm(); const [loading, setLoading] = useState(false) const [modal, contextHolder] = Modal.useModal(); const roleOptions = [ 'member', 'manager' ] const values: MemberModalData = Form.useWatch([], form); /** Close modal and reset form */ const handleClose = () => { setVisible(false); setEditingUser(null); form.resetFields(); setLoading(false) }; /** Open modal with optional member data for editing */ const handleOpen = (member?: Member | null) => { if (member) { setEditingUser(member); // Set form values form.setFieldsValue({ email: member.account, role: member.role }); } else { form.resetFields(); } setVisible(true); }; /** Save member (invite or update) */ const handleSave = () => { form .validateFields() .then(() => { setLoading(true) const response = editingUser?.id ? updateMember({ role: values.role, id: editingUser?.id }) : inviteMember(values) response.then((res) => { setLoading(false) refreshTable() if (editingUser?.id) { refreshTable() handleClose() } else { const inviteLink = `${window.location.origin}/#/invite-register/${(res as { invite_token: string }).invite_token}` modal.confirm({ title: t('member.inviteLinkTip'), content: {inviteLink}, okText: t('common.copy'), cancelText: t('common.cancel'), okType: 'danger', onOk: () => { copy(inviteLink) handleClose() message.success(t('common.copySuccess')) } }) } }) .catch(() => { setLoading(false) }); }) .catch((err) => { console.log('err', err) }); } /** Expose methods to parent component */ useImperativeHandle(ref, () => ({ handleOpen, handleClose })); /** Custom label renderer for role select */ const labelRender: LabelRender = (props) => { const { label, value } = props; if (label) { return t(`member.${value}`); } return No option match; }; return (
{contextHolder}
); }); export default MemberModal;