diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..3e212e1
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,21 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:react/recommended',
+ 'plugin:react/jsx-runtime',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
+ settings: { react: { version: '18.2' } },
+ plugins: ['react-refresh'],
+ rules: {
+ 'react/jsx-no-target-blank': 'off',
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..0c589ec
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b0dd678
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "quote-machine-redo",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@vitejs/plugin-react": "^4.2.1",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react": "^7.34.1",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.6",
+ "vite": "^5.2.0"
+ }
+}
diff --git a/public/vite.svg b/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/App.css b/src/App.css
new file mode 100644
index 0000000..3ca3017
--- /dev/null
+++ b/src/App.css
@@ -0,0 +1,99 @@
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+* {
+ border: none;
+}
+img {
+ display: block;
+ max-width: 100%;
+}
+a{
+ text-decoration: none;
+
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ html {
+ scroll-behavior: smooth;
+ }
+}
+
+a:hover{
+ text-align: none;
+ transform: scale(110%);
+}
+
+
+:root{
+ --header-font-family:'Archivo Black', sans-serif;
+ --quote-font-family:'Caprasimo', cursive;
+ --translucent-white:rgba(255,255,255,0.85);
+}
+
+
+html {
+ font-size: 62.5%; /* (62.5/100) * 16px = 10px */
+ color: var(--translucent-white);
+}
+body{
+margin:0;
+}
+h1{
+ font-family:var(--header-font-family);
+ font-size: clamp(3.5rem, 5vw, 8rem);
+ margin:0;
+ padding:1em 1em 0 1em;
+}
+blockquote{
+ font-family: var(--quote-font-family);
+ font-size: clamp(3rem, 5vw, 4.5rem);
+ text-shadow:0.1em 0.1em 2em var(--translucent-white);
+ height:60vh;
+ height: calc(var(--vh, 1vh) * 60);
+ display:flex;
+ flex-direction: column;
+ place-content: center;
+ margin-top: 0;
+}
+.quote::before{
+ content:"\201C";
+}
+.quote::after{
+ content:"\201D";
+}
+.quote{
+place-self: center;
+}
+figcaption{
+ font-family: var(--header-font-family);
+ font-size: clamp(2rem, 5vw, 4.5rem);
+ margin-bottom: 1em;;
+}
+.clickable{
+ font-family: var(--quote-font-family);
+ font-size: clamp(3.1rem, 5vw, 5rem);
+ background-color: rgba(255,255,255,0.3);
+ border-radius: 0.3em;
+ padding: 0.3em;
+ margin: 0.5em;
+ color:white;
+ cursor: pointer;
+}
+
+.quote-box{
+ width:min(90%,800px);
+ margin:auto;
+}
+
+.flex-container{
+ display:flex;
+ flex-direction: column;
+ align-content: center;
+ justify-content: flex-end;
+ text-align: center;
+ height:100vh;
+ height: calc(var(--vh, 1vh) * 100);
+}
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000..fea8e00
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,103 @@
+import './App.css';
+import { useState } from 'react';
+
+function App() {
+ const quotes = [
+ {
+ text:"Political power grows out of the barrel of a gun.",
+ author:"Mao Zedong"
+ },
+ {
+ text:"If destruction be our lot, we must ourselves be its author and finisher. As a nation of freemen, we must live through all time, or die by suicide.",
+ author:"Abraham Lincoln"
+ },
+ {
+ text:"Simplicity is a difficult thing to achieve.",
+ author:"Charlie Chaplin"
+ },
+ {
+ text:"When I was a child, ladies and gentlemen, I was a dreamer.",
+ author:"Elvis Presley"
+ },
+ {
+ text:"Education is the most powerful weapon which you can use to change the world.",
+ author:"Nelson Mandela"
+ },
+ {
+ text:"In a gentle way, you can shake the world.",
+ author:"Gandhi"
+ }
+ ]
+
+ const bgColors = [
+ "#37306B",
+ "#66347F",
+ "#9E4784",
+ "#D27685",
+ "#19376D",
+ "#576CBC",
+ "#A5D7E8"
+ ]
+ const [currentQuote, setCurrentQuote] = useState(getRandomArrayElement(quotes))
+ const [currentBgColor, setCurrentBgColor] = useState(getRandomArrayElement(bgColors))
+
+
+ function getRandomArrayElement(array){
+ return array[Math.floor(Math.random()*(array.length-1))]
+ }
+ function getDifferentArrayElement(array,currentElement){
+ let newElement = currentElement
+ while(JSON.stringify(newElement)===JSON.stringify(currentElement)){
+ newElement = getRandomArrayElement(array)
+ }
+ return newElement
+ }
+
+ function handleClick(){
+ setCurrentQuote(getDifferentArrayElement(quotes,currentQuote))
+ setCurrentBgColor(getDifferentArrayElement(bgColors,currentBgColor))
+ }
+ const params = new URLSearchParams({
+ text:currentQuote.text+" || "+currentQuote.author
+ }).toString()
+
+
+
+
+ return (
+ <>
+
+
+
Welcome to the quote machine!
+
+
+ BEGIN
+
+
+
+
+
+
+
+
+ {currentQuote.text}
+
+
+
+ {currentQuote.author}
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+export default App;
diff --git a/src/App.jsx b/src/App.jsx
new file mode 100644
index 0000000..b8b8473
--- /dev/null
+++ b/src/App.jsx
@@ -0,0 +1,35 @@
+import { useState } from 'react'
+import reactLogo from './assets/react.svg'
+import viteLogo from '/vite.svg'
+import './App.css'
+
+function App() {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+
+ Vite + React
+
+
+
+ Edit src/App.jsx
and save to test HMR
+
+
+
+ Click on the Vite and React logos to learn more
+
+ >
+ )
+}
+
+export default App
diff --git a/src/App.test.js b/src/App.test.js
new file mode 100644
index 0000000..1f03afe
--- /dev/null
+++ b/src/App.test.js
@@ -0,0 +1,8 @@
+import { render, screen } from '@testing-library/react';
+import App from './App';
+
+test('renders learn react link', () => {
+ render();
+ const linkElement = screen.getByText(/learn react/i);
+ expect(linkElement).toBeInTheDocument();
+});
diff --git a/src/assets/react.svg b/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..6119ad9
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,68 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..5d4fdcf
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+import reportWebVitals from './reportWebVitals';
+
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render(
+
+
+
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
diff --git a/src/logo.svg b/src/logo.svg
new file mode 100644
index 0000000..9dfc1c0
--- /dev/null
+++ b/src/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 0000000..54b39dd
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.jsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
new file mode 100644
index 0000000..5253d3a
--- /dev/null
+++ b/src/reportWebVitals.js
@@ -0,0 +1,13 @@
+const reportWebVitals = onPerfEntry => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
diff --git a/src/setupTests.js b/src/setupTests.js
new file mode 100644
index 0000000..8f2609b
--- /dev/null
+++ b/src/setupTests.js
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom';
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..5a33944
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})