├── public
├── robots.txt
├── favicon.ico
├── favicon.png
├── logo192.png
├── logo512.png
├── favicon-32.png
├── favicon-128.png
├── favicon-152.png
├── favicon-167.png
├── favicon-180.png
├── favicon-192.png
├── favicon-196.png
├── manifest.json
└── index.html
├── src
├── pages
│ ├── Stepper
│ │ ├── constants.js
│ │ ├── index.js
│ │ ├── components
│ │ │ ├── ThirdStep
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── StepperPage
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── FirstStep
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── SecondStep
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ └── TextField
│ │ │ │ └── index.jsx
│ │ └── services
│ │ │ ├── clearFormData.js
│ │ │ ├── setFormData.js
│ │ │ └── getFormData.js
│ ├── Home
│ │ ├── index.jsx
│ │ └── components
│ │ │ └── HomePage
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ ├── ClosePopup
│ │ ├── components
│ │ │ ├── CustomSessionHistory
│ │ │ │ ├── constants.js
│ │ │ │ ├── services
│ │ │ │ │ ├── clearCustomHistory.js
│ │ │ │ │ ├── getHasPrevRoute.js
│ │ │ │ │ ├── setCustomHistory.js
│ │ │ │ │ ├── getCustomHistory.js
│ │ │ │ │ └── updateSessionHistory.js
│ │ │ │ ├── hooks
│ │ │ │ │ └── useClosePopup.js
│ │ │ │ ├── HistoryLogger
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── CustomReduxHistory
│ │ │ │ ├── selectors
│ │ │ │ │ └── history.js
│ │ │ │ ├── hooks
│ │ │ │ │ ├── useGoBack.js
│ │ │ │ │ ├── usePush.js
│ │ │ │ │ ├── useReplace.js
│ │ │ │ │ └── useClosePopup.js
│ │ │ │ └── index.js
│ │ │ ├── State
│ │ │ │ ├── hooks
│ │ │ │ │ ├── usePreparePopupLink.js
│ │ │ │ │ └── useClosePopup.js
│ │ │ │ └── index.js
│ │ │ ├── ClosePopupPage
│ │ │ │ ├── styles.js
│ │ │ │ └── index.js
│ │ │ ├── GoBack
│ │ │ │ └── index.js
│ │ │ └── Push
│ │ │ │ └── index.js
│ │ └── index.js
│ ├── TwoPopups
│ │ ├── index.js
│ │ ├── components
│ │ │ ├── Post
│ │ │ │ ├── styles.js
│ │ │ │ ├── PostCard
│ │ │ │ │ ├── styles.js
│ │ │ │ │ ├── SimilarPicturesPopup
│ │ │ │ │ │ ├── OriginalImage
│ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── ViewersPopup
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── LikesPopup
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ └── index.jsx
│ │ │ │ └── index.jsx
│ │ │ ├── GetParameterPopups
│ │ │ │ ├── Popups
│ │ │ │ │ ├── SignIn
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── SignUp
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── NotificationDetails
│ │ │ │ │ │ ├── Details
│ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── Notifications
│ │ │ │ │ │ ├── NotificationsList
│ │ │ │ │ │ ├── NotificationItem
│ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ └── index.jsx
│ │ │ │ ├── index.jsx
│ │ │ │ └── hooks
│ │ │ │ │ └── useGetPopupsState.js
│ │ │ ├── Posts
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ └── TwoPopupsPage
│ │ │ │ └── index.jsx
│ │ └── data
│ │ │ └── notifications.json
│ ├── CustomPrompt
│ │ ├── index.js
│ │ └── components
│ │ │ ├── CustomPromptPage
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── SignUpForm
│ │ │ ├── styles.js
│ │ │ ├── usePreventReload.js
│ │ │ ├── useFormState.js
│ │ │ └── index.jsx
│ │ │ └── SignUpButton
│ │ │ └── index.jsx
│ ├── PopupsRoutes
│ │ ├── index.js
│ │ ├── components
│ │ │ ├── GetParameterPopups
│ │ │ │ ├── Popups
│ │ │ │ │ ├── Notifications
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ ├── NotificationsList
│ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ ├── NotificationItem
│ │ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ ├── NotificationDetails
│ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ └── index.jsx
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── SignIn
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ └── SignUp
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ ├── index.jsx
│ │ │ │ └── hooks
│ │ │ │ │ └── useGetPopupState.js
│ │ │ ├── Post
│ │ │ │ ├── styles.js
│ │ │ │ ├── PostCard
│ │ │ │ │ ├── styles.js
│ │ │ │ │ ├── ViewersPopup
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ ├── LikesPopup
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ └── index.jsx
│ │ │ │ │ └── index.jsx
│ │ │ │ └── index.jsx
│ │ │ ├── Posts
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ └── PopupsRoutesPage
│ │ │ │ └── index.jsx
│ │ └── data
│ │ │ ├── notifications.json
│ │ │ └── posts.json
│ ├── ResponsiveRoutes
│ │ ├── index.jsx
│ │ └── components
│ │ │ ├── Filter
│ │ │ ├── styles.js
│ │ │ ├── Make
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── Model
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── Body
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── Enging
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── Miles
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ ├── Year
│ │ │ │ ├── styles.js
│ │ │ │ └── index.jsx
│ │ │ └── index.jsx
│ │ │ ├── ResponsiveFilter
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── ResponsiveList
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── Sidebar
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── ResponsiveFilters
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── Desktop
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ ├── List
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ │ └── ResponsiveRoutesPage
│ │ │ └── index.jsx
│ └── RestorePreventedRoute
│ │ ├── index.js
│ │ ├── components
│ │ ├── RestorePreventedRoutePage
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── AuthStatus
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── Links
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── Login
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── Books
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── Food
│ │ │ ├── styles.js
│ │ │ └── index.jsx
│ │ ├── AuthRoute
│ │ │ └── index.jsx
│ │ └── Gallery
│ │ │ └── index.jsx
│ │ └── data
│ │ ├── books.json
│ │ └── gallery.json
├── contexts
│ └── DeviceInfoContext.js
├── assets
│ ├── images
│ │ ├── close-popup.png
│ │ ├── popus-routes.png
│ │ ├── two-popups.png
│ │ ├── custom-prompt.png
│ │ ├── multi-step-form.png
│ │ ├── responsive-routes.png
│ │ └── redirect-after-login.png
│ └── icons
│ │ ├── youtube.svg
│ │ └── github.svg
├── index.js
├── reducer
│ ├── index.js
│ └── history.js
├── hooks
│ └── router
│ │ ├── useGetParameter.js
│ │ └── usePrepareLink.js
├── actions
│ └── history.js
├── components
│ ├── App
│ │ ├── styles.js
│ │ └── index.jsx
│ ├── AppBar
│ │ ├── styles.js
│ │ └── index.jsx
│ ├── DeviceInfoHandler
│ │ └── index.jsx
│ ├── CustomPrompt
│ │ └── index.jsx
│ └── Router
│ │ └── index.jsx
├── const
│ ├── router.js
│ └── tricks.js
├── store.js
└── services
│ └── calculateDeviceInfo.js
├── config
├── jest
│ ├── cssTransform.js
│ └── fileTransform.js
├── pnpTs.js
├── paths.js
├── env.js
└── modules.js
├── .gitignore
├── .github
└── workflows
│ ├── master-deployment.yml
│ └── develop-deployment.yml
├── scripts
├── test.js
└── start.js
└── package.json
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/src/pages/Stepper/constants.js:
--------------------------------------------------------------------------------
1 | export const STEPPER_FORM_DATA_KEY = "stepper-form-data";
2 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/public/favicon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-32.png
--------------------------------------------------------------------------------
/src/pages/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import HomePage from "./components/HomePage";
2 |
3 | export default HomePage;
4 |
--------------------------------------------------------------------------------
/public/favicon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-128.png
--------------------------------------------------------------------------------
/public/favicon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-152.png
--------------------------------------------------------------------------------
/public/favicon-167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-167.png
--------------------------------------------------------------------------------
/public/favicon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-180.png
--------------------------------------------------------------------------------
/public/favicon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-192.png
--------------------------------------------------------------------------------
/public/favicon-196.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/public/favicon-196.png
--------------------------------------------------------------------------------
/src/contexts/DeviceInfoContext.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default React.createContext();
4 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/constants.js:
--------------------------------------------------------------------------------
1 | export const CUSTOM_SESSION_KEY = "custom-history";
2 |
--------------------------------------------------------------------------------
/src/pages/Stepper/index.js:
--------------------------------------------------------------------------------
1 | import StepperPage from "./components/StepperPage";
2 |
3 | export default StepperPage;
4 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/index.js:
--------------------------------------------------------------------------------
1 | import TwoPopupsPage from "./components/TwoPopupsPage";
2 |
3 | export default TwoPopupsPage;
4 |
--------------------------------------------------------------------------------
/src/assets/images/close-popup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/close-popup.png
--------------------------------------------------------------------------------
/src/assets/images/popus-routes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/popus-routes.png
--------------------------------------------------------------------------------
/src/assets/images/two-popups.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/two-popups.png
--------------------------------------------------------------------------------
/src/pages/ClosePopup/index.js:
--------------------------------------------------------------------------------
1 | import ClosePopupPage from "./components/ClosePopupPage";
2 |
3 | export default ClosePopupPage;
4 |
--------------------------------------------------------------------------------
/src/assets/images/custom-prompt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/custom-prompt.png
--------------------------------------------------------------------------------
/src/assets/images/multi-step-form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/multi-step-form.png
--------------------------------------------------------------------------------
/src/assets/images/responsive-routes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/responsive-routes.png
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/index.js:
--------------------------------------------------------------------------------
1 | import CustomPromptPage from "./components/CustomPromptPage";
2 |
3 | export default CustomPromptPage;
4 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/index.js:
--------------------------------------------------------------------------------
1 | import PopupsRoutesPage from "./components/PopupsRoutesPage";
2 |
3 | export default PopupsRoutesPage;
4 |
--------------------------------------------------------------------------------
/src/assets/images/redirect-after-login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sin9k/react-router-dom-tricks/HEAD/src/assets/images/redirect-after-login.png
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/index.jsx:
--------------------------------------------------------------------------------
1 | import ResponsiveRoutesPage from "./components/ResponsiveRoutesPage";
2 |
3 | export default ResponsiveRoutesPage;
4 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/index.js:
--------------------------------------------------------------------------------
1 | import RestorePreventedRoutePage from "./components/RestorePreventedRoutePage";
2 |
3 | export default RestorePreventedRoutePage;
4 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 |
4 | import App from "./components/App";
5 |
6 | ReactDOM.render(, document.getElementById("root"));
7 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/ThirdStep/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | label: {
5 | fontSize: 20,
6 | },
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | }
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/StepperPage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | },
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Make/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | }
7 | }));
8 |
--------------------------------------------------------------------------------
/src/reducer/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 |
3 | import history from "./history";
4 |
5 | const reducer = combineReducers({
6 | history
7 | });
8 |
9 | export default reducer;
10 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/CustomPromptPage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | }
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Model/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | }
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/Stepper/services/clearFormData.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { STEPPER_FORM_DATA_KEY } from "../constants";
3 |
4 | export default () => {
5 | sessionStorage.removeItem(STEPPER_FORM_DATA_KEY);
6 | };
7 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveFilter/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | button: {
5 | margin: "16px 16px 0"
6 | }
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Body/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | width: 200,
6 | height: 80
7 | }
8 | }));
9 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/FirstStep/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | field: {
5 | display: "block",
6 | marginBottom: 16,
7 | },
8 | }));
9 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Enging/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | width: 200,
6 | height: 80
7 | }
8 | }));
9 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/RestorePreventedRoutePage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | },
7 | }));
8 |
--------------------------------------------------------------------------------
/src/pages/Stepper/services/setFormData.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { STEPPER_FORM_DATA_KEY } from "../constants";
3 |
4 | export default (formData) => {
5 | sessionStorage.setItem(STEPPER_FORM_DATA_KEY, JSON.stringify(formData));
6 | };
7 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/services/clearCustomHistory.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { CUSTOM_SESSION_KEY } from "../constants";
3 |
4 | export default () => {
5 | sessionStorage.removeItem(CUSTOM_SESSION_KEY);
6 | };
7 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/services/getHasPrevRoute.js:
--------------------------------------------------------------------------------
1 | import getCustomHistory from "./getCustomHistory";
2 |
3 | export default () => {
4 | const customHistory = getCustomHistory();
5 |
6 | return customHistory.length > 0;
7 | };
8 |
--------------------------------------------------------------------------------
/src/hooks/router/useGetParameter.js:
--------------------------------------------------------------------------------
1 | /* global URLSearchParams */
2 | import { useLocation } from "react-router-dom";
3 |
4 | export default name => {
5 | const { search } = useLocation();
6 | const query = new URLSearchParams(search);
7 | return query.get(name);
8 | };
9 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveList/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | },
7 | filters: {
8 | marginBottom: 16
9 | }
10 | }));
11 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/AuthStatus/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | authorized: {
5 | color: "green"
6 | },
7 | notAuthorized: {
8 | color: "red"
9 | }
10 | }));
11 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/selectors/history.js:
--------------------------------------------------------------------------------
1 | import { createSelector } from "reselect";
2 |
3 | export const getHistory = state => state.history;
4 |
5 | export const getHasPrevRoute = createSelector(
6 | getHistory,
7 | history => history.length > 0
8 | );
9 |
--------------------------------------------------------------------------------
/src/actions/history.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 |
3 | const NAMESPACE = "HISTORY::";
4 |
5 | export const push = createAction(NAMESPACE + "PUSH");
6 | export const replace = createAction(NAMESPACE + "REPLACE");
7 | export const goBack = createAction(NAMESPACE + "GO_BACK");
8 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/services/setCustomHistory.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { CUSTOM_SESSION_KEY } from "../constants";
3 |
4 | export default customHistory => {
5 | sessionStorage.setItem(CUSTOM_SESSION_KEY, JSON.stringify(customHistory));
6 | };
7 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/State/hooks/usePreparePopupLink.js:
--------------------------------------------------------------------------------
1 | import usePrepareLink from "~/hooks/router/usePrepareLink";
2 |
3 | export default linkData => {
4 | return usePrepareLink({
5 | ...linkData,
6 | state: {
7 | hasPrevRoute: true
8 | }
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/SecondStep/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | backIcon: {
5 | marginBottom: 16,
6 | },
7 | field: {
8 | display: "block",
9 | marginBottom: 16,
10 | },
11 | }));
12 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | dialog: {
5 | maxWidth: 650
6 | },
7 | container: {
8 | display: "flex"
9 | }
10 | }));
11 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Miles/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | width: 200,
6 | height: 60,
7 | display: "flex",
8 | alignItems: "flex-end"
9 | }
10 | }));
11 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Year/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | width: 200,
6 | height: 60,
7 | display: "flex",
8 | alignItems: "flex-end"
9 | }
10 | }));
11 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Sidebar/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | title: {
5 | padding: "0 16px"
6 | },
7 | container: {
8 | background: "#f6f6f6",
9 | padding: 0
10 | }
11 | }));
12 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | },
7 | back: {
8 | marginBottom: 16
9 | },
10 | button: {
11 | marginRight: 16
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | },
7 | back: {
8 | marginBottom: 16
9 | },
10 | button: {
11 | marginRight: 16
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | card: {
5 | maxWidth: 345,
6 | margin: "0 16px 16px 0",
7 | textDecoration: "none"
8 | },
9 | media: {
10 | height: 140
11 | }
12 | }));
13 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | card: {
5 | maxWidth: 345,
6 | margin: "0 16px 16px 0",
7 | textDecoration: "none"
8 | },
9 | media: {
10 | height: 140
11 | }
12 | }));
13 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Links/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | link: {
5 | fontSize: 20
6 | },
7 | active: {
8 | pointerEvents: "none",
9 | textDecoration: "none",
10 | color: "black"
11 | }
12 | }));
13 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Login/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | button: {
5 | marginTop: 16
6 | },
7 | nextBooks: {
8 | color: "#9C51B6"
9 | },
10 | nextFood: {
11 | color: "#2243B6"
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationsList/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | root: {
5 | width: 300,
6 | backgroundColor: theme.palette.background.paper,
7 | flexShrink: 0
8 | }
9 | }));
10 |
--------------------------------------------------------------------------------
/src/components/App/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | "@global": {
5 | body: {
6 | margin: 0,
7 | backgroundColor: "#F1F1F1",
8 | },
9 | },
10 | container: {
11 | minWidth: "100vw",
12 | minHeight: "100vh",
13 | },
14 | }));
15 |
--------------------------------------------------------------------------------
/src/const/router.js:
--------------------------------------------------------------------------------
1 | export const GET_PARAMS = {
2 | popup: "popup",
3 | notificationId: "notification-id",
4 | };
5 |
6 | export const GET_ENUMS = {
7 | popup: {
8 | signIn: "sign-in",
9 | signUp: "sign-up",
10 | notifications: "notifications",
11 | notificationDetails: "notification-details",
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/pages/Stepper/services/getFormData.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { STEPPER_FORM_DATA_KEY } from "../constants";
3 |
4 | export default () => {
5 | const rawFormData = sessionStorage.getItem(STEPPER_FORM_DATA_KEY);
6 |
7 | if (!rawFormData) {
8 | return [];
9 | }
10 |
11 | return JSON.parse(rawFormData);
12 | };
13 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/SimilarPicturesPopup/OriginalImage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 0,
6 | border: "none",
7 | cursor: "pointer",
8 | height: 400,
9 | overflow: "hidden",
10 | },
11 | }));
12 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveFilters/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | button: {
5 | margin: "16px 16px 0"
6 | },
7 | title: {
8 | padding: "0 16px"
9 | },
10 | container: {
11 | background: "#f6f6f6",
12 | padding: 0
13 | }
14 | }));
15 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/SignIn/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | display: "flex",
7 | flexDirection: "column",
8 | minWidth: 400
9 | },
10 | field: {
11 | marginBottom: 20
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/SignUp/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | display: "flex",
7 | flexDirection: "column",
8 | minWidth: 400
9 | },
10 | field: {
11 | marginBottom: 20
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/SignIn/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | display: "flex",
7 | flexDirection: "column",
8 | minWidth: 400
9 | },
10 | field: {
11 | marginBottom: 20
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/SignUp/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | display: "flex",
7 | flexDirection: "column",
8 | minWidth: 400
9 | },
10 | field: {
11 | marginBottom: 20
12 | }
13 | }));
14 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationsList/NotificationItem/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | inline: {
5 | display: "inline"
6 | },
7 | item: {
8 | "&:hover": {
9 | backgroundColor: "#f0f0f0"
10 | }
11 | }
12 | }));
13 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/services/getCustomHistory.js:
--------------------------------------------------------------------------------
1 | /* global sessionStorage */
2 | import { CUSTOM_SESSION_KEY } from "../constants";
3 |
4 | export default () => {
5 | const rawCustomHistory = sessionStorage.getItem(CUSTOM_SESSION_KEY);
6 |
7 | if (!rawCustomHistory) {
8 | return [];
9 | }
10 |
11 | return JSON.parse(rawCustomHistory);
12 | };
13 |
--------------------------------------------------------------------------------
/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/en/webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/SignUpForm/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | display: "flex",
7 | flexDirection: "column",
8 | minWidth: 400
9 | },
10 | mobileContainer: {
11 | minWidth: 240
12 | },
13 | field: {
14 | marginBottom: 20
15 | }
16 | }));
17 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import { applyMiddleware, compose, createStore } from "redux";
2 |
3 | import reducer from "./reducer";
4 |
5 | export default () => {
6 | const middlewares = applyMiddleware();
7 |
8 | const composeEnhancers =
9 | window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
10 |
11 | const store = createStore(reducer, composeEnhancers(middlewares));
12 |
13 | return { store };
14 | };
15 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Desktop/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | maxWidth: 1024,
6 | display: "flex",
7 | padding: 16,
8 | margin: "0 auto"
9 | },
10 | sidebar: {
11 | flex: "1 0 25%"
12 | },
13 | list: {
14 | paddingLeft: 16,
15 | flex: "3 0 75%"
16 | }
17 | }));
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/TextField/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import MaterialTextField from "@material-ui/core/TextField";
4 |
5 | const TextField = ({ input, meta, className, label, variant }) => {
6 | return (
7 |
13 | );
14 | };
15 |
16 | export default TextField;
17 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/ViewersPopup/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | padding: 16,
6 | minWidth: 400
7 | },
8 | paper: {
9 | maxWidth: 400,
10 | margin: `${theme.spacing(1)}px auto`,
11 | padding: theme.spacing(2)
12 | },
13 | title: {
14 | display: "flex",
15 | alignItems: "center"
16 | }
17 | }));
18 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/List/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | color: "#444",
6 | backgroundColor: "#f6f6f6",
7 | cursor: "pointer",
8 | padding: "16px 0",
9 | marginBottom: 10,
10 |
11 | "&:hover": {
12 | boxShadow: "0 3px 6px 0 rgba(0,0,0,.35)"
13 | }
14 | },
15 | list: {
16 | margin: 0
17 | }
18 | }));
19 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/ViewersPopup/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | padding: 16,
6 | minWidth: 400
7 | },
8 | paper: {
9 | maxWidth: 400,
10 | margin: `${theme.spacing(1)}px auto`,
11 | padding: theme.spacing(2)
12 | },
13 | title: {
14 | display: "flex",
15 | alignItems: "center"
16 | }
17 | }));
18 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationDetails/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | borderLeft: "1px solid rgba(0, 0, 0, 0.12)"
6 | },
7 | large: {
8 | margin: "24px auto",
9 | width: 84,
10 | height: 84
11 | },
12 | title: {
13 | marginBottom: 12,
14 | textAlign: "center"
15 | }
16 | }));
17 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/NotificationDetails/Details/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles((theme) => ({
4 | container: {
5 | borderLeft: "1px solid rgba(0, 0, 0, 0.12)",
6 | },
7 | large: {
8 | margin: "24px auto",
9 | width: 200,
10 | height: 200,
11 | },
12 | title: {
13 | marginBottom: 12,
14 | textAlign: "center",
15 | },
16 | }));
17 |
--------------------------------------------------------------------------------
/src/components/AppBar/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | root: {
5 | flexGrow: 1
6 | },
7 | list: {
8 | width: 250
9 | },
10 | menuButton: {
11 | marginRight: theme.spacing(2)
12 | },
13 | title: {
14 | flexGrow: 1,
15 | color: "#ffffff",
16 | textDecoration: "none",
17 | "&:hover": {
18 | textDecoration: "underline"
19 | }
20 | }
21 | }));
22 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/Notifications/NotificationsList/NotificationItem/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | inline: {
5 | display: "inline",
6 | },
7 | item: {
8 | "&:hover": {
9 | backgroundColor: "#f0f0f0",
10 | },
11 | },
12 | avatar: {
13 | width: 50,
14 | height: 50,
15 | marginTop: 6,
16 | marginRight: 12,
17 | },
18 | }));
19 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Books/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | root: {
5 | display: "flex",
6 | flexWrap: "wrap",
7 | justifyContent: "space-around",
8 | overflow: "hidden",
9 | backgroundColor: theme.palette.background.paper
10 | },
11 | gridList: {
12 | width: 500,
13 | height: 450
14 | },
15 | icon: {
16 | color: "rgba(255, 255, 255, 0.54)"
17 | }
18 | }));
19 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/LikesPopup/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | padding: 16,
6 | minWidth: 400
7 | },
8 | paper: {
9 | maxWidth: 400,
10 | margin: `${theme.spacing(1)}px auto`,
11 | padding: theme.spacing(2)
12 | },
13 | title: {
14 | display: "flex",
15 | alignItems: "center"
16 | },
17 | avatar: {
18 | background: "#f50057"
19 | }
20 | }));
21 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/hooks/useGoBack.js:
--------------------------------------------------------------------------------
1 | import { useDispatch } from "react-redux";
2 | import { useHistory } from "react-router-dom";
3 | import { useCallback } from "react";
4 |
5 | import * as historyActions from "~/actions/history";
6 |
7 | export default () => {
8 | const history = useHistory();
9 | const dispatch = useDispatch();
10 |
11 | return useCallback(() => {
12 | history.goBack();
13 | dispatch(historyActions.goBack());
14 | }, [history, dispatch]);
15 | };
16 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/LikesPopup/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | padding: 16,
6 | minWidth: 400
7 | },
8 | paper: {
9 | maxWidth: 400,
10 | margin: `${theme.spacing(1)}px auto`,
11 | padding: theme.spacing(2)
12 | },
13 | title: {
14 | display: "flex",
15 | alignItems: "center"
16 | },
17 | avatar: {
18 | background: "#f50057"
19 | }
20 | }));
21 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/Notifications/NotificationsList/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles((theme) => ({
4 | container: {
5 | display: "flex",
6 | position: "relative",
7 | },
8 | root: {
9 | backgroundColor: theme.palette.background.paper,
10 | flexShrink: 0,
11 | margin: "0 auto",
12 | },
13 | close: {
14 | position: "absolute",
15 | top: 16,
16 | right: 16,
17 | },
18 | }));
19 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/ClosePopupPage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | display: "grid",
6 | gridTemplateColumns: "350px 200px",
7 | alignItems: "center",
8 | padding: 20
9 | },
10 | dialog: {
11 | width: 400,
12 | height: 600,
13 | display: "flex",
14 | flexDirection: "column",
15 | justifyContent: "center",
16 | alignItems: "center",
17 | fontSize: 24
18 | }
19 | }));
20 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/State/hooks/useClosePopup.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react";
2 | import { useRouteMatch, useLocation, useHistory } from "react-router-dom";
3 |
4 | export default () => {
5 | const { state } = useLocation();
6 | const history = useHistory();
7 | const match = useRouteMatch();
8 |
9 | return useCallback(() => {
10 | if (state && state.hasPrevRoute) {
11 | history.goBack();
12 | } else {
13 | history.replace(match.url);
14 | }
15 | }, [state, history, match.url]);
16 | };
17 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Posts/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16
6 | },
7 | button: {
8 | marginRight: 16
9 | },
10 | posts: {
11 | margin: "16px 0 16px 0",
12 | display: "flex",
13 | flexDirection: "row",
14 | flexWrap: "wrap"
15 | },
16 | card: {
17 | maxWidth: 345,
18 | margin: "0 16px 16px 0",
19 | textDecoration: "none"
20 | },
21 | media: {
22 | height: 140
23 | }
24 | }));
25 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/hooks/usePush.js:
--------------------------------------------------------------------------------
1 | import { useDispatch } from "react-redux";
2 | import { useHistory } from "react-router-dom";
3 | import { useCallback } from "react";
4 |
5 | import * as historyActions from "~/actions/history";
6 |
7 | export default () => {
8 | const history = useHistory();
9 | const dispatch = useDispatch();
10 |
11 | return useCallback(
12 | link => {
13 | history.push(link);
14 | dispatch(historyActions.push(link));
15 | },
16 | [history, dispatch]
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Desktop/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import List from "../List";
4 | import Sidebar from "../Sidebar";
5 | import useStyles from "./styles";
6 |
7 | const Desktop = () => {
8 | const styles = useStyles();
9 |
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | );
20 | };
21 |
22 | export default Desktop;
23 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Posts/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: 16,
6 | },
7 | button: {
8 | marginRight: 16,
9 | },
10 | posts: {
11 | margin: "16px 0 16px 0",
12 | display: "flex",
13 | flexDirection: "row",
14 | flexWrap: "wrap",
15 | },
16 | card: {
17 | maxWidth: 345,
18 | margin: "0 16px 16px 0",
19 | textDecoration: "none",
20 | },
21 | media: {
22 | height: 200,
23 | },
24 | }));
25 |
--------------------------------------------------------------------------------
/src/services/calculateDeviceInfo.js:
--------------------------------------------------------------------------------
1 | export default width => {
2 | if (width <= 768) {
3 | return {
4 | isMobile: true,
5 | isTablet: false,
6 | isDesktop: false,
7 | device: "mobile"
8 | };
9 | }
10 |
11 | if (width <= 1024) {
12 | return {
13 | isMobile: false,
14 | isTablet: true,
15 | isDesktop: false,
16 | device: "tablet"
17 | };
18 | }
19 |
20 | return {
21 | isMobile: false,
22 | isTablet: false,
23 | isDesktop: true,
24 | device: "desktop"
25 | };
26 | };
27 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/hooks/useReplace.js:
--------------------------------------------------------------------------------
1 | import { useDispatch } from "react-redux";
2 | import { useHistory } from "react-router-dom";
3 | import { useCallback } from "react";
4 |
5 | import * as historyActions from "~/actions/history";
6 |
7 | export default () => {
8 | const history = useHistory();
9 | const dispatch = useDispatch();
10 |
11 | return useCallback(
12 | link => {
13 | history.replace(link);
14 | dispatch(historyActions.replace(link));
15 | },
16 | [history, dispatch]
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/Notifications/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 |
4 | import Dialog from "@material-ui/core/Dialog";
5 |
6 | import NotificationsList from "./NotificationsList";
7 |
8 | const Notifications = ({ isOpened }) => {
9 | const history = useHistory();
10 |
11 | return (
12 |
15 | );
16 | };
17 |
18 | export default Notifications;
19 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/SignUpButton/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 |
6 | import usePrepareLink from "~/hooks/router/usePrepareLink";
7 |
8 | const SignUpButton = () => {
9 | const signUpLink = usePrepareLink({
10 | isRelativePath: true,
11 | to: "/sign-up"
12 | });
13 |
14 | return (
15 |
18 | );
19 | };
20 |
21 | export default SignUpButton;
22 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/AuthStatus/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 |
4 | import useStyles from "./styles";
5 |
6 | const AuthStatus = ({ isAuthorized }) => {
7 | const styles = useStyles();
8 |
9 | return isAuthorized ? (
10 | You are authorized
11 | ) : (
12 | You are not authorized
13 | );
14 | };
15 |
16 | AuthStatus.propTypes = {
17 | isAuthorized: PropTypes.bool.isRequired
18 | };
19 |
20 | export default AuthStatus;
21 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/SignUpForm/usePreventReload.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useCallback } from "react";
2 |
3 | export default isPrenvent => {
4 | const preventReload = useCallback(event => {
5 | event.preventDefault();
6 | event.returnValue = "";
7 | }, []);
8 |
9 | useEffect(() => {
10 | if (isPrenvent) {
11 | window.addEventListener("beforeunload", preventReload);
12 | }
13 | return () => {
14 | if (isPrenvent) {
15 | window.removeEventListener("beforeunload", preventReload);
16 | }
17 | };
18 | }, [isPrenvent, preventReload]);
19 | };
20 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Year/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "@material-ui/core/Slider";
3 |
4 | import useStyles from "./styles";
5 |
6 | const Year = () => {
7 | const styles = useStyles();
8 |
9 | return (
10 |
11 | `${value} Year`}
14 | valueLabelDisplay="on"
15 | step={1}
16 | marks
17 | min={1990}
18 | max={2020}
19 | />
20 |
21 | );
22 | };
23 |
24 | export default Year;
25 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/hooks/useClosePopup.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react";
2 | import { useRouteMatch, useHistory } from "react-router-dom";
3 |
4 | import getHasPrevRoute from "../services/getHasPrevRoute";
5 |
6 | export default () => {
7 | const history = useHistory();
8 | const match = useRouteMatch();
9 |
10 | const hasPrevRoute = getHasPrevRoute();
11 |
12 | return useCallback(() => {
13 | if (hasPrevRoute) {
14 | history.goBack();
15 | } else {
16 | history.replace(match.url);
17 | }
18 | }, [history, match.url, hasPrevRoute]);
19 | };
20 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Miles/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "@material-ui/core/Slider";
3 |
4 | import useStyles from "./styles";
5 |
6 | const Miles = () => {
7 | const styles = useStyles();
8 |
9 | return (
10 |
11 | `${value} miles`}
14 | valueLabelDisplay="on"
15 | step={10}
16 | marks
17 | min={0}
18 | max={1000}
19 | />
20 |
21 | );
22 | };
23 |
24 | export default Miles;
25 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Food/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(theme => ({
4 | root: {
5 | maxWidth: 345
6 | },
7 | media: {
8 | height: 0,
9 | paddingTop: "56.25%" // 16:9
10 | },
11 | expand: {
12 | transform: "rotate(0deg)",
13 | marginLeft: "auto",
14 | transition: theme.transitions.create("transform", {
15 | duration: theme.transitions.duration.shortest
16 | })
17 | },
18 | expandOpen: {
19 | transform: "rotate(180deg)"
20 | },
21 | avatar: {
22 | backgroundColor: "red"
23 | }
24 | }));
25 |
--------------------------------------------------------------------------------
/src/components/App/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Provider } from "react-redux";
3 |
4 | import createStore from "~/store";
5 |
6 | import Router from "../Router";
7 | import DeviceInfoHandler from "../DeviceInfoHandler";
8 | import useStyles from "./styles";
9 |
10 | const { store } = createStore();
11 | function App() {
12 | const styles = useStyles();
13 |
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/src/reducer/history.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 |
3 | import * as historyActions from "~/actions/history";
4 |
5 | const defaultState = [];
6 |
7 | export default handleActions(
8 | {
9 | [historyActions.push]: (state, action) => {
10 | return [...state, action.payload];
11 | },
12 | [historyActions.replace]: (state, action) => {
13 | if (state.length === 0) {
14 | return state;
15 | }
16 |
17 | return [...state.slice(0, -1), action.payload];
18 | },
19 | [historyActions.goBack]: state => {
20 | return state.slice(0, -1);
21 | }
22 | },
23 | defaultState
24 | );
25 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/HistoryLogger/index.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { useHistory } from "react-router-dom";
3 |
4 | import updateSessionHistory from "../services/updateSessionHistory";
5 | import clearCustomHistory from "../services/clearCustomHistory";
6 |
7 | const HistoryLogger = () => {
8 | const history = useHistory();
9 |
10 | useEffect(() => {
11 | const unlistenHistory = history.listen(updateSessionHistory);
12 |
13 | return () => {
14 | unlistenHistory();
15 | clearCustomHistory();
16 | };
17 | }, [history]);
18 |
19 | return null;
20 | };
21 |
22 | export default HistoryLogger;
23 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/services/updateSessionHistory.js:
--------------------------------------------------------------------------------
1 | import setCustomHistory from "./setCustomHistory";
2 | import getCustomHistory from "./getCustomHistory";
3 |
4 | export default (location, type) => {
5 | const customHistory = getCustomHistory();
6 |
7 | switch (type) {
8 | case "REPLACE": {
9 | customHistory.pop();
10 | customHistory.push(location);
11 | break;
12 | }
13 | case "PUSH": {
14 | customHistory.push(location);
15 | break;
16 | }
17 | case "POP": {
18 | customHistory.pop();
19 | break;
20 | }
21 | default: {
22 | }
23 | }
24 |
25 | setCustomHistory(customHistory);
26 | };
27 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import Body from "./Body";
4 | import Enging from "./Enging";
5 | import Make from "./Make";
6 | import Model from "./Model";
7 | import Miles from "./Miles";
8 | import Year from "./Year";
9 | import useStyles from "./styles";
10 |
11 | const TypeComponent = {
12 | body: Body,
13 | enging: Enging,
14 | make: Make,
15 | model: Model,
16 | miles: Miles,
17 | year: Year
18 | };
19 |
20 | const Filter = ({ type }) => {
21 | const styles = useStyles();
22 |
23 | const Component = TypeComponent[type];
24 |
25 | return {}
;
26 | };
27 |
28 | export default Filter;
29 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/TwoPopupsPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route, useRouteMatch, Redirect } from "react-router-dom";
3 |
4 | import Posts from "../Posts";
5 | import Post from "../Post";
6 | import GetParameterPopups from "../GetParameterPopups";
7 |
8 | const TwoPopupsPage = () => {
9 | const { url } = useRouteMatch();
10 |
11 | return (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | >
24 | );
25 | };
26 |
27 | export default TwoPopupsPage;
28 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/List/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import Vehicles from "../../data/vehicles.json";
4 | import useStyles from "./styles";
5 |
6 | const List = () => {
7 | const styles = useStyles();
8 |
9 | return Vehicles.map(vehicle => {
10 | return (
11 |
12 |
13 | - make: {vehicle.make}
14 | - model: {vehicle.model}
15 | - year: {vehicle.year}
16 | - engine: {vehicle.engine}
17 | - miles: {vehicle.miles}
18 | - bodyStyle: {vehicle.bodyStyle}
19 |
20 |
21 | );
22 | });
23 | };
24 |
25 | export default List;
26 |
--------------------------------------------------------------------------------
/config/pnpTs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const { resolveModuleName } = require('ts-pnp');
4 |
5 | exports.resolveModuleName = (
6 | typescript,
7 | moduleName,
8 | containingFile,
9 | compilerOptions,
10 | resolutionHost
11 | ) => {
12 | return resolveModuleName(
13 | moduleName,
14 | containingFile,
15 | compilerOptions,
16 | resolutionHost,
17 | typescript.resolveModuleName
18 | );
19 | };
20 |
21 | exports.resolveTypeReferenceDirective = (
22 | typescript,
23 | moduleName,
24 | containingFile,
25 | compilerOptions,
26 | resolutionHost
27 | ) => {
28 | return resolveModuleName(
29 | moduleName,
30 | containingFile,
31 | compilerOptions,
32 | resolutionHost,
33 | typescript.resolveTypeReferenceDirective
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/PopupsRoutesPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route, useRouteMatch, Redirect } from "react-router-dom";
3 |
4 | import Posts from "../Posts";
5 | import Post from "../Post";
6 | import GetParameterPopups from "../GetParameterPopups";
7 |
8 | const ResponsiveRoutesPage = () => {
9 | const { url } = useRouteMatch();
10 |
11 | return (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | >
24 | );
25 | };
26 |
27 | export default ResponsiveRoutesPage;
28 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveFilter/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useParams, useHistory } from "react-router-dom";
3 | import Button from "@material-ui/core/Button";
4 |
5 | import Filter from "../Filter";
6 | import useStyles from "./styles";
7 |
8 | const ResponsiveFilter = () => {
9 | const { type } = useParams();
10 | const styles = useStyles();
11 | const history = useHistory();
12 |
13 | return (
14 |
15 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default ResponsiveFilter;
29 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveList/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link, useRouteMatch } from "react-router-dom";
3 | import Button from "@material-ui/core/Button";
4 |
5 | import List from "../List";
6 | import useStyles from "./styles";
7 |
8 | const ResponsiveList = () => {
9 | const styles = useStyles();
10 | const { url } = useRouteMatch();
11 |
12 | return (
13 |
14 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default ResponsiveList;
29 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/AuthRoute/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Redirect } from "react-router-dom";
3 |
4 | import usePrepareLink from "~/hooks/router/usePrepareLink";
5 |
6 | const AuthRoute = ({ children, isAuthorized, ...rest }) => {
7 | const loginLink = usePrepareLink({
8 | to: "/login",
9 | isRelativePath: true
10 | });
11 |
12 | return (
13 |
16 | isAuthorized ? (
17 | children
18 | ) : (
19 |
25 | )
26 | }
27 | />
28 | );
29 | };
30 |
31 | export default AuthRoute;
32 |
--------------------------------------------------------------------------------
/src/assets/icons/youtube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/SignUpForm/useFormState.js:
--------------------------------------------------------------------------------
1 | import { useState, useCallback } from "react";
2 |
3 | export default () => {
4 | const [fields, setFields] = useState({});
5 |
6 | const onChange = useCallback(
7 | event => {
8 | const filteredFields = Object.entries({
9 | ...fields,
10 | [event.target.name]: event.target.value
11 | }).reduce((memo, [key, value]) => {
12 | if (value) {
13 | memo[key] = value;
14 | }
15 |
16 | return memo;
17 | }, {});
18 |
19 | setFields(filteredFields);
20 | },
21 | [fields]
22 | );
23 |
24 | const onSubmit = useCallback(event => {
25 | event.preventDefault();
26 | }, []);
27 |
28 | return {
29 | fields,
30 | onChange,
31 | onSubmit
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/hooks/useClosePopup.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react";
2 | import { useSelector } from "react-redux";
3 | import { useRouteMatch } from "react-router-dom";
4 |
5 | import * as historySelectors from "../selectors/history";
6 |
7 | import useGoBack from "./useGoBack";
8 | import useReplace from "./useReplace";
9 |
10 | export default () => {
11 | const hasPrevRoute = useSelector(state => {
12 | return historySelectors.getHasPrevRoute(state);
13 | });
14 |
15 | const match = useRouteMatch();
16 | const goBack = useGoBack();
17 | const replace = useReplace();
18 |
19 | return useCallback(() => {
20 | if (hasPrevRoute) {
21 | goBack();
22 | } else {
23 | replace(match.url);
24 | }
25 | }, [goBack, replace, match.url, hasPrevRoute]);
26 | };
27 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { GET_ENUMS } from "~/const/router";
4 |
5 | import useGetPopupState from "./hooks/useGetPopupState";
6 | import SignIn from "./Popups/SignIn";
7 | import SignUp from "./Popups/SignUp";
8 | import Notifications from "./Popups/Notifications";
9 |
10 | const popups = {
11 | [GET_ENUMS.popup.signIn]: SignIn,
12 | [GET_ENUMS.popup.signUp]: SignUp,
13 | [GET_ENUMS.popup.notifications]: Notifications
14 | };
15 |
16 | const GetParameterPopups = () => {
17 | const { mountedPopup, isOpened } = useGetPopupState();
18 | const Component = popups[mountedPopup];
19 |
20 | if (!Component) {
21 | return null;
22 | }
23 |
24 | return ;
25 | };
26 |
27 | export default GetParameterPopups;
28 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/ClosePopupPage/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import GoBack from "../GoBack";
4 | import Push from "../Push";
5 | import CustomSessionHistory from "../CustomSessionHistory";
6 | import CustomReduxHistory from "../CustomReduxHistory";
7 | import State from "../State";
8 | import useStyles from "./styles";
9 |
10 | const ClosePopupPage = () => {
11 | const styles = useStyles();
12 |
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 | };
23 |
24 | export default ClosePopupPage;
25 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Make/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import FormControl from "@material-ui/core/FormControl";
3 | import FormGroup from "@material-ui/core/FormGroup";
4 | import FormControlLabel from "@material-ui/core/FormControlLabel";
5 | import Checkbox from "@material-ui/core/Checkbox";
6 |
7 | const Make = () => {
8 | return (
9 |
10 |
11 | } label="Ford" />
12 | }
14 | label="Toyota"
15 | />
16 | }
18 | label="Nissan"
19 | />
20 | } label="Honda" />
21 |
22 |
23 | );
24 | };
25 |
26 | export default Make;
27 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/SimilarPicturesPopup/OriginalImage/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import PropTypes from "prop-types";
3 | import { useRouteMatch, useHistory } from "react-router-dom";
4 |
5 | import useStyles from "./styles";
6 |
7 | const OriginalImage = ({ pictures }) => {
8 | const styles = useStyles();
9 | const match = useRouteMatch();
10 | const history = useHistory();
11 | const [id] = useState(match && Number(match.params.id));
12 |
13 | const picture = pictures.find((picture) => picture.id === id);
14 |
15 | if (!picture) {
16 | return null;
17 | }
18 |
19 | return (
20 |
23 | );
24 | };
25 |
26 | OriginalImage.propTypes = {
27 | pictures: PropTypes.array.isRequired,
28 | };
29 |
30 | export default OriginalImage;
31 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/data/books.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "title": "Code Complete: A Practical Handbook of Software Construction",
4 | "img": "https://spzone-simpleprogrammer.netdna-ssl.com/wp-content/uploads/2015/03/codecomplete.jpg",
5 | "author": "Steve McConnell"
6 | },
7 | {
8 | "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
9 | "img": "https://spzone-simpleprogrammer.netdna-ssl.com/wp-content/uploads/2018/12/Clean-Code.png",
10 | "author": "Robert C. Martin"
11 | },
12 | {
13 | "title": "Design Patterns: Elements of Reusable Object-Oriented Software",
14 | "img": "https://images-na.ssl-images-amazon.com/images/I/51szD9HC9pL._SX395_BO1,204,203,200_.jpg",
15 | "author": "Erich Gamma"
16 | },
17 | {
18 | "title": "Head First Design Patterns: A Brain-Friendly Guide",
19 | "img": "https://images-na.ssl-images-amazon.com/images/I/61ZG-hATOeL._SX430_BO1,204,203,200_.jpg",
20 | "author": "Elisabeth Robson"
21 | }
22 | ]
23 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/data/notifications.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "avatar": "",
5 | "title": "Brunch this weekend?",
6 | "user": "Ali Connors",
7 | "shortText": "I'll be in your neighborhood doing errands in this…",
8 | "fullText": "I'll be in your neighborhood doing errands in this weekend and one more thing what i want to say"
9 | },
10 | {
11 | "id": 2,
12 | "avatar": "",
13 | "title": "Summer BBQ",
14 | "user": "to Scott, Alex, Jennifer",
15 | "shortText": "Wish I could come, but I'm out of town this…",
16 | "fullText": "Wish I could come, but I'm out of town this weekend but i need to ask you something important"
17 | },
18 | {
19 | "id": 3,
20 | "avatar": "",
21 | "title": "Oui Oui",
22 | "user": "Sandra Adams",
23 | "shortText": "Do you have Paris recommendations? Have you ever…",
24 | "fullText": "Do you have Paris recommendations? Have you ever been in Belarus? or it's not important for you today?"
25 | }
26 | ]
27 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/hooks/useGetPopupState.js:
--------------------------------------------------------------------------------
1 | /* global clearTimeout */
2 | import { useState, useEffect, useMemo } from "react";
3 |
4 | import { GET_PARAMS } from "~/const/router";
5 | import useGetParameter from "~/hooks/router/useGetParameter";
6 |
7 | let timeout;
8 |
9 | export default () => {
10 | const popupName = useGetParameter(GET_PARAMS.popup);
11 | const [mountedPopup, setMountedPopup] = useState(popupName);
12 |
13 | useEffect(() => {
14 | if (popupName) {
15 | timeout && clearTimeout(timeout);
16 | setMountedPopup(popupName);
17 | } else {
18 | timeout = setTimeout(() => {
19 | setMountedPopup(null);
20 | }, 300);
21 | }
22 | }, [popupName]);
23 |
24 | useEffect(() => {
25 | return () => {
26 | timeout && clearTimeout(timeout);
27 | };
28 | }, []);
29 |
30 | const isOpened = useMemo(() => Boolean(popupName), [popupName]);
31 |
32 | return {
33 | mountedPopup,
34 | isOpened
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationsList/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from "react";
2 | import List from "@material-ui/core/List";
3 | import Divider from "@material-ui/core/Divider";
4 |
5 | import notifications from "../../../../../data/notifications";
6 | import NotificationItem from "./NotificationItem";
7 | import useStyles from "./styles";
8 |
9 | const NotificationsList = () => {
10 | const styles = useStyles();
11 |
12 | return (
13 |
14 | {notifications.map((notification, index, notifications) => {
15 | const isLastNotification = notifications.length - 1 !== index;
16 |
17 | return (
18 |
19 |
20 | {isLastNotification && }
21 |
22 | );
23 | })}
24 |
25 | );
26 | };
27 |
28 | export default NotificationsList;
29 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/data/gallery.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "src": "https://i.ytimg.com/vi/pLqipJNItIo/hqdefault.jpg?sqp=-oaymwEYCNIBEHZIVfKriqkDCwgBFQAAiEIYAXAB&rs=AOn4CLBkklsyaw9FxDmMKapyBYCn9tbPNQ",
4 | "title": "Don Diablo @ Tomorrowland Main Stage 2019 | Official…",
5 | "channel": "Don Diablo",
6 | "views": "396 k views",
7 | "createdAt": "a week ago"
8 | },
9 | {
10 | "src": "https://i.ytimg.com/vi/_Uu12zY01ts/hqdefault.jpg?sqp=-oaymwEZCPYBEIoBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLCpX6Jan2rxrCAZxJYDXppTP4MoQA",
11 | "title": "Queen - Greatest Hits",
12 | "channel": "Queen Official",
13 | "views": "40 M views",
14 | "createdAt": "3 years ago"
15 | },
16 | {
17 | "src": "https://i.ytimg.com/vi/kkLk2XWMBf8/hqdefault.jpg?sqp=-oaymwEYCNIBEHZIVfKriqkDCwgBFQAAiEIYAXAB&rs=AOn4CLB4GZTFu1Ju2EPPPXnhMZtFVvYBaw",
18 | "title": "Calvin Harris, Sam Smith - Promises (Official Video)",
19 | "channel": "Calvin Harris",
20 | "views": "130 M views",
21 | "createdAt": "10 months ago"
22 | }
23 | ]
24 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Model/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import FormControl from "@material-ui/core/FormControl";
3 | import FormGroup from "@material-ui/core/FormGroup";
4 | import FormControlLabel from "@material-ui/core/FormControlLabel";
5 | import Checkbox from "@material-ui/core/Checkbox";
6 |
7 | const Model = () => {
8 | return (
9 |
10 |
11 | }
13 | label="Fusion S"
14 | />
15 | }
17 | label="Focus SE"
18 | />
19 | }
21 | label="Fiesta SE"
22 | />
23 | }
25 | label="Taurus SE"
26 | />
27 |
28 |
29 | );
30 | };
31 |
32 | export default Model;
33 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/SignIn/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 | import Dialog from "@material-ui/core/Dialog";
4 | import TextField from "@material-ui/core/TextField";
5 | import Button from "@material-ui/core/Button";
6 |
7 | import useStyles from "./styles";
8 |
9 | const SignIn = ({ isOpened }) => {
10 | const styles = useStyles();
11 | const history = useHistory();
12 |
13 | return (
14 |
29 | );
30 | };
31 |
32 | export default SignIn;
33 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/SignIn/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 | import Dialog from "@material-ui/core/Dialog";
4 | import TextField from "@material-ui/core/TextField";
5 | import Button from "@material-ui/core/Button";
6 |
7 | import useStyles from "./styles";
8 |
9 | const SignIn = ({ isOpened }) => {
10 | const styles = useStyles();
11 | const history = useHistory();
12 |
13 | return (
14 |
29 | );
30 | };
31 |
32 | export default SignIn;
33 |
--------------------------------------------------------------------------------
/src/components/DeviceInfoHandler/index.jsx:
--------------------------------------------------------------------------------
1 | /* global window */
2 | import React, { useState, useCallback, useEffect } from "react";
3 |
4 | import DeviceInfoContext from "~/contexts/DeviceInfoContext";
5 | import calculateDeviceInfo from "~/services/calculateDeviceInfo";
6 |
7 | const DeviceInfoHandler = ({ children }) => {
8 | const [deviceInfo, setDeviceInfo] = useState(
9 | calculateDeviceInfo(window.innerWidth)
10 | );
11 |
12 | const onResize = useCallback(() => {
13 | const newDeviceInfo = calculateDeviceInfo(window.innerWidth);
14 |
15 | if (deviceInfo.device !== newDeviceInfo.device) {
16 | setDeviceInfo(newDeviceInfo);
17 | }
18 | }, [deviceInfo]);
19 |
20 | useEffect(() => {
21 | window.addEventListener("resize", onResize);
22 | return () => {
23 | window.removeEventListener("resize", onResize);
24 | };
25 | }, [deviceInfo, onResize]);
26 |
27 | return (
28 |
29 | {children}
30 |
31 | );
32 | };
33 |
34 | export default DeviceInfoHandler;
35 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/NotificationDetails/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { useHistory } from "react-router-dom";
3 | import Dialog from "@material-ui/core/Dialog";
4 |
5 | import { GET_PARAMS } from "~/const/router";
6 | import useGetParameter from "~/hooks/router/useGetParameter";
7 |
8 | import Details from "./Details";
9 |
10 | const NotificationDetails = ({ isOpened }) => {
11 | const history = useHistory();
12 | const queryNotificationId = useGetParameter(GET_PARAMS.notificationId);
13 | const [notificationId, setNotificationId] = useState(
14 | Number(queryNotificationId)
15 | );
16 |
17 | useEffect(() => {
18 | if (queryNotificationId) {
19 | setNotificationId(Number(queryNotificationId));
20 | }
21 | }, [queryNotificationId]);
22 |
23 | return (
24 |
30 | );
31 | };
32 |
33 | export default NotificationDetails;
34 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { GET_ENUMS } from "~/const/router";
4 |
5 | import useGetPopupsState from "./hooks/useGetPopupsState";
6 | import SignIn from "./Popups/SignIn";
7 | import SignUp from "./Popups/SignUp";
8 | import Notifications from "./Popups/Notifications";
9 | import NotificationDetails from "./Popups/NotificationDetails";
10 |
11 | const mappedPopups = {
12 | [GET_ENUMS.popup.signIn]: SignIn,
13 | [GET_ENUMS.popup.signUp]: SignUp,
14 | [GET_ENUMS.popup.notifications]: Notifications,
15 | [GET_ENUMS.popup.notificationDetails]: NotificationDetails,
16 | };
17 |
18 | const GetParameterPopups = () => {
19 | const { mountedPopups, popups } = useGetPopupsState();
20 |
21 | return mountedPopups.map((mountedPopup) => {
22 | const Component = mappedPopups[mountedPopup];
23 |
24 | if (!Component) {
25 | return null;
26 | }
27 |
28 | return (
29 |
30 | );
31 | });
32 | };
33 |
34 | export default GetParameterPopups;
35 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/ViewersPopup/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Paper from "@material-ui/core/Paper";
3 | import Grid from "@material-ui/core/Grid";
4 | import Avatar from "@material-ui/core/Avatar";
5 | import Typography from "@material-ui/core/Typography";
6 |
7 | import useStyles from "./styles";
8 |
9 | const ViewersPopup = ({ viewers }) => {
10 | const styles = useStyles();
11 |
12 | return (
13 |
14 |
Viewers
15 | {viewers.map(like => {
16 | return (
17 |
18 |
19 |
20 | {like.title.charAt(0)}
21 |
22 |
23 | {like.title}
24 |
25 |
26 |
27 | );
28 | })}
29 |
30 | );
31 | };
32 |
33 | export default ViewersPopup;
34 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/ViewersPopup/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Paper from "@material-ui/core/Paper";
3 | import Grid from "@material-ui/core/Grid";
4 | import Avatar from "@material-ui/core/Avatar";
5 | import Typography from "@material-ui/core/Typography";
6 |
7 | import useStyles from "./styles";
8 |
9 | const ViewersPopup = ({ viewers }) => {
10 | const styles = useStyles();
11 |
12 | return (
13 |
14 |
Viewers
15 | {viewers.map(like => {
16 | return (
17 |
18 |
19 |
20 | {like.title.charAt(0)}
21 |
22 |
23 | {like.title}
24 |
25 |
26 |
27 | );
28 | })}
29 |
30 | );
31 | };
32 |
33 | export default ViewersPopup;
34 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/SimilarPicturesPopup/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles((theme) => ({
4 | container: {
5 | display: "flex",
6 | flexDirection: "column",
7 | padding: "16px 0",
8 | minWidth: 400,
9 | overflow: "hidden",
10 | },
11 | title: {
12 | marginTop: 0,
13 | padding: "0 16px",
14 | display: "flex",
15 | flexDirection: "row",
16 | justifyContent: "space-between",
17 | },
18 | grid: {
19 | flex: 1,
20 | display: "grid",
21 | "grid-template-columns": "220px 220px",
22 | "grid-gap": 10,
23 | overflow: "auto",
24 | padding: "0 16px",
25 | "&::-webkit-scrollbar-track": {
26 | "background-color": "#F5F5F5",
27 | },
28 | "&::-webkit-scrollbar": {
29 | width: 4,
30 | "border-radius": 10,
31 | "background-color": "#F5F5F5",
32 | },
33 | "&::-webkit-scrollbar-thumb": {
34 | "background-color": "#BCBCBC",
35 | },
36 | },
37 | button: {
38 | border: "none",
39 | padding: 0,
40 | cursor: "pointer",
41 | },
42 | }));
43 |
--------------------------------------------------------------------------------
/.github/workflows/master-deployment.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 |
6 | name: Deploy to Amazon EC2
7 |
8 | jobs:
9 | deploy:
10 | name: Deploy
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v2
16 |
17 | - name: Nodejs 12.14.0
18 | uses: actions/setup-node@v1
19 | with:
20 | node-version: 12.14.0
21 |
22 | - uses: actions/cache@v1
23 | with:
24 | path: ~/.npm
25 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
26 | restore-keys: |
27 | ${{ runner.os }}-node-
28 |
29 | - name: install and build
30 | run: |
31 | npm install
32 | npm run build
33 | env:
34 | CI: true
35 |
36 | - name: deploy
37 | uses: garygrossgarten/github-action-scp@release
38 | with:
39 | local: ./build
40 | remote: /var/www/sin9k
41 | host: ${{ secrets.SERVER_HOST }}
42 | username: ${{ secrets.SSH_USER }}
43 | privateKey: ${{ secrets.SERVER_SSH_KEY }}
44 |
--------------------------------------------------------------------------------
/.github/workflows/develop-deployment.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - develop
5 |
6 | name: Deploy to stage Amazon EC2
7 |
8 | jobs:
9 | deploy:
10 | name: Deploy
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v2
16 |
17 | - name: Nodejs 12.14.0
18 | uses: actions/setup-node@v1
19 | with:
20 | node-version: 12.14.0
21 |
22 | - uses: actions/cache@v1
23 | with:
24 | path: ~/.npm
25 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
26 | restore-keys: |
27 | ${{ runner.os }}-node-
28 |
29 | - name: install and build
30 | run: |
31 | npm install
32 | npm run build
33 | env:
34 | CI: true
35 |
36 | - name: deploy
37 | uses: garygrossgarten/github-action-scp@release
38 | with:
39 | local: ./build
40 | remote: /var/www/stage-sin9k
41 | host: ${{ secrets.SERVER_HOST }}
42 | username: ${{ secrets.SSH_USER }}
43 | privateKey: ${{ secrets.SERVER_SSH_KEY }}
44 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/LikesPopup/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Paper from "@material-ui/core/Paper";
3 | import Grid from "@material-ui/core/Grid";
4 | import Avatar from "@material-ui/core/Avatar";
5 | import Typography from "@material-ui/core/Typography";
6 |
7 | import useStyles from "./styles";
8 |
9 | const LikesPopup = ({ likes }) => {
10 | const styles = useStyles();
11 |
12 | return (
13 |
14 |
Likes
15 | {likes.map(like => {
16 | return (
17 |
18 |
19 |
20 |
21 | {like.title.charAt(0)}
22 |
23 |
24 |
25 | {like.title}
26 |
27 |
28 |
29 | );
30 | })}
31 |
32 | );
33 | };
34 |
35 | export default LikesPopup;
36 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/GoBack/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Link, useHistory } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 | import Dialog from "@material-ui/core/Dialog";
6 |
7 | import usePrepareLink from "~/hooks/router/usePrepareLink";
8 |
9 | const GoBack = ({ dialogClassName }) => {
10 | const history = useHistory();
11 |
12 | const goBackLink = usePrepareLink({
13 | to: "/history-go-back",
14 | isRelativePath: true
15 | });
16 |
17 | return (
18 | <>
19 | call history.goBack() by close -
20 |
21 |
24 |
{
27 | return (
28 |
31 | );
32 | }}
33 | />
34 |
35 | >
36 | );
37 | };
38 |
39 | export default GoBack;
40 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/LikesPopup/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Paper from "@material-ui/core/Paper";
3 | import Grid from "@material-ui/core/Grid";
4 | import Avatar from "@material-ui/core/Avatar";
5 | import Typography from "@material-ui/core/Typography";
6 |
7 | import useStyles from "./styles";
8 |
9 | const LikesPopup = ({ likes }) => {
10 | const styles = useStyles();
11 |
12 | return (
13 |
14 |
Likes
15 | {likes.map(like => {
16 | return (
17 |
18 |
19 |
20 |
21 | {like.title.charAt(0)}
22 |
23 |
24 |
25 | {like.title}
26 |
27 |
28 |
29 | );
30 | })}
31 |
32 | );
33 | };
34 |
35 | export default LikesPopup;
36 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Body/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import FormControl from "@material-ui/core/FormControl";
3 | import FormGroup from "@material-ui/core/FormGroup";
4 | import FormControlLabel from "@material-ui/core/FormControlLabel";
5 | import Checkbox from "@material-ui/core/Checkbox";
6 |
7 | const Body = () => {
8 | return (
9 |
10 |
11 | }
13 | label="Convertibles"
14 | />
15 | }
17 | label="Coupes"
18 | />
19 | }
21 | label="Hatchbacks"
22 | />
23 | }
25 | label="Sedans"
26 | />
27 | }
29 | label="Trucks"
30 | />
31 |
32 |
33 | );
34 | };
35 |
36 | export default Body;
37 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/hooks/useGetPopupsState.js:
--------------------------------------------------------------------------------
1 | /* global clearTimeout */
2 | import { useState, useEffect, useMemo } from "react";
3 |
4 | import { GET_PARAMS } from "~/const/router";
5 | import useGetParameter from "~/hooks/router/useGetParameter";
6 |
7 | let timeout;
8 |
9 | function parseStringifiedValue(value) {
10 | return value ? value.split(",") : [];
11 | }
12 |
13 | export default () => {
14 | const rawPopups = useGetParameter(GET_PARAMS.popup);
15 | const [mountedPopups, setMountedPopups] = useState(
16 | parseStringifiedValue(rawPopups)
17 | );
18 |
19 | useEffect(() => {
20 | if (rawPopups) {
21 | timeout && clearTimeout(timeout);
22 | setMountedPopups(rawPopups.split(","));
23 | } else {
24 | timeout = setTimeout(() => {
25 | setMountedPopups([]);
26 | }, 300);
27 | }
28 | }, [rawPopups]);
29 |
30 | useEffect(() => {
31 | return () => {
32 | timeout && clearTimeout(timeout);
33 | };
34 | }, []);
35 |
36 | const popups = useMemo(() => parseStringifiedValue(rawPopups), [rawPopups]);
37 |
38 | return {
39 | mountedPopups,
40 | popups,
41 | };
42 | };
43 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/State/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link, Route } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 | import Dialog from "@material-ui/core/Dialog";
6 |
7 | import usePreparePopupLink from "./hooks/usePreparePopupLink";
8 | import useClosePopup from "./hooks/useClosePopup";
9 |
10 | const State = ({ dialogClassName }) => {
11 | const stateLink = usePreparePopupLink({
12 | to: "/state",
13 | isRelativePath: true
14 | });
15 |
16 | const closePopup = useClosePopup();
17 |
18 | return (
19 | <>
20 | use state to detect goBack or replace by close -
21 |
22 |
25 |
{
28 | return (
29 |
32 | );
33 | }}
34 | />
35 |
36 | >
37 | );
38 | };
39 |
40 | export default State;
41 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Gallery/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import Grid from "@material-ui/core/Grid";
4 | import Box from "@material-ui/core/Box";
5 | import Typography from "@material-ui/core/Typography";
6 |
7 | import gallery from "../../data/gallery";
8 |
9 | const Gallery = () => {
10 | return (
11 |
12 | {gallery.map((item, index) => (
13 |
14 |
19 |
20 |
21 |
22 | {item.title}
23 |
24 |
25 | {item.channel}
26 |
27 |
28 | {`${item.views} • ${item.createdAt}`}
29 |
30 |
31 |
32 | ))}
33 |
34 | );
35 | };
36 |
37 | export default Gallery;
38 |
--------------------------------------------------------------------------------
/src/hooks/router/usePrepareLink.js:
--------------------------------------------------------------------------------
1 | import { useLocation, useRouteMatch } from "react-router-dom";
2 |
3 | export default ({
4 | to,
5 | isRelativePath = false,
6 | query = {},
7 | pushToQuery = {},
8 | hash,
9 | keepOldQuery = false,
10 | state = {},
11 | }) => {
12 | const location = useLocation();
13 | const match = useRouteMatch();
14 |
15 | let pathname;
16 |
17 | if (match && isRelativePath) {
18 | pathname = match.url + to;
19 | } else {
20 | pathname = to || location.pathname;
21 | }
22 |
23 | const newQuery = keepOldQuery
24 | ? new URLSearchParams(location.search)
25 | : new URLSearchParams();
26 |
27 | Object.entries(query).forEach(([key, value]) => {
28 | newQuery.set(key, value);
29 | });
30 |
31 | Object.entries(pushToQuery).forEach(([key, value]) => {
32 | const currentValue = newQuery.get(key);
33 | const splittedValue = currentValue ? currentValue.split(",") : [];
34 | splittedValue.push(value);
35 |
36 | newQuery.set(key, splittedValue);
37 | });
38 |
39 | return {
40 | pathname: pathname.replace(/\/\//g, "/"),
41 | search: newQuery.toString() ? `?${newQuery.toString()}` : "",
42 | hash,
43 | state,
44 | };
45 | };
46 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Filter/Enging/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import FormControl from "@material-ui/core/FormControl";
3 | import FormGroup from "@material-ui/core/FormGroup";
4 | import FormControlLabel from "@material-ui/core/FormControlLabel";
5 | import Checkbox from "@material-ui/core/Checkbox";
6 |
7 | const Enging = () => {
8 | return (
9 |
10 |
11 | }
13 | label="2 Cylinders"
14 | />
15 | }
17 | label="3 Cylinders"
18 | />
19 | }
21 | label="4 Cylinders"
22 | />
23 | }
25 | label="5 Cylinders"
26 | />
27 | }
29 | label="6 Cylinders"
30 | />
31 |
32 |
33 | );
34 | };
35 |
36 | export default Enging;
37 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveRoutesPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react";
2 | import { useRouteMatch, Switch, Route, Redirect } from "react-router-dom";
3 |
4 | import DeviceInfoContext from "~/contexts/DeviceInfoContext";
5 |
6 | import Desktop from "../Desktop";
7 | import ResponsiveList from "../ResponsiveList";
8 | import ResponsiveFilters from "../ResponsiveFilters";
9 | import ResponsiveFilter from "../ResponsiveFilter";
10 |
11 | const ResponsiveRoutesPage = () => {
12 | const { url } = useRouteMatch();
13 |
14 | const deviceInfo = useContext(DeviceInfoContext);
15 | return deviceInfo.isDesktop ? (
16 |
17 |
18 |
19 |
20 |
21 |
22 | ) : (
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | );
36 | };
37 |
38 | export default ResponsiveRoutesPage;
39 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/ThirdStep/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useCallback } from "react";
2 | import PropTypes from "prop-types";
3 | import { useHistory } from "react-router-dom";
4 |
5 | import IconButton from "@material-ui/core/IconButton";
6 | import KeyboardBackspace from "@material-ui/icons/KeyboardBackspace";
7 |
8 | import getFormData from "../../services/getFormData";
9 | import useStyles from "./styles";
10 |
11 | const ThirdStep = ({ title }) => {
12 | const [initialValues] = useState(getFormData());
13 | const history = useHistory();
14 | const styles = useStyles();
15 |
16 | const onBack = useCallback(() => {
17 | history.goBack();
18 | }, [history]);
19 |
20 | return (
21 |
22 |
{title}
23 |
24 |
25 |
26 | {Object.entries(initialValues).map(([label, value]) => {
27 | return (
28 |
29 | {label}: {value}
30 |
31 | );
32 | })}
33 |
34 | );
35 | };
36 |
37 | ThirdStep.propTypes = {
38 | title: PropTypes.string.isRequired,
39 | };
40 |
41 | export default ThirdStep;
42 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/SignUp/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 | import Dialog from "@material-ui/core/Dialog";
4 | import TextField from "@material-ui/core/TextField";
5 | import Button from "@material-ui/core/Button";
6 |
7 | import useStyles from "./styles";
8 |
9 | const SignUp = ({ isOpened }) => {
10 | const styles = useStyles();
11 | const history = useHistory();
12 |
13 | return (
14 |
32 | );
33 | };
34 |
35 | export default SignUp;
36 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/SignUp/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 | import Dialog from "@material-ui/core/Dialog";
4 | import TextField from "@material-ui/core/TextField";
5 | import Button from "@material-ui/core/Button";
6 |
7 | import useStyles from "./styles";
8 |
9 | const SignUp = ({ isOpened }) => {
10 | const styles = useStyles();
11 | const history = useHistory();
12 |
13 | return (
14 |
32 | );
33 | };
34 |
35 | export default SignUp;
36 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/Push/index.js:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { useHistory, useRouteMatch, Link, Route } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 | import Dialog from "@material-ui/core/Dialog";
6 |
7 | import usePrepareLink from "~/hooks/router/usePrepareLink";
8 |
9 | const Push = ({ dialogClassName }) => {
10 | const match = useRouteMatch();
11 | const history = useHistory();
12 |
13 | const pushLink = usePrepareLink({
14 | to: "/push",
15 | isRelativePath: true
16 | });
17 |
18 | const goBack = useCallback(() => {
19 | history.push(match.url);
20 | }, [history, match.url]);
21 |
22 | return (
23 | <>
24 | call push() to previous route by close -
25 |
26 |
29 |
{
32 | return (
33 |
36 | );
37 | }}
38 | />
39 |
40 | >
41 | );
42 | };
43 |
44 | export default Push;
45 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { useHistory } from "react-router-dom";
3 |
4 | import Dialog from "@material-ui/core/Dialog";
5 |
6 | import { GET_PARAMS } from "~/const/router";
7 | import useGetParameter from "~/hooks/router/useGetParameter";
8 |
9 | import NotificationsList from "./NotificationsList";
10 | import NotificationDetails from "./NotificationDetails";
11 | import useStyles from "./styles";
12 |
13 | const Notifications = ({ isOpened }) => {
14 | const notificationId = useGetParameter(GET_PARAMS.notificationId);
15 | const history = useHistory();
16 | const [id, setId] = useState(notificationId);
17 | const styles = useStyles();
18 |
19 | useEffect(() => {
20 | if (notificationId) {
21 | setId(notificationId);
22 | }
23 | }, [notificationId]);
24 |
25 | return (
26 |
38 | );
39 | };
40 |
41 | export default Notifications;
42 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationDetails/index.jsx:
--------------------------------------------------------------------------------
1 | /*global parseInt */
2 | import React from "react";
3 | import Card from "@material-ui/core/Card";
4 | import CardContent from "@material-ui/core/CardContent";
5 | import Typography from "@material-ui/core/Typography";
6 | import Avatar from "@material-ui/core/Avatar";
7 |
8 | import notifications from "../../../../../data/notifications";
9 | import useStyles from "./styles";
10 |
11 | const NotificationDetails = ({ notificationId }) => {
12 | const styles = useStyles();
13 |
14 | const notification = notifications.find(
15 | notification => parseInt(notificationId) === notification.id
16 | );
17 |
18 | if (!notification) {
19 | return null;
20 | }
21 |
22 | return (
23 |
24 |
25 |
30 |
31 | {notification.title}
32 |
33 |
34 | {notification.fullText}
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | export default NotificationDetails;
42 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/Notifications/NotificationsList/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from "react";
2 | import { useHistory } from "react-router-dom";
3 | import List from "@material-ui/core/List";
4 | import Divider from "@material-ui/core/Divider";
5 | import IconButton from "@material-ui/core/IconButton";
6 | import CloseIcon from "@material-ui/icons/Close";
7 |
8 | import notifications from "../../../../../data/notifications";
9 | import NotificationItem from "./NotificationItem";
10 | import useStyles from "./styles";
11 |
12 | const NotificationsList = () => {
13 | const styles = useStyles();
14 | const history = useHistory();
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | {notifications.map((notification, index, notifications) => {
23 | const isLastNotification = notifications.length - 1 !== index;
24 |
25 | return (
26 |
27 |
28 | {isLastNotification && }
29 |
30 | );
31 | })}
32 |
33 |
34 | );
35 | };
36 |
37 | export default NotificationsList;
38 |
--------------------------------------------------------------------------------
/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const camelcase = require('camelcase');
5 |
6 | // This is a custom Jest transformer turning file imports into filenames.
7 | // http://facebook.github.io/jest/docs/en/webpack.html
8 |
9 | module.exports = {
10 | process(src, filename) {
11 | const assetFilename = JSON.stringify(path.basename(filename));
12 |
13 | if (filename.match(/\.svg$/)) {
14 | // Based on how SVGR generates a component name:
15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
16 | const pascalCaseFilename = camelcase(path.parse(filename).name, {
17 | pascalCase: true,
18 | });
19 | const componentName = `Svg${pascalCaseFilename}`;
20 | return `const React = require('react');
21 | module.exports = {
22 | __esModule: true,
23 | default: ${assetFilename},
24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
25 | return {
26 | $$typeof: Symbol.for('react.element'),
27 | type: 'svg',
28 | ref: ref,
29 | key: null,
30 | props: Object.assign({}, props, {
31 | children: ${assetFilename}
32 | })
33 | };
34 | }),
35 | };`;
36 | }
37 |
38 | return `module.exports = ${assetFilename};`;
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/src/components/CustomPrompt/index.jsx:
--------------------------------------------------------------------------------
1 | /* global JSON */
2 | import React from "react";
3 |
4 | import Dialog from "@material-ui/core/Dialog";
5 | import Button from "@material-ui/core/Button";
6 | import DialogActions from "@material-ui/core/DialogActions";
7 | import DialogContent from "@material-ui/core/DialogContent";
8 | import DialogContentText from "@material-ui/core/DialogContentText";
9 |
10 | const CustomPrompt = ({ message, cleanUp }) => {
11 | const parsedMessage = JSON.parse(message);
12 |
13 | const cancel = () => cleanUp(false);
14 | const ok = () => cleanUp(true);
15 |
16 | return (
17 |
41 | );
42 | };
43 |
44 | export default CustomPrompt;
45 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomReduxHistory/index.js:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Route } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 | import Dialog from "@material-ui/core/Dialog";
6 |
7 | import usePrepareLink from "~/hooks/router/usePrepareLink";
8 |
9 | import useClosePopup from "./hooks/useClosePopup";
10 | import usePush from "./hooks/usePush";
11 |
12 | const CustomReduxHistory = ({ dialogClassName }) => {
13 | const customReduxHistoryLink = usePrepareLink({
14 | to: "/custom-redux-history",
15 | isRelativePath: true
16 | });
17 |
18 | const closePopup = useClosePopup();
19 | const push = usePush();
20 |
21 | const openPopup = useCallback(() => {
22 | push(customReduxHistoryLink);
23 | }, [push, customReduxHistoryLink]);
24 |
25 | return (
26 | <>
27 | use custom history to detect goBack or replace by close -
28 |
29 |
32 |
(
35 |
38 | )}
39 | />
40 |
41 | >
42 | );
43 | };
44 |
45 | export default CustomReduxHistory;
46 |
--------------------------------------------------------------------------------
/src/pages/ClosePopup/components/CustomSessionHistory/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Link } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 | import Dialog from "@material-ui/core/Dialog";
6 |
7 | import usePrepareLink from "~/hooks/router/usePrepareLink";
8 |
9 | import useClosePopup from "./hooks/useClosePopup";
10 | import HistoryLogger from "./HistoryLogger";
11 |
12 | const CustomSessionHistory = ({ dialogClassName }) => {
13 | const customSessionHistoryLink = usePrepareLink({
14 | to: "/custom-session-history",
15 | isRelativePath: true
16 | });
17 |
18 | const closePopup = useClosePopup();
19 |
20 | return (
21 | <>
22 |
23 | use custom history to detect goBack or replace by close -
24 |
25 |
32 |
{
35 | return (
36 |
39 | );
40 | }}
41 | />
42 |
43 | >
44 | );
45 | };
46 |
47 | export default CustomSessionHistory;
48 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/NotificationDetails/Details/index.jsx:
--------------------------------------------------------------------------------
1 | /*global parseInt */
2 | import React from "react";
3 | import Card from "@material-ui/core/Card";
4 | import CardContent from "@material-ui/core/CardContent";
5 | import Typography from "@material-ui/core/Typography";
6 | import Avatar from "@material-ui/core/Avatar";
7 |
8 | import notifications from "../../../../../data/notifications";
9 | import useStyles from "./styles";
10 |
11 | const Details = ({ notificationId }) => {
12 | const styles = useStyles();
13 |
14 | const notification = notifications.find(
15 | (notification) => parseInt(notificationId) === notification.id
16 | );
17 |
18 | if (!notification) {
19 | return null;
20 | }
21 |
22 | return (
23 |
24 |
25 |
30 |
31 | {notification.title}
32 |
33 |
34 | {notification.user}
35 |
36 |
37 | {notification.fullText}
38 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default Details;
45 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/CustomPromptPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react";
2 | import { Switch, Route, useHistory } from "react-router-dom";
3 |
4 | import Dialog from "@material-ui/core/Dialog";
5 |
6 | import DeviceInfoContext from "~/contexts/DeviceInfoContext";
7 |
8 | import SignUpButton from "../SignUpButton";
9 | import SignUpForm from "../SignUpForm";
10 | import useStyles from "./styles";
11 |
12 | const CustomPromptPage = () => {
13 | const styles = useStyles();
14 | const deviceInfo = useContext(DeviceInfoContext);
15 | const history = useHistory();
16 |
17 | return (
18 |
19 | {deviceInfo.isMobile ? (
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | ) : (
29 | <>
30 |
31 |
32 |
33 | {
36 | return (
37 |
40 | );
41 | }}
42 | />
43 | >
44 | )}
45 |
46 | );
47 | };
48 |
49 | export default CustomPromptPage;
50 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/StepperPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { useLocation } from "react-router-dom";
3 |
4 | import Stepper from "@material-ui/core/Stepper";
5 | import Step from "@material-ui/core/Step";
6 | import StepLabel from "@material-ui/core/StepLabel";
7 |
8 | import clearFormData from "../../services/clearFormData";
9 | import FirstStep from "../FirstStep";
10 | import SecondStep from "../SecondStep";
11 | import ThirdStep from "../ThirdStep";
12 | import useStyles from "./styles";
13 |
14 | const TABS = [
15 | {
16 | component: FirstStep,
17 | title: "First Step",
18 | },
19 | {
20 | component: SecondStep,
21 | title: "Second Step",
22 | },
23 | {
24 | component: ThirdStep,
25 | title: "Review",
26 | },
27 | ];
28 |
29 | const StepperPage = () => {
30 | const { state = { activeStep: 0 } } = useLocation();
31 | const styles = useStyles();
32 |
33 | const tab = TABS[state.activeStep];
34 |
35 | useEffect(() => {
36 | return () => {
37 | clearFormData();
38 | };
39 | }, []);
40 |
41 | return (
42 |
43 |
Stepper
44 |
45 | {TABS.map(({ title }) => {
46 | return (
47 |
48 | {title}
49 |
50 | );
51 | })}
52 |
53 | {tab && }
54 |
55 | );
56 | };
57 |
58 | export default StepperPage;
59 |
--------------------------------------------------------------------------------
/scripts/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Do this as the first thing so that any code reading it knows the right env.
4 | process.env.BABEL_ENV = 'test';
5 | process.env.NODE_ENV = 'test';
6 | process.env.PUBLIC_URL = '';
7 |
8 | // Makes the script crash on unhandled rejections instead of silently
9 | // ignoring them. In the future, promise rejections that are not handled will
10 | // terminate the Node.js process with a non-zero exit code.
11 | process.on('unhandledRejection', err => {
12 | throw err;
13 | });
14 |
15 | // Ensure environment variables are read.
16 | require('../config/env');
17 |
18 |
19 | const jest = require('jest');
20 | const execSync = require('child_process').execSync;
21 | let argv = process.argv.slice(2);
22 |
23 | function isInGitRepository() {
24 | try {
25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
26 | return true;
27 | } catch (e) {
28 | return false;
29 | }
30 | }
31 |
32 | function isInMercurialRepository() {
33 | try {
34 | execSync('hg --cwd . root', { stdio: 'ignore' });
35 | return true;
36 | } catch (e) {
37 | return false;
38 | }
39 | }
40 |
41 | // Watch unless on CI or explicitly running all tests
42 | if (
43 | !process.env.CI &&
44 | argv.indexOf('--watchAll') === -1 &&
45 | argv.indexOf('--watchAll=false') === -1
46 | ) {
47 | // https://github.com/facebook/create-react-app/issues/5210
48 | const hasSourceControl = isInGitRepository() || isInMercurialRepository();
49 | argv.push(hasSourceControl ? '--watch' : '--watchAll');
50 | }
51 |
52 |
53 | jest.run(argv);
54 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Books/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import GridList from "@material-ui/core/GridList";
4 | import GridListTile from "@material-ui/core/GridListTile";
5 | import GridListTileBar from "@material-ui/core/GridListTileBar";
6 | import ListSubheader from "@material-ui/core/ListSubheader";
7 | import IconButton from "@material-ui/core/IconButton";
8 | import InfoIcon from "@material-ui/icons/Info";
9 |
10 | import books from "../../data/books";
11 | import useStyles from "./styles";
12 |
13 | const Books = () => {
14 | const styles = useStyles();
15 |
16 | return (
17 |
18 |
19 |
20 | December
21 |
22 | {books.map(book => (
23 |
24 |
25 | by: {book.author}}
28 | actionIcon={
29 |
33 |
34 |
35 | }
36 | />
37 |
38 | ))}
39 |
40 |
41 | );
42 | };
43 |
44 | export default Books;
45 |
--------------------------------------------------------------------------------
/src/pages/Home/components/HomePage/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 |
3 | export default makeStyles(() => ({
4 | container: {
5 | padding: "16px",
6 | },
7 | card: {
8 | display: "flex",
9 | flexDirection: "row",
10 | marginBottom: 16,
11 | textDecoration: "none",
12 | maxWidth: 850,
13 | position: "relative",
14 | "&:hover": {
15 | backgroundColor: "#E8E8E8",
16 | },
17 | "@media (max-width: 750px)": {
18 | maxWidth: 450,
19 | flexDirection: "column",
20 | margin: "0 auto 30px",
21 | },
22 | },
23 | cardLink: {
24 | position: "absolute",
25 | top: 0,
26 | right: 0,
27 | bottom: 0,
28 | left: 0,
29 | },
30 | info: {
31 | overflow: "hidden",
32 | display: "flex",
33 | flexDirection: "column",
34 | padding: "6px 0",
35 | },
36 | image: {
37 | flexShrink: 0,
38 | width: 300,
39 | marginRight: 16,
40 | "@media (max-width: 750px)": {
41 | width: "100%",
42 | },
43 | },
44 | title: {
45 | color: "#030303",
46 | fontSize: 22,
47 | marginTop: 0,
48 | marginBottom: 6,
49 | textOverflow: "ellipsis",
50 | overflow: "hidden",
51 | whiteSpace: "nowrap",
52 | },
53 | description: {
54 | margin: 0,
55 | color: "#606060",
56 | overflow: "hidden",
57 | textOverflow: "ellipsis",
58 | display: "-webkit-box",
59 | "-webkit-line-clamp": 4,
60 | "-webkit-box-orient": "vertical",
61 | "@media (max-width: 750px)": {
62 | "-webkit-line-clamp": 6,
63 | },
64 | },
65 | social: {
66 | marginTop: "auto",
67 | marginBottom: 0,
68 | paddingTop: 12,
69 | },
70 | link: {
71 | textDecoration: "none",
72 | marginRight: 12,
73 | },
74 | }));
75 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/GetParameterPopups/Popups/Notifications/NotificationsList/NotificationItem/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | import ListItem from "@material-ui/core/ListItem";
5 | import ListItemText from "@material-ui/core/ListItemText";
6 | import ListItemAvatar from "@material-ui/core/ListItemAvatar";
7 | import Avatar from "@material-ui/core/Avatar";
8 | import Typography from "@material-ui/core/Typography";
9 |
10 | import usePrepareLink from "~/hooks/router/usePrepareLink";
11 | import { GET_PARAMS } from "~/const/router";
12 |
13 | import useStyles from "./styles";
14 |
15 | const NotificationsItem = ({ notification }) => {
16 | const styles = useStyles();
17 |
18 | const link = usePrepareLink({
19 | query: {
20 | [GET_PARAMS.notificationId]: notification.id
21 | },
22 | keepOldQuery: true
23 | });
24 |
25 | return (
26 |
33 |
34 |
35 |
36 |
40 |
46 | {notification.user}
47 |
48 | {notification.shortText}
49 |
50 | }
51 | />
52 |
53 | );
54 | };
55 |
56 | export default NotificationsItem;
57 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/RestorePreventedRoutePage/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Switch, Route, Redirect } from "react-router-dom";
3 |
4 | import AuthRoute from "../AuthRoute";
5 | import AuthStatus from "../AuthStatus";
6 | import Links from "../Links";
7 | import Gallery from "../Gallery";
8 | import Books from "../Books";
9 | import Login from "../Login";
10 | import Food from "../Food";
11 | import useStyles from "./styles";
12 |
13 | const RestorePreventedRoutePage = () => {
14 | const [isAuthorized, setIsAuthorized] = useState(false);
15 | const styles = useStyles();
16 |
17 | return (
18 |
19 |
20 |
21 |
22 |
23 | HOME PAGE
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 | );
52 | };
53 |
54 | export default RestorePreventedRoutePage;
55 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/ResponsiveFilters/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link, useRouteMatch, useHistory } from "react-router-dom";
3 | import List from "@material-ui/core/List";
4 | import ListItem from "@material-ui/core/ListItem";
5 | import ListItemText from "@material-ui/core/ListItemText";
6 | import Divider from "@material-ui/core/Divider";
7 | import Button from "@material-ui/core/Button";
8 |
9 | import useStyles from "./styles";
10 |
11 | const ResponsiveFilters = () => {
12 | const styles = useStyles();
13 | const { url } = useRouteMatch();
14 | const history = useHistory();
15 |
16 | return (
17 | <>
18 |
26 | Filters
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | >
53 | );
54 | };
55 |
56 | export default ResponsiveFilters;
57 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/GetParameterPopups/Popups/Notifications/NotificationsList/NotificationItem/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | import ListItem from "@material-ui/core/ListItem";
5 | import ListItemText from "@material-ui/core/ListItemText";
6 | import ListItemAvatar from "@material-ui/core/ListItemAvatar";
7 | import Avatar from "@material-ui/core/Avatar";
8 | import Typography from "@material-ui/core/Typography";
9 |
10 | import usePrepareLink from "~/hooks/router/usePrepareLink";
11 | import { GET_PARAMS, GET_ENUMS } from "~/const/router";
12 |
13 | import useStyles from "./styles";
14 |
15 | const NotificationsItem = ({ notification }) => {
16 | const styles = useStyles();
17 |
18 | const link = usePrepareLink({
19 | query: {
20 | [GET_PARAMS.notificationId]: notification.id,
21 | },
22 | pushToQuery: {
23 | [GET_PARAMS.popup]: GET_ENUMS.popup.notificationDetails,
24 | },
25 | keepOldQuery: true,
26 | });
27 |
28 | return (
29 |
35 |
36 |
41 |
42 |
46 |
52 | {notification.user}
53 |
54 |
55 | {notification.shortText}
56 |
57 | }
58 | />
59 |
60 | );
61 | };
62 |
63 | export default NotificationsItem;
64 |
--------------------------------------------------------------------------------
/src/components/Router/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import ReactDOM from "react-dom";
3 | import { BrowserRouter, Switch, Route } from "react-router-dom";
4 |
5 | import Home from "~/pages/Home";
6 | import ResponsiveRoutesPage from "~/pages/ResponsiveRoutes";
7 | import PopupsRoutesPage from "~/pages/PopupsRoutes";
8 | import CustomPromptPage from "~/pages/CustomPrompt";
9 | import ClosePopupPage from "~/pages/ClosePopup";
10 | import RestorePreventedRoutePage from "~/pages/RestorePreventedRoute";
11 | import StepperPage from "~/pages/Stepper";
12 | import TwoPopupsPage from "~/pages/TwoPopups";
13 |
14 | import AppBar from "../AppBar";
15 | import CustomPrompt from "../CustomPrompt";
16 |
17 | const Router = () => {
18 | const userConfirmation = useCallback((message, callback) => {
19 | const node = document.getElementById("custom-prompt");
20 |
21 | const cleanUp = (answer) => {
22 | ReactDOM.unmountComponentAtNode(node);
23 | callback(answer);
24 | };
25 |
26 | ReactDOM.render(, node);
27 | }, []);
28 |
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | );
60 | };
61 |
62 | export default Router;
63 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Links/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { NavLink } from "react-router-dom";
3 |
4 | import usePrepareLink from "~/hooks/router/usePrepareLink";
5 |
6 | import useStyles from "./styles";
7 |
8 | const Links = () => {
9 | const styles = useStyles();
10 |
11 | const homeLink = usePrepareLink({
12 | to: "/",
13 | isRelativePath: true
14 | });
15 |
16 | const galleryLink = usePrepareLink({
17 | to: "/gallery",
18 | isRelativePath: true
19 | });
20 |
21 | const booksLink = usePrepareLink({
22 | to: "/books",
23 | isRelativePath: true
24 | });
25 |
26 | const foodLink = usePrepareLink({
27 | to: "/food",
28 | isRelativePath: true
29 | });
30 |
31 | const loginLink = usePrepareLink({
32 | to: "/login",
33 | isRelativePath: true
34 | });
35 |
36 | return (
37 |
38 | -
39 |
45 | Home Page
46 |
47 |
48 | -
49 |
54 | Gallery for everyone
55 |
56 |
57 | -
58 |
63 | Books for authorized users
64 |
65 |
66 | -
67 |
72 | Food for authorized users
73 |
74 |
75 | -
76 |
81 | Login
82 |
83 |
84 |
85 | );
86 | };
87 |
88 | export default Links;
89 |
--------------------------------------------------------------------------------
/src/pages/RestorePreventedRoute/components/Login/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useState } from "react";
2 | import { useLocation, useHistory, Route, Switch } from "react-router-dom";
3 |
4 | import MaterialSwitch from "@material-ui/core/Switch";
5 | import FormControl from "@material-ui/core/FormControl";
6 | import FormControlLabel from "@material-ui/core/FormControlLabel";
7 | import Button from "@material-ui/core/Button";
8 |
9 | import useStyles from "./styles";
10 |
11 | const Login = ({ isAuthorized, setIsAuthorized }) => {
12 | const { state } = useLocation();
13 | const history = useHistory();
14 |
15 | const [value, setValue] = useState(isAuthorized);
16 |
17 | const onChange = useCallback((event, value) => setValue(value), [setValue]);
18 | const onSignIn = useCallback(() => {
19 | setIsAuthorized(value);
20 | const link = (state && state.from) || "/restore-prevented-route";
21 | history.replace(link);
22 | }, [setIsAuthorized, value, history, state]);
23 |
24 | const styles = useStyles();
25 |
26 | return (
27 |
28 | Login
29 |
32 | }
33 | label="Toggle to authorize and press button to apply"
34 | />
35 |
44 | {state && state.from && (
45 |
46 |
47 | The next page is Books!
48 |
49 |
50 | The next page is Food!
51 |
52 |
53 | )}
54 |
55 | );
56 | };
57 |
58 | export default Login;
59 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/FirstStep/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useState } from "react";
2 | import PropTypes from "prop-types";
3 | import { useHistory, useLocation } from "react-router-dom";
4 | import { Form, Field } from "react-final-form";
5 |
6 | import Button from "@material-ui/core/Button";
7 |
8 | import setFormData from "../../services/setFormData";
9 | import getFormData from "../../services/getFormData";
10 | import TextField from "../TextField";
11 | import useStyles from "./styles";
12 |
13 | const FirstStep = ({ title }) => {
14 | const history = useHistory();
15 | const location = useLocation();
16 | const [initialValues] = useState(getFormData());
17 |
18 | const styles = useStyles();
19 |
20 | const onSubmit = useCallback(
21 | (values) => {
22 | setFormData(values);
23 | history.push({
24 | ...location,
25 | state: {
26 | activeStep: 1,
27 | },
28 | });
29 | },
30 | [history, location]
31 | );
32 |
33 | return (
34 |
35 |
{title}
36 |
63 | )}
64 | />
65 |
66 | );
67 | };
68 |
69 | FirstStep.propTypes = {
70 | title: PropTypes.string.isRequired,
71 | };
72 |
73 | export default FirstStep;
74 |
--------------------------------------------------------------------------------
/src/pages/CustomPrompt/components/SignUpForm/index.jsx:
--------------------------------------------------------------------------------
1 | /* global JSON */
2 | import React, { useContext, useMemo } from "react";
3 | import classNames from "classnames";
4 | import { Prompt } from "react-router-dom";
5 |
6 | import TextField from "@material-ui/core/TextField";
7 | import Button from "@material-ui/core/Button";
8 |
9 | import DeviceInfoContext from "~/contexts/DeviceInfoContext";
10 |
11 | import usePreventReload from "./usePreventReload";
12 | import useFormState from "./useFormState";
13 | import useStyles from "./styles";
14 |
15 | const SignUpForm = () => {
16 | const styles = useStyles();
17 | const deviceInfo = useContext(DeviceInfoContext);
18 |
19 | const { fields, onChange, onSubmit } = useFormState();
20 |
21 | const containerClasses = classNames(styles.container, {
22 | [styles.mobileContainer]: deviceInfo.isMobile
23 | });
24 |
25 | const isEmpty = Object.keys(fields).length === 0;
26 |
27 | usePreventReload(!isEmpty);
28 |
29 | const promptMessage = useMemo(() => JSON.stringify({ fields }), [fields]);
30 |
31 | return (
32 |
74 | );
75 | };
76 |
77 | export default SignUpForm;
78 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/PostCard/SimilarPicturesPopup/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Route, Link, useHistory } from "react-router-dom";
3 |
4 | import Dialog from "@material-ui/core/Dialog";
5 | import Button from "@material-ui/core/Button";
6 |
7 | import usePrepareLink from "~/hooks/router/usePrepareLink";
8 | import { GET_PARAMS, GET_ENUMS } from "~/const/router";
9 |
10 | import OriginalImage from "./OriginalImage";
11 | import useStyles from "./styles";
12 |
13 | const SimilarPicturesPopup = ({ pictures }) => {
14 | const styles = useStyles();
15 | const history = useHistory();
16 |
17 | const [similarPictureLink] = useState(
18 | usePrepareLink({
19 | to: "/:id",
20 | isRelativePath: true,
21 | })
22 | );
23 |
24 | const signInLink = usePrepareLink({
25 | query: {
26 | [GET_PARAMS.popup]: GET_ENUMS.popup.signIn,
27 | },
28 | });
29 |
30 | return (
31 | <>
32 |
33 |
34 | Similar Pictures{" "}
35 |
44 |
45 |
46 | {pictures.map((picture) => {
47 | return (
48 |
53 |

54 |
55 | );
56 | })}
57 |
58 |
59 | {
62 | return (
63 |
70 | );
71 | }}
72 | />
73 | >
74 | );
75 | };
76 |
77 | export default SimilarPicturesPopup;
78 |
--------------------------------------------------------------------------------
/src/pages/ResponsiveRoutes/components/Sidebar/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useCallback } from "react";
2 | import List from "@material-ui/core/List";
3 | import ListItem from "@material-ui/core/ListItem";
4 | import ListItemText from "@material-ui/core/ListItemText";
5 | import Popover from "@material-ui/core/Popover";
6 | import Divider from "@material-ui/core/Divider";
7 |
8 | import Filter from "../Filter";
9 | import useStyles from "./styles";
10 |
11 | const Sidebar = () => {
12 | const styles = useStyles();
13 | const [anchorEl, setAnchorEl] = useState(null);
14 | const [type, setType] = useState(null);
15 |
16 | const handleClick = useCallback(
17 | type => event => {
18 | setAnchorEl(event.currentTarget);
19 | setType(type);
20 | },
21 | []
22 | );
23 |
24 | const handleClose = useCallback(() => {
25 | setAnchorEl(null);
26 | }, []);
27 |
28 | return (
29 | <>
30 | Filters
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
69 |
70 |
71 | >
72 | );
73 | };
74 |
75 | export default Sidebar;
76 |
--------------------------------------------------------------------------------
/src/pages/Stepper/components/SecondStep/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useState } from "react";
2 | import PropTypes from "prop-types";
3 | import { useHistory, useLocation } from "react-router-dom";
4 | import { Form, Field } from "react-final-form";
5 |
6 | import IconButton from "@material-ui/core/IconButton";
7 | import Button from "@material-ui/core/Button";
8 | import KeyboardBackspace from "@material-ui/icons/KeyboardBackspace";
9 |
10 | import setFormData from "../../services/setFormData";
11 | import getFormData from "../../services/getFormData";
12 | import TextField from "../TextField";
13 | import useStyles from "./styles";
14 |
15 | const SecondStep = ({ title }) => {
16 | const history = useHistory();
17 | const location = useLocation();
18 | const [initialValues] = useState(getFormData());
19 |
20 | const styles = useStyles();
21 |
22 | const onSubmit = useCallback(
23 | (values) => {
24 | setFormData(values);
25 | history.push({
26 | ...location,
27 | state: {
28 | activeStep: 2,
29 | },
30 | });
31 | },
32 | [history, location]
33 | );
34 |
35 | const onBack = useCallback(() => {
36 | history.goBack();
37 | }, [history]);
38 |
39 | return (
40 |
41 |
{title}
42 |
43 |
44 |
45 |
72 | )}
73 | />
74 |
75 | );
76 | };
77 |
78 | SecondStep.propTypes = {
79 | title: PropTypes.string.isRequired,
80 | };
81 |
82 | export default SecondStep;
83 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/index.jsx:
--------------------------------------------------------------------------------
1 | /* global parseInt */
2 | import React from "react";
3 | import { useParams, useHistory, Link } from "react-router-dom";
4 |
5 | import usePrepareLink from "~/hooks/router/usePrepareLink";
6 | import { GET_PARAMS, GET_ENUMS } from "~/const/router";
7 |
8 | import Button from "@material-ui/core/Button";
9 | import DeleteIcon from "@material-ui/icons/Delete";
10 | import SaveIcon from "@material-ui/icons/Save";
11 | import CloudUploadIcon from "@material-ui/icons/CloudUpload";
12 |
13 | import posts from "../../data/posts";
14 | import PostCard from "./PostCard";
15 | import useStyles from "./styles";
16 |
17 | const Post = () => {
18 | const { id } = useParams();
19 | const history = useHistory();
20 | const styles = useStyles();
21 |
22 | const signInLink = usePrepareLink({
23 | query: {
24 | [GET_PARAMS.popup]: GET_ENUMS.popup.signIn
25 | }
26 | });
27 | const signUpLink = usePrepareLink({
28 | query: {
29 | [GET_PARAMS.popup]: GET_ENUMS.popup.signUp
30 | }
31 | });
32 | const notificationsLink = usePrepareLink({
33 | query: {
34 | [GET_PARAMS.popup]: GET_ENUMS.popup.notifications
35 | }
36 | });
37 |
38 | const post = posts.find(post => post.id === parseInt(id));
39 |
40 | if (!post) {
41 | return null;
42 | }
43 |
44 | return (
45 |
46 |
54 |
55 |
56 | }
61 | component={Link}
62 | to={signInLink}
63 | >
64 | Sign In
65 |
66 | }
71 | component={Link}
72 | to={signUpLink}
73 | >
74 | Sign Up
75 |
76 | }
81 | component={Link}
82 | to={notificationsLink}
83 | >
84 | Notifications
85 |
86 |
87 |
88 | );
89 | };
90 |
91 | export default Post;
92 |
--------------------------------------------------------------------------------
/src/pages/TwoPopups/components/Post/index.jsx:
--------------------------------------------------------------------------------
1 | /* global parseInt */
2 | import React from "react";
3 | import { useParams, useHistory, Link } from "react-router-dom";
4 |
5 | import usePrepareLink from "~/hooks/router/usePrepareLink";
6 | import { GET_PARAMS, GET_ENUMS } from "~/const/router";
7 |
8 | import Button from "@material-ui/core/Button";
9 | import DeleteIcon from "@material-ui/icons/Delete";
10 | import SaveIcon from "@material-ui/icons/Save";
11 | import CloudUploadIcon from "@material-ui/icons/CloudUpload";
12 |
13 | import posts from "../../data/posts";
14 | import PostCard from "./PostCard";
15 | import useStyles from "./styles";
16 |
17 | const Post = () => {
18 | const { id } = useParams();
19 | const history = useHistory();
20 | const styles = useStyles();
21 |
22 | const signInLink = usePrepareLink({
23 | query: {
24 | [GET_PARAMS.popup]: GET_ENUMS.popup.signIn,
25 | },
26 | });
27 | const signUpLink = usePrepareLink({
28 | query: {
29 | [GET_PARAMS.popup]: GET_ENUMS.popup.signUp,
30 | },
31 | });
32 | const notificationsLink = usePrepareLink({
33 | query: {
34 | [GET_PARAMS.popup]: GET_ENUMS.popup.notifications,
35 | },
36 | });
37 |
38 | const post = posts.find((post) => post.id === parseInt(id));
39 |
40 | if (!post) {
41 | return null;
42 | }
43 |
44 | return (
45 |
46 |
54 |
55 |
56 | }
61 | component={Link}
62 | to={signInLink}
63 | >
64 | Sign In
65 |
66 | }
71 | component={Link}
72 | to={signUpLink}
73 | >
74 | Sign Up
75 |
76 | }
81 | component={Link}
82 | to={notificationsLink}
83 | >
84 | Notifications
85 |
86 |
87 |
88 | );
89 | };
90 |
91 | export default Post;
92 |
--------------------------------------------------------------------------------
/src/components/AppBar/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useCallback } from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | import ApplicationBar from "@material-ui/core/AppBar";
5 | import Toolbar from "@material-ui/core/Toolbar";
6 | import Typography from "@material-ui/core/Typography";
7 | import IconButton from "@material-ui/core/IconButton";
8 | import MenuIcon from "@material-ui/icons/Menu";
9 | import Drawer from "@material-ui/core/Drawer";
10 | import List from "@material-ui/core/List";
11 | import ListItem from "@material-ui/core/ListItem";
12 | import ListItemIcon from "@material-ui/core/ListItemIcon";
13 | import ListItemText from "@material-ui/core/ListItemText";
14 | import FormatListBulleted from "@material-ui/icons/FormatListBulleted";
15 |
16 | import useStyles from "./styles";
17 | import { TRICKS_ROUTES } from "~/const/tricks";
18 |
19 | const AppBar = () => {
20 | const styles = useStyles();
21 | const [isOpenedDrawer, setIsOpenedDrawer] = useState(false);
22 |
23 | const toggleDrawer = useCallback(() => {
24 | setIsOpenedDrawer(!isOpenedDrawer);
25 | }, [isOpenedDrawer]);
26 |
27 | return (
28 | <>
29 |
30 |
31 |
37 |
38 |
39 |
45 | React Router Tricks
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | {TRICKS_ROUTES.map((trick) => (
59 |
60 |
61 |
62 |
63 |
64 |
65 | ))}
66 |
67 |
68 |
69 | >
70 | );
71 | };
72 |
73 | export default AppBar;
74 |
--------------------------------------------------------------------------------
/src/pages/PopupsRoutes/components/Post/PostCard/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Link, useHistory } from "react-router-dom";
3 |
4 | import usePrepareLink from "~/hooks/router/usePrepareLink";
5 |
6 | import Button from "@material-ui/core/Button";
7 | import Card from "@material-ui/core/Card";
8 | import CardContent from "@material-ui/core/CardContent";
9 | import CardMedia from "@material-ui/core/CardMedia";
10 | import Typography from "@material-ui/core/Typography";
11 | import CardActions from "@material-ui/core/CardActions";
12 | import Dialog from "@material-ui/core/Dialog";
13 |
14 | import useStyles from "./styles";
15 | import LikesPopup from "./LikesPopup";
16 | import ViewersPopup from "./ViewersPopup";
17 |
18 | const PostCard = ({ post }) => {
19 | const styles = useStyles();
20 | const history = useHistory();
21 |
22 | const likesLink = usePrepareLink({
23 | to: "/likes",
24 | isRelativePath: true
25 | });
26 |
27 | const viewersLink = usePrepareLink({
28 | to: "/viewers",
29 | isRelativePath: true
30 | });
31 |
32 | return (
33 | <>
34 |
35 |
40 |
41 |
42 | {post.title}
43 |
44 |
45 | {post.description}
46 |
47 |
48 |
49 |
52 |
60 |
61 |
62 | {
65 | return (
66 |
69 | );
70 | }}
71 | />
72 | {
75 | return (
76 |
79 | );
80 | }}
81 | />
82 | >
83 | );
84 | };
85 |
86 | export default PostCard;
87 |
--------------------------------------------------------------------------------
/src/assets/icons/github.svg:
--------------------------------------------------------------------------------
1 |
55 |
--------------------------------------------------------------------------------
/src/pages/Home/components/HomePage/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | import Button from "@material-ui/core/Button";
5 |
6 | import YouTube from "~/assets/icons/youtube.svg";
7 | import GitHub from "~/assets/icons/github.svg";
8 | import { TRICKS_ROUTES } from "~/const/tricks";
9 |
10 | import useStyles from "./styles";
11 | import { IconButton } from "@material-ui/core";
12 |
13 | const HomePage = () => {
14 | const styles = useStyles();
15 |
16 | return (
17 |
18 |
React Router Tricks
19 | {TRICKS_ROUTES.map((trick) => {
20 | return (
21 |
22 |
23 |

24 |
25 |
{trick.title}
26 |
{trick.description}
27 |
28 | {Boolean(trick.enYouTube) && (
29 | }
33 | component="a"
34 | href={trick.enYouTube}
35 | target="_blank"
36 | rel="noopener noreferrer"
37 | className={styles.link}
38 | >
39 | EN
40 |
41 | )}
42 | {Boolean(trick.ruYouTube) && (
43 | }
47 | component="a"
48 | href={trick.ruYouTube}
49 | target="_blank"
50 | rel="noopener noreferrer"
51 | className={styles.link}
52 | >
53 | RU
54 |
55 | )}
56 |
57 | {Boolean(trick.github) && (
58 |
65 |
66 |
67 | )}
68 |
69 |
70 |
71 | );
72 | })}
73 |
74 | );
75 | };
76 |
77 | export default HomePage;
78 |
--------------------------------------------------------------------------------
/config/paths.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const fs = require('fs');
5 | const url = require('url');
6 |
7 | // Make sure any symlinks in the project folder are resolved:
8 | // https://github.com/facebook/create-react-app/issues/637
9 | const appDirectory = fs.realpathSync(process.cwd());
10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
11 |
12 | const envPublicUrl = process.env.PUBLIC_URL;
13 |
14 | function ensureSlash(inputPath, needsSlash) {
15 | const hasSlash = inputPath.endsWith('/');
16 | if (hasSlash && !needsSlash) {
17 | return inputPath.substr(0, inputPath.length - 1);
18 | } else if (!hasSlash && needsSlash) {
19 | return `${inputPath}/`;
20 | } else {
21 | return inputPath;
22 | }
23 | }
24 |
25 | const getPublicUrl = appPackageJson =>
26 | envPublicUrl || require(appPackageJson).homepage;
27 |
28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer
29 | // "public path" at which the app is served.
30 | // Webpack needs to know it to put the right
9 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
42 |
47 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
65 |
66 |
67 |
68 |
72 |
73 |
77 |
78 |
87 |
91 | React-Router Tricks
92 |
93 |
94 |
95 |
96 |
97 |
107 |
108 |
112 |
121 |
122 |