diff --git a/.github/docker-compose-dev.yml b/.github/docker-compose-dev.yml index 6fd7fd7be..815a207e2 100644 --- a/.github/docker-compose-dev.yml +++ b/.github/docker-compose-dev.yml @@ -11,7 +11,6 @@ services: - RAZZLE_GA_MEASUREMENT_ID=G-CYK1FN5G9P - RAZZLE_GTM_ID=GTM-KVZ7DZQ - RAZZLE_GOOGLE_APP_ID=879657963776-d8j1hq8dk38alp456ncvnq6mqh4f6bua.apps.googleusercontent.com - - RAZZLE_AMPLITUDE_API_KEY=d0b279a29601ca776f6557710220b79a - RAZZLE_ENVIRONMENT=dev - RAZZLE_TAP_PAY_APP_ID=125271 - RAZZLE_TAP_PAY_APP_KEY=app_WBWcR9mkiSMUQ3qZV5tUidkq7vfamUzmdWi5QR33ksT6ttbiZ9BJxbz5Fvma diff --git a/.github/docker-compose-dev2.yml b/.github/docker-compose-dev2.yml deleted file mode 100644 index b40890710..000000000 --- a/.github/docker-compose-dev2.yml +++ /dev/null @@ -1,18 +0,0 @@ -version: "2" -services: - node: - image: goodjobshare:dev - build: - context: .. - dockerfile: docker/Dockerfile - args: - - RAZZLE_API_HOST=https://api-dev.goodjob.life - - RAZZLE_FACEBOOK_APP_ID=1844389232511081 - - RAZZLE_GA_ID=UA-79990667-2 - - RAZZLE_GTM_ID=GTM-KVZ7DZQ - - RAZZLE_GOOGLE_APP_ID=879657963776-d8j1hq8dk38alp456ncvnq6mqh4f6bua.apps.googleusercontent.com - - RAZZLE_AMPLITUDE_API_KEY=d0b279a29601ca776f6557710220b79a - - RAZZLE_ENVIRONMENT=dev - - RAZZLE_TAP_PAY_APP_ID=125271 - - RAZZLE_TAP_PAY_APP_KEY=app_WBWcR9mkiSMUQ3qZV5tUidkq7vfamUzmdWi5QR33ksT6ttbiZ9BJxbz5Fvma - - RAZZLE_TAP_PAY_SERVER_TYPE=production diff --git a/.github/docker-compose-production.yml b/.github/docker-compose-production.yml index d10ee97ae..b2c0ba2fb 100644 --- a/.github/docker-compose-production.yml +++ b/.github/docker-compose-production.yml @@ -12,7 +12,6 @@ services: - RAZZLE_PIXEL_ID=603414113402034 - RAZZLE_GTM_ID=GTM-54PH93D - RAZZLE_GOOGLE_APP_ID=879657963776-nb0kdpkb5sfdf0285ov9o353dnt0l5iq.apps.googleusercontent.com - - RAZZLE_AMPLITUDE_API_KEY=4d69f09de855a21f8790bf0f42c47cda - RAZZLE_ENVIRONMENT=production - RAZZLE_TAP_PAY_APP_ID=125271 - RAZZLE_TAP_PAY_APP_KEY=app_WBWcR9mkiSMUQ3qZV5tUidkq7vfamUzmdWi5QR33ksT6ttbiZ9BJxbz5Fvma diff --git a/.github/docker-compose-stage.yml b/.github/docker-compose-stage.yml index 72c4e174a..cf07d1e68 100644 --- a/.github/docker-compose-stage.yml +++ b/.github/docker-compose-stage.yml @@ -11,5 +11,4 @@ services: - RAZZLE_GA_MEASUREMENT_ID=G-CYK1FN5G9P - RAZZLE_GTM_ID=GTM-KVZ7DZQ - RAZZLE_GOOGLE_APP_ID=879657963776-nb0kdpkb5sfdf0285ov9o353dnt0l5iq.apps.googleusercontent.com - - RAZZLE_AMPLITUDE_API_KEY=d0b279a29601ca776f6557710220b79a - RAZZLE_ENVIRONMENT=stage diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f7f7b6c5..7e8c611a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -72,9 +72,6 @@ jobs: - run: docker-compose -f .github/docker-compose-dev.yml build - run: docker tag ${IMAGE} ${REGISTRY}/${REPO}:dev - run: docker push ${REGISTRY}/${REPO}:dev - - run: docker-compose -f .github/docker-compose-dev2.yml build - - run: docker tag ${IMAGE} ${REGISTRY}/${REPO}:dev2 - - run: docker push ${REGISTRY}/${REPO}:dev2 deploy-stage: if: github.repository == 'goodjoblife/GoodJobShare' && github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: ubuntu-latest diff --git a/docker/Dockerfile b/docker/Dockerfile index 3eb486611..e506eca21 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,6 @@ ARG RAZZLE_GA_MEASUREMENT_ID ARG RAZZLE_GTM_ID ARG RAZZLE_PIXEL_ID ARG RAZZLE_GOOGLE_APP_ID -ARG RAZZLE_AMPLITUDE_API_KEY ARG RAZZLE_ENVIRONMENT ARG RAZZLE_TAP_PAY_APP_ID ARG RAZZLE_TAP_PAY_APP_KEY @@ -22,7 +21,6 @@ ENV RAZZLE_API_HOST="${RAZZLE_API_HOST}" \ RAZZLE_GTM_ID="$RAZZLE_GTM_ID" \ RAZZLE_PIXEL_ID="$RAZZLE_PIXEL_ID" \ RAZZLE_GOOGLE_APP_ID="$RAZZLE_GOOGLE_APP_ID" \ - RAZZLE_AMPLITUDE_API_KEY="$RAZZLE_AMPLITUDE_API_KEY" \ RAZZLE_ENVIRONMENT="$RAZZLE_ENVIRONMENT" \ RAZZLE_TAP_PAY_APP_ID="$RAZZLE_TAP_PAY_APP_ID" \ RAZZLE_TAP_PAY_APP_KEY="$RAZZLE_TAP_PAY_APP_KEY" \ diff --git a/package.json b/package.json index 9dd337b5d..d0c9dc587 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "airbnb-prop-types": "^2.15.0", "classnames": "^2.2.5", "date-fns": "^2.30.0", - "express": "^4.16.3", + "express": "^4.17.3", "history": "^4.7.2", "immutable": "^3.8.1", "isomorphic-fetch": "^2.2.1", @@ -72,7 +72,7 @@ "postcss-nested": "^3.0.0", "postcss-simple-vars": "^4.1.0", "prop-types": "^15.6.0", - "qs": "^6.4.0", + "qs": "^6.7.3", "ramda": "^0.23.0", "razzle": "^2.4.0", "react": "^16.12.0", diff --git a/src/actions/auth.js b/src/actions/auth.js index 4594f3180..16e6697c4 100644 --- a/src/actions/auth.js +++ b/src/actions/auth.js @@ -1,6 +1,5 @@ import ReactGA from 'react-ga4'; import authStatus from '../constants/authStatus'; -import { UserTracker } from '../utils/eventBasedTracking'; export const SET_LOGIN = '@@auth/SET_LOGIN'; export const SET_USER = '@@auth/SET_USER'; @@ -24,8 +23,6 @@ const logOutAction = () => ({ export const logout = () => (dispatch, getState, { history }) => { dispatch(logOutAction()); history.push('/'); - // reset user for Amplitude - UserTracker.resetUser(); }; /** @@ -94,8 +91,6 @@ export const loginWithToken = token => (dispatch, getState, { api }) => { .then(user => { dispatch(setUser(user)); dispatch(setLogin(authStatus.CONNECTED, token)); - // identify user for Amplitude - UserTracker.identifyUser(user._id); // identify user for Google Analytics ReactGA.set({ userId: user._id }); }) diff --git a/src/actions/experience.js b/src/actions/experience.js new file mode 100644 index 000000000..707a583fa --- /dev/null +++ b/src/actions/experience.js @@ -0,0 +1,132 @@ +import { concat } from 'ramda'; +import { getError, getFetched, toFetching, isFetching } from 'utils/fetchBox'; +import { relatedExperiencesStateSelector } from 'selectors/experienceSelector'; + +export const SET_RELATED_EXPERIENCES = '@@EXPERIENCE/SET_RELATED_EXPERIENCES'; + +const setRelatedExperiencesState = relatedExperiencesState => ({ + type: SET_RELATED_EXPERIENCES, + relatedExperiencesState, +}); + +export const queryRelatedExperiencesOnExperience = experienceId => async ( + dispatch, + getState, + { api }, +) => { + const page = 0; + + dispatch( + setRelatedExperiencesState( + // this is an work around + toFetching({ + data: { + experienceId, + page, + relatedExperiences: [], + hasMore: false, + }, + }), + ), + ); + + try { + const relatedExperiences = await api.experiences.queryRelatedExperiences({ + id: experienceId, + start: page * 5, + limit: 5, + }); + + const previousState = relatedExperiencesStateSelector(getState()); // FetchBox + + if ( + experienceId === previousState.data.experienceId && + page === previousState.data.page + ) { + const hasMore = relatedExperiences.length < 5 ? false : true; + + dispatch( + setRelatedExperiencesState( + getFetched({ + experienceId, + page, + relatedExperiences, + hasMore, + }), + ), + ); + } + } catch (error) { + dispatch(setRelatedExperiencesState(getError(error))); + } +}; + +export const loadMoreRelatedExperiences = () => async ( + dispatch, + getState, + { api }, +) => { + const state = relatedExperiencesStateSelector(getState()); // FetchBox + + // 判斷 isFetching + if (isFetching(state)) { + return; + } + + const experienceId = state.data.experienceId; + const page = state.data.page + 1; + + dispatch( + setRelatedExperiencesState( + // this is an work around + toFetching({ + data: { + experienceId, + page, + relatedExperiences: state.data.relatedExperiences, + hasMore: false, + }, + }), + ), + ); + + try { + const relatedExperiences = await api.experiences.queryRelatedExperiences({ + id: experienceId, + start: page * 5, + limit: 5, + }); + + const previousState = relatedExperiencesStateSelector(getState()); // FetchBox + + if ( + experienceId === previousState.data.experienceId && + page === previousState.data.page + ) { + const hasMore = relatedExperiences.length < 5 ? false : true; + + dispatch( + setRelatedExperiencesState( + getFetched({ + experienceId, + page, + relatedExperiences: concat( + previousState.data.relatedExperiences, + relatedExperiences, + ), + hasMore, + }), + ), + ); + } + } catch (error) { + const previousState = relatedExperiencesStateSelector(getState()); // FetchBox + + if ( + experienceId === previousState.data.experienceId && + page === previousState.data.page + ) { + dispatch(setRelatedExperiencesState(getError(error))); + } + } +}; diff --git a/src/apis/experiencesApi.js b/src/apis/experiencesApi.js index f4e961aa0..94fa9ce37 100644 --- a/src/apis/experiencesApi.js +++ b/src/apis/experiencesApi.js @@ -3,7 +3,10 @@ import R from 'ramda'; import fetchUtil from 'utils/fetchUtil'; import graphqlClient from 'utils/graphqlClient'; -import { getExperienceQuery } from 'graphql/experience'; +import { + getExperienceQuery, + queryRelatedExperiencesGql, +} from 'graphql/experience'; import { getPopularExperiencesQuery } from 'graphql/popularExperience'; import { deleteReplyLike, createReplyLike } from 'graphql/reply'; @@ -120,6 +123,14 @@ const patchExperience = ({ id, status, token }) => token, }); +export const queryRelatedExperiences = async ({ id, start, limit }) => { + const data = await graphqlClient({ + query: queryRelatedExperiencesGql, + variables: { id, start, limit }, + }); + return data.experience.relatedExperiences; +}; + export default { getExperience, getPopularExperiences, @@ -134,4 +145,5 @@ export default { newExperienceSearchBy, patchExperience, patchReply, + queryRelatedExperiences, }; diff --git a/src/apis/payment.js b/src/apis/payment.js index 4d045159b..11881af7a 100644 --- a/src/apis/payment.js +++ b/src/apis/payment.js @@ -4,6 +4,7 @@ import { checkoutSubscriptionWithPrimeMutation, paymentRecord, myCurrentSubscription as myCurrentSubscriptionQuery, + mySubscriptions as mySubscriptionsQuery, } from 'graphql/payment'; const getSubscriptionPlans = () => @@ -54,9 +55,16 @@ const getMyCurrentSubscription = token => () => token, }).then(({ myCurrentSubscription }) => myCurrentSubscription); +const getMySubscriptions = token => () => + graphqlClient({ + query: mySubscriptionsQuery, + token, + }).then(({ mySubscriptions }) => mySubscriptions); + export default { checkoutSubscriptionWithPrime, getSubscriptionPlans, getPaymentRecord, getMyCurrentSubscription, + getMySubscriptions, }; diff --git a/src/components/App/Footer/Footer.module.css b/src/components/App/Footer/Footer.module.css index 1ac5ef215..d0cfa1e68 100644 --- a/src/components/App/Footer/Footer.module.css +++ b/src/components/App/Footer/Footer.module.css @@ -48,7 +48,7 @@ } .logo { - fill: #fff; + filter: invert(1); width: 120px; margin-right: 8px; } diff --git a/src/components/App/Footer/index.js b/src/components/App/Footer/index.js index 62c481fd0..804ac059b 100644 --- a/src/components/App/Footer/index.js +++ b/src/components/App/Footer/index.js @@ -1,10 +1,12 @@ import React from 'react'; import { Link } from 'react-router-dom'; import cn from 'classnames'; -import i from 'common/icons'; +import GjLogo from 'common/icons/GjLogo.svg'; import { Wrapper, P } from 'common/base'; import LinkItem from './LinkItem'; import styles from './Footer.module.css'; +import MediasImg from './medias.jpg'; +import LogoG0vImg from './logo-g0v-white.svg'; const link1 = [ { to: '/salary-work-times/latest', text: '薪資工時' }, @@ -29,7 +31,7 @@ const Footer = () => (