Browse Source

fix: replace drawer with modal

RegMs If 3 years ago
parent
commit
dd7459fa79

+ 10 - 9
src/components/DictDrawer.tsx → src/components/DictModal.tsx

@@ -1,16 +1,16 @@
 import React, { useState } from 'react';
-import { Drawer, Form, Input, Button, message } from 'antd';
-import type { DrawerProps } from 'antd';
+import { Modal, Form, Input, Button, message } from 'antd';
+import type { ModalProps } from 'antd';
 import type { DictResult } from '../apis/dicts';
 import { useCreateDict, useUpdateDict } from '../apis/dicts';
 
-interface DictDrawerProps extends DrawerProps {
+interface DictModalProps extends ModalProps {
   initialDict?: DictResult;
   refresh: () => void;
-  onClose: () => void;
+  onCancel: () => void;
 }
 
-const DictDrawer: React.FC<DictDrawerProps> = ({
+const DictModal: React.FC<DictModalProps> = ({
   initialDict,
   refresh,
   ...props
@@ -21,8 +21,9 @@ const DictDrawer: React.FC<DictDrawerProps> = ({
   const updateDict = useUpdateDict();
 
   return (
-    <Drawer
+    <Modal
       title={initialDict ? '更新词库' : '创建新词库'}
+      footer={null}
       destroyOnClose
       {...props}
     >
@@ -47,8 +48,8 @@ const DictDrawer: React.FC<DictDrawerProps> = ({
                 await createDict(values);
                 void message.success('创建成功');
               }
+              props.onCancel();
               refresh();
-              props.onClose();
             } catch (err) {
               if (err instanceof Error) {
                 void message.error(err.message);
@@ -92,8 +93,8 @@ const DictDrawer: React.FC<DictDrawerProps> = ({
           </Button>
         </Form.Item>
       </Form>
-    </Drawer>
+    </Modal>
   );
 };
 
-export default DictDrawer;
+export default DictModal;

+ 10 - 9
src/components/UserDrawer.tsx → src/components/UserModal.tsx

@@ -1,6 +1,6 @@
 import React, { useState } from 'react';
-import { Drawer, Form, Input, Button, message } from 'antd';
-import type { DrawerProps } from 'antd';
+import { Modal, Form, Input, Button, message } from 'antd';
+import type { ModalProps } from 'antd';
 import { useAuth } from '../apis/AuthProvider';
 import { useRegister, useLogin } from '../apis/users';
 
@@ -9,11 +9,11 @@ enum Mode {
   Login,
 }
 
-interface UserDrawerProps extends DrawerProps {
-  onClose: () => void;
+interface UserModalProps extends ModalProps {
+  onCancel: () => void;
 }
 
-const UserDrawer: React.FC<UserDrawerProps> = props => {
+const UserModal: React.FC<UserModalProps> = props => {
   const [mode, setMode] = useState<Mode>(Mode.Login);
   const [loading, setLoading] = useState(false);
 
@@ -22,8 +22,9 @@ const UserDrawer: React.FC<UserDrawerProps> = props => {
   const login = useLogin();
 
   return (
-    <Drawer
+    <Modal
       title={mode === Mode.Register ? '注册' : '登录'}
+      footer={null}
       destroyOnClose
       {...props}
     >
@@ -41,8 +42,8 @@ const UserDrawer: React.FC<UserDrawerProps> = props => {
               }
               await login(values);
               void message.success('登录成功');
+              props.onCancel();
               refresh();
-              props.onClose();
             } catch (err) {
               if (err instanceof Error) {
                 void message.error(err.message);
@@ -92,8 +93,8 @@ const UserDrawer: React.FC<UserDrawerProps> = props => {
           </Button>
         </Form.Item>
       </Form>
-    </Drawer>
+    </Modal>
   );
 };
 
-export default UserDrawer;
+export default UserModal;

+ 22 - 11
src/components/WordDrawer.tsx → src/components/WordModal.tsx

@@ -1,17 +1,17 @@
-import React, { useState } from 'react';
-import { Drawer, Form, Input, Button, message } from 'antd';
-import type { DrawerProps } from 'antd';
+import React, { useState, useEffect } from 'react';
+import { Modal, Form, Input, Button, message } from 'antd';
+import type { ModalProps } from 'antd';
 import type { WordResult } from '../apis/words';
 import { useCreateWord, useUpdateWord } from '../apis/words';
 
-interface WordDrawerProps extends DrawerProps {
+interface WordModalProps extends ModalProps {
   dictID: number;
   initialWord?: WordResult;
   refresh: () => void;
-  onClose: () => void;
+  onCancel: () => void;
 }
 
-const WordDrawer: React.FC<WordDrawerProps> = ({
+const WordModal: React.FC<WordModalProps> = ({
   dictID,
   initialWord,
   refresh,
@@ -19,12 +19,21 @@ const WordDrawer: React.FC<WordDrawerProps> = ({
 }) => {
   const [loading, setLoading] = useState(false);
 
+  const [form] = Form.useForm();
+
+  useEffect(() => {
+    if (props.open) {
+      form.setFieldsValue(initialWord);
+    }
+  }, [props.open, form, initialWord]);
+
   const createWord = useCreateWord();
   const updateWord = useUpdateWord();
 
   return (
-    <Drawer
+    <Modal
       title={initialWord ? '更新单词' : '创建新单词'}
+      footer={null}
       destroyOnClose
       {...props}
     >
@@ -32,7 +41,8 @@ const WordDrawer: React.FC<WordDrawerProps> = ({
         name="word"
         labelCol={{ span: 6 }}
         wrapperCol={{ span: 18 }}
-        initialValues={initialWord}
+        form={form}
+        preserve={false}
         onFinish={(values: { value: string; meaning: string; extra: string }) =>
           void (async () => {
             try {
@@ -40,12 +50,13 @@ const WordDrawer: React.FC<WordDrawerProps> = ({
               if (initialWord) {
                 await updateWord({ ...initialWord, ...values });
                 void message.success('更新成功');
+                props.onCancel();
               } else {
                 await createWord({ ...values, dictID });
                 void message.success('创建成功');
+                form.resetFields();
               }
               refresh();
-              props.onClose();
             } catch (err) {
               if (err instanceof Error) {
                 void message.error(err.message);
@@ -81,8 +92,8 @@ const WordDrawer: React.FC<WordDrawerProps> = ({
           </Button>
         </Form.Item>
       </Form>
-    </Drawer>
+    </Modal>
   );
 };
 
-export default WordDrawer;
+export default WordModal;

+ 14 - 0
src/layout/PageLayout.module.css

@@ -1,3 +1,12 @@
+.arrow {
+  position: absolute;
+  transition: all 0.3s;
+}
+
+.hide {
+  opacity: 0;
+}
+
 .header {
   background-color: white;
   box-shadow: 0px 4px 4px -2px lightgray;
@@ -6,6 +15,11 @@
 
 .title {
   font-size: 24px;
+  transition: all 0.3s;
+}
+
+.margin {
+  margin-left: 40px;
 }
 
 .content {

+ 11 - 12
src/layout/PageLayout.tsx

@@ -3,7 +3,7 @@ import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom';
 import { Layout, Row, Col, Typography, Button, Result } from 'antd';
 import { ArrowLeftOutlined } from '@ant-design/icons';
 import { useAuth } from '../apis/AuthProvider';
-import UserDrawer from '../components/UserDrawer';
+import UserModal from '../components/UserModal';
 import styles from './PageLayout.module.css';
 
 const { Header, Content } = Layout;
@@ -15,6 +15,8 @@ const PageLayout: React.FC = () => {
   const { pathname } = useLocation();
   const navigate = useNavigate();
 
+  const hideArrow = pathname === '/' || pathname === '/dicts';
+
   useEffect(() => {
     if (pathname === '/') {
       navigate('/dicts');
@@ -27,19 +29,16 @@ const PageLayout: React.FC = () => {
     <Layout>
       <Header className={styles.header}>
         <Row gutter={8}>
-          <Col>
+          <Col className={`${styles.arrow} ${hideArrow ? styles.hide : ''}`}>
             <Link to={pathname.slice(0, pathname.lastIndexOf('/'))}>
-              <Button
-                type="link"
-                icon={<ArrowLeftOutlined />}
-                disabled={pathname === '/dicts'}
-              />
+              <Button type="link" icon={<ArrowLeftOutlined />} />
             </Link>
           </Col>
-          <Col flex={1}>
-            <Text className={styles.title} strong>
-              Woord
-            </Text>
+          <Col
+            className={`${styles.title} ${hideArrow ? '' : styles.margin}`}
+            flex={1}
+          >
+            <Text strong>Woord</Text>
           </Col>
           <Col>
             {user ? (
@@ -55,7 +54,7 @@ const PageLayout: React.FC = () => {
       <Content className={styles.content}>
         {user ? <Outlet /> : <Result status="403" subTitle="请先登录" />}
       </Content>
-      <UserDrawer open={open} onClose={() => setOpen(false)} />
+      <UserModal open={open} onCancel={() => setOpen(false)} />
     </Layout>
   );
 };

+ 3 - 3
src/pages/DictPage.tsx

@@ -22,7 +22,7 @@ import {
 import { useGetDict } from '../apis/dicts';
 import type { WordResult } from '../apis/words';
 import { useUpdateWord, useDeleteWord } from '../apis/words';
-import WordDrawer from '../components/WordDrawer';
+import WordModal from '../components/WordModal';
 import styles from './DictPage.module.css';
 
 const { Text } = Typography;
@@ -176,12 +176,12 @@ const DictPage: React.FC = () => {
           </List.Item>
         )}
       />
-      <WordDrawer
+      <WordModal
         dictID={parseInt(dictID)}
         initialWord={initialWord}
         refresh={refresh}
         open={open}
-        onClose={() => setOpen(false)}
+        onCancel={() => setOpen(false)}
       />
     </div>
   );

+ 3 - 3
src/pages/DictsPage.tsx

@@ -14,7 +14,7 @@ import {
 import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
 import type { DictResult } from '../apis/dicts';
 import { useListDicts, useDeleteDict } from '../apis/dicts';
-import DictDrawer from '../components/DictDrawer';
+import DictModal from '../components/DictModal';
 import styles from './DictsPage.module.css';
 
 const { Text } = Typography;
@@ -102,11 +102,11 @@ const DictsPage: React.FC = () => {
           ))}
         </Row>
       </Spin>
-      <DictDrawer
+      <DictModal
         initialDict={initialDict}
         refresh={refresh}
         open={open}
-        onClose={() => setOpen(false)}
+        onCancel={() => setOpen(false)}
       />
     </div>
   );