diff --git a/bun.lockb b/bun.lockb index f1c32c9..b32388c 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2646e71..21b8805 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,9 @@ }, "dependencies": { "@dnd-kit/core": "^6.3.1", - "@reduxjs/toolkit": "^2.5.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-redux": "^9.2.0" + "zustand": "^5.0.3" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/src/App.tsx b/src/App.tsx index 6e16f8a..87e3ee7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,9 @@ -import { useEffect, useRef } from 'react'; +import { useRef } from 'react'; +import { useShallow } from 'zustand/shallow'; import './App.scss'; import { TierImage } from './components/Image'; import { Tier, TierProps } from './components/Tier'; -import { useAppDispatch, useAppSelector } from './hooks'; -import { addTierImage } from './store'; +import useStore from './store'; const default_tier_levels: TierProps[] = [ { @@ -30,11 +30,7 @@ interface tierImage { } function App() { - const images = useAppSelector(state => state.tierImages); - const dispatch = useAppDispatch(); - useEffect(() => { - console.log(images); - }, [images]); + const [images, addTierImage] = useStore(useShallow(state => [state.images, state.addTierImage])); const uploadBtn = useRef(null); @@ -49,7 +45,7 @@ function App() { const handleAdd = (images: tierImage[]) => { images.forEach(image => { - dispatch(addTierImage(image)); + addTierImage(image); }); }; diff --git a/src/components/Image.tsx b/src/components/Image.tsx index e9ea963..c744dc6 100644 --- a/src/components/Image.tsx +++ b/src/components/Image.tsx @@ -1,3 +1,4 @@ +import { useDraggable } from '@dnd-kit/core'; import { tierImage } from '../store'; import './Image.scss'; interface ImageProps { @@ -5,14 +6,22 @@ interface ImageProps { onDragStart?: () => void; } -export const TierImage = ({ image, onDragStart }: ImageProps) => { +export const TierImage = ({ image }: ImageProps) => { + const { attributes, listeners, setNodeRef, transform } = useDraggable({ + id: `draggable:${image.name}`, + }); + const style = transform + ? { + transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`, + } + : undefined; return (
{ - // e.preventDefault(); - if (onDragStart) onDragStart(); - }} + {...listeners} + {...attributes} + ref={setNodeRef} + style={style} >
{image.name} diff --git a/src/components/Tier.tsx b/src/components/Tier.tsx index c1fdef3..f40e8eb 100644 --- a/src/components/Tier.tsx +++ b/src/components/Tier.tsx @@ -1,6 +1,4 @@ -import { useState } from 'react'; -import { useAppDispatch, useAppSelector } from '../hooks'; -import { changeTierImage, tierImage } from '../store'; +import useStore from '../store'; import { TierImage } from './Image'; export interface TierProps { @@ -11,8 +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); - const dispatch = useAppDispatch(); + const tierImages = useStore(state => state.images); switch (color) { case 'green': color_code = '#00b894'; @@ -34,31 +31,9 @@ export const Tier = ({ color, name, textColor }: TierProps) => { text_color_code = '#2d3436'; } - const [currentDragImage, setCurrentDragImage] = useState(null); - const [currentDragTier, setCurrentDragTier] = useState(''); - - const onDragStart = (image: tierImage) => { - setCurrentDragImage(image); - }; - return ( <> -
{ - // e.preventDefault(); - if (currentDragImage) { - if (currentDragImage.category === name) return; - console.log(currentDragImage); - console.log(name); - dispatch(changeTierImage({ ...currentDragImage, category: name })); - } - setCurrentDragImage(null); - }} - onDragOver={() => { - if (currentDragTier !== name) setCurrentDragTier(name); - }} - > +
{ {tierImages .filter(image => image.category === name) .map((image, index) => ( - onDragStart(image)} /> + ))}
diff --git a/src/hooks.ts b/src/hooks.ts deleted file mode 100644 index 956153f..0000000 --- a/src/hooks.ts +++ /dev/null @@ -1,5 +0,0 @@ -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 aa8806a..66a65dc 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,14 +1,13 @@ +import { DndContext } from '@dnd-kit/core'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; -import { Provider } from 'react-redux'; import App from './App.tsx'; import './index.scss'; -import store from './store.ts'; createRoot(document.getElementById('root')!).render( - + - + , ); diff --git a/src/store.ts b/src/store.ts index 6406849..ecc77d0 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,4 +1,5 @@ -import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; export interface tierImage { name: string; @@ -6,34 +7,27 @@ export interface tierImage { 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); - }, - changeTierImage: (state, action: PayloadAction) => { - return state.map(image => { - if (image.name == action.payload.name) return action.payload; - return image; - }); - }, - }, -}); +interface tierStore { + images: tierImage[]; + addTierImage: (image: tierImage) => void; + editTierImage: (image: tierImage, tier: string) => void; + removeTierImage: (image: tierImage) => void; +} -export const { addTierImage, removeTierImage, changeTierImage } = tierImages.actions; +const useStore = create( + devtools( + set => ({ + images: [] as tierImage[], + addTierImage: (image: tierImage) => set(state => ({ images: [...state.images, image] })), + editTierImage: (image: tierImage, tier: string) => + set(state => ({ images: state.images.map(i => (i.name === image.name ? { ...i, category: tier } : i)) })), + removeTierImage: (image: tierImage) => { + URL.revokeObjectURL(image.url); + set(state => ({ images: state.images.filter(i => i.name !== image.name) })); + }, + }), + { name: 'tierStore' }, + ), +); -const store = configureStore({ - reducer: { - tierImages: tierImages.reducer, - }, -}); - -export type RootState = ReturnType; -export type AppDispatch = typeof store.dispatch; - -export default store; +export default useStore;