moving online

This commit is contained in:
QkoSad
2022-11-07 19:38:16 +02:00
parent 53737bce7f
commit 6b5c61de0b
34 changed files with 2005 additions and 144 deletions
+1004
View File
File diff suppressed because it is too large Load Diff
+290
View File
@@ -11,10 +11,19 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.1.3",
"daisyui": "^2.38.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.6.0",
"react-router-dom": "^6.4.3",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"postcss": "^8.4.18",
"tailwindcss": "^3.2.1"
}
},
"node_modules/@adobe/css-tools": {
@@ -3085,6 +3094,14 @@
}
}
},
"node_modules/@remix-run/router": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
"integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==",
"engines": {
"node": ">=14"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -4963,6 +4980,29 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
"integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -5667,6 +5707,18 @@
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg=="
},
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -5680,6 +5732,31 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/color/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/colord": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
@@ -6099,6 +6176,15 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@@ -6290,6 +6376,21 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
"node_modules/daisyui": {
"version": "2.38.0",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.38.0.tgz",
"integrity": "sha512-/AIT/XrNY8QLpXnoEXU7aFv5NRU7R3NSpg13ujs+hkTlDlR8pkjsGMqTRKvMf7orCX9833VLFAFJw+CH4EORvA==",
"dependencies": {
"color": "^4.2",
"css-selector-tokenizer": "^0.8.0",
"postcss-js": "^4.0.0",
"tailwindcss": "^3"
},
"peerDependencies": {
"autoprefixer": "^10.0.2",
"postcss": "^8.1.6"
}
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -7791,6 +7892,11 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
},
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
},
"node_modules/fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@@ -13851,6 +13957,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -14140,6 +14251,14 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-icons": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -14153,6 +14272,36 @@
"node": ">=0.10.0"
}
},
"node_modules/react-router": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
"integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
"dependencies": {
"@remix-run/router": "1.0.3"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
"integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
"dependencies": {
"@remix-run/router": "1.0.3",
"react-router": "6.4.3"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -14975,6 +15124,19 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/simple-swizzle/node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -19040,6 +19202,11 @@
"source-map": "^0.7.3"
}
},
"@remix-run/router": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
"integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q=="
},
"@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -20444,6 +20611,28 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.5.1.tgz",
"integrity": "sha512-1exVbW0X1O/HSr/WMwnaweyqcWOgZgLiVxdLG34pvSQk4NlYQr9OUy0JLwuhFfuVNQzzqgH57eYzkFBCb3bIsQ=="
},
"axios": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
"integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -20975,6 +21164,30 @@
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg=="
},
"color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"dependencies": {
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -20988,6 +21201,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"colord": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
@@ -21276,6 +21498,15 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
"css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"requires": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@@ -21418,6 +21649,17 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
"daisyui": {
"version": "2.38.0",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.38.0.tgz",
"integrity": "sha512-/AIT/XrNY8QLpXnoEXU7aFv5NRU7R3NSpg13ujs+hkTlDlR8pkjsGMqTRKvMf7orCX9833VLFAFJw+CH4EORvA==",
"requires": {
"color": "^4.2",
"css-selector-tokenizer": "^0.8.0",
"postcss-js": "^4.0.0",
"tailwindcss": "^3"
}
},
"damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -22540,6 +22782,11 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
},
"fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
},
"fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@@ -26718,6 +26965,11 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -26924,6 +27176,12 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"react-icons": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
"requires": {}
},
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -26934,6 +27192,23 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
},
"react-router": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
"integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
"requires": {
"@remix-run/router": "1.0.3"
}
},
"react-router-dom": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
"integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
"requires": {
"@remix-run/router": "1.0.3",
"react-router": "6.4.3"
}
},
"react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -27527,6 +27802,21 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"requires": {
"is-arrayish": "^0.3.1"
},
"dependencies": {
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+9
View File
@@ -6,8 +6,12 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.1.3",
"daisyui": "^2.38.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.6.0",
"react-router-dom": "^6.4.3",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
@@ -34,5 +38,10 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"postcss": "^8.4.18",
"tailwindcss": "^3.2.1"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
+10 -42
View File
@@ -1,43 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="../dist/output" rel="stylesheet">
</head>
<body>
<div id="root"/>
</body>
</html>
-38
View File
@@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
+31 -21
View File
@@ -1,25 +1,35 @@
import logo from './logo.svg';
import './App.css';
import Home from "./pages/Home";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
import Footer from "./components/layout/Footer";
import Navbar from "./components/layout/Navbar";
import Alert from "./components/layout/Alert";
import User from './pages/User'
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { GithubProvider } from "./context/github/GithubContext";
import { AlertProvider } from "./context/alert/AlertContext";
function App() {
export default function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<GithubProvider>
<AlertProvider>
<Router>
<div className="flex flex-col justify-between h-screen">
<Navbar />
<main className="container mx-auto px-3 pb-12">
<Alert />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:login" element={<User />} />
<Route path="/notfound" element={<NotFound />} />
<Route path="/*" element={<NotFound />} />
</Routes>
</main>
<Footer />
</div>
</Router>
</AlertProvider>
</GithubProvider>
);
}
export default App;
-8
View File
@@ -1,8 +0,0 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
+31
View File
@@ -0,0 +1,31 @@
import { useContext } from "react";
import AlertContext from "../../context/alert/AlertContext";
function Alert() {
const { alert } = useContext(AlertContext);
return (
<div
className={`grid grid-cols-1 xl:grid-cols-2 lg:grid-cols-2 md:grid-cols-2 gap-8 mb-4`}
style={{ visibility: alert ? "visible" : "hidden" }}
>
<div className="alert alert-error">
<div>
<svg
fill="none"
viewBox="0 0 24 24"
className="w-6 h-6 stroke-current mr-3"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"
></path>
</svg>
<strong>{alert?.msg}</strong>
</div>
</div>
</div>
);
}
export default Alert;
+22
View File
@@ -0,0 +1,22 @@
export default function Footer() {
const footerYear = new Date().getFullYear();
return (
<footer className="footer p-10 bg-gray-700 text-primary-content footer-center">
<div>
<svg
width="50"
height="50"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fillRule="evenodd"
clipRule="evenodd"
className="inline-block fill-current"
>
<path d="M22.672 15.226l-2.432.811.841 2.515c.33 1.019-.209 2.127-1.23 2.456-1.15.325-2.148-.321-2.463-1.226l-.84-2.518-5.013 1.677.84 2.517c.391 1.203-.434 2.542-1.831 2.542-.88 0-1.601-.564-1.86-1.314l-.842-2.516-2.431.809c-1.135.328-2.145-.317-2.463-1.229-.329-1.018.211-2.127 1.231-2.456l2.432-.809-1.621-4.823-2.432.808c-1.355.384-2.558-.59-2.558-1.839 0-.817.509-1.582 1.327-1.846l2.433-.809-.842-2.515c-.33-1.02.211-2.129 1.232-2.458 1.02-.329 2.13.209 2.461 1.229l.842 2.515 5.011-1.677-.839-2.517c-.403-1.238.484-2.553 1.843-2.553.819 0 1.585.509 1.85 1.326l.841 2.517 2.431-.81c1.02-.33 2.131.211 2.461 1.229.332 1.018-.21 2.126-1.23 2.456l-2.433.809 1.622 4.823 2.433-.809c1.242-.401 2.557.484 2.557 1.838 0 .819-.51 1.583-1.328 1.847m-8.992-6.428l-5.01 1.675 1.619 4.828 5.011-1.674-1.62-4.829z"></path>
</svg>
<p>Copyright &copy; {footerYear} All rights reserved</p>
</div>
</footer>
);
}
+30
View File
@@ -0,0 +1,30 @@
import { FaGithub } from "react-icons/fa";
import { Link } from "react-router-dom";
import PropTypes from "prop-types";
function Navbar({ title }) {
return (
<nav className="navbar mb-12 shadow-lg bg-neutral text-neutral-content">
<div className="container mx-auto">
<div className="flex-none px-2 mx-2">
<FaGithub className="inline pr-2 text-3xl"/>
<Link to='/' className="text-ls font-bold aling-middle">
{title}
</Link>
</div>
<div className="flex-1 px-2 mx-2">
<div className="flex justify-end">
<Link to='/'className="btn btn-ghost btn-sm rouded-btn">Home</Link>
<Link to='/about'className="btn btn-ghost btn-sm rouded-btn">About</Link>
</div>
</div>
</div>
</nav>
);
}
Navbar.defaultProps = {
title: "Github Finder",
};
Navbar.propTypes = { title: PropTypes.string };
export default Navbar;
+14
View File
@@ -0,0 +1,14 @@
import spinner from "./assets/spinner.gif";
export default function Spinner() {
return (
<div className="w-100 mt-20">
<img
width={180}
src={spinner}
alt="Loading"
className="text-center mx-auto"
/>
</div>
);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

+48
View File
@@ -0,0 +1,48 @@
import { FaEye, FaInfo, FaLink, FaStar, FaUtensils } from 'react-icons/fa'
import PropTypes from 'prop-types'
function RepoItem({ repo }) {
const {
name,
description,
html_url,
forks,
open_issues,
watchers_count,
stargazers_count,
} = repo
return (
<div className='mb-2 rounded-md card bg-base-200 hover:bg-base-300'>
<div className='card-body'>
<h3 className='mb-2 text-xl font-semibold'>
<a href={html_url}>
<FaLink className='inline mr-1' /> {name}
</a>
</h3>
<p className='mb-3'>{description}</p>
<div>
<div className='mr-2 badge badge-info badge-lg'>
<FaEye className='mr-2' /> {watchers_count}
</div>
<div className='mr-2 badge badge-success badge-lg'>
<FaStar className='mr-2' /> {stargazers_count}
</div>
<div className='mr-2 badge badge-error badge-lg'>
<FaInfo className='mr-2' /> {open_issues}
</div>
<div className='mr-2 badge badge-warning badge-lg'>
<FaUtensils className='mr-2' /> {forks}
</div>
</div>
</div>
</div>
)
}
RepoItem.propTypes = {
repo: PropTypes.object.isRequired,
}
export default RepoItem
+21
View File
@@ -0,0 +1,21 @@
import RepoItem from "./RepoItem";
import PropTypes from "prop-types";
export default function RepoList({ repos }) {
return (
<div className="rounded-lg shadow-lg card-bg-base-100">
<div className="card-body">
<h2 className="text-3xl my-4 front-bold card-title">
Latest Repositories
</h2>
{repos.map((repo) => (
<RepoItem key={repo.id} repo={repo}/>
))}
</div>
</div>
);
}
RepoList.propTypes = {
repos: PropTypes.array.isRequired,
};
+31
View File
@@ -0,0 +1,31 @@
import { Link } from "react-router-dom";
import PropTypes from "prop-types";
export default function UserItem({ user: { login, avatar_url } }) {
return (
<div className="card shadow-md compact side bg-base-100">
<div className="flex=row items-center space-x-4 card-body">
<div>
<div className="avatar">
<div className="rounded-full shadow w-14 h-14">
<img src={avatar_url} alt="Profile" />
</div>
</div>
</div>
<div>
<h2 className="card-title"></h2>
<Link
className="text-base-content text-opacity-40"
to={`/user/${login}`}
>
Visit Profile
</Link>
</div>
</div>
</div>
);
}
UserItem.propTypes = {
user: PropTypes.object.isRequired,
};
+20
View File
@@ -0,0 +1,20 @@
import Spinner from "../layout/Spinner";
import UserItem from "./UserItem";
import { useContext } from "react";
import GithubContext from "../../context/github/GithubContext";
export default function UserResults() {
const { users, loading } = useContext(GithubContext);
if (!loading) {
return (
<div className="grid grid-cols-1 gap-8 xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2">
{users.map((user) => (
<UserItem key={user.id} user={user} />
))}
</div>
);
} else {
return <Spinner />;
}
}
+60
View File
@@ -0,0 +1,60 @@
import AlertContext from "../../context/alert/AlertContext";
import GithubContext from "../../context/github/GithubContext";
import { searchUsers } from "../../context/github/GithubActions";
import { useContext, useState } from "react";
export default function UserSearch() {
const [text, setText] = useState("");
const { users, dispatch } = useContext(GithubContext);
const { setAlert } = useContext(AlertContext);
const handleChange = (e) => setText(e.target.value);
const handleSubmit = async (e) => {
e.preventDefault();
if (text === "") {
setAlert("Please enter something", "error");
} else {
dispatch({ type: "SET_LOADING" });
const users = await searchUsers(text);
dispatch({ type: "GET_USERS", payload: users });
setText("");
}
};
return (
<div className="grid grid-cols-1 xl:grid-cols2- lg:grid-cols-2 md:grid-cols-2 mb-8 gap-8">
<div>
<form onSubmit={handleSubmit}>
<div className="form-control">
<div className="relative">
<input
type="text"
className="w-full pr-40 bg-gray-200 input input-lg text-black "
placeholder="Search"
onChange={handleChange}
value={text}
/>
<button
className="absolute top-0 right-0 rounded-l-none w-36 btn btn-lg"
type="submit"
>
Go
</button>
</div>
</div>
</form>
</div>
{users.length > 0 && (
<div>
<button
onClick={() => dispatch({ type: "CLEAR_USERS" })}
className="btn btn-ghost btn-lg"
>
Clear
</button>
</div>
)}
</div>
);
}
+22
View File
@@ -0,0 +1,22 @@
import { createContext, useReducer } from "react";
import alertReducer from "./AlertReducer";
const AlertContext = createContext();
export const AlertProvider = ({ children }) => {
const initialState = null;
const [state, dispatch] = useReducer(alertReducer, initialState);
const setAlert = (msg, type)=>{
dispatch({
type:"SET_ALERT",
payload:{msg,type}
})
setTimeout(()=> dispatch({type:"REMOVE_ALERT"}),3000)
}
return (
<AlertContext.Provider value={{ alert: state ,setAlert}}>
{children}
</AlertContext.Provider>
);
};
export default AlertContext;
+11
View File
@@ -0,0 +1,11 @@
const alertReducer = (state, action) => {
switch (action.type) {
case "SET_ALERT":
return action.payload;
case "REMOVE_ALERT":
return null;
default:
return state;
}
};
export default alertReducer;
+27
View File
@@ -0,0 +1,27 @@
import axios from 'axios'
const GITHUB_URL = process.env.REACT_APP_GITHUB_URL
const GITHUB_TOKEN = process.env.REACT_APP_GITHUB_TOKEN
const github = axios.create({
baseURL: GITHUB_URL,
headers: { Authorization: `token ${GITHUB_TOKEN}` },
})
export const searchUsers = async (text) => {
const params = new URLSearchParams({
q: text,
})
const response = await github.get(`/search/users?${params}`)
return response.data.items
}
export const getUserAndRepos = async (login) => {
const [user, repos] = await Promise.all([
github.get(`/users/${login}`),
github.get(`/users/${login}/repos`),
])
return { user: user.data, repos: repos.data }
}
+25
View File
@@ -0,0 +1,25 @@
import { createContext, useReducer } from "react";
import githubReducer from "./GithubReducer";
const GithubContext = createContext();
export const GithubProvider = ({ children }) => {
const initialState = {
users: [],
user:{},
repos:[],
loading: false,
};
const [state, dispatch] = useReducer(githubReducer, initialState);
return (
<GithubContext.Provider
value={{
...state,
dispatch,
}}
>
{children}
</GithubContext.Provider>
);
};
export default GithubContext;
+30
View File
@@ -0,0 +1,30 @@
const githubReducer = (state, action) => {
switch (action.type) {
case "GET_USERS":
return {
...state,
users: action.payload,
loading: false,
};
case "SET_LOADING":
return {
...state,
loading: true,
};
case "CLEAR_USERS":
return {
...state,
users: [],
};
case "GET_USER_AND_REPOS":
return{
...state,
user: action.payload.user,
repos: action.payload.repos,
loading: false
}
default:
return state;
}
};
export default githubReducer;
+6 -11
View File
@@ -1,13 +1,8 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@tailwind base;
@tailwind components;
@tailwind utilities;
.custom-card-image .card.image-full:before {
border-radius: 0.5rem;
opacity: 0.45;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
-5
View File
@@ -2,7 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
@@ -11,7 +10,3 @@ root.render(
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

+29
View File
@@ -0,0 +1,29 @@
export default function About() {
return (
<div>
<h1 className="text-6xl mb-4">Github Finder</h1>
<p className="mb-4 text-2xl font-light">
A React app to search GitHub profiles and see profile details. This
project is part of the
<a href="https://www.udemy.com/course/modern-react-front-to-back/">
{" "}
React Front To Back
</a>{" "}
Udemy course by
<strong>
<a href="https://traversymedia.com"> Brad Traversy</a>
</strong>
.
</p>
<p className="text-lg text-gray-400">
Version <span className="text-white">1.0.0</span>
</p>
<p className="text-lg text-gray-400">
Layout By:
<a className="text-white" href="https://twitter.com/hassibmoddasser">
Hassib Moddasser
</a>
</p>
</div>
);
}
+10
View File
@@ -0,0 +1,10 @@
import UserResults from "../components/users/UserResults";
import UserSearch from "../components/users/UserSearch";
export default function Home() {
return (
<>
<UserResults />
<UserSearch />
</>
);
}
+19
View File
@@ -0,0 +1,19 @@
import { FaHome } from "react-icons/fa";
import { Link } from "react-router-dom";
export default function NotFound() {
return (
<div className="hero">
<div className="text-center hero-content">
<div className="max-w-lg">
<h1 className="text-8xl font-bold mb-8">Oop!</h1>
<p className="text-5xl mb-8">404 - Page not found!</p>
<Link className="btn btn-primary btn-lg" to="/">
<FaHome className="mr-2" />
Back To Home
</Link>
</div>
</div>
</div>
);
}
+186
View File
@@ -0,0 +1,186 @@
import { FaCodepen, FaStore, FaUserFriends, FaUsers } from 'react-icons/fa'
import { useEffect, useContext } from 'react'
import { useParams, Link } from 'react-router-dom'
import Spinner from '../components/layout/Spinner'
import RepoList from '../components/repos/RepoList'
import GithubContext from '../context/github/GithubContext'
import { getUserAndRepos } from '../context/github/GithubActions'
function User() {
const { user, loading, repos, dispatch } = useContext(GithubContext)
const params = useParams()
useEffect(() => {
dispatch({ type: 'SET_LOADING' })
const getUserData = async () => {
const userData = await getUserAndRepos(params.login)
dispatch({ type: 'GET_USER_AND_REPOS', payload: userData })
}
getUserData()
}, [dispatch, params.login])
const {
name,
type,
avatar_url,
location,
bio,
blog,
twitter_username,
login,
html_url,
followers,
following,
public_repos,
public_gists,
hireable,
} = user
if (loading) {
return <Spinner />
}
// NOTE: check for valid url to users website
const websiteUrl = blog?.startsWith('http') ? blog : 'https://' + blog
// NOTE: code here has been fixed so that stats no longer show scroll bar on
// mobile / small devices
// https://www.udemy.com/course/react-front-to-back-2022/learn/lecture/29768968#questions/16902278
// NOTE: if you are having problems with the name and login showing at the top
// of the image then you need the className='flex-grow-0' on the <p> tag
// default styling on <p> in daisyUI now has flex-grow-1
return (
<>
<div className='w-full mx-auto lg:w-10/12'>
<div className='mb-4'>
<Link to='/' className='btn btn-ghost'>
Back To Search
</Link>
</div>
<div className='grid grid-cols-1 xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-3 mb-8 md:gap-8'>
<div className='custom-card-image mb-6 md:mb-0'>
<div className='rounded-lg shadow-xl card image-full'>
<figure>
<img src={avatar_url} alt='' />
</figure>
<div className='card-body justify-end'>
<h2 className='card-title mb-0'>{name}</h2>
<p className='flex-grow-0'>{login}</p>
</div>
</div>
</div>
<div className='col-span-2'>
<div className='mb-6'>
<h1 className='text-3xl card-title'>
{name}
<div className='ml-2 mr-1 badge badge-success'>{type}</div>
{hireable && (
<div className='mx-1 badge badge-info'>Hireable</div>
)}
</h1>
<p>{bio}</p>
<div className='mt-4 card-actions'>
<a
href={html_url}
target='_blank'
rel='noreferrer'
className='btn btn-outline'
>
Visit Github Profile
</a>
</div>
</div>
<div className='w-full rounded-lg shadow-md bg-base-100 stats'>
{location && (
<div className='stat'>
<div className='stat-title text-md'>Location</div>
<div className='text-lg stat-value'>{location}</div>
</div>
)}
{blog && (
<div className='stat'>
<div className='stat-title text-md'>Website</div>
<div className='text-lg stat-value'>
<a href={websiteUrl} target='_blank' rel='noreferrer'>
{websiteUrl}
</a>
</div>
</div>
)}
{twitter_username && (
<div className='stat'>
<div className='stat-title text-md'>Twitter</div>
<div className='text-lg stat-value'>
<a
href={`https://twitter.com/${twitter_username}`}
target='_blank'
rel='noreferrer'
>
{twitter_username}
</a>
</div>
</div>
)}
</div>
</div>
</div>
<div className='w-full py-5 mb-6 rounded-lg shadow-md bg-base-100 stats'>
<div className='grid grid-cols-1 md:grid-cols-3'>
<div className='stat'>
<div className='stat-figure text-secondary'>
<FaUsers className='text-3xl md:text-5xl' />
</div>
<div className='stat-title pr-5'>Followers</div>
<div className='stat-value pr-5 text-3xl md:text-4xl'>
{followers}
</div>
</div>
<div className='stat'>
<div className='stat-figure text-secondary'>
<FaUserFriends className='text-3xl md:text-5xl' />
</div>
<div className='stat-title pr-5'>Following</div>
<div className='stat-value pr-5 text-3xl md:text-4xl'>
{following}
</div>
</div>
<div className='stat'>
<div className='stat-figure text-secondary'>
<FaCodepen className='text-3xl md:text-5xl' />
</div>
<div className='stat-title pr-5'>Public Repos</div>
<div className='stat-value pr-5 text-3xl md:text-4xl'>
{public_repos}
</div>
</div>
<div className='stat'>
<div className='stat-figure text-secondary'>
<FaStore className='text-3xl md:text-5xl' />
</div>
<div className='stat-title pr-5'>Public Gists</div>
<div className='stat-value pr-5 text-3xl md:text-4xl'>
{public_gists}
</div>
</div>
</div>
</div>
<RepoList repos={repos} />
</div>
</>
)
}
export default User
-13
View File
@@ -1,13 +0,0 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
-5
View File
@@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
+10
View File
@@ -0,0 +1,10 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [require('daisyui')],
}