]> git.localhorst.tv Git - alttp.git/blob - resources/js/pages/Technique.js
try to respond more appropriately
[alttp.git] / resources / js / pages / Technique.js
1 import axios from 'axios';
2 import PropTypes from 'prop-types';
3 import React, { useEffect, useState } from 'react';
4 import { Helmet } from 'react-helmet';
5 import { withTranslation } from 'react-i18next';
6 import { useParams } from 'react-router-dom';
7 import toastr from 'toastr';
8
9 import CanonicalLinks from '../components/common/CanonicalLinks';
10 import ErrorBoundary from '../components/common/ErrorBoundary';
11 import ErrorMessage from '../components/common/ErrorMessage';
12 import Loading from '../components/common/Loading';
13 import NotFound from '../pages/NotFound';
14 import Detail from '../components/techniques/Detail';
15 import Dialog from '../components/techniques/Dialog';
16 import {
17         mayEditContent,
18 } from '../helpers/permissions';
19 import { getLanguages, getMatchedLocale, getTranslation } from '../helpers/Technique';
20 import { useUser } from '../hooks/user';
21 import i18n from '../i18n';
22
23 const Technique = ({ basepath, type }) => {
24         const params = useParams();
25         const { name } = params;
26         const { user } = useUser();
27
28         const [error, setError] = useState(null);
29         const [loading, setLoading] = useState(true);
30         const [technique, setTechnique] = useState(null);
31
32         const [editContent, setEditContent] = useState(null);
33         const [showContentDialog, setShowContentDialog] = useState(false);
34
35         const actions = React.useMemo(() => ({
36                 editContent: mayEditContent(user) ? content => {
37                         setEditContent(content);
38                         setShowContentDialog(true);
39                 } : null,
40         }), [user]);
41
42         const saveContent = React.useCallback(async values => {
43                 try {
44                         const response = await axios.put(`/api/content/${values.id}`, {
45                                 parent_id: technique.id,
46                                 ...values,
47                         });
48                         toastr.success(i18n.t('content.saveSuccess'));
49                         setTechnique(response.data);
50                         setShowContentDialog(false);
51                 } catch (e) {
52                         toastr.error(i18n.t('content.saveError'));
53                 }
54         }, [technique && technique.id]);
55
56         useEffect(() => {
57                 const ctrl = new AbortController();
58                 setLoading(true);
59                 axios
60                         .get(`/api/pages/${type}/${name}`, { signal: ctrl.signal })
61                         .then(response => {
62                                 setError(null);
63                                 setLoading(false);
64                                 setTechnique(response.data);
65                         })
66                         .catch(error => {
67                                 setError(error);
68                                 setLoading(false);
69                                 setTechnique(null);
70                         });
71                 return () => {
72                         ctrl.abort();
73                 };
74         }, [name, type]);
75
76         if (loading) {
77                 return <Loading />;
78         }
79
80         if (error) {
81                 return <ErrorMessage error={error} />;
82         }
83
84         if (!technique) {
85                 return <NotFound />;
86         }
87
88         return <ErrorBoundary>
89                 <Helmet>
90                         <title>{getTranslation(technique, 'title', i18n.language)}</title>
91                         <meta name="description" content={getTranslation(technique, 'short', i18n.language)} />
92                 </Helmet>
93                 {technique.image ? <Helmet>
94                         <meta property="og:image" content={technique.image} />
95                         <meta property="twitter:image" content={technique.image} />
96                 </Helmet> : null}
97                 {!technique.image && technique.gif ? <Helmet>
98                         <meta property="og:image" content={technique.gif} />
99                         <meta property="twitter:image" content={technique.gif} />
100                 </Helmet> : null}
101                 <CanonicalLinks
102                         base={`/${basepath}/${technique.name}`}
103                         lang={getMatchedLocale(technique, i18n.language)}
104                         langs={getLanguages(technique)}
105                 />
106                 <Detail actions={actions} technique={technique} />
107                 <Dialog
108                         content={editContent}
109                         language={i18n.language}
110                         onHide={() => { setShowContentDialog(false); }}
111                         onSubmit={saveContent}
112                         show={showContentDialog}
113                 />
114         </ErrorBoundary>;
115 };
116
117 Technique.propTypes = {
118         basepath: PropTypes.string,
119         type: PropTypes.string,
120 };
121
122 export default withTranslation()(Technique);