├── public
├── favicon.ico
├── logo192.png
├── logo512.png
├── robots.txt
├── manifest.json
└── index.html
├── src
├── assets
│ ├── 4927.eps
│ ├── 4927.jpg
│ ├── Sword.ai
│ ├── bmo.png
│ ├── close.png
│ ├── cool.gif
│ ├── goku.png
│ ├── logos.zip
│ ├── vector.ai
│ ├── button.png
│ ├── daymode.jpg
│ ├── dsword.png
│ ├── example.png
│ ├── favicon.ico
│ ├── favicon.png
│ ├── feedbg.jpg
│ ├── feedbg2.jpg
│ ├── feedbg3.jpg
│ ├── feedbg4.jpg
│ ├── refresh.png
│ ├── scroll.png
│ ├── scroll2.png
│ ├── sword2.png
│ ├── unknown.png
│ ├── vector.jpg
│ ├── vector.png
│ ├── wooden.png
│ ├── favicon_io.zip
│ ├── finnsword.png
│ ├── finnsword2.png
│ ├── light-bulb.png
│ ├── lightbulb2.png
│ ├── nightmode.jpg
│ ├── untitled-1.png
│ ├── Demon_Sword.webp
│ ├── deletebutton.jpg
│ ├── nftpalbanner.png
│ ├── RetroComputer.woff
│ ├── RetroComputer.woff2
│ ├── Watermelon Days.otf
│ ├── Watermelon Days.ttf
│ ├── favicon-32x32.png
│ ├── question-mark.png
│ ├── retro_computer.zip
│ ├── watermelon_days.zip
│ ├── lemonpie-webfont.woff
│ ├── Adventure Time Logo.ttf
│ ├── adventure-time-logo.zip
│ ├── candy_beans-webfont.woff
│ ├── lemon_days-webfont.woff
│ ├── lemon_days-webfont.woff2
│ ├── lemonpie-webfont.woff2
│ ├── candy_beans-webfont.woff2
│ ├── watermelon_days-webfont.woff
│ ├── watermelon_days-webfont.woff2
│ ├── retro_computer_personal_use.ttf
│ ├── webfontkit-20220809-192019.zip
│ ├── webfontkit-20220810-172416.zip
│ ├── adventure_time_logo-webfont.woff
│ ├── adventure_time_logo-webfont.woff2
│ ├── tumblr_mayy7wWuRf1qzrbk9o1_500.jpg
│ ├── transfonter.org-20220805-032912.zip
│ ├── nothung__billy_s_sword__by_dandoorlando_d6qwgex-pre.jpg
│ ├── torn-leaf-parchment-magic-diploma-fairy-grunge-cartoon-vector-illustration_81894-5813.jpg
│ ├── ethereum-gold.svg
│ ├── nftnerd.svg
│ ├── etherscan.svg
│ ├── eth.svg
│ ├── opensea.svg
│ ├── ethereum.svg
│ ├── Sword.svg
│ └── vector.svg
├── setupTests.js
├── App.test.js
├── reportWebVitals.js
├── Styles
│ ├── Menu.css
│ ├── Banner.css
│ ├── index.css
│ ├── Stats.css
│ ├── App.css
│ └── ModuleHandler.css
├── App.css
├── index.js
├── Banner.js
├── logo.svg
├── App.js
├── Menu.js
├── Stats.js
├── BackupModuleHandler.js
└── ModuleHandler.js
├── .gitignore
├── package.json
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/src/assets/4927.eps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/4927.eps
--------------------------------------------------------------------------------
/src/assets/4927.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/4927.jpg
--------------------------------------------------------------------------------
/src/assets/Sword.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/Sword.ai
--------------------------------------------------------------------------------
/src/assets/bmo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/bmo.png
--------------------------------------------------------------------------------
/src/assets/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/close.png
--------------------------------------------------------------------------------
/src/assets/cool.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/cool.gif
--------------------------------------------------------------------------------
/src/assets/goku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/goku.png
--------------------------------------------------------------------------------
/src/assets/logos.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/logos.zip
--------------------------------------------------------------------------------
/src/assets/vector.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/vector.ai
--------------------------------------------------------------------------------
/src/assets/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/button.png
--------------------------------------------------------------------------------
/src/assets/daymode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/daymode.jpg
--------------------------------------------------------------------------------
/src/assets/dsword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/dsword.png
--------------------------------------------------------------------------------
/src/assets/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/example.png
--------------------------------------------------------------------------------
/src/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/favicon.ico
--------------------------------------------------------------------------------
/src/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/favicon.png
--------------------------------------------------------------------------------
/src/assets/feedbg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/feedbg.jpg
--------------------------------------------------------------------------------
/src/assets/feedbg2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/feedbg2.jpg
--------------------------------------------------------------------------------
/src/assets/feedbg3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/feedbg3.jpg
--------------------------------------------------------------------------------
/src/assets/feedbg4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/feedbg4.jpg
--------------------------------------------------------------------------------
/src/assets/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/refresh.png
--------------------------------------------------------------------------------
/src/assets/scroll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/scroll.png
--------------------------------------------------------------------------------
/src/assets/scroll2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/scroll2.png
--------------------------------------------------------------------------------
/src/assets/sword2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/sword2.png
--------------------------------------------------------------------------------
/src/assets/unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/unknown.png
--------------------------------------------------------------------------------
/src/assets/vector.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/vector.jpg
--------------------------------------------------------------------------------
/src/assets/vector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/vector.png
--------------------------------------------------------------------------------
/src/assets/wooden.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/wooden.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/assets/favicon_io.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/favicon_io.zip
--------------------------------------------------------------------------------
/src/assets/finnsword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/finnsword.png
--------------------------------------------------------------------------------
/src/assets/finnsword2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/finnsword2.png
--------------------------------------------------------------------------------
/src/assets/light-bulb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/light-bulb.png
--------------------------------------------------------------------------------
/src/assets/lightbulb2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/lightbulb2.png
--------------------------------------------------------------------------------
/src/assets/nightmode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/nightmode.jpg
--------------------------------------------------------------------------------
/src/assets/untitled-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/untitled-1.png
--------------------------------------------------------------------------------
/src/assets/Demon_Sword.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/Demon_Sword.webp
--------------------------------------------------------------------------------
/src/assets/deletebutton.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/deletebutton.jpg
--------------------------------------------------------------------------------
/src/assets/nftpalbanner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/nftpalbanner.png
--------------------------------------------------------------------------------
/src/assets/RetroComputer.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/RetroComputer.woff
--------------------------------------------------------------------------------
/src/assets/RetroComputer.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/RetroComputer.woff2
--------------------------------------------------------------------------------
/src/assets/Watermelon Days.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/Watermelon Days.otf
--------------------------------------------------------------------------------
/src/assets/Watermelon Days.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/Watermelon Days.ttf
--------------------------------------------------------------------------------
/src/assets/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/favicon-32x32.png
--------------------------------------------------------------------------------
/src/assets/question-mark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/question-mark.png
--------------------------------------------------------------------------------
/src/assets/retro_computer.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/retro_computer.zip
--------------------------------------------------------------------------------
/src/assets/watermelon_days.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/watermelon_days.zip
--------------------------------------------------------------------------------
/src/assets/lemonpie-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/lemonpie-webfont.woff
--------------------------------------------------------------------------------
/src/assets/Adventure Time Logo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/Adventure Time Logo.ttf
--------------------------------------------------------------------------------
/src/assets/adventure-time-logo.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/adventure-time-logo.zip
--------------------------------------------------------------------------------
/src/assets/candy_beans-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/candy_beans-webfont.woff
--------------------------------------------------------------------------------
/src/assets/lemon_days-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/lemon_days-webfont.woff
--------------------------------------------------------------------------------
/src/assets/lemon_days-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/lemon_days-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/lemonpie-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/lemonpie-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/candy_beans-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/candy_beans-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/watermelon_days-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/watermelon_days-webfont.woff
--------------------------------------------------------------------------------
/src/assets/watermelon_days-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/watermelon_days-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/retro_computer_personal_use.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/retro_computer_personal_use.ttf
--------------------------------------------------------------------------------
/src/assets/webfontkit-20220809-192019.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/webfontkit-20220809-192019.zip
--------------------------------------------------------------------------------
/src/assets/webfontkit-20220810-172416.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/webfontkit-20220810-172416.zip
--------------------------------------------------------------------------------
/src/assets/adventure_time_logo-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/adventure_time_logo-webfont.woff
--------------------------------------------------------------------------------
/src/assets/adventure_time_logo-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/adventure_time_logo-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/tumblr_mayy7wWuRf1qzrbk9o1_500.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/tumblr_mayy7wWuRf1qzrbk9o1_500.jpg
--------------------------------------------------------------------------------
/src/assets/transfonter.org-20220805-032912.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/transfonter.org-20220805-032912.zip
--------------------------------------------------------------------------------
/src/assets/nothung__billy_s_sword__by_dandoorlando_d6qwgex-pre.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/nothung__billy_s_sword__by_dandoorlando_d6qwgex-pre.jpg
--------------------------------------------------------------------------------
/src/assets/torn-leaf-parchment-magic-diploma-fairy-grunge-cartoon-vector-illustration_81894-5813.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jckhe/nftpal/HEAD/src/assets/torn-leaf-parchment-magic-diploma-fairy-grunge-cartoon-vector-illustration_81894-5813.jpg
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render( );
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/.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/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/Styles/Menu.css:
--------------------------------------------------------------------------------
1 |
2 | .buttonLabelDiv span {
3 | z-index: 7;
4 | user-select: none;
5 | position: relative;
6 | left: 29%;
7 | top: 40%;
8 | font-size: 1.3rem;
9 | font-family: 'watermelondays'
10 | }
11 |
12 | .buttonLabelDiv strong {
13 | font-weight: normal;
14 | }
15 |
16 | .buttonLabelDiv {
17 | position: absolute;
18 | cursor: pointer;
19 | height: 120px;
20 | width: 200px;
21 | overflow: visible;
22 | padding: 0;
23 | top: -30px;
24 | left: -3%;
25 | filter:drop-shadow(1px 2px 5px black);
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/assets/ethereum-gold.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './Styles/index.css';
4 | import {App} from './App';
5 | import {Banner} from './Banner.js'
6 | import { CookiesProvider } from "react-cookie";
7 | import reportWebVitals from './reportWebVitals';
8 |
9 | const root = ReactDOM.createRoot(document.getElementById('root'));
10 | root.render(
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 |
20 | // If you want to start measuring performance in your app, pass a function
21 | // to log results (for example: reportWebVitals(console.log))
22 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
23 | reportWebVitals();
24 |
--------------------------------------------------------------------------------
/src/Banner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import bannerPNG from './assets/nftpalbanner.png'
3 | import './Styles/Banner.css'
4 |
5 |
6 |
7 | export function Banner (props) {
8 | return (
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/src/assets/nftnerd.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/assets/etherscan.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.3.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.2.0",
10 | "react-cookie": "^4.1.1",
11 | "react-dom": "^18.2.0",
12 | "react-favicon": "^1.0.1",
13 | "react-router-dom": "^6.3.0",
14 | "react-scripts": "5.0.1",
15 | "react-switch": "^7.0.0",
16 | "react-usestateref": "^1.0.8",
17 | "universal-cookie": "^4.0.4",
18 | "web-vitals": "^2.1.4"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test",
24 | "eject": "react-scripts eject"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | },
44 | "devDependencies": {
45 | "@iconify/react": "^3.2.2"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/assets/eth.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/Styles/Banner.css:
--------------------------------------------------------------------------------
1 | .header {
2 | display: flex;
3 | justify-content: center;
4 | flex-direction: column;
5 | align-items: center;
6 | caret-color: transparent!important;
7 | z-index: 4;
8 | position: relative;
9 | }
10 |
11 | .banner {
12 |
13 | padding: 7px;
14 | }
15 |
16 | .menu {
17 | display: flex;
18 | justify-content: center;
19 | gap: 100px;
20 | margin-bottom: 15px;
21 | }
22 |
23 | .menu button {
24 |
25 |
26 | }
27 |
28 | .button-74 {
29 | height: 40px;
30 | width: 115px;
31 | text-transform: uppercase;
32 | color: #000;
33 | cursor: pointer;
34 | border: 3px solid;
35 | padding: 0.25em 0.5em;
36 | box-shadow: 1px 1px 0px 0px, 2px 2px 0px 0px, 3px 3px 0px 0px, 4px 4px 0px 0px, 5px 5px 0px 0px;
37 | position: relative;
38 | user-select: none;
39 | -webkit-user-select: none;
40 | touch-action: manipulation;
41 | }
42 |
43 |
44 |
45 | .button-74:active {
46 | box-shadow: 0px 0px 0px 0px;
47 | top: 5px;
48 | left: 5px;
49 | }
50 |
51 |
52 |
53 | .button-74 span {
54 |
55 | bottom: -15px;
56 | left: 45px;
57 | letter-spacing: 3px;
58 | font-family: 'watermelondays';
59 | color: #000000;
60 | -webkit-text-stroke: 0.1px;
61 | -webkit-text-stroke-color: rgba(255, 255, 255, .5);
62 | }
63 |
64 | .buttonHolder {
65 | display: flex;
66 | align-items: center;
67 | flex-direction: row;
68 | }
69 |
70 | .buttonHolder2 {
71 | display: flex;
72 | align-items: center;
73 | flex-direction: row;
74 | }
75 |
76 | @media (min-width: 768px) {
77 | .button-74 {
78 | min-width: 120px;
79 | padding: 0 25px;
80 | }
81 | }
--------------------------------------------------------------------------------
/src/Styles/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'lemonpieregular';
3 | src: url('../assets/lemonpie-webfont.woff2') format('woff2'),
4 | url('../assets/lemonpie-webfont.woff') format('woff');
5 | font-weight: normal;
6 | font-style: normal;
7 |
8 | }
9 |
10 | @font-face {
11 | font-family: 'watermelondays';
12 | src: url('../assets/watermelon_days-webfont.woff2') format('woff2'),
13 | url('../assets/watermelon_days-webfont.woff') format('woff');
14 | font-weight: normal;
15 | font-style: normal;
16 |
17 | }
18 |
19 | @font-face {
20 | font-family: 'Retro Computer';
21 | src: url('../assets/RetroComputer.woff2') format('woff2'),
22 | url('../assets/RetroComputer.woff') format('woff');
23 | font-weight: normal;
24 | font-style: normal;
25 | font-display: swap;
26 | }
27 |
28 |
29 | @font-face {
30 | font-family: 'candy_beansregular';
31 | src: url('../assets/candy_beans-webfont.woff2') format('woff2'),
32 | url('../assets/candy_beans-webfont.woff') format('woff');
33 | font-weight: normal;
34 | font-style: normal;
35 |
36 | }
37 |
38 | @font-face {
39 | font-family: 'atime';
40 | src: url('../assets/adventure_time_logo-webfont.woff2') format('woff2'),
41 | url('../assets/adventure_time_logo-webfont.woff') format('woff');
42 | font-weight: normal;
43 | font-style: normal;
44 |
45 | }
46 |
47 | body {
48 | margin: 0;
49 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'lemonpieregular', 'Roboto', 'Oxygen',
50 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'candy_beansregular' , 'Droid Sans', 'Helvetica Neue',
51 | sans-serif;
52 | -webkit-font-smoothing: antialiased;
53 | -moz-osx-font-smoothing: grayscale;
54 |
55 | }
56 |
57 | #root {
58 |
59 | }
60 |
61 |
62 | code {
63 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
64 | monospace;
65 | }
66 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Styles/Stats.css:
--------------------------------------------------------------------------------
1 |
2 | .stats {
3 | display: flex;
4 | flex-direction: row;
5 | align-items: center;
6 | width: 90%;
7 | height: 20%;
8 | cursor: pointer;
9 | gap: 100px;
10 | justify-content: space-evenly;
11 | margin-left: 3px;
12 | margin-top: 5px;
13 | margin-bottom: 5px;
14 | padding: 0 10px 5px;
15 |
16 | border-bottom: 1px DOTTED rgba(0, 0, 0, .5);
17 | position: relative;
18 | }
19 |
20 |
21 | #bigVal {
22 | padding-left: 5px;
23 | white-space: nowrap;
24 | }
25 |
26 | .stats:hover {
27 | border-bottom: 2px DOTTED rgb(255, 255, 255);
28 | }
29 |
30 |
31 | .stats-val {
32 | z-index: 100;
33 | font-weight: bolder;
34 | font-size: 1rem;
35 | font-family: 'candy_beansregular';
36 | letter-spacing: 2px;
37 | -webkit-text-stroke: 1px;
38 | -webkit-text-fill-color: rgb(7, 255, 255);
39 | }
40 |
41 | .bigPlayButtonTrue {
42 | width: 210px;
43 | height: 90px;
44 | padding-top: 2px;
45 | position: absolute;
46 | transition: height .2s linear;
47 | transition: width .1s linear;
48 | filter:drop-shadow(1px 2px 1px black)
49 | drop-shadow(-1px -1px 0 rgb(121,189,154));
50 | }
51 |
52 | .bigPlayButtonFalse {
53 | width: 200px;
54 | height: 70px;
55 | padding-top: 2px;
56 | position: absolute;
57 | transition: height .05s linear;
58 | transition: width .05s linear;
59 | filter:drop-shadow(1px 2px 1px black)
60 | drop-shadow(-1px -1px 0 rgb(121,189,154));
61 | }
62 |
63 | .playButtonHoverFalse {
64 | width: 120px;
65 | height: 70px;
66 | padding-top: 2px;
67 | position: absolute;
68 | transition: heigh width 2s;
69 | filter:drop-shadow(1px 2px 1px black)
70 | drop-shadow(-1px -1px 0 rgb(121,189,154));
71 |
72 | }
73 |
74 | .playButtonHoverTrue {
75 | width: 150px;
76 | height: 90px;
77 | padding-top: 2px;
78 | position: absolute;
79 | transition: height .2s linear;
80 | transition: width .1s linear;
81 | filter:drop-shadow(1px 2px 1px black)
82 | drop-shadow(-1px -1px 0 rgb(121,189,154));
83 |
84 | }
85 |
86 | .playButton {
87 | width: 120px;
88 | height: 70px;
89 | padding-top: 2px;
90 | position: absolute;
91 | transition: heigh width 2s;
92 | filter:drop-shadow(1px 2px 1px black)
93 | drop-shadow(-1px -1px 0 rgb(121,189,154));
94 |
95 | }
96 |
97 | .playButtonLarge {
98 | padding-top: 2px;
99 | position: absolute;
100 | padding-left: 10px;
101 | margin-left: 1px;
102 | filter:drop-shadow(1px 2px 1px black)
103 | drop-shadow(-1px -1px 0 rgb(121,189,154));
104 | }
105 |
106 |
107 | .bmo {
108 | border: 2px solid rgba(0, 0, 0, .3);
109 | border-radius: 2px;
110 | position: absolute;
111 | top: -3px;
112 | filter:drop-shadow(1px 2px 3px rgba(216, 211, 211,.3))
113 | drop-shadow(-1px -1px 0 rgba(228, 228, 228, .3));
114 | }
115 |
116 | #floorprice {
117 | display: flex;
118 | flex-direction: row;
119 | align-items: center;
120 | gap: 2px;
121 | }
122 |
123 | .eth {
124 | color: #1f1d1d;
125 | filter:drop-shadow(1px 1px 3px rgb(167, 170, 7)) ;
126 | }
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { ModuleHandler } from './ModuleHandler';
2 | import './Styles/App.css';
3 | import React, { useEffect } from 'react';
4 | import useState from 'react-usestateref'
5 | import feedBG from './assets/feedbg4.jpg'
6 | import nightBG from './assets/nightmode.jpg'
7 | import Favico from './assets/favicon.png'
8 | import Favicon from "react-favicon";
9 | import { AutoRefreshButton, ETHPrice, ManualRefreshButton, NightModeToggle } from './Menu';
10 |
11 |
12 | export function App() {
13 |
14 | const [nightMode, setNightMode] = useState(true);
15 | const [manuelRefresh, toggleRefresh] = useState();
16 | const [autoRefresh, toggleAutoRefresh] = useState(false);
17 | const [autoRefreshTimer, setRefreshTimer] = useState(0);
18 |
19 | //props for auto-refresh intervals
20 | const IntervalTimerFunc = (num) => {
21 | setRefreshTimer(num)
22 | console.log(num)
23 | console.log(autoRefreshTimer)
24 | }
25 |
26 | //night mode stuff
27 | const nightModeFunc = (e) => {
28 | setNightMode(!nightMode)
29 | }
30 |
31 | const nightModeHandler = () => {
32 | if (nightMode === false) {
33 | return {
34 | backgroundColor: "#cdd7b6"
35 | }
36 | } else {
37 | return {
38 | backgroundColor: "#383B32"
39 | }
40 | }
41 | }
42 |
43 | const nightModeBG = () => {
44 | if (nightMode === true) {
45 | return {
46 | backgroundImage: `url(${nightBG})`
47 | }
48 | } else {
49 | return {
50 | backgroundImage: `url(${feedBG})`
51 | }
52 | }
53 | }
54 | //ETH Price
55 |
56 | const fetchETHPrice = () => {
57 | const options = {method: 'GET'};
58 | fetch("https://api.etherscan.io/api?module=stats&action=ethprice&apikey=NU8841D6JKV8NY9HXD3F9DEVRD9Z6VG5W4", options)
59 | .then(response => response.json())
60 | .then(response => {
61 | let eth = response.result.ethusd;
62 | console.log(eth)
63 | })
64 | }
65 |
66 | //manual refresh stuff
67 | const refreshClick = () => {
68 | toggleRefresh(true)
69 |
70 | }
71 |
72 |
73 |
74 | //props function
75 | const autoRefreshHandle = () => {
76 | toggleAutoRefresh(!autoRefresh)
77 | setRefreshTimer(300000)
78 | }
79 |
80 |
81 |
82 |
83 | useEffect(() => {
84 | document.title = 'NFTPal'
85 | let sessionID = localStorage.getItem('session_id');
86 | console.log(sessionID)
87 | console.log("hey")
88 | if (autoRefresh === true) {
89 | setTimeout(() => {
90 | setRefreshTimer(autoRefreshTimer + 1);
91 | console.log("yo: " + autoRefreshTimer)
92 | }, autoRefreshTimer);
93 | } else {
94 | setRefreshTimer(0)
95 | }
96 | toggleRefresh();
97 | }, [autoRefresh, autoRefreshTimer])
98 |
99 | return (
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | );
117 | }
118 |
119 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/src/assets/opensea.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ethereum.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Menu.js:
--------------------------------------------------------------------------------
1 | import "./Styles/Menu.css";
2 | import React, { useEffect } from "react";
3 | import playButton from './assets/button.png'
4 | import useState from 'react-usestateref'
5 |
6 |
7 | export const NightModeToggle = (props) => {
8 |
9 | const [nightModeStatus, toggleNightMode, nightModeRef] = useState(true);
10 | let propsFunc = props.func;
11 |
12 |
13 | const handleClick = () => {
14 | toggleNightMode(!nightModeStatus);
15 | propsFunc();
16 | }
17 |
18 | const nightModeChecker = () => {
19 | if (nightModeStatus === false) {
20 | return 'OFF'
21 | } else {
22 | return 'ON'
23 | }
24 | }
25 |
26 |
27 | return (
28 | <>
29 |
34 |
35 | Night mode: {nightModeChecker()}
36 |
37 | >
38 | )
39 | }
40 |
41 | export const ManualRefreshButton = (props) => {
42 | const [refreshStatus, toggleRefreshAnimation] = useState('Refresh All')
43 |
44 |
45 | const refreshAnimation = () => {
46 | setTimeout(() => {
47 | toggleRefreshAnimation('Refreshing')
48 | setTimeout(() => {
49 | toggleRefreshAnimation('Refreshing.')
50 | setTimeout(() => {
51 | toggleRefreshAnimation('Refreshing..')
52 | setTimeout(() => {
53 | toggleRefreshAnimation('Refreshing...')
54 | setTimeout(() => {
55 | toggleRefreshAnimation('Refresh All')
56 | }, 350);
57 | }, 400);
58 | }, 400);
59 | }, 400);
60 | }, 5);
61 | }
62 |
63 | return (
64 | <>
65 |
66 | {
67 | refreshAnimation();
68 | props.refresh();
69 | }} className="buttonLabelDiv2" style={{
70 | backgroundImage: `url(${playButton})`,
71 | backgroundSize: 'cover'
72 | }}
73 | >
74 | {refreshStatus}
75 |
76 | >
77 | )
78 | }
79 |
80 | export const AutoRefreshButton = (props) => {
81 | const [refreshStatus, toggleRefreshStatus] = useState(false);
82 | const [clickedTimer, setTimer] = useState(300000)
83 | const [defaultChecked, setDefaultChecked, defaultCheckRef] = useState(false)
84 |
85 |
86 | const clickedChecker = () => {
87 | if (defaultChecked === false) {
88 | return false;
89 | } else {
90 | return true;
91 | }
92 | }
93 | //style handling
94 | const autoRefreshStatusSpan = () => {
95 | if (refreshStatus === true) {
96 | return 'ON'
97 | } else {
98 | return 'OFF'
99 | }
100 | }
101 | //gets the input value for the timer
102 | const handleChange = (e) => {
103 | let inputTimer = e.target.value;
104 | console.log(e.target.value);
105 | setTimer(inputTimer);
106 | props.intervalFunc(clickedTimer)
107 | }
108 |
109 | useEffect(() => {
110 |
111 | }, [])
112 |
113 |
114 |
115 | return (
116 | <>
117 |
125 | {
126 | toggleRefreshStatus(!refreshStatus)
127 | setDefaultChecked(!defaultChecked)
128 | props.func();
129 | }} className="buttonLabelDiv3" style={{
130 | backgroundImage: `url(${playButton})`,
131 | backgroundSize: 'cover'
132 | }}
133 | >
134 | Auto-Refresh: {autoRefreshStatusSpan()}
135 |
136 | >
137 | )
138 | }
139 |
140 |
141 | export function ETHPrice(props) {
142 | //usestate for eth price
143 | const [ethPrice, setETHPrice] = useState();
144 | const [spanText, setSpanText] = useState("")
145 |
146 |
147 |
148 | const fetchETHPrice = () => {
149 | const options = {method: 'GET'};
150 | setTimeout(() => {
151 | setETHPrice("")
152 | setSpanText("Updating")
153 | setTimeout(() => {
154 | setSpanText("Updating.")
155 | setTimeout(() => {
156 | setSpanText("Updating..")
157 | setTimeout(() => {
158 | setSpanText("ETH:$ ")
159 | fetch("https://api.coinbase.com/v2/prices/ETH-USD/spot", options)
160 | .then(response => response.json())
161 | .then(response => {
162 | let eth = response.data.amount;
163 | console.log(response)
164 | setETHPrice(eth);
165 | })
166 | }, 777);
167 | }, 555);
168 | }, 555);
169 | }, 100);
170 | }
171 |
172 | useEffect(() => {
173 | fetchETHPrice();
174 | }, [])
175 |
176 |
177 | return (
178 | <>
179 | {fetchETHPrice()}}
184 | >
185 | {spanText}{ethPrice}
186 |
187 | >
188 | )
189 | }
--------------------------------------------------------------------------------
/src/Stats.js:
--------------------------------------------------------------------------------
1 | import {React, useEffect, useState} from 'react';
2 | import playButton from './assets/button.png'
3 | import './Styles/ModuleHandler.css'
4 | import bmo from './assets/bmo.png'
5 | import { Icon } from '@iconify/react';
6 |
7 |
8 |
9 | //Each "stat module" is a div/container in the module
10 | export function SalesModule(props) {
11 | const [statInfoStyle, setStatInfoStyle] = useState("playButtonHoverFalse")
12 | let sales = props.sales;
13 |
14 |
15 | return (
16 | setStatInfoStyle("playButtonHoverTrue")}
17 | onMouseLeave={() => setStatInfoStyle("playButtonHoverFalse")}
18 | className="stats">
19 |
20 |
22 |
Sales:
23 |
24 |
25 |
26 |
{sales}
27 |
28 |
29 | )
30 | }
31 |
32 | export function SupplyModule(props) {
33 | const [statInfoStyle, setStatInfoStyle] = useState("playButtonHoverFalse")
34 | let supply = props.supply;
35 |
36 |
37 | return (
38 | setStatInfoStyle("playButtonHoverTrue")}
39 | onMouseLeave={() => setStatInfoStyle("playButtonHoverFalse")}
40 | className="stats">
41 |
42 |
43 |
Supply:
44 |
45 |
46 |
47 |
{supply}
48 |
49 |
50 | )
51 | }
52 |
53 | export function VolumeModule(props) {
54 | const [statInfoStyle, setStatInfoStyle] = useState("bigPlayButtonFalse")
55 | let volume = props.volume;
56 |
57 |
58 | return (
59 | setStatInfoStyle("bigPlayButtonTrue")}
60 | onMouseLeave={() => setStatInfoStyle("bigPlayButtonFalse")}
61 | className="stats">
62 |
63 |
65 |
Total Volume:
66 |
67 |
68 |
69 |
{volume}
70 |
71 |
72 | )
73 | }
74 |
75 | export function HoldersModule(props) {
76 | const [statInfoStyle, setStatInfoStyle] = useState("bigPlayButtonFalse")
77 | let holders = props.holders;
78 |
79 |
80 | return (
81 | setStatInfoStyle("bigPlayButtonTrue")}
82 | onMouseLeave={() => setStatInfoStyle("bigPlayButtonFalse")}
83 | className="stats">
84 |
85 |
87 |
# of Holders:
88 |
89 |
90 |
91 |
{holders}
92 |
93 |
94 | )
95 | }
96 |
97 |
98 | export function HolderRatioModule(props) {
99 | const [statInfoStyle, setStatInfoStyle] = useState("bigPlayButtonFalse")
100 | let holderRatio = props.holderRatio;
101 |
102 |
103 | return (
104 | setStatInfoStyle("bigPlayButtonTrue")}
105 | onMouseLeave={() => setStatInfoStyle("bigPlayButtonFalse")}
106 | className="stats">
107 |
108 |
110 |
Holder Ratio:
111 |
112 |
113 |
114 |
{holderRatio}
115 |
116 |
117 | )
118 | }
119 |
120 |
121 | export function FeeModule(props) {
122 | const [statInfoStyle, setStatInfoStyle] = useState("bigPlayButtonFalse")
123 | let royaltyFee = props.royaltyFee;
124 |
125 |
126 | return (
127 | setStatInfoStyle("bigPlayButtonTrue")}
128 | onMouseLeave={() => setStatInfoStyle("bigPlayButtonFalse")} className="stats">
129 |
130 |
133 |
Royalty Fee:
134 |
135 |
136 |
137 |
{royaltyFee}
138 |
139 |
140 | )
141 | }
142 |
143 |
144 | export function FloorPriceModule(props) {
145 | const [statInfoStyle, setStatInfoStyle] = useState("bigPlayButtonFalse")
146 | let floorPrice = props.floorPrice;
147 |
148 |
149 | return (
150 | setStatInfoStyle("bigPlayButtonTrue")}
151 | onMouseLeave={() => setStatInfoStyle("bigPlayButtonFalse")}
152 | className="stats">
153 |
154 |
155 |
Floor Price:
156 |
157 |
158 |
159 |
{floorPrice}
160 |
161 |
162 | )
163 | }
--------------------------------------------------------------------------------
/src/Styles/App.css:
--------------------------------------------------------------------------------
1 | .feed {
2 | width: 66.7%;
3 | height: fit-content;
4 | display: flex;
5 | border: 5px solid rgba(0, 0, 0, 1);
6 | padding: 20px 5px 5px;
7 | margin-top: 50px;
8 | padding-bottom: 15px;
9 | flex-direction: column;
10 | flex-wrap: wrap;
11 | background-size: cover;
12 | justify-content: center;
13 | box-shadow: 0px 8px 32px 8px rgba(0,0,0,0.35);
14 | border-radius: 15px;
15 | margin-bottom: 10px;
16 | overflow: hidden;
17 | align-items: center;
18 | align-self: center;
19 | z-index: 2;
20 | }
21 |
22 | .nbuttonContainer {
23 | display: flex;
24 | position: relative;
25 | top: 14%;
26 | left: -1%;
27 | padding-left: 0;
28 | margin-left: 0;
29 |
30 |
31 | }
32 |
33 | @media only screen and (min-width: 1280px) {
34 | .feed {
35 | width: 80%;
36 | }
37 | }
38 |
39 |
40 | .body {
41 | display: flex;
42 | min-width: 100%;
43 | min-height: 100%;
44 | padding-top: 350px;
45 | position: absolute;
46 | top: 0;
47 | z-index: 0;
48 |
49 | flex-direction: column;
50 | align-items: center;
51 | justify-content: center;
52 | }
53 |
54 | .switch {
55 | width: 75%;
56 | height: 200px;
57 | z-index: -1;
58 | position: absolute;
59 | top: 15.5%;
60 | caret-color: transparent!important;
61 |
62 | }
63 |
64 | .buttonLabelDiv2 {
65 | position: absolute;
66 | cursor: pointer;
67 | height: 120px;
68 | width: 200px;
69 | overflow: visible;
70 | padding: 0;
71 | top: -30px;
72 | left: 16%;
73 | filter:drop-shadow(1px 2px 5px black);
74 | }
75 |
76 | .buttonLabelDiv2 span {
77 | z-index: 7;
78 | user-select: none;
79 | position: relative;
80 | left: 32.5%;
81 | top: 40%;
82 | letter-spacing: 1px;
83 | font-size: 1.35em;
84 | font-family: 'watermelondays'
85 | }
86 |
87 | .buttonLabelDiv:hover span {
88 | -webkit-text-fill-color: rgb(0, 0, 0); /* Will override color (regardless of order) */
89 | -webkit-text-stroke-width: 0.5px;
90 | -webkit-text-stroke-color: rgba(255, 248, 248, .5);
91 | }
92 |
93 | .buttonLabelDiv:active {
94 | filter:drop-shadow(1px 2px 5px rgb(150, 148, 148));
95 | }
96 |
97 | .buttonLabelDiv2:hover span {
98 | -webkit-text-fill-color: rgb(0, 0, 0); /* Will override color (regardless of order) */
99 | -webkit-text-stroke-width: 0.5px;
100 | -webkit-text-stroke-color: rgba(255, 248, 248, .5);
101 | }
102 |
103 | .buttonLabelDiv2:active {
104 | filter:drop-shadow(1px 2px 5px rgb(150, 148, 148));
105 | }
106 |
107 | .buttonLabelDiv3 {
108 | position: absolute;
109 | cursor: pointer;
110 | height: 120px;
111 | width: 200px;
112 | overflow: visible;
113 | padding: 0;
114 | top: -30px;
115 | left: 6.5%;
116 | z-index: 10;
117 | filter:drop-shadow(1px 2px 5px black);
118 | }
119 |
120 | .buttonLabelDiv3 span {
121 | z-index: 7;
122 | user-select: none;
123 | position: relative;
124 | left: 26.5%;
125 | top: 40%;
126 | font-size: 1.3em;
127 | font-family: 'watermelondays'
128 | }
129 |
130 | .buttonLabelDiv3:hover span {
131 | -webkit-text-fill-color: rgb(0, 0, 0); /* Will override color (regardless of order) */
132 | -webkit-text-stroke-width: 0.5px;
133 | -webkit-text-stroke-color: rgba(255, 248, 248, .5);
134 | }
135 |
136 | .buttonLabelDiv3:active {
137 | filter:drop-shadow(1px 2px 5px rgb(150, 148, 148));
138 | }
139 |
140 | div.autorefreshoptions {
141 | position: relative;
142 | cursor: pointer;
143 | top: -40px;
144 | left: 9.3%;
145 | display: flex;
146 | flex-direction: row;
147 | border: 3px solid black;
148 | border-radius: 15px;
149 | width: 105px;
150 | justify-content: space-evenly;
151 | overflow: hidden;
152 | padding: 0px 5px;
153 | background-color: #d7d4ce;
154 | height: 35px;
155 | filter:drop-shadow(1px 2px 5px black);
156 | z-index: 99;
157 | }
158 |
159 | div.autorefreshoptions:hover {
160 | filter:drop-shadow(1px 1px 5px rgb(255, 208, 0))
161 | }
162 |
163 | .autorefreshoptions div {
164 | border: 1px solid black;
165 | cursor: pointer;
166 | z-index: 10;
167 | cursor: pointer;
168 | }
169 |
170 | .autorefreshoptions label {
171 | cursor: pointer;
172 | }
173 |
174 |
175 | .autorefreshoptions span {
176 | font-family: 'watermelondays';
177 | font-size: 1.3rem;
178 | }
179 |
180 | div.auto1 {
181 | display: flex;
182 | }
183 |
184 | div.auto2 {
185 | display: flex;
186 | }
187 |
188 |
189 | div.auto3 {
190 | display: flex;
191 | }
192 |
193 | input#demo {
194 | display: none;
195 | }
196 |
197 | input#demo2 {
198 | display: none;
199 | }
200 |
201 |
202 | input#demo3 {
203 | display: none;
204 | }
205 |
206 | #demo:checked ~ label {
207 | background-color: rgba(191,77,40,.9);
208 | border: 2px solid rgba(191,77,40,.9);
209 | }
210 |
211 | #demo2:checked + label {
212 | background-color: rgba(191,77,40,.9);
213 | border: 2px solid rgba(191,77,40,.9);
214 | }
215 |
216 | #demo3:checked + label {
217 | background-color: rgba(191,77,40,.9);
218 | border: 2px solid rgba(191,77,40,.9);
219 | }
220 |
221 | .auto1 span {
222 | white-space: nowrap;
223 | }
224 |
225 |
226 | .auto2 span {
227 | white-space: nowrap;
228 | }
229 |
230 |
231 |
232 | .auto3 span {
233 | white-space: nowrap;
234 | }
235 |
236 | label.a1label {
237 | border: 1px solid rgb(255, 255, 255);
238 | z-index: 88888;
239 | position: relative;
240 | bottom: 0;
241 | width: 100%;
242 | white-space: nowrap;
243 | padding: 8px;
244 | }
245 |
246 | label.a2label {
247 | border: 1px solid rgb(255, 255, 255);
248 | z-index: 88888;
249 | position: relative;
250 | bottom: 0;
251 | width: 100%;
252 | white-space: nowrap;
253 | padding: 8px;
254 | }
255 |
256 | label.a3label {
257 | border: 1px solid rgb(255, 255, 255);
258 | z-index: 88888;
259 | position: relative;
260 | bottom: 0;
261 | width: 100%;
262 | white-space: nowrap;
263 | padding: 8px 6px 8px;
264 | }
265 |
266 | .buttonLabelDiv4 {
267 | position: absolute;
268 | cursor: pointer!important;
269 | height: 120px;
270 | width: 200px;
271 | overflow: visible;
272 | padding: 0;
273 | top: -30px;
274 | right: 6.5%;
275 | z-index: 10;
276 | filter:drop-shadow(1px 2px 5px black);
277 | }
278 |
279 | .buttonLabelDiv4 span {
280 | z-index: 7;
281 | cursor: pointer!important;
282 | user-select: none;
283 | position: relative;
284 | left: 30.5%;
285 | top: 37.5%;
286 | font-size: 1.5rem;
287 | font-family: 'watermelondays'
288 | }
289 |
290 | .buttonLabelDiv4 strong {
291 |
292 | position: relative;
293 | right: 4px;
294 | z-index: 9999;
295 | font-size: 1.55rem;
296 | font-weight: normal;
297 | color: rgb(122,179,23);
298 | text-shadow:
299 | 0.08em 0 #000000,
300 | 0 0.1em #000000,
301 | -0.07em 0 #000000,
302 | 0 -0.07em #000000;
303 | filter:drop-shadow(1px 1px 2px rgb(0, 0, 0));
304 | }
305 |
306 | .buttonLabelDiv4 strong:hover {
307 | font-size: 1.6rem;
308 | transition: all 0.1s linear;
309 | }
--------------------------------------------------------------------------------
/src/assets/Sword.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/BackupModuleHandler.js:
--------------------------------------------------------------------------------
1 | import React, {useEffect, useState} from 'react';
2 | import './Styles/ModuleHandler.css'
3 | import scrollbg from './assets/vector.png'
4 | import sword from './assets/finnsword.png'
5 | import sword2 from './assets/finnsword2.png'
6 | import delButton from './assets/deletebutton.jpg'
7 | import delButton2 from './assets/close.png'
8 | import lightBulb2 from './assets/lightbulb2.png'
9 | import exampleSlug from './assets/example.png'
10 | import refButton from './assets/refresh.png'
11 | import questionMark from './assets/question-mark.png'
12 | import loadingScreen from './assets/cool.gif'
13 | import osicon from './assets/opensea.svg'
14 | import esicon from './assets/etherscan.svg'
15 | import nerdicon from './assets/nftnerd.svg'
16 | import playButton from './assets/button.png'
17 | import { SupplyModule, SalesModule, VolumeModule, HoldersModule, HolderRatioModule, FeeModule, FloorPriceModule } from './Stats';
18 |
19 |
20 |
21 | //this component handles the modules and their orientation within the feed.
22 | //Essentially this component is the main parent of all the modules.
23 | export function ModuleHandler ({...props}) {
24 | //usestate props that will be toggled whenever these props are passed in. Refresh/Nightmode. If props aren't passed in, then
25 | //they won't trigger anything.
26 | const [manualRefresher, toggleRefresh] = useState(props.refresh);
27 | let nightMode = props.nightMode;
28 |
29 | useEffect(() => {
30 | //handles persist
31 | const sessionSlug = localStorage.getItem("slug")
32 | //Refreshes all modules
33 | if (props.autoRefresh !== 0) {
34 | toggleRefresh(true)
35 | }
36 | toggleRefresh()
37 | if (sessionSlug) {
38 | console.log(sessionSlug)
39 | }
40 | }, [props.refresh, props.autoRefresh])
41 |
42 | return (
43 | <>
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | >
55 | )
56 | }
57 |
58 |
59 | //this Module handles the process between the search and the intialization (passing the slug over)
60 | function Module (props) {
61 | const [init, setInit] = useState(false);
62 | const [slug, setSlug] = useState('');
63 | const [defaultModule, setDefault] = useState(props.default)
64 | const [savedSession, toggleSaved] = useState();
65 | let defaultModule2 = props.default2;
66 | let defaultModule3 = props.default3;
67 |
68 |
69 | let nightMode = props.nightMode;
70 |
71 |
72 | const initHandler = (e) => {
73 | setSlug(e);
74 | setInit(true)
75 | }
76 |
77 | const delHandler = (e) => {
78 | setSlug('')
79 | setDefault()
80 | setInit(false)
81 | }
82 |
83 | const savedChecker = (data) => {
84 | toggleSaved(true)
85 | setSlug(data)
86 | }
87 |
88 | useEffect(() => {
89 | if (savedSession) {
90 | setInit(true)
91 | }
92 | if (defaultModule === true || defaultModule2 === true || defaultModule3 === true) {
93 | setInit(true)
94 | }
95 |
96 | }, [savedSession])
97 |
98 | if (init === false) {
99 | return (
100 | <>
101 |
102 | >
103 | )
104 | } else {
105 | return (
106 | <>
107 |
108 | >
109 | )
110 | }
111 | }
112 |
113 |
114 |
115 | //this component handles the loading screen animation in between the search module and the initialized module.
116 | //the loading screen is purely for entertainment, stylistic purposes since it makes the module look more robust.
117 | function LoadingScreenComp (props) {
118 | // animation/style handling here for the loading screen
119 | const [animationClass, setClass] = useState("loadingScreen1")
120 | const [loading, setLoading] = useState(true);
121 | //default Modules - these are only here to be passed into ModuleInit
122 | let defaultModule = props.default;
123 | let defaultModule2 = props.default2;
124 | let defaultModule3 = props.default3;
125 | let slug = props.slug;
126 | let delHandler = props.func;
127 | let nightMode = props.nightMode;
128 | let saved = props.saved;
129 |
130 |
131 | //set the slug for default modules here
132 | if (defaultModule === true) {
133 | slug = "proof-moonbirds"
134 | }
135 |
136 | if (defaultModule2 === true) {
137 | slug = "boredapeyachtclub"
138 | }
139 |
140 | if (defaultModule3 === true) {
141 | slug = "azuki"
142 | }
143 |
144 |
145 |
146 | //nightMode style handler
147 | const nightModeHandler = () => {
148 | if (nightMode === true) {
149 | return {
150 | backgroundColor: '#6B8074'
151 | }
152 | } else {
153 | return {
154 | backgroundColor: '#A8DBA8'
155 | }
156 | }
157 | }
158 |
159 |
160 | useEffect(() => {
161 | if (props.refresh || props.autoRefresh !== 0) {
162 | console.log("hey")
163 | setLoading(true)
164 | }
165 |
166 | setTimeout(() => {
167 | setClass("loadingScreen2")
168 | setTimeout(() => {
169 | setClass("loadingScreen3")
170 | setTimeout(() => {
171 | setClass("loadingScreen2")
172 | setTimeout(() => {
173 | setClass("loadingScreen3")
174 | setTimeout(() => {
175 | setLoading(false)
176 | }, 100);
177 | }, 200);
178 | }, 200);
179 | }, 300);
180 | }, 50);
181 | }, [props.refresh, props.autoRefresh])
182 |
183 |
184 | // this clause will always run first before the ModuleInit is rendered because the useState of loading is set to true by default
185 | // -> Because this runs first, the useEffect will be activated afterwards to set Loading to false thus returning ModuleInit next.
186 |
187 | if (loading === true) {
188 | return (
189 |
190 |
191 |
192 |
193 |
194 | )
195 | } else {
196 | return (
197 | <>
198 |
199 | >
200 | )
201 | }
202 | }
203 |
204 |
205 |
206 |
207 |
208 | //This is the search component of the module. Basically this is the pre-initialized state.
209 | function ModuleSearch (props) {
210 | const [slugInput, slugInputter] = useState('');
211 | const [swordAnimation, setSwordAnimation] = useState(0);
212 | const [swordAnimation2, setSwordAnimation2] = useState(0);
213 | const [slugHelpStatus, toggleHelp] = useState(false);
214 |
215 |
216 | let nightMode = props.nightMode;
217 |
218 | const handleChange = (e) => {
219 | slugInputter(e.target.value)
220 | }
221 |
222 | //nightMode style handler
223 | const nightModeHandler = () => {
224 | if (nightMode === true) {
225 | return {
226 | backgroundColor: '#6B8074'
227 | }
228 | } else {
229 | return {
230 | backgroundColor: '#A8DBA8'
231 | }
232 | }
233 | }
234 |
235 |
236 | //Helper Div Stuff
237 | const slugHelperClick = () => {
238 | toggleHelp(true)
239 | }
240 |
241 | const delslugHelperClicker = () => {
242 | toggleHelp(false)
243 | }
244 |
245 | const slugHelper = () => {
246 | if (slugHelpStatus === true) {
247 | return (
248 |
249 |
250 |
251 |
What is a slug?
252 |
The slug of an NFT project can be found at the end of their opensea collection's URL.
253 |
{"For example, in the image above, the slug for Moonbirds is: "} 'proof-moonbirds' {"(with the dash)"}
254 |
{delslugHelperClicker()}} src={delButton2} className="delButton3" alt="" height="18px" width="18px" />
255 |
256 |
257 | )
258 | }
259 | }
260 |
261 | //style functions
262 | const rotateonClick = () => {
263 | let rotation = swordAnimation + 90;
264 | setSwordAnimation(rotation)
265 | }
266 | const rotateonClick2 = () => {
267 | let rotation = swordAnimation2 + 90;
268 | setSwordAnimation2(rotation)
269 | }
270 |
271 | const lightBulbStyleHandling = () => {
272 | if (slugHelpStatus === true) {
273 | return {
274 | bottom: "55px",
275 | opacity: '0',
276 | position: 'absolute'
277 | }
278 | }
279 | }
280 |
281 | const HelperDivStyling = () => {
282 | if (slugHelpStatus === true) {
283 | return {
284 | opacity: '0.8',
285 | transition: 'opacity 1s linear'
286 | }
287 | }
288 | }
289 |
290 |
291 | return (
292 |
293 |
294 |
298 |
299 |
300 | {slugHelper()}
301 |
302 |
{slugHelperClick()}}src={lightBulb2} alt="" height="50px" width="50px" />
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
SUBMIT
314 |
315 |
316 | {props.func(slugInput)}} className="searchSubmit" type="submit" value=" " />
317 |
318 |
319 |
320 |
321 |
325 |
326 |
327 | )
328 | }
329 |
330 |
331 |
332 | //This is the intialized component of the module.
333 | export function ModuleInit (props) {
334 | //info variables
335 | const [slug, setSlug] = useState(props.slug)
336 | const [name, setName] = useState();
337 | const [collectionImage, setImage] = useState();
338 | //stats
339 | const [sales, setSales] = useState();
340 | const [floorPrice, setFloorPrice] = useState();
341 | const [supply, setSupply] = useState();
342 | const [volume, setVol] = useState();
343 | const [holders, setHolders] = useState();
344 | const [holderRatio, setRatio] = useState();
345 | const [royaltyFee, setFee] = useState();
346 | //links/control variables
347 | const [opensea, setOS] = useState();
348 | const [nftnerd, setNerd] = useState();
349 | const [etherscan, setES] = useState();
350 | const [refreshHelp, toggleRefHelp] = useState(false);
351 | const [savePrompt, setSavePrompt] = useState();
352 | //style
353 | const [cnamelength, setcname] = useState('cname');
354 | //important usestate here: basically will check if this module has been initialized
355 | const [init, toggleInit] = useState(false);
356 |
357 |
358 | //props and etc
359 | let nightMode = props.nightMode;
360 | let url = `https://api.opensea.io/api/v1/collection/${slug}`
361 | let delHandler = props.func;
362 |
363 | const nightModeHandler = () => {
364 | if (nightMode === true) {
365 | return {
366 | backgroundColor: '#6B8074'
367 | }
368 | } else {
369 | return {
370 | backgroundColor: '#A8DBA8'
371 | }
372 | }
373 | }
374 |
375 | //Manual Refresh Function
376 |
377 | const refHandler = () => {
378 | fetchCollection(url)
379 | }
380 |
381 | //Helper Div Stuff
382 | const refHelpClick = () => {
383 | toggleRefHelp(true)
384 | }
385 |
386 | const delRefHelp = () => {
387 | toggleRefHelp(false)
388 | }
389 |
390 | const refreshDiv = () => {
391 | if (refreshHelp === true) {
392 | return (
393 |
394 |
{delRefHelp()}} id="rhelpdelbutton" className="delButton2" src={delButton2} height="18px" width="18px" alt="delete button 2" />
395 |
If nothing changes after refreshing, it usually just means that there's nothing to update or refresh regarding the stats of the collection. Try again later when you think thing's might've changed!
396 |
397 | )
398 | }
399 | }
400 |
401 |
402 |
403 | //save stuff
404 |
405 | const handleSaver = () => {
406 | localStorage.setItem("slug", slug)
407 | setSavePrompt();
408 | }
409 | const SavePrompt = (
410 |
411 | Save ?
412 |
413 | )
414 |
415 |
416 |
417 | const handleSaveClick = () => {
418 | setTimeout(() => {
419 | setSavePrompt(true)
420 | }, 1000);
421 | }
422 |
423 |
424 |
425 | //main function to fetch the data from the Opensea API, then sets the useState variables accordingly.
426 | const fetchCollection = (collectionUrl) => {
427 | const options = {method: 'GET'};
428 | fetch(collectionUrl, options)
429 | .then(response => response.json())
430 | .then(response => {
431 | let stats = response.collection.stats;
432 | let contract = response.collection.primary_asset_contracts[0].address;
433 | let floorPrice = stats.floor_price;
434 | let collectionName = response.collection.primary_asset_contracts[0].name;
435 |
436 | const fee = () => {
437 | const jsonFee = response.collection.primary_asset_contracts[0].seller_fee_basis_points / 100
438 | const percentageFee = jsonFee.toString() + "%"
439 | return percentageFee;
440 | }
441 |
442 | const floorPriceParser = (floorPrice) => {
443 | if (floorPrice < 1) {
444 | return Number.parseFloat(floorPrice).toFixed(3)
445 | } else {
446 | return Number.parseFloat(floorPrice).toFixed(2)
447 | }
448 | }
449 |
450 | setFloorPrice(floorPriceParser(floorPrice))
451 | setName(response.collection.primary_asset_contracts[0].name)
452 | setImage(response.collection.image_url)
453 | setSales(stats.total_sales)
454 | setSupply(stats.total_supply)
455 | setVol(Math.round(stats.total_volume))
456 | setHolders(stats.num_owners)
457 | setRatio((stats.total_supply/stats.num_owners).toFixed(2))
458 | setFee(fee())
459 | setOS(`https://opensea.io/collection/${slug}`)
460 | setNerd(`https://nftnerds.ai/collection/${contract}/liveview`)
461 | setES(`https://etherscan.io/address/${contract}`)
462 | if (collectionName.length > 18) {
463 | setcname('cname2')
464 | } else if (collectionName.length > 12) {
465 | setcname('cname1')
466 | }
467 |
468 | })
469 |
470 | }
471 |
472 | const ModuleImg = (
473 |
474 | )
475 |
476 |
477 | useEffect(() => {
478 | const session = localStorage.getItem("slug")
479 | if (session) {
480 | props.saved(slug)
481 | }
482 | fetchCollection(url);
483 | }, [SavePrompt])
484 |
485 |
486 | return (
487 |
488 |
489 |
490 |
{delHandler()}} src={delButton} height="40px" width="40px" />
491 |
492 |
493 |
{refHandler()}} src={refButton} height="40px" width="40px" />
494 |
495 |
496 |
{refHelpClick()}}alt="questionMark" src={questionMark} className="question-mark" height="16px" width="16px" />
497 |
498 | {refreshDiv()}
499 | {!savePrompt && ModuleImg}
500 | {savePrompt && SavePrompt}
501 |
502 |
503 |
504 |
505 |
506 |
{name}
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
523 |
524 |
525 | )
526 | }
527 |
--------------------------------------------------------------------------------
/src/ModuleHandler.js:
--------------------------------------------------------------------------------
1 | import React, {useEffect, useState} from 'react';
2 | import './Styles/ModuleHandler.css'
3 | import scrollbg from './assets/vector.png'
4 | import sword from './assets/finnsword.png'
5 | import sword2 from './assets/finnsword2.png'
6 | import delButton from './assets/deletebutton.jpg'
7 | import delButton2 from './assets/close.png'
8 | import lightBulb2 from './assets/lightbulb2.png'
9 | import exampleSlug from './assets/example.png'
10 | import refButton from './assets/refresh.png'
11 | import questionMark from './assets/question-mark.png'
12 | import loadingScreen from './assets/cool.gif'
13 | import osicon from './assets/opensea.svg'
14 | import esicon from './assets/etherscan.svg'
15 | import nerdicon from './assets/nftnerd.svg'
16 | import playButton from './assets/button.png'
17 | import { SupplyModule, SalesModule, VolumeModule, HoldersModule, HolderRatioModule, FeeModule, FloorPriceModule } from './Stats';
18 |
19 |
20 |
21 | //this component handles the modules and their orientation within the feed.
22 | //Essentially this component is the main parent of all the modules.
23 | export function ModuleHandler ({...props}) {
24 | //usestate props that will be toggled whenever these props are passed in. Refresh/Nightmode. If props aren't passed in, then
25 | //they won't trigger anything.
26 | const [manualRefresher, toggleRefresh] = useState(props.refresh);
27 | let nightMode = props.nightMode;
28 |
29 |
30 | //we can make an object here that will store all the saved slugs/session
31 | //this object will store the key (the order of the module) and their saved slug
32 | let savedSlugs = {}
33 |
34 |
35 | //function here will be passed down as a prop.
36 | //this function will help save the key value pair into savedSlugs object IF saved
37 | const saveSession = (data) => {
38 | let toSave = data;
39 | savedSlugs[data[0]] = data[1];
40 | localStorage.setItem("savedSlugs", JSON.stringify(savedSlugs));
41 | }
42 |
43 | const savePersist = (data) => {
44 | let toSave = data;
45 | savedSlugs[data[0]] = data[1];
46 | localStorage.setItem("savedSlugs", JSON.stringify(savedSlugs));
47 | }
48 |
49 | const delPersist = (data) => {
50 | delete savedSlugs[data[0]];
51 | localStorage.setItem("savedSlugs", JSON.stringify(savedSlugs));
52 | }
53 |
54 | useEffect(() => {
55 | //Refreshes all modules
56 | if (props.autoRefresh !== 0) {
57 | toggleRefresh(true)
58 | }
59 | toggleRefresh()
60 |
61 | //checks if saved sessions exist
62 |
63 | }, [props.refresh, props.autoRefresh])
64 |
65 |
66 | if (localStorage.getItem("savedSlugs")) {
67 | console.log(JSON.parse(localStorage.getItem("savedSlugs")))
68 | savedSlugs = JSON.parse(localStorage.getItem("savedSlugs"))
69 | }
70 |
71 | return (
72 | <>
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | >
84 | )
85 | }
86 |
87 |
88 | //THIS DETERMINES WHETHER THE MODULE IS INIT OR NOT
89 | function Module (props) {
90 | const [init, setInit] = useState(false);
91 | const [slug, setSlug] = useState('');
92 | const [slugStore, setSlugStore] = useState(props.slugStore)
93 | let nightMode = props.nightMode;
94 | let key = props.mKey;
95 | let savedSlug = [key, slug]
96 |
97 | const initHandler = (e) => {
98 | setSlug(e);
99 | setInit(true)
100 | }
101 |
102 | const delHandler = (e) => {
103 | props.delPersist(savedSlug)
104 | setSlug('')
105 | setInit(false)
106 | }
107 |
108 |
109 |
110 |
111 |
112 | useEffect(() => {
113 | if (props.slug) {
114 | setSlug(props.slug)
115 | setInit(true)
116 | }
117 |
118 | }, [])
119 |
120 | useEffect(() => {
121 | if (key in slugStore) {
122 | setSlug(slugStore[key])
123 | setInit(true)
124 | }
125 | }, [])
126 |
127 |
128 | if (init === false) {
129 | return (
130 | <>
131 |
132 | >
133 | )
134 | } else {
135 | return (
136 | <>
137 |
138 | >
139 | )
140 | }
141 | }
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | //This is the search component of the module. Basically this is the pre-initialized state.
152 | function ModuleSearch (props) {
153 | const [slugInput, slugInputter] = useState('');
154 | const [swordAnimation, setSwordAnimation] = useState(0);
155 | const [swordAnimation2, setSwordAnimation2] = useState(0);
156 | const [slugHelpStatus, toggleHelp] = useState(false);
157 | let key = props.mKey;
158 | let savedSlug = [key, slugInput];
159 |
160 |
161 | let nightMode = props.nightMode;
162 |
163 | const handleChange = (e) => {
164 | slugInputter(e.target.value)
165 | }
166 |
167 | //nightMode style handler
168 | const nightModeHandler = () => {
169 | if (nightMode === true) {
170 | return {
171 | backgroundColor: '#6B8074'
172 | }
173 | } else {
174 | return {
175 | backgroundColor: '#A8DBA8'
176 | }
177 | }
178 | }
179 |
180 |
181 | //Helper Div Stuff
182 | const slugHelperClick = () => {
183 | toggleHelp(true)
184 | }
185 |
186 | const delslugHelperClicker = () => {
187 | toggleHelp(false)
188 | }
189 |
190 | const slugHelper = () => {
191 | if (slugHelpStatus === true) {
192 | return (
193 |
194 |
195 |
196 |
What is a slug?
197 |
The slug of an NFT project can be found at the end of their opensea collection's URL.
198 |
{"For example, in the image above, the slug for Moonbirds is: "} 'proof-moonbirds' {"(with the dash)"}
199 |
{delslugHelperClicker()}} src={delButton2} className="delButton3" alt="" height="18px" width="18px" />
200 |
201 |
202 | )
203 | }
204 | }
205 |
206 | //style functions
207 | const rotateonClick = () => {
208 | let rotation = swordAnimation + 90;
209 | setSwordAnimation(rotation)
210 | }
211 | const rotateonClick2 = () => {
212 | let rotation = swordAnimation2 + 90;
213 | setSwordAnimation2(rotation)
214 | }
215 |
216 | const lightBulbStyleHandling = () => {
217 | if (slugHelpStatus === true) {
218 | return {
219 | bottom: "55px",
220 | opacity: '0',
221 | position: 'absolute'
222 | }
223 | }
224 | }
225 |
226 | const HelperDivStyling = () => {
227 | if (slugHelpStatus === true) {
228 | return {
229 | opacity: '0.8',
230 | transition: 'opacity 1s linear'
231 | }
232 | }
233 | }
234 |
235 |
236 | return (
237 |
238 |
239 |
243 |
244 |
245 | {slugHelper()}
246 |
247 |
{slugHelperClick()}}src={lightBulb2} alt="" height="50px" width="50px" />
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
SUBMIT
259 |
260 |
261 | {props.func(slugInput);
262 | props.savePersist(savedSlug)}} className="searchSubmit" type="submit" value=" " />
263 |
264 |
265 |
266 |
267 |
271 |
272 |
273 | )
274 | }
275 |
276 |
277 |
278 | //This is the intialized component of the module.
279 | export function ModuleInit (props) {
280 | //info variables
281 | const [slug, setSlug] = useState(props.slug)
282 | const [name, setName] = useState();
283 | const [collectionImage, setImage] = useState();
284 | //stats
285 | const [sales, setSales] = useState();
286 | const [floorPrice, setFloorPrice] = useState();
287 | const [supply, setSupply] = useState();
288 | const [volume, setVol] = useState();
289 | const [holders, setHolders] = useState();
290 | const [holderRatio, setRatio] = useState();
291 | const [royaltyFee, setFee] = useState();
292 | //links/control variables
293 | const [opensea, setOS] = useState();
294 | const [nftnerd, setNerd] = useState();
295 | const [etherscan, setES] = useState();
296 | const [refreshHelp, toggleRefHelp] = useState(false);
297 | const [savePrompt, setSavePrompt] = useState();
298 | //style
299 | const [cnamelength, setcname] = useState('cname');
300 | //important usestate here: basically will check if this module has been initialized
301 | const [init, toggleInit] = useState(false);
302 | let saveslug;
303 |
304 | //props and etc
305 | let nightMode = props.nightMode;
306 | let url = `https://api.opensea.io/api/v1/collection/${slug}`
307 | let delHandler = props.func;
308 |
309 | const nightModeHandler = () => {
310 | if (nightMode === true) {
311 | return {
312 | backgroundColor: '#6B8074'
313 | }
314 | } else {
315 | return {
316 | backgroundColor: '#A8DBA8'
317 | }
318 | }
319 | }
320 |
321 | //Manual Refresh Function
322 |
323 | const refHandler = () => {
324 | fetchCollection(url)
325 | }
326 |
327 | //Helper Div Stuff
328 | const refHelpClick = () => {
329 | toggleRefHelp(true)
330 | }
331 |
332 | const delRefHelp = () => {
333 | toggleRefHelp(false)
334 | }
335 |
336 | const refreshDiv = () => {
337 | if (refreshHelp === true) {
338 | return (
339 |
340 |
{delRefHelp()}} id="rhelpdelbutton" className="delButton2" src={delButton2} height="18px" width="18px" alt="delete button 2" />
341 |
If nothing changes after refreshing, it usually just means that there's nothing to update or refresh regarding the stats of the collection. Try again later when you think thing's might've changed!
342 |
343 | )
344 | }
345 | }
346 |
347 |
348 |
349 | //save stuff
350 |
351 | //this is the function for the onClick event of the button (to save)
352 | function saveSession () {
353 | saveslug = [props.mKey, slug]
354 | props.saveFunc(saveslug)
355 | setSavePrompt()
356 | }
357 |
358 |
359 |
360 | //this handles clicking on the collection image -> which then prompts the savePrompt button
361 | const handleSaveClick = () => {
362 | setTimeout(() => {
363 | setSavePrompt(true)
364 | }, 1000);
365 | }
366 |
367 |
368 | //this the button that pops up to prompt a save session
369 | const SavePrompt = (
370 |
371 | Save ?
372 |
373 | )
374 |
375 |
376 | //main function to fetch the data from the Opensea API, then sets the useState variables accordingly.
377 | const fetchCollection = (collectionUrl) => {
378 | const options = {method: 'GET'};
379 | fetch(collectionUrl, options)
380 | .then(response => response.json())
381 | .then(response => {
382 | let stats = response.collection.stats;
383 | let contract = response.collection.primary_asset_contracts[0].address;
384 | let floorPrice = stats.floor_price;
385 | let collectionName = response.collection.primary_asset_contracts[0].name;
386 |
387 | const fee = () => {
388 | const jsonFee = response.collection.primary_asset_contracts[0].seller_fee_basis_points / 100
389 | const percentageFee = jsonFee.toString() + "%"
390 | return percentageFee;
391 | }
392 |
393 | const floorPriceParser = (floorPrice) => {
394 | if (floorPrice < 1) {
395 | return Number.parseFloat(floorPrice).toFixed(3)
396 | } else {
397 | return Number.parseFloat(floorPrice).toFixed(2)
398 | }
399 | }
400 |
401 | setFloorPrice(floorPriceParser(floorPrice))
402 | setName(response.collection.primary_asset_contracts[0].name)
403 | setImage(response.collection.image_url)
404 | setSales(stats.total_sales)
405 | setSupply(stats.total_supply)
406 | setVol(Math.round(stats.total_volume))
407 | setHolders(stats.num_owners)
408 | setRatio((stats.total_supply/stats.num_owners).toFixed(2))
409 | setFee(fee())
410 | setOS(`https://opensea.io/collection/${slug}`)
411 | setNerd(`https://nftnerds.ai/collection/${contract}/liveview`)
412 | setES(`https://etherscan.io/address/${contract}`)
413 | if (collectionName.length > 18) {
414 | setcname('cname2')
415 | } else if (collectionName.length > 12) {
416 | setcname('cname1')
417 | }
418 |
419 | })
420 |
421 | }
422 |
423 | const ModuleImg = (
424 |
425 | )
426 |
427 |
428 | useEffect(() => {
429 |
430 | fetchCollection(url);
431 | }, [])
432 |
433 |
434 | return (
435 |
436 |
437 |
438 |
{delHandler()}} src={delButton} height="40px" width="40px" />
439 |
440 |
441 |
{refHandler()}} src={refButton} height="40px" width="40px" />
442 |
443 |
444 |
{refHelpClick()}}alt="questionMark" src={questionMark} className="question-mark" height="16px" width="16px" />
445 |
446 | {refreshDiv()}
447 | {!savePrompt && ModuleImg}
448 | {savePrompt && SavePrompt}
449 |
450 |
451 |
452 |
453 |
454 |
{name}
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
471 |
472 |
473 | )
474 | }
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 | //this component handles the loading screen animation in between the search module and the initialized module.
487 | //the loading screen is purely for entertainment, stylistic purposes since it makes the module look more robust.
488 | function LoadingScreenComp (props) {
489 | // animation/style handling here for the loading screen
490 | const [animationClass, setClass] = useState("loadingScreen1")
491 | const [loading, setLoading] = useState(true);
492 |
493 |
494 | useEffect(() => {
495 | if (props.refresh || props.autoRefresh !== 0) {
496 | setLoading(true)
497 | }
498 |
499 | setTimeout(() => {
500 | setClass("loadingScreen2")
501 | setTimeout(() => {
502 | setClass("loadingScreen3")
503 | setTimeout(() => {
504 | setClass("loadingScreen2")
505 | setTimeout(() => {
506 | setClass("loadingScreen3")
507 | setTimeout(() => {
508 | setLoading(false)
509 | }, 100);
510 | }, 200);
511 | }, 200);
512 | }, 300);
513 | }, 50);
514 | }, [])
515 |
516 |
517 | // this clause will always run first before the ModuleInit is rendered because the useState of loading is set to true by default
518 | // -> Because this runs first, the useEffect will be activated afterwards to set Loading to false thus returning ModuleInit next.
519 |
520 | return (
521 |
522 |
523 |
524 |
525 |
526 | )
527 | }
--------------------------------------------------------------------------------
/src/Styles/ModuleHandler.css:
--------------------------------------------------------------------------------
1 | .row {
2 | display: flex;
3 | flex-direction: row;
4 | width: 95%;
5 | margin-top: 10px;
6 | justify-content: space-evenly;
7 | }
8 |
9 |
10 | @media only screen and (max-width: 1280px) {
11 | .module {
12 | width: 500px;
13 | margin-left: 10px;
14 | margin-right: 10px;
15 | }
16 |
17 | .scroll {
18 | max-width: 310px;
19 | height: 90px;
20 | }
21 |
22 |
23 | .bigPlayButtonTrue {
24 | left: -48.5px;
25 | transition: height .2s linear;
26 | transition: width .1s linear;
27 | }
28 |
29 | .bigPlayButtonFalse {
30 | left: -48.5px;
31 | transition: height .05s linear;
32 | transition: width .05s linear;
33 | }
34 |
35 |
36 |
37 | .stats-info {
38 | white-space: nowrap;
39 | }
40 |
41 | .bigstat {
42 | position: absolute;
43 | left: 6px;
44 | transition: left .05s linear;
45 | }
46 |
47 | .stats-left:hover > .bigstat {
48 | left: 6.3px;
49 | position: absolute;
50 | transition: left .05s linear;
51 | }
52 |
53 |
54 | .stats-right {
55 | max-width: 70%;
56 | }
57 |
58 | .stats-left {
59 | min-width: 20%;
60 | max-width: 30%;
61 | }
62 |
63 | .stats {
64 | gap: 0px;
65 | max-width: 80%;
66 | margin: 0;
67 | justify-content: center;
68 | padding: 0;
69 | }
70 | }
71 |
72 |
73 |
74 | .module {
75 | border: 4px solid rgb(0, 0, 0);
76 | width: 400px;
77 | height: 810px;
78 | background-color: #A8DBA8;
79 | border-radius: 20px;
80 | caret-color: transparent!important;
81 | display: flex;
82 | justify-content: center;
83 | filter:drop-shadow(1px 5px 10px black) ;
84 | align-items: center;
85 | flex-direction: column;
86 | box-shadow: inset 0 2px 5px 1px #807e7e;
87 | }
88 |
89 | .module:hover {
90 | filter:drop-shadow(1px 5px 10px rgba(199, 186, 2, .5));
91 | transition: all 0.1s ease-in-out;
92 | z-index: 8888;
93 | }
94 |
95 |
96 | .mainModuleSearchDiv {
97 | display: flex;
98 | flex-direction: column;
99 | align-items: center;
100 | width: 100%;
101 | justify-content: space-between;
102 | height: 80%;
103 | cursor: pointer;
104 | }
105 |
106 | .swordImg:hover {
107 | filter:drop-shadow(1px 5px 25px rgb(255, 208, 0));
108 | transition: filter 0.1s linear;
109 | }
110 |
111 | .swordFlipped:hover {
112 | filter:drop-shadow(1px 5px 25px rgb(255, 208, 0));
113 | transition: filter 0.1s linear;
114 | }
115 |
116 | .scrollcontainer2:hover .scroll2 {
117 | filter:drop-shadow(1px 5px 20px rgb(255, 208, 0));
118 | transition: filter 0.1s linear;
119 | }
120 |
121 | .searchInputContainer:hover .scroll2 {
122 | filter:drop-shadow(1px 5px 20px rgb(255, 208, 0));
123 | transition: filter 0.1s linear;
124 | }
125 |
126 | .searchInputContainer:hover .search {
127 | caret-color: black;
128 | }
129 |
130 | .searchDiv {
131 | display: flex;
132 | flex-direction: column;
133 | align-items: center;
134 | width: 100%;
135 | cursor: pointer
136 | ;
137 | }
138 |
139 |
140 | .searchInputContainer {
141 | height: auto;
142 | position: relative;
143 | width: 50%;
144 | z-index: 3;
145 | margin-bottom: 10px;
146 | display: flex;
147 | flex-direction: column;
148 | align-items: center;
149 | user-select: none;
150 | caret-color: darkslategrey!important;
151 | }
152 |
153 | .searchInputContainer input {
154 | width: 100%;
155 | position: relative;
156 | user-select: none;
157 | height: 50px;
158 | text-align: center;
159 | background-color: transparent;
160 | z-index: 3;
161 | outline: none;
162 | border: none;
163 | font-family: 'watermelondays';
164 | font-size: 1.3rem;
165 | color: darkslategrey;
166 | text-decoration: underline;
167 | }
168 |
169 | .searchSubmitContainer {
170 | z-index: 3;
171 | margin: 0;
172 | position: relative;
173 | display: flex;
174 | flex-direction: column;
175 | align-items: center;
176 | width: 57.5%;
177 | height: auto;
178 | }
179 |
180 | .searchButtonDiv {
181 | z-index: 3;
182 | cursor: pointer;
183 | position: absolute;
184 | top: 32.5px;
185 | display: flex;
186 | flex-direction: column;
187 | align-items: center;
188 | width: 98%;
189 | }
190 |
191 | .searchSubmitContainer input {
192 | cursor: pointer;
193 | position: relative;
194 | background-color: transparent;
195 | width: 100%;
196 | border: none;
197 | font-family: 'candy_beansregular';
198 | padding: 5px;
199 | height: 32.5px;
200 | }
201 |
202 |
203 | .searchSubmitContainer span {
204 | position: absolute;
205 | bottom: 35%;
206 | -webkit-text-stroke: 0.5px;
207 | font-size: 1.3rem;
208 | padding-bottom: 2.5px;
209 | font-family: 'watermelondays';
210 | color: #0B486B;
211 | -webkit-text-stroke-color: rgb(213,195,149);
212 | }
213 |
214 |
215 | .searchSubmitContainer:hover span {
216 | text-decoration: underline;
217 | text-decoration-color: black;
218 | }
219 |
220 | .searchSubmitContainer:hover img {
221 | width: 315px;
222 | transition: width 0.05s linear;
223 | }
224 |
225 | .info {
226 | display: flex;
227 | position: relative;
228 |
229 | flex-direction: column;
230 | align-items: center;
231 | align-content: flex-start;
232 | border-bottom: 2px solid #000000;
233 | width: 100%;
234 | padding: 10px 0 25px;
235 | overflow: hidden;
236 | height: 42.5%;
237 | }
238 |
239 | .bottom {
240 | height: 71.5%;
241 | width: 100%;
242 | margin-left: auto;
243 | margin-right: auto;
244 | padding: 15px 0;
245 | line-height: 1px;
246 | align-items: center;
247 | display: flex;
248 | overflow: hidden;
249 | flex-direction: column;
250 |
251 | }
252 |
253 |
254 | .ImageDiv {
255 | height: 132px;
256 | width: 132px;
257 | margin-top: 15px;
258 | margin-bottom: 15px;
259 |
260 | }
261 |
262 |
263 | .start-btn{
264 | text-align: center;
265 | display: inline-block;
266 | margin:5px;
267 | user-select: none;
268 | letter-spacing: 1px;
269 | font-size: 1.2rem;
270 | font-family: 'watermelondays';
271 | padding: 10px 10px 10px 10px ;
272 | background-color: rgb(211, 211, 211);
273 | text-shadow: -1px -1px rgb(255, 255, 255), 1px 1px white;
274 | color: rgb(0, 0, 0);
275 | -webkit-border-radius: 7px;
276 | -moz-border-radius: 7px;
277 | -o-border-radius: 7px;
278 | border-radius: 7px;
279 | box-shadow: 0 .2em gray;
280 | cursor: pointer;
281 | width: 100px;
282 | position: relative;
283 | border: 2px solid rgb(119, 117, 117);
284 | top: 57px;
285 | }
286 |
287 | .start-btn:active {
288 | box-shadow: 0 .0em gray;
289 | top: 60px;
290 | }
291 |
292 | .moduleImg {
293 | border: 1px solid black;
294 | user-select: none!important;
295 | padding: 5px;
296 | cursor: pointer;
297 | margin-top: 15px;
298 | margin-bottom: 15px;
299 | background-color: grey;
300 | filter:drop-shadow(1px 5px 12px rgb(0, 0, 0));
301 | }
302 |
303 | .moduleImg:hover {
304 | filter:drop-shadow(1px 5px 15px rgb(255, 208, 0))
305 | drop-shadow(-1px -1px 0 rgb(121,189,154));
306 | }
307 |
308 |
309 | .stats {
310 | display: flex;
311 | flex-direction: row;
312 | align-items: center;
313 | width: 90%;
314 | height: 20%;
315 | gap: 100px;
316 | margin-left: 3px;
317 | margin-top: 5px;
318 | margin-bottom: 5px;
319 | padding: 0 10px 5px;
320 | border-bottom: 1px DOTTED rgba(0, 0, 0, .5);
321 | position: relative;
322 | }
323 |
324 | .stats:hover {
325 | border-bottom: 2px DOTTED rgb(255, 255, 255);
326 | }
327 |
328 | .nameContainer {
329 | width: 100%;
330 | height: 100px;
331 | display: flex;
332 | cursor: pointer;
333 | justify-content: center;
334 | align-items: center;
335 | }
336 |
337 | .scrollcontainer {
338 | user-select: none;
339 | position: absolute;
340 | cursor: pointer;
341 | }
342 |
343 | .scroll {
344 | filter:drop-shadow(1px 5px 10px black) ;
345 | width: 375px;
346 | user-select: none;
347 | cursor: pointer;
348 | height: 110px;
349 | transition: filter 0.2s ease-out;
350 | }
351 |
352 | .scrollcontainer2 {
353 | position: absolute;
354 | z-index: 1;
355 | cursor: pointer;
356 | bottom: -25px;
357 | }
358 |
359 | .scroll2 {
360 | width: 300px;
361 | height: 100px;
362 | filter:drop-shadow(1px 5px 10px black);
363 | }
364 |
365 | .submitPlayButtonDiv {
366 | position: absolute;
367 | z-index: 1;
368 | bottom: -50x;
369 | cursor: pointer;
370 | display: flex;
371 | justify-content: center;
372 | }
373 |
374 | .submitPlayButton {
375 | width: 300px;
376 | height: 100px;
377 | filter:drop-shadow(1px 2px 1px black) ;
378 | }
379 |
380 | .nameContainer:hover .scroll {
381 | filter:drop-shadow(1px 5px 20px rgb(255, 208, 0));
382 | transition: filter 0.1s linear;
383 | }
384 |
385 | .nameContainer:hover .cname {
386 | font-size: 2.7rem;
387 | -webkit-text-stroke-color: rgba(255, 255, 255, 0.7);
388 | transition: font-size .2s ease-in;
389 | transition: -webkit-text-stroke-color .1s linear;
390 | }
391 |
392 |
393 | .nameContainer:hover .cname1 {
394 | font-size: 2.2rem;
395 | -webkit-text-stroke-color: rgba(255, 255, 255, 0.7);
396 | transition: font-size .2s ease-in;
397 | transition: -webkit-text-stroke-color .1s linear;
398 | }
399 |
400 | .nameContainer:hover .cname2 {
401 | font-size: 1.85rem;
402 | -webkit-text-stroke-color: rgba(255, 255, 255, 0.7);
403 | transition: font-size .2s ease-in;
404 | transition: -webkit-text-stroke-color .1s linear;
405 | }
406 |
407 |
408 |
409 | .cname {
410 | white-space: nowrap;
411 | text-align: center;
412 | font-family:'watermelondays';
413 | user-select: text;
414 | padding: 15px 0 0;
415 | font-size: 2.6rem;
416 | color: rgb(0, 0, 0);
417 | letter-spacing: 1.6px;
418 | -webkit-text-stroke-width: 0.1px;
419 | -webkit-text-stroke-color: rgba(255, 255, 255, .7);
420 | }
421 |
422 | .cname1 {
423 | white-space: nowrap;
424 | text-align: center;
425 | font-family:'watermelondays';
426 | padding: 15px 0 0;
427 | font-size: 2rem;
428 | color: rgb(0, 0, 0);
429 | letter-spacing: 1.6px;
430 | -webkit-text-stroke-width: 0.1px;
431 | -webkit-text-stroke-color: rgba(255, 255, 255, .7);
432 | }
433 |
434 |
435 | .cname2 {
436 | white-space: nowrap;
437 | text-align: center;
438 | font-family:'watermelondays';
439 | padding: 15px 0 0;
440 | font-size: 1.7rem;
441 | color: rgb(0, 0, 0);
442 | letter-spacing: 1.6px;
443 | -webkit-text-stroke-width: 0.1px;
444 | -webkit-text-stroke-color: rgba(255, 255, 255, .7);
445 | }
446 |
447 |
448 | .name {
449 | z-index: 100;
450 | width: 50%;
451 | display: flex;
452 | padding-bottom: 5px;
453 | margin-bottom: 10px;
454 | justify-content: center;
455 | }
456 |
457 | .stats-info {
458 | font-family: 'candy_beansregular';
459 | user-select: none;
460 | cursor: pointer;
461 | font-size: 1.125rem;
462 | z-index: 200;
463 | -webkit-text-stroke: 1px;
464 | position: relative;
465 | color: #0B486B;
466 | -webkit-text-stroke-color: rgb(213,195,149);
467 | }
468 |
469 | .swordDiv {
470 | margin: 15px 0;
471 | }
472 |
473 | .swordImg {
474 | user-select: none;
475 | filter:drop-shadow(1px 5px 10px black);
476 | transition: filter 0.1s linear;
477 |
478 | }
479 |
480 | .swordFlipped {
481 | transform: scaleX(-1);
482 | transition: filter 0.1s linear;
483 | filter:drop-shadow(1px 5px 10px black);
484 | }
485 |
486 |
487 | .stats-left {
488 |
489 | width: 60%;
490 | height: 100%;
491 | display: flex;
492 | align-items: center;
493 | justify-content: center;
494 | }
495 |
496 | .stats-right {
497 | width: 70%;
498 | justify-content: center;
499 | position: relative;
500 | height: 100%;
501 | display: flex;
502 | align-items: center;
503 | }
504 |
505 | .controls {
506 | display: flex;
507 | cursor: default;
508 |
509 | flex-direction: row;
510 | box-shadow: 0px 2px 7px 0px rgba(0,0,0,.5);
511 | align-items: center;
512 | width: 90%;
513 | height: 15%;
514 | justify-content: space-evenly;
515 | margin-left: 3px;
516 | margin-top: 5px;
517 | margin-bottom: 5px;
518 | padding: 5px 3px 5px;
519 | border-radius: 5px;
520 | border: 2px solid rgba(0, 0, 0, 0.5);
521 | background-color: rgba(205,215,182, 1);
522 | }
523 |
524 | .osdiv, .esdiv {
525 | border: 1px solid rgba(0, 0, 0, 0.2);
526 | border-radius: 50%;
527 | filter:drop-shadow(1px 2px 1px rgba(0, 0, 0, .3));
528 | cursor: pointer;
529 | }
530 |
531 | .nerddiv {
532 | filter:drop-shadow(1px 2px 1px rgba(0, 0, 0, .3));
533 | display: flex;
534 | align-items: center;
535 | flex-direction: column;
536 | border: 1px solid rgba(0, 0, 0, 0.1);
537 | border-radius: 50%;
538 | height: 25px;
539 | width: 25px;
540 | background-color: rgba(85, 85, 84, 0.2);
541 | cursor: pointer;
542 | }
543 |
544 | .osdiv:hover, .esdiv:hover, .nerddiv:hover {
545 | border: 1px solid rgba(0, 0, 0, 1);
546 | }
547 |
548 | #bigVal {
549 | padding-left: 5px;
550 | white-space: nowrap;
551 | }
552 |
553 |
554 | .stats-val {
555 | z-index: 100;
556 | cursor: pointer;
557 | font-size: 1.3rem;
558 | font-family: 'candy_beansregular';
559 | letter-spacing: 2px;
560 | -webkit-text-stroke: 1px;
561 | color: rgba(0, 0, 0, 0.67);
562 | transition: font-size 0.1s linear;
563 | -webkit-text-fill-color: rgb(219, 132, 212);
564 | }
565 |
566 | .bigPlayButtonTrue {
567 | width: 210px;
568 | height: 90px;
569 | padding-top: 2px;
570 | user-select: none;
571 | position: absolute;
572 | transition: height .2s linear;
573 | transition: width .1s linear;
574 | cursor:pointer;
575 | filter:drop-shadow(1px 2px 1px black);
576 | }
577 |
578 | .bigPlayButtonFalse {
579 | user-select: none;
580 | width: 200px;
581 | height: 70px;
582 | padding-top: 2px;
583 | cursor:pointer;
584 | position: absolute;
585 | transition: height .05s linear;
586 | transition: width .05s linear;
587 | filter:drop-shadow(1px 2px 1px black);
588 | }
589 |
590 | .playButtonHoverFalse {
591 | width: 120px;
592 | height: 70px;
593 | user-select: none;
594 | cursor:pointer;
595 | padding-top: 2px;
596 | position: absolute;
597 | transition: heigh width 2s;
598 | filter:drop-shadow(1px 2px 1px black);
599 |
600 | }
601 |
602 | .playButtonHoverTrue {
603 | width: 150px;
604 | height: 90px;
605 | padding-top: 2px;
606 | user-select: none;
607 | cursor:pointer;
608 | position: absolute;
609 | transition: height .2s linear;
610 | transition: width .1s linear;
611 | filter:drop-shadow(1px 2px 1px black);
612 |
613 | }
614 |
615 |
616 | .bmo {
617 | border: 2px solid rgba(0, 0, 0, .3);
618 | border-radius: 2px;
619 | position: absolute;
620 | top: -6px;
621 | cursor: pointer;
622 | filter:drop-shadow(1px 2px 3px rgba(216, 211, 211,.3))
623 | drop-shadow(-1px -1px 0 rgba(228, 228, 228, .3));
624 | }
625 |
626 | .bmo:hover {
627 | border: 2px solid rgba(255, 255, 255, .1);
628 | transform: scale(1.05);
629 | transition: transform 0.1s linear;
630 | filter:drop-shadow(1px 2px 5px rgba(216, 211, 211,.3));
631 | }
632 |
633 | .stats:hover .stats-val {
634 | font-size: 1.6rem;
635 | transition: font-size 0.1s linear;
636 | }
637 |
638 | #floorprice {
639 | display: flex;
640 | flex-direction: row;
641 | align-items: center;
642 | gap: 2px;
643 | }
644 |
645 | .eth {
646 | color: #1f1d1d;
647 | filter:drop-shadow(1px 1px 3px rgb(167, 170, 7)) ;
648 | }
649 |
650 | .loadingScreen1 {
651 | opacity: 0.1;
652 | transition: opacity 0.5s ease-in;
653 | }
654 |
655 | .loadingScreen2 {
656 | opacity: 1;
657 | transition: opacity 0.5s ease-in;
658 | }
659 |
660 | .loadingScreen3 {
661 | opacity: 0.05;
662 | transition: opacity 0.3s ease-out;
663 | }
664 |
665 | .refreshButtonDiv {
666 | user-select: none!important;
667 | position: absolute;
668 | cursor: pointer;
669 | right: 10%;
670 | top: 9%;
671 | filter:drop-shadow(1px 1px 2px rgb(0, 0, 0))
672 | drop-shadow(-1px -1px 0 rgba(228, 228, 228, .3));
673 | }
674 |
675 | .refreshButtonDiv img {
676 | filter: grayscale(80%);
677 | -webkit-transition: all 0.5s linear;
678 | -moz-transition: all 0.5s linear;
679 | -o-transition: all 0.5s linear;
680 | -ms-transition: all 0.5s linear;
681 | transition: all 0.5s linear;
682 | }
683 |
684 | .refreshButtonDiv:hover > img {
685 | filter: grayscale(0%);
686 | transform: rotate(-170deg);
687 | }
688 |
689 | .deleteButtonDiv {
690 | user-select: none!important;
691 | position: absolute;
692 | cursor: pointer;
693 | left: 27.5px;
694 | top: 30px;
695 | filter:drop-shadow(1px 1px 5px rgb(0, 0, 0))
696 | drop-shadow(-1px -1px 0 rgba(228, 228, 228, .3));
697 | }
698 |
699 | .deleteButtonDiv img {
700 | filter: grayscale(80%);
701 | -webkit-transition: all 0.2s linear;
702 | -moz-transition: all 0.2s linear;
703 | -o-transition: all 0.2s linear;
704 | -ms-transition: all 0.2s linear;
705 | transition: all 0.2s linear;
706 | }
707 |
708 | .deleteButtonDiv:hover > img {
709 | filter: grayscale(0%);
710 | transform: rotate(-10deg);
711 |
712 | }
713 |
714 | .questionMarkDiv {
715 | position: absolute;
716 | right: 5%;
717 | top: 5%;
718 | cursor: pointer;
719 | }
720 |
721 | .questionMarkDiv img {
722 | filter: grayscale(80%);
723 | }
724 |
725 | .questionMarkDiv:hover img {
726 | filter: grayscale(0%);
727 | }
728 |
729 | .refreshHelpDiv {
730 | position: absolute;
731 | z-index: 8000;
732 | height: 100px;
733 | width: 300px;
734 | background-color: rgba(255, 255, 255, .7);
735 | border: 3px solid black;
736 | border-radius: 10px;
737 | font-family: 'watermelondays';
738 | cursor: pointer;
739 | text-align: center;
740 | left: 50px;
741 | line-height: 20px;
742 | padding: 20px;
743 | }
744 |
745 | .refreshHelpContent {
746 | position: absolute;
747 | top: 10px;
748 | right: 0;
749 | font-size: 1.2rem;
750 | text-shadow:
751 | 0.07em 0 #a2c505,
752 | 0 0.07em #a2c505,
753 | -0.07em 0 #a2c505,
754 | 0 -0.07em #a2c505;
755 | color: black;
756 | }
757 |
758 | img.delButton2 {
759 | position: absolute;
760 | top: 1%;
761 | right: 1%;
762 | filter: grayscale(100%);
763 | padding: 2px;
764 | border: 2px solid black;
765 | border-radius: 16px;
766 | background-color: wheat;
767 | }
768 |
769 | .delButton2:hover {
770 | filter: grayscale(0);
771 | }
772 |
773 | .lightBulbDiv {
774 | position: relative;
775 | z-index: 5555;
776 | }
777 |
778 | .lightBulbDiv img {
779 | position: relative;
780 | bottom: 125px;
781 | opacity: 30%;
782 | filter:drop-shadow(1px 5px 10px black) ;
783 | transition: all 0.15s ease-out;
784 |
785 | }
786 |
787 | .lightBulbDiv img:hover {
788 | filter:drop-shadow(1px 5px 25px rgb(255, 208, 0)) ;
789 | transition: all 0.1s ease-in;
790 | transform: rotate(10deg);
791 | opacity: 80%;
792 | }
793 |
794 | div.slugHelperDiv {
795 | position: relative;
796 | bottom: 12%;
797 | background-color: wheat;
798 | max-width: 300px;
799 | right: 0%;
800 | padding: 20px 15px 0;
801 | border: 2px solid black;
802 | border-radius: 15px;
803 | display: flex;
804 | flex-direction: column;
805 | align-items: center;
806 | justify-content: center;
807 | z-index: 7777;
808 | opacity: 0;
809 | filter:drop-shadow(1px 5px 10px black) ;
810 | transition: all 0.5s ease-out;
811 | }
812 |
813 | .slugHelperDiv:hover {
814 | filter:drop-shadow(1px 5px 15px rgb(85, 77, 1));
815 |
816 | }
817 |
818 | .slugHelperDiv p:hover {
819 | filter:drop-shadow(1px 5px 12px rgb(0, 0, 0)) ;
820 | font-size: 1.05rem;
821 | transition: all 0.1s linear;
822 | }
823 |
824 |
825 | .slugHelperContent {
826 | padding-top: 25px;
827 | margin-top: 10px;
828 | }
829 |
830 | img.exampleSlug {
831 | filter:drop-shadow(1px 5px 10px black) ;
832 | border: 2px solid black;
833 | border-radius: 10px;
834 | transform: scale(1);
835 |
836 | }
837 |
838 | img.exampleSlug:hover {
839 | transform: scale(1.05);
840 | transition: all 0.2s linear;
841 | }
842 |
843 | .slugHelperContent strong {
844 | font-weight: 550;
845 | text-decoration: underline;
846 | }
847 |
848 | .slugHelperContent p {
849 | text-align: center;
850 | text-shadow:
851 | 0.07em 0 #a2c505,
852 | 0 0.07em #a2c505,
853 | -0.07em 0 #a2c505,
854 | 0 -0.07em #a2c505;
855 | line-height: 22px;
856 | filter:drop-shadow(1px 5px 8px rgb(0, 0, 0)) ;
857 | font-family: 'watermelondays';
858 | }
859 |
860 | img.delButton3 {
861 | border: none;
862 | filter: grayscale(50%);
863 | z-index: 5555;
864 | top: 5%;
865 | right: 45%;
866 | position: absolute;
867 | }
868 |
869 | img.delButton3:hover {
870 | filter: grayscale(0%);
871 | filter:drop-shadow(1px 5px 10px black) ;
872 | }
873 |
874 |
--------------------------------------------------------------------------------
/src/assets/vector.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------