From 98a441a09b2d05ef5dc9cba7ec253377cbe44752 Mon Sep 17 00:00:00 2001 From: Cryptizism Date: Wed, 9 Aug 2023 04:05:23 +0100 Subject: [PATCH] Fully working --- package-lock.json | 131 +++++++++++++++++++++++++++ package.json | 2 + src/App.tsx | 13 ++- src/components/ImageHolder.tsx | 7 +- src/components/Modal.tsx | 84 +++++++++++++++++ src/components/Tier.tsx | 159 ++++++++++++++++++++++++++++----- src/components/TierList.tsx | 52 ++++++++--- 7 files changed, 410 insertions(+), 38 deletions(-) create mode 100644 src/components/Modal.tsx diff --git a/package-lock.json b/package-lock.json index 60e4d5e..00076c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@types/react": "^18.2.19", "@types/react-dom": "^18.2.7", "react": "^18.2.0", + "react-color": "^2.19.3", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "react-sortablejs": "^6.1.4", @@ -24,6 +25,7 @@ "web-vitals": "^2.1.4" }, "devDependencies": { + "@types/react-color": "^3.0.6", "@types/sortablejs": "^1.15.1", "tailwindcss": "^3.3.3" } @@ -2399,6 +2401,14 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -4101,6 +4111,16 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-color": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.6.tgz", + "integrity": "sha512-OzPIO5AyRmLA7PlOyISlgabpYUa3En74LP8mTMa0veCA719SvYQov4WLMsHvCgXP+L+KI9yGhYnqZafVGG0P4w==", + "dev": true, + "dependencies": { + "@types/react": "*", + "@types/reactcss": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.2.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", @@ -4109,6 +4129,15 @@ "@types/react": "*" } }, + "node_modules/@types/reactcss": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz", + "integrity": "sha512-qaIzpCuXNWomGR1Xq8SCFTtF4v8V27Y6f+b9+bzHiv087MylI/nTCqqdChNeWS7tslgROmYB7yeiruWX7WnqNg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -11737,6 +11766,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -11835,6 +11869,11 @@ "tmpl": "1.0.5" } }, + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -14173,6 +14212,23 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -14407,6 +14463,14 @@ "sortablejs": "1" } }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -15945,6 +16009,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -18857,6 +18926,12 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "requires": {} + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -20119,6 +20194,16 @@ "csstype": "^3.0.2" } }, + "@types/react-color": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.6.tgz", + "integrity": "sha512-OzPIO5AyRmLA7PlOyISlgabpYUa3En74LP8mTMa0veCA719SvYQov4WLMsHvCgXP+L+KI9yGhYnqZafVGG0P4w==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/reactcss": "*" + } + }, "@types/react-dom": { "version": "18.2.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", @@ -20127,6 +20212,15 @@ "@types/react": "*" } }, + "@types/reactcss": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz", + "integrity": "sha512-qaIzpCuXNWomGR1Xq8SCFTtF4v8V27Y6f+b9+bzHiv087MylI/nTCqqdChNeWS7tslgROmYB7yeiruWX7WnqNg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -25657,6 +25751,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -25742,6 +25841,11 @@ "tmpl": "1.0.5" } }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -27239,6 +27343,20 @@ } } }, + "react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "requires": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -27413,6 +27531,14 @@ "tiny-invariant": "1.2.0" } }, + "reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "requires": { + "lodash": "^4.0.1" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -28545,6 +28671,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, + "tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", diff --git a/package.json b/package.json index e4f9333..664dc13 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@types/react": "^18.2.19", "@types/react-dom": "^18.2.7", "react": "^18.2.0", + "react-color": "^2.19.3", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "react-sortablejs": "^6.1.4", @@ -43,6 +44,7 @@ ] }, "devDependencies": { + "@types/react-color": "^3.0.6", "@types/sortablejs": "^1.15.1", "tailwindcss": "^3.3.3" }, diff --git a/src/App.tsx b/src/App.tsx index 0f51161..d8f392a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,21 @@ // src/App.tsx -import React from 'react'; +import React, {useState} from 'react'; import './index.css'; import TierList from './components/TierList'; import ImageHolder from './components/ImageHolder'; +import Modal from './components/Modal'; const App = () => { + const [modalOpen, setModalOpen] = useState(true); + + const openModal = () => { + setModalOpen(true); + }; + + const closeModal = () => { + setModalOpen(false); + }; + return (
diff --git a/src/components/ImageHolder.tsx b/src/components/ImageHolder.tsx index eee40c9..f9c85bb 100644 --- a/src/components/ImageHolder.tsx +++ b/src/components/ImageHolder.tsx @@ -92,8 +92,11 @@ const ImageHolder = () => { group="shared" className="react-sortablejs flex space-x-4 p-4 bg-stone-700 min-h-[7rem] flex-wrap mt-8" > - {images.map((image) => ( - {`Image + {images.length === 0 ? ( +

Drag & Drop or Copy and Paste images in here!
If this is your first time using this you can right click tiers to edit them and drag them about, clicking the plus will add more tiers

+ ) : + images.map((image) => ( + ))} ); diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx new file mode 100644 index 0000000..c2f759d --- /dev/null +++ b/src/components/Modal.tsx @@ -0,0 +1,84 @@ +import React, { useState, ChangeEvent, FormEvent } from 'react'; +import { SketchPicker } from 'react-color'; + +interface ModalProps { + isOpen: boolean; + onClose: () => void; + onAddTier: (color: string, name: string) => void; +} + +const Modal: React.FC = ({ isOpen, onClose, onAddTier }) => { + const [name, setName] = useState(''); + const [color, setColor] = useState(''); + + const handleNameChange = (event: ChangeEvent) => { + setName(event.target.value); + }; + + const handleColorChange = (newColor: any) => { + setColor(newColor.hex); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + // Call the onAddTier function with the new tier's data + onAddTier(color, name); + onClose(); + }; + + if (!isOpen) { + return null; + } + + return ( +
+
+

New Tier

+
+
+ + +
+
+ +
+ +
+
+
+ + +
+
+
+
+ ); +}; + +export default Modal; diff --git a/src/components/Tier.tsx b/src/components/Tier.tsx index 6cb08c1..522d021 100644 --- a/src/components/Tier.tsx +++ b/src/components/Tier.tsx @@ -1,33 +1,144 @@ -// src/components/Tier.tsx -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { ReactSortable } from 'react-sortablejs'; +import { SketchPicker } from 'react-color'; -const Tier = ({ color, name }: { color: string, name: string }) => { +interface ImageItem { + id: number; + url: string; +} - interface ImageItem { - id: number; - url: string; +interface TierProps { + color: string; + id: string; + onDelete: () => void; +} + +const Tier: React.FC = ({ color, id, onDelete }) => { + const [images, setImages] = useState([]); + const [editedColor, setEditedColor] = useState(color); + const [editedName, setEditedName] = useState(id); + const [isContextMenuOpen, setIsContextMenuOpen] = useState(false); + const [contextMenuPosition, setContextMenuPosition] = useState({ left: 0, top: 0 }); + + const contextMenuRef = useRef(null); + + useEffect(() => { + setEditedColor(color); + }, [color]); + + useEffect(() => { + setEditedName(id); + }, [id]); + + useEffect(() => { + const handleOutsideClick = (e: MouseEvent) => { + if ( + isContextMenuOpen && + contextMenuRef.current && + !contextMenuRef.current.contains(e.target as Node) + ) { + handleCloseContextMenu(); } + }; + + window.addEventListener('click', handleOutsideClick); + + return () => { + window.removeEventListener('click', handleOutsideClick); + }; + }, [isContextMenuOpen]); + + const handleColorChange = (newColor: any) => { + setEditedColor(newColor.hex); + }; + + const handleNameChange = (event: React.ChangeEvent) => { + setEditedName(event.target.value); + }; + + const handleContextMenu = (e: React.MouseEvent) => { + e.preventDefault(); + setIsContextMenuOpen(true); + setContextMenuPosition({ left: e.clientX, top: e.clientY }); + }; + + const handleCloseContextMenu = () => { + setIsContextMenuOpen(false); + }; + + const handleDeleteTier = () => { + onDelete(); + handleCloseContextMenu(); + }; + + return ( +
+
+

+ {editedName} +

+
+ + {images.map((image) => ( + + ))} + - const [images, setImages] = useState([]); - - return ( -
-
-

{name}

-
- - {images.map((image) => ( - {`Image - ))} - + {isContextMenuOpen && ( +
+
+ + +
+
+ + +
+
+ + Delete Tier + +
- ); + )} +
+ ); }; export default Tier; diff --git a/src/components/TierList.tsx b/src/components/TierList.tsx index 169185b..59d90c5 100644 --- a/src/components/TierList.tsx +++ b/src/components/TierList.tsx @@ -1,22 +1,52 @@ -// src/components/TierList.tsx import React, { useState } from 'react'; +import { ReactSortable } from 'react-sortablejs'; import Tier from './Tier'; +import Modal from './Modal'; const TierList = () => { const [tiers, setTiers] = useState([ - { color: 'red', name: 'S' }, - { color: 'orange', name: 'A' }, - { color: 'gold', name: 'B' }, - { color: 'yellow', name: 'C' }, - { color: 'green', name: 'D' }, + { color: '#FF7F7F', id: 'S' }, + { color: '#FFBF7F', id: 'A' }, + { color: '#FFDF80', id: 'B' }, + { color: '#FFFF7F', id: 'C' }, + { color: '#BFFF7F', id: 'D' }, ]); + const addTier = (color: string, id: string) => { + const newTier = { color, id }; + setTiers((prevTiers) => [...prevTiers, newTier]); + }; + + const deleteTier = (index: number) => { + const updatedTiers = tiers.filter((_, i) => i !== index); + setTiers(updatedTiers); + }; + + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => { + setIsModalOpen(true); + }; + + const closeModal = () => { + setIsModalOpen(false); + }; + return ( -
- {tiers.map((tier, index) => ( - - ))} -
+ <> + + {tiers.map((tier, index) => ( + deleteTier(index)} + /> + ))} + + + + ); };