Compare commits

...

65 Commits
1.0.0 ... main

Author SHA1 Message Date
6053179f25 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 15s
2026-03-29 17:01:41 +00:00
2f95e39f0a Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 41s
2026-03-29 16:47:49 +00:00
404856622f Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 55s
2026-03-29 16:37:45 +00:00
d08b9b3721 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 42s
2026-03-29 16:32:01 +00:00
53c3464104 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 45s
2026-03-29 16:26:44 +00:00
27732e3033 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 43s
2026-03-29 16:19:35 +00:00
62d38422f7 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 1m32s
2026-03-29 16:13:14 +00:00
d09083de8b Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 53s
2026-03-28 04:13:06 +00:00
32fd6a3154 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 41s
2026-03-28 04:07:50 +00:00
496c85f625 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 40s
2026-03-28 04:01:38 +00:00
0dd6249fc2 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 41s
2026-03-28 03:57:59 +00:00
2cda367152 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 10s
2026-03-28 03:56:27 +00:00
87060c4340 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 0s
2026-03-28 03:54:29 +00:00
d17deb57e4 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 11s
2026-03-28 03:51:26 +00:00
c7a22cfe3e Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 41s
2026-03-28 03:47:19 +00:00
e4977f9960 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 42s
2026-03-28 03:40:15 +00:00
92211502e2 Update .gitea/workflows/codeant.yml
All checks were successful
Codeant Security Scan / codeant-scan (push) Successful in 1m0s
2026-03-28 03:28:41 +00:00
48e28bb2a0 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 59s
2026-03-28 03:22:37 +00:00
917886a208 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 39s
2026-03-28 03:19:03 +00:00
521a0d7885 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 57s
2026-03-28 03:01:58 +00:00
5e8a701f64 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 1m11s
2026-03-28 02:59:55 +00:00
8c1d8b0274 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 39s
2026-03-28 02:32:37 +00:00
f0ded5b4b6 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 11s
2026-03-28 02:31:20 +00:00
ce26bc1b69 Update .gitea/workflows/codeant.yml
Some checks failed
CodeAnt CLI Scan / codeant-scan (push) Failing after 48s
2026-03-28 02:28:42 +00:00
2909de8763 Update .gitea/workflows/codeant.yml
Some checks failed
CodeAnt CLI Scan / codeant-scan (push) Failing after 1m4s
2026-03-27 11:36:54 +00:00
e7a45eaa50 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 11s
2026-03-27 11:21:54 +00:00
cd9e5d2e11 Update .gitea/workflows/sonar.bak
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 6s
2026-03-27 11:17:17 +00:00
244db1c207 Update .gitea/workflows/codeant.yml
Some checks failed
Codeant Security Scan / codeant-scan (push) Failing after 7s
SonarQube Analysis / SonarQube Scan (push) Successful in 44s
2026-03-27 10:59:32 +00:00
7f0ffc0674 Update .gitea/workflows/codeant.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 49s
2026-03-27 10:57:25 +00:00
d1ed394a9f Add .gitea/workflows/codeant.yml
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
2026-03-27 10:56:32 +00:00
af75c75332 Update .gitea/workflows/sonar.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 50s
2026-02-18 16:30:36 +00:00
5faf125fe7 Update .gitea/workflows/sonar.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 28s
2026-02-18 16:24:23 +00:00
7e2d250f1a Update .gitea/workflows/sonar.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 30s
2026-02-18 16:13:01 +00:00
e66e062370 Update .gitea/workflows/sonar.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 29s
2026-02-18 14:53:30 +00:00
b823a75886 Update .gitea/workflows/sonar.yml
All checks were successful
SonarQube Analysis / SonarQube Scan (push) Successful in 28s
2026-02-18 14:24:05 +00:00
60f0f542d4 Update .gitea/workflows/sonar.yml
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Failing after 20s
2026-02-18 14:17:47 +00:00
cc860b15ee Update .gitea/workflows/sonar.yml
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Failing after 22s
2026-02-18 14:13:30 +00:00
645c5f7bff Add .gitea/workflows/sonar.yml
Some checks failed
SonarQube Analysis / sonarqube (push) Failing after 22s
2026-02-18 13:47:59 +00:00
Raymond
d68a8d6f1f Merge pull request #24 from Rhymond/dependabot/npm_and_yarn/lodash-es-4.17.21
Bump lodash-es from 4.17.4 to 4.17.21
2022-04-03 18:17:16 +01:00
Raymond
971af955f9 Merge pull request #22 from Rhymond/dependabot/npm_and_yarn/urijs-1.19.10
Bump urijs from 1.18.12 to 1.19.10
2022-04-03 18:17:05 +01:00
Raymond
4492822065 Merge pull request #20 from Rhymond/dependabot/npm_and_yarn/url-parse-1.5.10
Bump url-parse from 1.4.3 to 1.5.10
2022-04-03 18:16:56 +01:00
Raymond
f32c001de3 Merge pull request #17 from Rhymond/dependabot/npm_and_yarn/follow-redirects-1.14.8
Bump follow-redirects from 1.5.7 to 1.14.8
2022-04-03 18:16:47 +01:00
Raymond
8b058c1b92 Merge pull request #16 from Rhymond/dependabot/npm_and_yarn/handlebars-4.7.7
Bump handlebars from 4.0.11 to 4.7.7
2022-04-03 18:16:32 +01:00
Raymond
249e45216c Merge pull request #15 from Rhymond/dependabot/npm_and_yarn/node-sass-4.14.1
Bump node-sass from 4.9.3 to 4.14.1
2022-04-03 18:16:05 +01:00
Raymond
28d4ca64cb Merge pull request #14 from Rhymond/dependabot/npm_and_yarn/ua-parser-js-0.7.31
Bump ua-parser-js from 0.7.18 to 0.7.31
2022-04-03 18:15:53 +01:00
Raymond
f0823eec57 Merge pull request #11 from Rhymond/dependabot/npm_and_yarn/tmpl-1.0.5
Bump tmpl from 1.0.4 to 1.0.5
2022-04-03 18:15:43 +01:00
Raymond
6f8650b8a8 Merge pull request #9 from Rhymond/dependabot/npm_and_yarn/dns-packet-1.3.4
Bump dns-packet from 1.3.1 to 1.3.4
2022-04-03 18:13:52 +01:00
dependabot[bot]
1f652b172d Bump lodash-es from 4.17.4 to 4.17.21
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.4 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.4...4.17.21)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-15 18:34:36 +00:00
dependabot[bot]
912f1218fd Bump urijs from 1.18.12 to 1.19.10
Bumps [urijs](https://github.com/medialize/URI.js) from 1.18.12 to 1.19.10.
- [Release notes](https://github.com/medialize/URI.js/releases)
- [Changelog](https://github.com/medialize/URI.js/blob/gh-pages/CHANGELOG.md)
- [Commits](https://github.com/medialize/URI.js/compare/v1.18.12...v1.19.10)

---
updated-dependencies:
- dependency-name: urijs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-08 21:30:19 +00:00
dependabot[bot]
2d057c7e3a Bump url-parse from 1.4.3 to 1.5.10
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.3 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.3...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-26 01:37:22 +00:00
dependabot[bot]
a4b10dc3da Bump follow-redirects from 1.5.7 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.5.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.5.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 07:35:00 +00:00
dependabot[bot]
3261386cd6 Bump handlebars from 4.0.11 to 4.7.7
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.0.11 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.0.11...v4.7.7)

---
updated-dependencies:
- dependency-name: handlebars
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-11 00:41:57 +00:00
dependabot[bot]
590babbf3a Bump node-sass from 4.9.3 to 4.14.1
Bumps [node-sass](https://github.com/sass/node-sass) from 4.9.3 to 4.14.1.
- [Release notes](https://github.com/sass/node-sass/releases)
- [Changelog](https://github.com/sass/node-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/node-sass/compare/v4.9.3...v4.14.1)

---
updated-dependencies:
- dependency-name: node-sass
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-09 23:20:10 +00:00
dependabot[bot]
94b8507ef6 Bump ua-parser-js from 0.7.18 to 0.7.31
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.18 to 0.7.31.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.18...0.7.31)

---
updated-dependencies:
- dependency-name: ua-parser-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-09 22:56:49 +00:00
dependabot[bot]
23af127430 Bump tmpl from 1.0.4 to 1.0.5
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-20 20:37:18 +00:00
dependabot[bot]
5b03415f96 Bump dns-packet from 1.3.1 to 1.3.4
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-26 20:29:32 +00:00
Raymond
69c9055a16 Merge pull request #7 from Rhymond/dependabot/npm_and_yarn/eslint-4.18.2
Bump eslint from 3.19.0 to 4.18.2
2019-11-02 14:31:16 +00:00
dependabot[bot]
300d734bcf Bump eslint from 3.19.0 to 4.18.2
Bumps [eslint](https://github.com/eslint/eslint) from 3.19.0 to 4.18.2.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v3.19.0...v4.18.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-11-02 13:11:13 +00:00
Raymond
ef8bbd18d2 fixing vulnerable dep 2019-02-08 13:43:00 +00:00
Raymond
a26a4a85f0 Merge pull request #3 from ksakiyama/feature/resolve-webpack-vulnerabilities
Feature/resolve webpack vulnerabilities
2018-09-06 23:00:29 +01:00
ksakiyama
38f27ba1d2 resolve npm WARNs(included as both a dev and production dependency) 2018-09-02 10:51:12 +09:00
ksakiyama
7411582d9b update package versions related webpack 2018-09-02 10:47:44 +09:00
Raymond
4f97c49d2f change images, update readme 2018-07-05 16:41:28 +01:00
Raymond
eeecbb54ec Merge pull request #2 from Rhymond/responsiveFixes
Pretify code
2017-10-08 16:56:38 +01:00
Ray
9f6d256a96 Pretify code, remove unnecessary semicolon, function => const 2017-10-08 16:55:00 +01:00
25 changed files with 9554 additions and 3789 deletions

View File

@@ -0,0 +1,68 @@
name: Codeant Security Scan
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
codeant-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '22'
- name: Install CodeAnt CLI
run: npm install -g codeant-cli
# ✅ KEEP THIS (correct method)
- name: Configure CodeAnt Auth
env:
CODEANT_API_TOKEN: ${{ secrets.CODEANT_API_TOKEN }}
run: |
mkdir -p $HOME/.codeant
printf '{"apiKey":"%s"}\n' "$CODEANT_API_TOKEN" > $HOME/.codeant/config.json
- name: Setup Git identity
run: |
git config --global user.email "ci@gitea.local"
git config --global user.name "Gitea CI"
# 🔥 Full scan only on schedule
- name: Full repo AI scan (daily)
if: github.event_name == 'schedule'
run: |
echo "Running FULL repo scan..."
git checkout -b codeant-fullscan || git checkout codeant-fullscan
find . -type f \
-not -path "./.git/*" \
-exec sh -c 'echo "" >> "$1"' _ {} \;
git add .
git commit -m "full repo scan" || true
codeant review --committed > review.txt || true
# ⚡ Incremental scan
- name: Incremental AI scan
if: github.event_name != 'schedule'
run: |
echo "Running incremental scan..."
codeant review --committed > review.txt || true
- name: Show results
run: cat review.txt

View File

@@ -0,0 +1,36 @@
name: SonarQube Analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
sonarqube:
name: SonarQube Scan
runs-on: ubuntu-latest
# This runs the whole job INSIDE the sonar-scanner container
container:
image: sonarsource/sonar-scanner-cli:12.0.0.3214_8.0.1
options: --user root
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run Scan
run: |
# Gitea repo name
REPO_NAME=${{ gitea.event.repository.name }}
# We call the scanner directly since we are already inside its container
sonar-scanner \
-Dsonar.projectKey=$REPO_NAME \
-Dsonar.projectName=$REPO_NAME \
-Dsonar.sources=. \
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} \
-Dsonar.token=${{ secrets.SONARQUBE_TOKEN }} \
-Dsonar.exclusions=node_modules/**,dist/**,coverage/** \
-Dsonar.qualitygate.wait=true

View File

@@ -2,7 +2,7 @@
Product comparison page build using **React** + **Redux** + **Bootstrap** + **SASS** Product comparison page build using **React** + **Redux** + **Bootstrap** + **SASS**
![Screenshot](http://i.imgur.com/0fTmInU.png) ![Screenshot](https://s8.postimg.cc/fdfsvumkl/Screen_Shot_2018-07-05_at_16.36.17.png)
It's build on top of [`create-react-app`](http://www.google.lt) It's build on top of [`create-react-app`](http://www.google.lt)
@@ -26,8 +26,3 @@ License
The MIT License (MIT). Please see License File for more information. The MIT License (MIT). Please see License File for more information.
[![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/Rhymond/product-compare-react) [![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/Rhymond/product-compare-react)
Todo
-
- [ ] Write tests
- [ ] Integrate CI

12976
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,55 +4,47 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"autoprefixer": "7.1.1", "autoprefixer": "7.1.1",
"babel-core": "6.25.0", "babel-core": "^6.26.3",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3", "babel-jest": "20.0.3",
"babel-loader": "7.0.0", "babel-loader": "8.0.1",
"babel-preset-react-app": "^3.0.1", "babel-preset-react-app": "^3.1.2",
"babel-runtime": "6.23.0", "babel-runtime": "6.23.0",
"bootstrap": "^4.0.0-alpha.6", "bootstrap": "^4.1.1",
"case-sensitive-paths-webpack-plugin": "2.1.1", "case-sensitive-paths-webpack-plugin": "2.1.2",
"chalk": "1.1.3", "chalk": "1.1.3",
"css-loader": "0.28.4", "css-loader": "0.28.4",
"dotenv": "^4.0.0", "dotenv": "^4.0.0",
"eslint": "3.19.0",
"eslint-config-react-app": "^1.0.5",
"eslint-loader": "1.7.1",
"eslint-plugin-flowtype": "2.34.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "5.0.3",
"eslint-plugin-react": "7.1.0",
"extract-text-webpack-plugin": "2.1.2", "extract-text-webpack-plugin": "2.1.2",
"file-loader": "0.11.2", "file-loader": "2.0.0",
"fs-extra": "3.0.1", "fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0", "html-webpack-plugin": "3.2.0",
"jest": "20.0.4", "jest": "20.0.4",
"node-sass-chokidar": "0.0.3", "node-sass-chokidar": "0.0.3",
"npm-run-all": "^4.1.1", "npm-run-all": "^4.1.3",
"object-assign": "4.1.1", "object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.0.0", "postcss-flexbugs-fixes": "3.0.0",
"postcss-loader": "2.0.6", "postcss-loader": "3.0.0",
"promise": "7.1.1", "promise": "7.1.1",
"react": "^15.6.1", "react": "^15.6.2",
"react-addons-css-transition-group": "^15.6.0", "react-addons-css-transition-group": "^15.6.2",
"react-addons-transition-group": "^15.6.0", "react-addons-transition-group": "^15.6.2",
"react-dev-utils": "^3.0.2", "react-dev-utils": "^3.0.2",
"react-dom": "^15.6.1", "react-dom": "^15.6.2",
"react-error-overlay": "^1.0.9", "react-error-overlay": "^1.0.9",
"react-redux": "^5.0.5", "react-redux": "^5.0.7",
"react-router": "^4.1.1", "react-router": "^4.3.1",
"react-router-dom": "^4.1.1", "react-router-dom": "^4.3.1",
"react-scripts": "^1.0.10", "react-scripts": "^1.1.5",
"react-select": "^1.0.0-rc.5", "react-select": "^1.2.1",
"redux": "^3.0.0", "redux": "^3.0.0",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0", "redux-thunk": "^2.3.0",
"style-loader": "0.18.2", "style-loader": "0.23.0",
"sw-precache-webpack-plugin": "0.11.3", "sw-precache-webpack-plugin": "0.11.5",
"url-loader": "0.5.9", "url-loader": "1.1.1",
"webpack": "2.6.1", "webpack": "4.17.1",
"webpack-dev-server": "2.5.0", "webpack-dev-server": "^3.1.14",
"webpack-manifest-plugin": "1.1.0", "webpack-manifest-plugin": "2.0.3",
"whatwg-fetch": "2.0.3" "whatwg-fetch": "2.0.3"
}, },
"scripts": { "scripts": {
@@ -65,10 +57,11 @@
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "^7.2.3", "babel-eslint": "^7.2.3",
"eslint": "^3.19.0", "eslint": "^4.18.2",
"eslint-config-react-app": "^1.0.5", "eslint-config-react-app": "^1.0.5",
"eslint-loader": "^1.7.1",
"eslint-plugin-flowtype": "^2.33.0", "eslint-plugin-flowtype": "^2.33.0",
"eslint-plugin-import": "^2.2.0", "eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^5.0.1", "eslint-plugin-jsx-a11y": "^5.0.1",
"eslint-plugin-react": "^7.0.1" "eslint-plugin-react": "^7.0.1"
}, },

BIN
public/images/Cherry.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
public/images/Nuts.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

BIN
public/images/Orange.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View File

@@ -1,39 +1,39 @@
{ {
"products": [{ "products": [{
"id": "1", "id": "1",
"name": "Chair", "name": "Cherry",
"image": "https://devitems.com/preview/furnish/img/product/1.jpg", "image": "images/Cherry.png",
"price": "$39", "price": "$1.99",
"colors": ["red", "green", "blue"], "colors": ["red", "green", "blue"],
"condition": "New", "condition": "Fresh",
"description": "Black chair" "description": "Two Cherries"
}, },
{ {
"id": "2", "id": "2",
"name": "Lamp", "name": "Orange",
"image": "https://devitems.com/preview/furnish/img/product/2.jpg", "image": "images/Orange.png",
"price": "$319", "price": "$2.99",
"colors": ["green", "blue"], "colors": ["green", "blue"],
"condition": "Used", "condition": "Frozen",
"description": "Amazing lamp" "description": "Giant Orange"
}, },
{ {
"id": "3", "id": "3",
"name": "Statue", "name": "Nuts",
"image": "https://devitems.com/preview/furnish/img/product/3.jpg", "image": "images/Nuts.png",
"price": "$239", "price": "$1.00",
"colors": ["red"], "colors": ["red"],
"condition": "Used", "condition": "Frozen",
"description": "Used Statue" "description": "Mixed Nuts"
}, },
{ {
"id": "4", "id": "4",
"name": "Seat", "name": "Strawberry",
"image": "https://devitems.com/preview/furnish/img/product/4.jpg", "image": "images/Strawberry.png",
"price": "$239", "price": "$1.49",
"colors": ["blue"], "colors": ["blue"],
"condition": "New", "condition": "Fresh",
"description": "Large Seat" "description": "Just Strawberry"
} }
] ]
} }

View File

@@ -1 +0,0 @@
export * from './product';

View File

@@ -1,18 +1,17 @@
import * as types from '../constants/types'; import * as types from '../constants/types'
export function getProducts() { export const getProducts = () =>
return dispatch => { dispatch =>
fetch(`products.json`) fetch(`products.json`)
.then(response => response.json()) .then(response => response.json())
.then(response => { .then(response => {
dispatch({ dispatch({
type: types.FETCH_PRODUCTS, type: types.FETCH_PRODUCTS,
payload: response.products payload: response.products
}); })
}) })
}
}
export function compare(product) { export const compare = product => ({
return {type: types.COMPARE_PRODUCT, product}; type: types.COMPARE_PRODUCT,
} product
})

View File

@@ -7,7 +7,7 @@ const Compare = ({products}) =>
<table className="table"> <table className="table">
<thead className="thead-default"> <thead className="thead-default">
<tr> <tr>
<th></th> <th />
{products.map(product => {products.map(product =>
<th key={product.id}> <th key={product.id}>
{product.name} {product.name}
@@ -27,7 +27,7 @@ const Compare = ({products}) =>
{products.map(product => {products.map(product =>
<td key={product.id}> <td key={product.id}>
{product.colors.map((color, index) => {product.colors.map((color, index) =>
<span key={index} className={"bg-" + color}></span> <span key={index} className={"bg-" + color} />
)} )}
</td> </td>
)} )}
@@ -35,7 +35,7 @@ const Compare = ({products}) =>
<tr className="condition"> <tr className="condition">
<th scope="row">Condition</th> <th scope="row">Condition</th>
{products.map(product => {products.map(product =>
<td key={product.id} className={product.condition === "Used" ? "bg-red" : "bg-green"}> <td key={product.id} className={product.condition === "Frozen" ? "bg-red" : "bg-green"}>
{product.condition} {product.condition}
</td> </td>
)} )}
@@ -45,4 +45,4 @@ const Compare = ({products}) =>
</div> </div>
</div>; </div>;
export default Compare; export default Compare

View File

@@ -5,7 +5,7 @@
background-color: #fff; background-color: #fff;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
box-shadow: 0px 13px 21px -5px rgba(0, 0, 0, 0.05); box-shadow: 0 13px 21px -5px rgba(0, 0, 0, 0.05);
border: 1px solid #eee; border: 1px solid #eee;
font-size: 18px; font-size: 18px;
table-layout: fixed; table-layout: fixed;

View File

@@ -5,7 +5,7 @@ const Product = ({product, compare}) =>
<div key={product.id} className="col-sm-6 col-md-3"> <div key={product.id} className="col-sm-6 col-md-3">
<div className={"product " + (product.compare ? "compare" : "")} > <div className={"product " + (product.compare ? "compare" : "")} >
<img src={product.image} alt={product.name} /> <img src={product.image} alt={product.name} />
<div className="image_overlay"></div> <div className="image_overlay"/>
<div className="view_details" onClick={() => compare(product)}> <div className="view_details" onClick={() => compare(product)}>
{product.compare ? "Remove" : "Compare"} {product.compare ? "Remove" : "Compare"}
</div> </div>
@@ -19,4 +19,4 @@ const Product = ({product, compare}) =>
</div> </div>
</div>; </div>;
export default Product; export default Product

View File

@@ -10,8 +10,9 @@ $product-main-color: $green;
overflow: hidden; overflow: hidden;
transition: all 500ms ease-out; transition: all 500ms ease-out;
margin-bottom: 30px; margin-bottom: 30px;
border: 1px solid #ddd;
&:hover { &:hover {
box-shadow: 0px 13px 21px -5px rgba(0, 0, 0, 0.2); box-shadow: 0 13px 21px -5px rgba(0, 0, 0, 0.2);
.image_overlay { .image_overlay {
opacity: $image-overlay-opacity; opacity: $image-overlay-opacity;
} }

View File

@@ -1,13 +1,11 @@
import React from 'react' import React from 'react'
import {Product} from '../'; import {Product} from '../'
const ProductList = ({products, compare}) => const ProductList = ({products, compare}) =>
<div> <div className="row mt-3">
<div className="row mt-3"> {products.map(product =>
{products.map(product => <Product key={product.id} product={product} compare={compare} />
<Product key={product.id} product={product} compare={compare} /> )}
)}
</div>
</div>; </div>;
export default ProductList; export default ProductList

View File

@@ -1,12 +1,12 @@
import React, {Component} from 'react'; import React, {Component} from 'react'
import {Route, Switch} from 'react-router-dom' import {Route, Switch} from 'react-router-dom'
import {Home, NotFound} from '../'; import {Home, NotFound} from '../'
export default class App extends Component { class App extends Component {
render() { render() {
return ( return (
<div className="App"> <div className="app">
<div className="container mt-4"> <div className="container mt-4">
<Switch> <Switch>
<Route exact path="/" component={Home}/> <Route exact path="/" component={Home}/>
@@ -14,6 +14,8 @@ export default class App extends Component {
</Switch> </Switch>
</div> </div>
</div> </div>
); )
} }
} }
export default App

View File

@@ -1,12 +1,12 @@
import React from 'react'; import React, {Component} from 'react'
import {bindActionCreators} from 'redux'; import {bindActionCreators} from 'redux'
import {Compare, ProductList} from '../../components'; import {Compare, ProductList} from '../../components'
import * as productActions from '../../actions'; import * as productActions from '../../actions/product'
import {connect} from 'react-redux'; import {connect} from 'react-redux'
class Home extends React.Component { class Home extends Component {
componentWillMount() { componentWillMount() {
this.props.actions.getProducts(); this.props.actions.getProducts()
} }
render() { render() {
@@ -14,27 +14,26 @@ class Home extends React.Component {
const compareProducts = products.filter(product => product.compare); const compareProducts = products.filter(product => product.compare);
return ( return (
<div className="Home mt-5"> <div className="home mt-5">
<div className="row">
<div className="col-12">
<h2 className="mb-3">Compare Products</h2>
</div>
</div>
<ProductList products={products} compare={actions.compare}/> <ProductList products={products} compare={actions.compare}/>
{compareProducts.length >= 2 ? <Compare products={compareProducts}/> : null} {compareProducts.length >= 2 &&
<Compare products={compareProducts}/>
}
</div> </div>
); )
} }
} }
function mapStateToProps(state) {
return {
products: state.product.products
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(productActions, dispatch)
};
}
export default connect( export default connect(
mapStateToProps, state => ({
mapDispatchToProps products: state.product.products
)(Home); }),
dispatch => ({
actions: bindActionCreators(productActions, dispatch)
})
)(Home)

View File

@@ -1,12 +1,14 @@
import React from 'react' import React, {Component} from 'react'
export default class NotFound extends React.Component { class NotFound extends Component {
render() { render() {
return ( return (
<div> <div className="not-found">
<h1>404</h1> <h1>404</h1>
<h3>Page not found</h3> <h3>Page not found</h3>
</div> </div>
); )
} }
} }
export default NotFound

View File

@@ -1,6 +1,6 @@
import registerServiceWorker from './registerServiceWorker'; import registerServiceWorker from './registerServiceWorker'
import React from 'react'; import React from 'react'
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom'
import {BrowserRouter} from 'react-router-dom' import {BrowserRouter} from 'react-router-dom'
import {createStore, applyMiddleware} from 'redux' import {createStore, applyMiddleware} from 'redux'
import {Provider} from 'react-redux' import {Provider} from 'react-redux'
@@ -12,20 +12,23 @@ import App from './containers/App'
import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/css/bootstrap.css'
import './styles.css' import './styles.css'
const loggerMiddleware = createLogger() const loggerMiddleware = createLogger();
const store = createStore( const store = createStore(
reducer, reducer,
applyMiddleware( applyMiddleware(
thunkMiddleware, // lets us dispatch() functions thunkMiddleware,
loggerMiddleware // neat middleware that logs actions loggerMiddleware
) )
) );
ReactDOM.render( ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter>
<App /> <App />
</BrowserRouter> </BrowserRouter>
</Provider>, document.getElementById('root')); </Provider>,
document.getElementById('root')
);
registerServiceWorker(); registerServiceWorker();

View File

@@ -1,8 +1,8 @@
import { combineReducers } from 'redux' import { combineReducers } from 'redux'
import product from './product_reducer' import product from './productReducer'
const compareApp = combineReducers({ const compareApp = combineReducers({
product product
}) });
export default compareApp export default compareApp

View File

@@ -1,4 +1,4 @@
import * as types from '../constants/types'; import * as types from '../constants/types'
const INITIAL_STATE = { const INITIAL_STATE = {
products: [] products: []
@@ -21,6 +21,6 @@ export default function (state = INITIAL_STATE, action) {
) )
}; };
default: default:
return state; return state
} }
} }

View File

@@ -2,6 +2,6 @@ body {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: sans-serif; font-family: sans-serif;
background: #eaebec; background: #f6f7f8;
color: #393c45; color: #393c45;
} }