diff --git a/src/Checkbox.jsx b/src/Checkbox.jsx
index c61f44f..3e1c02b 100644
--- a/src/Checkbox.jsx
+++ b/src/Checkbox.jsx
@@ -1,28 +1,15 @@
-import React from "react";
-
-/**
- * @note This is a basic checkbox component without onClick event handling.
- * 💡 Please check the console for warning messages.
- */
-class Checkbox extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- check: false,
- };
- }
-
- render() {
- const { name, label } = this.props;
-
- return (
-
-
-
-
- );
- }
+function Checkbox({ name, label, checked, onChange }) {
+ return (
+
+
+
+
+ );
}
export default Checkbox;
diff --git a/src/CheckboxOnclick.jsx b/src/CheckboxOnclick.jsx
deleted file mode 100644
index 76b8976..0000000
--- a/src/CheckboxOnclick.jsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from "react";
-
-class CheckboxOnclick extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- checked: false,
- };
- }
-
- handleCheck = () => {
- this.setState({
- checked: !this.state.checked,
- });
- };
-
- render() {
- const { name, label } = this.props;
-
- return (
-
-
-
-
- );
- }
-}
-
-export default CheckboxOnclick;
diff --git a/src/ExampleDidMount.jsx b/src/ExampleDidMount.jsx
deleted file mode 100644
index edbaf16..0000000
--- a/src/ExampleDidMount.jsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from "react";
-
-class ExampleDidMount extends React.Component {
- constructor(props) {
- super(props);
- console.log("Constructor");
- }
-
- componentDidMount() {
- console.log("Component did mount!");
- }
-
- render() {
- return Component Mounted
;
- }
-}
-
-export default ExampleDidMount;
diff --git a/src/ExampleDidUpdate.jsx b/src/ExampleDidUpdate.jsx
deleted file mode 100644
index ab04c15..0000000
--- a/src/ExampleDidUpdate.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from "react";
-
-class ExampleDidUpdate extends React.Component {
- constructor(props) {
- super(props);
- this.state = { count: 0 };
- }
-
- componentDidUpdate() {
- console.log("Component did update!");
- }
-
- increment = () => {
- this.setState({ count: this.state.count + 1 });
- };
-
- render() {
- return (
-
-
Count: {this.state.count}
-
-
- );
- }
-}
-
-export default ExampleDidUpdate;
diff --git a/src/ExampleWillUnmount.jsx b/src/ExampleWillUnmount.jsx
deleted file mode 100644
index e28c249..0000000
--- a/src/ExampleWillUnmount.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from "react";
-
-class ExampleWillUnmount extends React.Component {
- componentWillUnmount() {
- console.log("Component will unmount!");
- }
-
- render() {
- return Goodbye!
;
- }
-}
-
-export default ExampleWillUnmount;
diff --git a/src/ParentComponent.jsx b/src/ParentComponent.jsx
new file mode 100644
index 0000000..24bb600
--- /dev/null
+++ b/src/ParentComponent.jsx
@@ -0,0 +1,21 @@
+import { useState } from "react";
+import Checkbox from "./Checkbox";
+
+function ParentComponent() {
+ const [hasAcceptedTerms, setHasAcceptedTerms] = useState(false);
+
+ const handleAcceptTerms = () => {
+ setHasAcceptedTerms(!hasAcceptedTerms);
+ };
+
+ return (
+
+ );
+}
+
+export default ParentComponent;
diff --git a/src/components/Game.css b/src/components/Game.css
index 308b448..034820a 100644
--- a/src/components/Game.css
+++ b/src/components/Game.css
@@ -1,6 +1,12 @@
.game {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin: 2rem 20rem;
+}
+
+.game .left {
display: flex;
flex-direction: column;
align-items: center;
- width: 40%;
}
diff --git a/src/components/Game.jsx b/src/components/Game.jsx
index 073a38e..2d309d8 100644
--- a/src/components/Game.jsx
+++ b/src/components/Game.jsx
@@ -1,29 +1,64 @@
-import React from "react";
+import { useEffect, useState } from "react";
import "./Game.css";
+import items from "../items.json";
import { Gitcoin } from "./Gitcoin";
+import { Office } from "./Office";
import { Score } from "./Score";
+import { Store } from "./Store";
-export class Game extends React.Component {
- constructor(props) {
- super(props);
+export function Game() {
+ const [lines, setLines] = useState(0);
+ const [linesPerMillisecond, setLinesPerMillisecond] = useState(0);
+ const [ownedItems, setOwnedItems] = useState({});
- this.state = {
- lines: 0,
- };
- }
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setLines(lines + linesPerMillisecond);
+ }, 100);
- handleClick() {
- this.setState({
- lines: this.state.lines + 1,
+ return () => clearInterval(interval);
+ }, [lines, linesPerMillisecond]);
+
+ useEffect(() => {
+ let count = 0;
+
+ for (const name of Object.keys(ownedItems)) {
+ const item = items.find((element) => element.name === name);
+ count += item.linesPerMillisecond * ownedItems[name];
+ }
+
+ setLinesPerMillisecond(count);
+ }, [ownedItems]);
+
+ const handleClick = () => {
+ setLines(lines + 1);
+ };
+
+ const handleBuy = (item) => {
+ setLines(lines - item.price);
+ setOwnedItems({
+ ...ownedItems,
+ [item.name]: (ownedItems[item.name] || 0) + 1,
});
- }
-
- render() {
- return (
-
-
-
-
- );
- }
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
}
diff --git a/src/components/Gitcoin.css b/src/components/Gitcoin.css
index 77ad013..87aa5ff 100644
--- a/src/components/Gitcoin.css
+++ b/src/components/Gitcoin.css
@@ -6,8 +6,32 @@
background: transparent;
outline: none;
cursor: pointer;
+
+ & > img {
+ width: 100%;
+ border-radius: 100%;
+ animation: bounce-up 0.2s;
+ }
+
+ &:active > img {
+ animation: bounce-down 0.2s;
+ }
}
-.gitcoin > img {
- width: 100%;
+@keyframes bounce-up {
+ 0% {
+ transform: scale(0.9)
+ }
+ 100% {
+ transform: scale(1)
+ }
}
+
+@keyframes bounce-down {
+ 0% {
+ transform: scale(1)
+ }
+ 100% {
+ transform: scale(0.9)
+ }
+}
\ No newline at end of file
diff --git a/src/components/Gitcoin.jsx b/src/components/Gitcoin.jsx
index 1253f02..f18eac6 100644
--- a/src/components/Gitcoin.jsx
+++ b/src/components/Gitcoin.jsx
@@ -1,15 +1,10 @@
-import React from "react";
import "./Gitcoin.css";
-import githubIcon from "../assets/github.svg";
+import githubIcon from "@/assets/github.svg";
-export class Gitcoin extends React.Component {
- render() {
- const { onClick } = this.props;
-
- return (
-
- );
- }
+export function Gitcoin({ onClick }) {
+ return (
+
+ );
}
diff --git a/src/components/Office.jsx b/src/components/Office.jsx
new file mode 100644
index 0000000..f07f047
--- /dev/null
+++ b/src/components/Office.jsx
@@ -0,0 +1,16 @@
+export function Office({ items }) {
+ return (
+ <>
+ Office
+
+ {Object.keys(items).map((name) => (
+ -
+
+ {items[name]} {name}
+
+
+ ))}
+
+ >
+ );
+}
diff --git a/src/components/Score.jsx b/src/components/Score.jsx
index f170105..cf6cba4 100644
--- a/src/components/Score.jsx
+++ b/src/components/Score.jsx
@@ -1,9 +1,8 @@
-import React from "react";
-
-export class Score extends React.Component {
- render() {
- const { lines } = this.props;
-
- return {lines} lines
;
- }
+export function Score({ lines, linesPerSecond }) {
+ return (
+ <>
+ {lines} lines
+ per second: {linesPerSecond}
+ >
+ );
}
diff --git a/src/components/Store.css b/src/components/Store.css
new file mode 100644
index 0000000..b7b0b21
--- /dev/null
+++ b/src/components/Store.css
@@ -0,0 +1,11 @@
+.item {
+ display: flex;
+ width: 15rem;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.item > span,
+.item > button {
+ margin-bottom: 0.5rem;
+}
diff --git a/src/components/Store.jsx b/src/components/Store.jsx
new file mode 100644
index 0000000..87d88af
--- /dev/null
+++ b/src/components/Store.jsx
@@ -0,0 +1,27 @@
+import "./Store.css";
+import items from "@/items.json";
+
+export function Store({ lines, onBuy }) {
+ const canBuy = (item) => {
+ return lines >= item.price;
+ };
+
+ return (
+
+ {items.map((item) => (
+ -
+
+ {item.name} - {item.price}
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/items.json b/src/items.json
new file mode 100644
index 0000000..f53c149
--- /dev/null
+++ b/src/items.json
@@ -0,0 +1,27 @@
+[
+ {
+ "name": "Bash",
+ "price": 10,
+ "linesPerMillisecond": 0.1
+ },
+ {
+ "name": "Git",
+ "price": 100,
+ "linesPerMillisecond": 1.2
+ },
+ {
+ "name": "Javascript",
+ "price": 10000,
+ "linesPerMillisecond": 14.0
+ },
+ {
+ "name": "React",
+ "price": 50000,
+ "linesPerMillisecond": 75.0
+ },
+ {
+ "name": "Vim",
+ "price": 999999,
+ "linesPerMillisecond": 10000.0
+ }
+]
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index 4db58c9..b69ab72 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,49 +1,12 @@
-import React from "react";
import { createRoot } from "react-dom/client";
-import Checkbox from "./Checkbox";
-import CheckboxOnclick from "./CheckboxOnclick";
-import ExampleDidMount from "./ExampleDidMount";
-import ExampleDidUpdate from "./ExampleDidUpdate";
-import ExampleWillUnmount from "./ExampleWillUnmount";
+import ParentComponent from "./ParentComponent";
import { Game } from "./components/Game";
-class Example extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- showComponent: true,
- };
- }
-
- toggleComponent = () => {
- this.setState((prevState) => ({
- showComponent: !prevState.showComponent,
- }));
- };
-
- render() {
- return (
-
-
- {this.state.showComponent && }
-
- );
- }
-}
-
const root = createRoot(document.getElementById("root"));
root.render(
<>
-
-
- React Lifecycle Methods
-
-
-
- {/* 💡 During the demo, uncomment the following lines ↙️ */}
- {/* GitClicker
- */}
+
+ {/* 💡 Uncomment the following to enable the Game component */}
+ {/* */}
>,
);
diff --git a/vite.config.js b/vite.config.js
index 8b0f57b..356efd0 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -1,7 +1,13 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
+import path from "node:path";
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
-})
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+});