diff --git a/frontend/.babelrc b/frontend/.babelrc new file mode 100644 index 0000000..60bc261 --- /dev/null +++ b/frontend/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["next/babel", "@emotion/babel-preset-css-prop"] +} diff --git a/frontend/.env.development b/frontend/.env.development index cc53660..cd36707 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -1 +1,3 @@ -NEXT_PUBLIC_API_URL=http://localhost:8080 \ No newline at end of file +NEXT_PUBLIC_API_URL=http://localhost:8080 +NEXT_PUBLIC_GOOGLE_AD_CLIENT=ca-pub-7134126650568891 +NEXT_PUBLIC_GOOGLE_AD_SLOT=2983860255 \ No newline at end of file diff --git a/frontend/.env.production b/frontend/.env.production index c9b6a18..2930c3b 100644 --- a/frontend/.env.production +++ b/frontend/.env.production @@ -1 +1,3 @@ -NEXT_PUBLIC_API_URL=https://pairwise-api.yuuniworks.com \ No newline at end of file +NEXT_PUBLIC_API_URL=https://pairwise-api.yuuniworks.com +NEXT_PUBLIC_GOOGLE_AD_CLIENT=ca-pub-7134126650568891 +NEXT_PUBLIC_GOOGLE_AD_SLOT=2983860255 \ No newline at end of file diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js deleted file mode 100644 index 0ea7661..0000000 --- a/frontend/.eslintrc.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react/recommended', - 'plugin:prettier/recommended', - 'prettier', - 'prettier/react', - ], - plugins: ['@typescript-eslint', 'prettier', 'react-hooks'], - globals: { - document: true, - window: true, - }, - rules: { - 'no-unused-expressions': [ - 'error', - { allowShortCircuit: true, allowTernary: true }, - ], - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn', - 'react/prop-types': 'off', - }, -}; diff --git a/frontend/package.json b/frontend/package.json index e933f80..d572b0b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,23 +9,17 @@ "export": "next build && next export" }, "dependencies": { + "@emotion/core": "^10.0.28", "adblock-detector-hook": "^0.1.0", - "emotion": "^10.0.27", - "next": "9.5.0", + "next": "9.5.4", "normalize.css": "^8.0.1", "react": "16.13.1", "react-dom": "16.13.1" }, "devDependencies": { + "@emotion/babel-preset-css-prop": "^10.0.27", "@types/node": "^14.0.27", "@types/react": "^16.9.43", - "@typescript-eslint/eslint-plugin": "^3.7.1", - "@typescript-eslint/parser": "^3.7.1", - "eslint": "^7.5.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.5", - "eslint-plugin-react-hooks": "^4.0.8", "typescript": "^3.9.7" } } diff --git a/frontend/public/ads.txt b/frontend/public/ads.txt new file mode 100644 index 0000000..fc1ff59 --- /dev/null +++ b/frontend/public/ads.txt @@ -0,0 +1 @@ +google.com, pub-7134126650568891, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/frontend/src/components/Button/Button.module.css b/frontend/src/components/Button/Button.module.css index eb761e1..e69de29 100644 --- a/frontend/src/components/Button/Button.module.css +++ b/frontend/src/components/Button/Button.module.css @@ -1,21 +0,0 @@ -.button { - cursor: pointer; - color: #343a40; - border-color: #343a40; - padding: 0.375rem 0.75rem; - font-size: 1rem; - border-radius: 0.25rem; - transition: all 0.15s; -} - -.button:hover { - color: #fff; - background-color: #343a40; - border-color: #343a40; -} - -.button:focus { - box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); - outline: 0; - text-decoration: none; -} diff --git a/frontend/src/components/Button/Button.tsx b/frontend/src/components/Button/Button.tsx index e402400..7c764ac 100644 --- a/frontend/src/components/Button/Button.tsx +++ b/frontend/src/components/Button/Button.tsx @@ -1,10 +1,35 @@ -import React from 'react'; -import style from './Button.module.css'; +import { css } from '@emotion/core'; export const Button = (props) => { - const { children, ...rest } = props; + const { children, className, ...rest } = props; + + const styles = { + button: css` + cursor: pointer; + color: #343a40; + border-color: #343a40; + padding: 0.375rem 0.75rem; + font-size: 1rem; + border-radius: 0.25rem; + transition: all 0.15s; + width: 100%; + + :hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; + } + + :focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + outline: 0; + text-decoration: none; + } + `, + }; + return ( - ); diff --git a/frontend/src/components/ModalDialog/ModalDialog.tsx b/frontend/src/components/ModalDialog/ModalDialog.tsx index 7a74f10..784efc5 100644 --- a/frontend/src/components/ModalDialog/ModalDialog.tsx +++ b/frontend/src/components/ModalDialog/ModalDialog.tsx @@ -1,4 +1,4 @@ -import { css } from 'emotion'; +import { css } from '@emotion/core'; import React from 'react'; import { Portal } from '../Portal/Portal'; @@ -45,9 +45,9 @@ export const ModalDialog: React.FC = (props) => { return ( -
-
-
{children}
+
+
+
{children}
); diff --git a/frontend/src/features/ads/AdBlockGuard.tsx b/frontend/src/features/ads/AdBlockGuard.tsx index 8d0769a..04afd94 100644 --- a/frontend/src/features/ads/AdBlockGuard.tsx +++ b/frontend/src/features/ads/AdBlockGuard.tsx @@ -1,5 +1,5 @@ +import { css } from '@emotion/core'; import { useAdBlockDetector } from 'adblock-detector-hook'; -import { css } from 'emotion'; import React, { useCallback, useEffect, useState } from 'react'; import { ModalDialog } from '../../components/ModalDialog'; @@ -41,12 +41,12 @@ export const AdBlockGuard: React.FC = (props) => {

We've noticed that you are using an ad blocker.

- Please disable your ad blocker for this site and help us to + Please disable your ad blocker for this site and help us to provide free services.

-
-
diff --git a/frontend/src/features/ads/AdCard.tsx b/frontend/src/features/ads/AdCard.tsx new file mode 100644 index 0000000..a7038fc --- /dev/null +++ b/frontend/src/features/ads/AdCard.tsx @@ -0,0 +1,25 @@ +import React, { useEffect } from 'react'; + +interface IProps {} + +export const AdCard: React.FC = ({}) => { + useEffect(() => { + if (!process.browser) { + return; + } + if (!window.adsbygoogle) { + window.adsbygoogle = []; + } + window.adsbygoogle.push({}); + }, []); + + return ( + + ); +}; diff --git a/frontend/src/features/header/Header.module.css b/frontend/src/features/header/Header.module.css deleted file mode 100644 index 9a32914..0000000 --- a/frontend/src/features/header/Header.module.css +++ /dev/null @@ -1,30 +0,0 @@ -.rootContainer { - align-items: center; - background: #333; - color: white; - display: flex; - font-size: 1.5rem; - height: 48px; - padding-left: 1rem; -} - -.icon { - width: 32px; - margin-right: 0.5rem; -} - -.title { - flex: 1; - font-size: 1.5rem; -} - -.coffeeImgContainer { - border-radius: 5px; - display: inline-flex; - margin-right: 1rem; - overflow: hidden; -} - -.coffeeImg { - width: 130px; -} diff --git a/frontend/src/features/header/Header.tsx b/frontend/src/features/header/Header.tsx index b70cf88..b8d7e28 100644 --- a/frontend/src/features/header/Header.tsx +++ b/frontend/src/features/header/Header.tsx @@ -1,31 +1,69 @@ -import React from 'react'; -import style from './Header.module.css'; +import { css } from '@emotion/core'; export const Header = () => { + const styles = { + rootContainer: css` + align-items: center; + background: #333; + color: white; + display: flex; + font-size: 1.5rem; + height: 48px; + padding-left: 1rem; + `, + icon: css` + width: 32px; + margin-right: 0.5rem; + `, + title: css` + flex: 1; + font-size: 1.5rem; + `, + coffeeImgContainer: css` + border-radius: 5px; + display: inline-flex; + margin-right: 1rem; + overflow: hidden; + @media (max-width: 700px) { + display: none; + } + `, + coffeeImg: css` + width: 130px; + `, + githubContainer: css` + @media (max-width: 700px) { + display: none; + } + `, + }; + return ( -
- document -

Pairwise Pict Online

+
+ document +

Pairwise Pict Online

Buy Me A Coffee - +
+ +
); }; diff --git a/frontend/src/features/top/Top.module.css b/frontend/src/features/top/Top.module.css deleted file mode 100644 index a6087ed..0000000 --- a/frontend/src/features/top/Top.module.css +++ /dev/null @@ -1,39 +0,0 @@ -.rootContainer { - background: #fafafa; - display: flex; - flex-direction: column; - height: 100vh; - width: 100vw; -} - -.description { - padding: 0 1rem; - margin-top: 1rem; - line-height: 1.8; -} - -.row { - align-items: stretch; - display: flex; - flex: 1 1; /* expand */ - justify-content: space-between; - padding: 1rem; -} - -.factors { - display: flex; - flex-direction: column; - flex: 1; -} - -.results { - display: flex; - flex-direction: column; - flex: 1; -} - -.download { - display: block; - margin: 0.5rem 0 1rem; - text-align: center; -} diff --git a/frontend/src/features/top/Top.tsx b/frontend/src/features/top/Top.tsx index db5d696..cf47cc9 100644 --- a/frontend/src/features/top/Top.tsx +++ b/frontend/src/features/top/Top.tsx @@ -1,8 +1,8 @@ -import React, { useCallback, useState } from 'react'; +import { css } from '@emotion/core'; +import { useCallback, useState } from 'react'; import { Button } from '../../components/Button'; import { Textarea } from '../../components/Textarea'; import { Header } from '../header'; -import style from './Top.module.css'; export const Top = () => { const [isFetching, setIsFetching] = useState(false); @@ -25,11 +25,65 @@ export const Top = () => { .finally(() => setIsFetching(false)); }, [factorText]); + const style = { + rootContainer: css` + background: #fafafa; + display: flex; + flex-direction: column; + height: 100vh; + width: 100vw; + `, + description: css` + padding: 0 1rem; + margin-top: 1rem; + line-height: 1.8; + `, + converterRow: css` + align-items: stretch; + display: flex; + flex: 1 0; /* expand */ + justify-content: space-between; + padding: 1rem; + @media (max-width: 700px) { + flex-direction: column; + } + `, + adsRow: css` + flex: 0 0 90px; + margin-top: 1rem; + overflow: hidden; + text-align: center; + `, + factors: css` + display: flex; + flex-direction: column; + flex: 1; + `, + results: css` + display: flex; + flex-direction: column; + flex: 1; + `, + buttonContainer: css` + align-self: center; + width: 8rem; + margin: 1rem; + `, + download: css` + display: block; + margin: 0.5rem 0 1rem; + text-align: center; + @media (max-width: 700px) { + display: none; + } + `, + }; + return ( -
+
-
+
An online service that easily generates pair-wise test cases.
It's powered by @@ -37,8 +91,8 @@ export const Top = () => { hood.
-
-
+
+