]> git.localhorst.tv Git - alttp.git/blob - resources/js/components/pages/Technique.js
basic content editing
[alttp.git] / resources / js / components / 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 '../common/CanonicalLinks';
10 import ErrorBoundary from '../common/ErrorBoundary';
11 import ErrorMessage from '../common/ErrorMessage';
12 import Loading from '../common/Loading';
13 import NotFound from '../pages/NotFound';
14 import Detail from '../techniques/Detail';
15 import Dialog from '../techniques/Dialog';
16 import {
17         mayEditContent,
18 } from '../../helpers/permissions';
19 import { getLanguages, getMatchedLocale, getTranslation } from '../../helpers/Technique';
20 import { useUser } from '../../helpers/UserContext';
21 import i18n from '../../i18n';
22
23 const Technique = ({ 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                 <CanonicalLinks
94                         base={`/tech/${technique.name}`}
95                         lang={getMatchedLocale(technique, i18n.language)}
96                         langs={getLanguages(technique)}
97                 />
98                 <Detail actions={actions} technique={technique} />
99                 <Dialog
100                         content={editContent}
101                         language={i18n.language}
102                         onHide={() => { setShowContentDialog(false); }}
103                         onSubmit={saveContent}
104                         show={showContentDialog}
105                 />
106         </ErrorBoundary>;
107 };
108
109 Technique.propTypes = {
110         type: PropTypes.string,
111 };
112
113 export default withTranslation()(Technique);