diff --git a/bun.lockb b/bun.lockb index 545166e..9b061fb 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 6a5f5de..22c7a7a 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ }, "dependencies": { "@dnd-kit/core": "^6.3.1", + "@reduxjs/toolkit": "^2.5.0", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-redux": "^9.2.0" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/src/App.tsx b/src/App.tsx index b6685fe..a85fef6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,9 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; import './App.css'; import { TierImage } from './components/Image'; import { Tier, TierProps } from './components/Tier'; +import { useAppDispatch, useAppSelector } from './hooks'; +import { addTierImage } from './store'; const default_tier_levels: TierProps[] = [ { @@ -21,17 +23,36 @@ const default_tier_levels: TierProps[] = [ }, ]; +interface tierImage { + name: string; + url: string; + category: string; +} + function App() { - const [images, setImages] = useState([]); + const images = useAppSelector(state => state.tierImages); + const dispatch = useAppDispatch(); useEffect(() => { console.log(images); }, [images]); + const uploadBtn = useRef(null); const clickUpload = () => { if (uploadBtn.current) uploadBtn.current.click(); }; + const getRandomCategoryName = () => { + const categoryNames = default_tier_levels.flatMap(category => category.name); + return categoryNames[Math.floor(Math.random() * categoryNames.length)]; + }; + + const handleAdd = (images: tierImage[]) => { + images.forEach(image => { + dispatch(addTierImage(image)); + }); + }; + return ( <>
@@ -45,9 +66,11 @@ function App() { ))}
- {images.map((image, index) => ( - - ))} + {images + .filter(image => image.category === '') + .map((image, index) => ( + + ))}
Upload @@ -60,12 +83,16 @@ function App() { onChange={event => { console.log(event.target.files); if (event.target.files) { - const upload_images: string[] = []; + const upload_images: tierImage[] = []; for (let i = 0; i < event.target.files.length; i++) { const url = URL.createObjectURL(event.target.files[i]); - upload_images.push(url); + upload_images.push({ + url: url, + name: event.target.files[i].name.replace('.jpeg', ''), + category: getRandomCategoryName(), + }); } - setImages(prev => [...prev, ...upload_images]); + handleAdd(upload_images); } }} /> diff --git a/src/components/Image.tsx b/src/components/Image.tsx index 3a518cf..cb32811 100644 --- a/src/components/Image.tsx +++ b/src/components/Image.tsx @@ -6,7 +6,7 @@ interface ImageProps { export const TierImage = ({ image, name }: ImageProps) => { return (
-
+
{name}
{name}
diff --git a/src/components/Tier.tsx b/src/components/Tier.tsx index 26969a5..63c5c2d 100644 --- a/src/components/Tier.tsx +++ b/src/components/Tier.tsx @@ -1,3 +1,6 @@ +import { useAppSelector } from '../hooks'; +import { TierImage } from './Image'; + export interface TierProps { color: 'red' | 'yellow' | 'green'; name: string; @@ -6,6 +9,7 @@ export interface TierProps { export const Tier = ({ color, name, textColor }: TierProps) => { let color_code = ''; let text_color_code = ''; + const tierImages = useAppSelector(state => state.tierImages); switch (color) { case 'green': color_code = '#00b894'; @@ -38,7 +42,13 @@ export const Tier = ({ color, name, textColor }: TierProps) => { >

{name}

-
+
+ {tierImages + .filter(image => image.category === name) + .map((image, index) => ( + + ))} +

diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 0000000..956153f --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,5 @@ +import { useDispatch, useSelector } from 'react-redux'; +import { AppDispatch, RootState } from './store'; + +export const useAppDispatch = useDispatch.withTypes(); +export const useAppSelector = useSelector.withTypes(); diff --git a/src/main.tsx b/src/main.tsx index bef5202..dbac8e5 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,14 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { Provider } from 'react-redux'; +import App from './App.tsx'; +import './index.css'; +import store from './store.ts'; createRoot(document.getElementById('root')!).render( - + + + , -) +); diff --git a/src/store.ts b/src/store.ts new file mode 100644 index 0000000..4c17dd7 --- /dev/null +++ b/src/store.ts @@ -0,0 +1,33 @@ +import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit'; + +interface tierImage { + name: string; + url: string; + category: string; +} + +const tierImages = createSlice({ + name: 'images', + initialState: [] as tierImage[], + reducers: { + addTierImage: (state, action: PayloadAction) => { + state.push(action.payload); + }, + removeTierImage: (state, action: PayloadAction) => { + return state.filter(image => image.name !== action.payload); + }, + }, +}); + +export const { addTierImage, removeTierImage } = tierImages.actions; + +const store = configureStore({ + reducer: { + tierImages: tierImages.reducer, + }, +}); + +export type RootState = ReturnType; +export type AppDispatch = typeof store.dispatch; + +export default store;