From 74806e6f61776d89fded1cb079a3ebca25007c49 Mon Sep 17 00:00:00 2001 From: Yen-chi Chen Date: Thu, 5 Jan 2023 15:55:22 +0000 Subject: [PATCH] Rewrite apis, and remove unnecessary action --- .eslintrc.js | 1 + jsconfig.json | 3 +- package.json | 3 +- src/actions/viewLog.js | 21 -------- .../TimeAndSalary/ViewLog.js | 53 +++++-------------- .../ReactionZone/ReportInspectModal.js | 4 +- .../ExperienceDetail/hooks/useToggleLike.js | 6 +-- .../ExperienceDetail/hooks/useTrace.js | 23 ++------ src/components/Me/useQuery.js | 12 +++-- .../InterviewForm/TypeForm/index.js | 4 +- .../ShareExperience/common/CompanyQuery.js | 6 +-- .../ShareExperience/common/JobTitle.js | 6 +-- .../common/facebook/FacebookWrapper.js | 44 +++++---------- .../common/form/TextInput/SearchTextInput.js | 10 ++-- src/hooks/usePermission.js | 2 +- src/hooks/viewLog/index.js | 23 ++++++++ src/razzle-plugins/alias.js | 1 + 17 files changed, 82 insertions(+), 140 deletions(-) delete mode 100644 src/actions/viewLog.js create mode 100644 src/hooks/viewLog/index.js diff --git a/.eslintrc.js b/.eslintrc.js index c01b4dfe1..d3905f300 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -45,6 +45,7 @@ module.exports = { hooks: path.resolve('./src/hooks'), contexts: path.resolve('./src/contexts'), constants: path.resolve('./src/constants'), + apis: path.resolve('./src/apis'), }, }, }, diff --git a/jsconfig.json b/jsconfig.json index 2d86650eb..04ea47135 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -7,7 +7,8 @@ "graphql/*": ["src/graphql/*"], "hooks/*": ["src/hooks/*"], "contexts/*": ["src/contexts/*"], - "constants/*": ["src/constants/*"] + "constants/*": ["src/constants/*"], + "apis/*": ["src/apis/*"] } }, "exclude": ["node_modules", "dist"] diff --git a/package.json b/package.json index 257791ccd..2a40dcb61 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "^graphql(.*)": "/src/graphql$1", "^hooks(.*)": "/src/hooks$1", "^contexts(.*)": "/src/contexts$1", - "^constants(.*)": "/src/constants$1" + "^constants(.*)": "/src/constants$1", + "^apis(.*)": "/src/apis$1" } }, "devDependencies": { diff --git a/src/actions/viewLog.js b/src/actions/viewLog.js deleted file mode 100644 index 1dfb953bc..000000000 --- a/src/actions/viewLog.js +++ /dev/null @@ -1,21 +0,0 @@ -import { tokenSelector } from '../selectors/authSelector'; - -export const viewSalaryWorkTimes = ({ contentIds, referrer }) => ( - dispatch, - getState, - { api }, -) => { - const state = getState(); - const token = tokenSelector(state); - return api.viewLog.viewSalaryWorkTimes({ token, contentIds, referrer }); -}; - -export const viewExperiences = ({ contentIds, referrer }) => ( - dispatch, - getState, - { api }, -) => { - const state = getState(); - const token = tokenSelector(state); - return api.viewLog.viewExperiences({ token, contentIds, referrer }); -}; diff --git a/src/components/CompanyAndJobTitle/TimeAndSalary/ViewLog.js b/src/components/CompanyAndJobTitle/TimeAndSalary/ViewLog.js index 85e45c0e9..1bd18811c 100644 --- a/src/components/CompanyAndJobTitle/TimeAndSalary/ViewLog.js +++ b/src/components/CompanyAndJobTitle/TimeAndSalary/ViewLog.js @@ -1,36 +1,18 @@ -import { Component } from 'react'; +import { useEffect } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; +import { useViewSalaryWorkTimes } from 'hooks/viewLog'; -import { viewSalaryWorkTimes } from '../../../actions/viewLog'; - -class ViewLog extends Component { - componentDidMount() { - const { contentIds } = this.props; +const ViewLog = ({ pageName, page, contentIds }) => { + // Send view to backend + const viewSalaryWorkTimes = useViewSalaryWorkTimes(); + useEffect(() => { const referrer = window.location.href; + viewSalaryWorkTimes({ contentIds, referrer }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pageName, page, viewSalaryWorkTimes]); - this.props.viewSalaryWorkTimes({ contentIds, referrer }); - } - - componentDidUpdate(prevProps) { - const prevPageName = prevProps.pageName; - const prevPage = prevProps.page; - const pageName = this.props.pageName; - const page = this.props.page; - - if (prevPageName !== pageName || prevPage !== page) { - const { contentIds } = this.props; - const referrer = window.location.href; - - this.props.viewSalaryWorkTimes({ contentIds, referrer }); - } - } - - render() { - return null; - } -} + return null; +}; ViewLog.propTypes = { // key @@ -38,17 +20,6 @@ ViewLog.propTypes = { page: PropTypes.number.isRequired, contentIds: PropTypes.arrayOf(PropTypes.string).isRequired, - - // method - viewSalaryWorkTimes: PropTypes.func.isRequired, }; -const mapStateToProps = state => ({}); - -const mapDispatchToProps = dispatch => - bindActionCreators({ viewSalaryWorkTimes }, dispatch); - -export default connect( - mapStateToProps, - mapDispatchToProps, -)(ViewLog); +export default ViewLog; diff --git a/src/components/ExperienceDetail/ReactionZone/ReportInspectModal.js b/src/components/ExperienceDetail/ReactionZone/ReportInspectModal.js index 9ccfd87f1..aee4d2dd0 100644 --- a/src/components/ExperienceDetail/ReactionZone/ReportInspectModal.js +++ b/src/components/ExperienceDetail/ReactionZone/ReportInspectModal.js @@ -4,12 +4,12 @@ import { useAsyncFn } from 'react-use'; import Modal from 'common/Modal'; import Loader from 'common/Loader'; import { Heading, P } from 'common/base'; -import api from '../../../apis'; +import reportApi from 'apis/reportApi'; import styles from './ReportInspectModal.module.css'; const useGetReports = experienceId => { return useAsyncFn(async () => { - return await api.report.getReports({ id: experienceId }); + return await reportApi.getReports({ id: experienceId }); }, [experienceId]); }; diff --git a/src/components/ExperienceDetail/hooks/useToggleLike.js b/src/components/ExperienceDetail/hooks/useToggleLike.js index d9b46b964..0d243edd0 100644 --- a/src/components/ExperienceDetail/hooks/useToggleLike.js +++ b/src/components/ExperienceDetail/hooks/useToggleLike.js @@ -1,18 +1,18 @@ import { useCallback } from 'react'; import { useToken } from 'hooks/auth'; -import api from '../../../apis'; +import experiencesApi from 'apis/experiencesApi'; const useToggleLike = experienceId => { const token = useToken(); return useCallback( liked => { if (liked) { - return api.experiences.deleteExperienceLikes({ + return experiencesApi.deleteExperienceLikes({ id: experienceId, token, }); } else { - return api.experiences.postExperienceLikes({ + return experiencesApi.postExperienceLikes({ id: experienceId, token, }); diff --git a/src/components/ExperienceDetail/hooks/useTrace.js b/src/components/ExperienceDetail/hooks/useTrace.js index 3bb9e0d51..f25e3e1a2 100644 --- a/src/components/ExperienceDetail/hooks/useTrace.js +++ b/src/components/ExperienceDetail/hooks/useTrace.js @@ -1,29 +1,16 @@ -import { useEffect, useCallback } from 'react'; -import { useDispatch } from 'react-redux'; +import { useEffect } from 'react'; import ReactPixel from 'react-facebook-pixel'; import PIXEL_CONTENT_CATEGORY from '../../../constants/pixelConstants'; -import { viewExperiences as viewExperiencesAction } from '../../../actions/viewLog'; - -const useView = experienceId => { - const dispatch = useDispatch(); - const viewExperiences = useCallback( - ({ contentIds, referrer }) => { - dispatch(viewExperiencesAction({ contentIds, referrer })); - }, - [dispatch], - ); +import { useViewExperiences } from 'hooks/viewLog'; +const useTrace = experienceId => { + // Send view to backend + const viewExperiences = useViewExperiences(); useEffect(() => { const contentIds = [experienceId]; const referrer = window.location.href; - console.log({ contentIds, referrer }); viewExperiences({ contentIds, referrer }); }, [experienceId, viewExperiences]); -}; - -const useTrace = experienceId => { - // Send view to backend - useView(experienceId); // send Facebook Pixel 'ViewContent' event useEffect(() => { diff --git a/src/components/Me/useQuery.js b/src/components/Me/useQuery.js index 5e15c22fe..c6d37cb9c 100644 --- a/src/components/Me/useQuery.js +++ b/src/components/Me/useQuery.js @@ -1,12 +1,14 @@ import { useCallback } from 'react'; import { useAsyncFn } from 'react-use'; import { useToken } from 'hooks/auth'; -import api from '../../apis'; +import meApi from 'apis/me'; +import experiencesApi from 'apis/experiencesApi'; +import timeAndSalaryApi from 'apis/timeAndSalaryApi'; export const useFetchMyPublishes = () => { const token = useToken(); - const [state, callback] = useAsyncFn(() => api.me.getMyPublishes({ token }), [ + const [state, callback] = useAsyncFn(() => meApi.getMyPublishes({ token }), [ token, ]); @@ -17,7 +19,7 @@ export const useToggleExperienceStatus = () => { const token = useToken(); return useCallback( o => { - return api.experiences.patchExperience({ + return experiencesApi.patchExperience({ id: o.id, status: o.status === 'published' ? 'hidden' : 'published', token, @@ -31,7 +33,7 @@ export const useToggleSalaryWorkTimeStatus = () => { const token = useToken(); return useCallback( o => { - return api.timeAndSalary.patchWorking({ + return timeAndSalaryApi.patchWorking({ id: o.id, status: o.status === 'published' ? 'hidden' : 'published', token, @@ -45,7 +47,7 @@ export const useToggleReplyStatus = () => { const token = useToken(); return useCallback( o => { - return api.experiences.patchReply({ + return experiencesApi.patchReply({ id: o.id, status: o.status === 'published' ? 'hidden' : 'published', token, diff --git a/src/components/ShareExperience/InterviewForm/TypeForm/index.js b/src/components/ShareExperience/InterviewForm/TypeForm/index.js index 972505d39..ca46157dc 100644 --- a/src/components/ShareExperience/InterviewForm/TypeForm/index.js +++ b/src/components/ShareExperience/InterviewForm/TypeForm/index.js @@ -29,8 +29,8 @@ import FormBuilder from 'common/FormBuilder'; import ConfirmModal from 'common/FormBuilder/Modals/ConfirmModal'; import Header, { CompanyJobTitleHeader } from '../../common/TypeFormHeader'; import Footer from '../../common/TypeFormFooter'; -import { getCompaniesSearch } from '../../../../apis/companySearchApi'; -import { getJobTitlesSearch } from '../../../../apis/jobTitleSearchApi'; +import { getCompaniesSearch } from 'apis/companySearchApi'; +import { getJobTitlesSearch } from 'apis/jobTitleSearchApi'; import { experienceCountSelector, timeAndSalaryCountSelector, diff --git a/src/components/ShareExperience/common/CompanyQuery.js b/src/components/ShareExperience/common/CompanyQuery.js index 9bc1bbd1b..0c280befd 100644 --- a/src/components/ShareExperience/common/CompanyQuery.js +++ b/src/components/ShareExperience/common/CompanyQuery.js @@ -2,11 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import AutoCompleteTextInput from 'common/form/AutoCompleteTextInput'; - import { debounce } from 'utils/streamUtils'; +import companySearchApi from 'apis/companySearchApi'; import InputTitle from './InputTitle'; -import { getCompaniesSearch } from '../../../apis/companySearchApi'; const getItemValue = item => item.label; @@ -26,7 +25,8 @@ class CompanyQuery extends React.Component { search = debounce((e, value) => { if (value) { - return getCompaniesSearch({ key: value }) + return companySearchApi + .getCompaniesSearch({ key: value }) .then(r => Array.isArray(r) ? this.handleAutocompleteItems(r.map(mapToAutocompleteList)) diff --git a/src/components/ShareExperience/common/JobTitle.js b/src/components/ShareExperience/common/JobTitle.js index 88755f773..e2349d345 100644 --- a/src/components/ShareExperience/common/JobTitle.js +++ b/src/components/ShareExperience/common/JobTitle.js @@ -2,11 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import AutoCompleteTextInput from 'common/form/AutoCompleteTextInput'; - import { debounce } from 'utils/streamUtils'; +import jobTitleSearchApi from 'apis/jobTitleSearchApi'; import InputTitle from './InputTitle'; -import { getJobTitlesSearch } from '../../../apis/jobTitleSearchApi'; const getItemValue = item => item.label; @@ -26,7 +25,8 @@ class JobTitle extends React.Component { search = debounce((e, value) => { if (value) { - return getJobTitlesSearch({ key: value }) + return jobTitleSearchApi + .getJobTitlesSearch({ key: value }) .then(r => Array.isArray(r) ? this.handleAutocompleteItems(r.map(mapToAutocompleteList)) diff --git a/src/components/common/facebook/FacebookWrapper.js b/src/components/common/facebook/FacebookWrapper.js index 05728e1be..50b38a6a5 100644 --- a/src/components/common/facebook/FacebookWrapper.js +++ b/src/components/common/facebook/FacebookWrapper.js @@ -1,42 +1,22 @@ -import React, { Component } from 'react'; +import React, { useContext, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; -import withFB from './withFB'; +import FacebookContext from 'contexts/FacebookContext'; -class FacebookWrapper extends Component { - constructor(props) { - super(props); - this.container = null; - this.handleContainer = this.handleContainer.bind(this); - } +const FacebookWrapper = ({ children }) => { + const FB = useContext(FacebookContext); + const container = useRef(null); - componentDidMount() { - if (this.props.FB && this.container) { - this.props.FB.XFBML.parse(this.container); + useEffect(() => { + if (FB && container) { + FB.XFBML.parse(container.current); } - } + }); - // 讓 FB 重新 parse children - componentDidUpdate() { - // if FB instance - if (this.props.FB && this.container) { - this.props.FB.XFBML.parse(this.container); - } - } - - handleContainer(container) { - this.container = container; - } - - render() { - const { children } = this.props; - - return
{children}
; - } -} + return
{children}
; +}; FacebookWrapper.propTypes = { children: PropTypes.node, - FB: PropTypes.object, }; -export default withFB(FacebookWrapper); +export default FacebookWrapper; diff --git a/src/components/common/form/TextInput/SearchTextInput.js b/src/components/common/form/TextInput/SearchTextInput.js index dbb69726e..94947ee88 100644 --- a/src/components/common/form/TextInput/SearchTextInput.js +++ b/src/components/common/form/TextInput/SearchTextInput.js @@ -3,13 +3,9 @@ import PropTypes from 'prop-types'; import R from 'ramda'; import { debounce } from 'utils/streamUtils'; +import timeAndSalaryApi from 'apis/timeAndSalaryApi'; import TextInput from '.'; -import { - fetchCompanyCandidates, - fetchJobTitleCandidates, -} from '../../../../apis/timeAndSalaryApi'; - const take5 = R.take(5); const SearchTextInput = ({ value, onChange, onSelected, ...restProps }) => { @@ -17,11 +13,11 @@ const SearchTextInput = ({ value, onChange, onSelected, ...restProps }) => { const eleRef = useRef(null); const searchCompanyNames = useCallback( - value => fetchCompanyCandidates({ key: value }), + value => timeAndSalaryApi.fetchCompanyCandidates({ key: value }), [], ); const searchJobTitles = useCallback( - value => fetchJobTitleCandidates({ key: value }), + value => timeAndSalaryApi.fetchJobTitleCandidates({ key: value }), [], ); diff --git a/src/hooks/usePermission.js b/src/hooks/usePermission.js index 9d8269e7e..02337ace2 100644 --- a/src/hooks/usePermission.js +++ b/src/hooks/usePermission.js @@ -1,7 +1,7 @@ import { useContext, useCallback } from 'react'; import PermissionContext from 'common/permission-context/PermissionContext'; import { useToken } from 'hooks/auth'; -import { getHasSearchPermission } from '../apis/me'; +import { getHasSearchPermission } from 'apis/me'; export default () => { const token = useToken(); diff --git a/src/hooks/viewLog/index.js b/src/hooks/viewLog/index.js new file mode 100644 index 000000000..29af33ef2 --- /dev/null +++ b/src/hooks/viewLog/index.js @@ -0,0 +1,23 @@ +import { useCallback } from 'react'; +import { useToken } from 'hooks/auth'; +import viewLogApi from 'apis/viewLogApi'; + +export const useViewExperiences = () => { + const token = useToken(); + return useCallback( + ({ contentIds, referrer }) => { + return viewLogApi.viewExperiences({ token, contentIds, referrer }); + }, + [token], + ); +}; + +export const useViewSalaryWorkTimes = () => { + const token = useToken(); + return useCallback( + ({ contentIds, referrer }) => { + return viewLogApi.viewSalaryWorkTimes({ token, contentIds, referrer }); + }, + [token], + ); +}; diff --git a/src/razzle-plugins/alias.js b/src/razzle-plugins/alias.js index 34e4c704c..5d80e5948 100644 --- a/src/razzle-plugins/alias.js +++ b/src/razzle-plugins/alias.js @@ -14,6 +14,7 @@ module.exports = config => { hooks: path.resolve('./src/hooks'), contexts: path.resolve('./src/contexts'), constants: path.resolve('./src/constants'), + apis: path.resolve('./src/apis'), }; return config; };