Feat: moved to zustand from redux
This commit is contained in:
@@ -11,10 +11,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@reduxjs/toolkit": "^2.5.0",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-redux": "^9.2.0"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.17.0",
|
"@eslint/js": "^9.17.0",
|
||||||
|
|||||||
14
src/App.tsx
14
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 './App.scss';
|
||||||
import { TierImage } from './components/Image';
|
import { TierImage } from './components/Image';
|
||||||
import { Tier, TierProps } from './components/Tier';
|
import { Tier, TierProps } from './components/Tier';
|
||||||
import { useAppDispatch, useAppSelector } from './hooks';
|
import useStore from './store';
|
||||||
import { addTierImage } from './store';
|
|
||||||
|
|
||||||
const default_tier_levels: TierProps[] = [
|
const default_tier_levels: TierProps[] = [
|
||||||
{
|
{
|
||||||
@@ -30,11 +30,7 @@ interface tierImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const images = useAppSelector(state => state.tierImages);
|
const [images, addTierImage] = useStore(useShallow(state => [state.images, state.addTierImage]));
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(images);
|
|
||||||
}, [images]);
|
|
||||||
|
|
||||||
const uploadBtn = useRef<HTMLInputElement>(null);
|
const uploadBtn = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
@@ -49,7 +45,7 @@ function App() {
|
|||||||
|
|
||||||
const handleAdd = (images: tierImage[]) => {
|
const handleAdd = (images: tierImage[]) => {
|
||||||
images.forEach(image => {
|
images.forEach(image => {
|
||||||
dispatch(addTierImage(image));
|
addTierImage(image);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useDraggable } from '@dnd-kit/core';
|
||||||
import { tierImage } from '../store';
|
import { tierImage } from '../store';
|
||||||
import './Image.scss';
|
import './Image.scss';
|
||||||
interface ImageProps {
|
interface ImageProps {
|
||||||
@@ -5,14 +6,22 @@ interface ImageProps {
|
|||||||
onDragStart?: () => void;
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className='flex flex-wrap justify-center gap-4 mr-1 anime-container'
|
className='flex flex-wrap justify-center gap-4 mr-1 anime-container'
|
||||||
onDragStart={() => {
|
{...listeners}
|
||||||
// e.preventDefault();
|
{...attributes}
|
||||||
if (onDragStart) onDragStart();
|
ref={setNodeRef}
|
||||||
}}
|
style={style}
|
||||||
>
|
>
|
||||||
<div className={`w-[calc(10rem*.5625)] h-40 relative`}>
|
<div className={`w-[calc(10rem*.5625)] h-40 relative`}>
|
||||||
<img src={image.url} alt={image.name} className='h-full w-full object-cover' />
|
<img src={image.url} alt={image.name} className='h-full w-full object-cover' />
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import useStore from '../store';
|
||||||
import { useAppDispatch, useAppSelector } from '../hooks';
|
|
||||||
import { changeTierImage, tierImage } from '../store';
|
|
||||||
import { TierImage } from './Image';
|
import { TierImage } from './Image';
|
||||||
|
|
||||||
export interface TierProps {
|
export interface TierProps {
|
||||||
@@ -11,8 +9,7 @@ export interface TierProps {
|
|||||||
export const Tier = ({ color, name, textColor }: TierProps) => {
|
export const Tier = ({ color, name, textColor }: TierProps) => {
|
||||||
let color_code = '';
|
let color_code = '';
|
||||||
let text_color_code = '';
|
let text_color_code = '';
|
||||||
const tierImages = useAppSelector(state => state.tierImages);
|
const tierImages = useStore(state => state.images);
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
switch (color) {
|
switch (color) {
|
||||||
case 'green':
|
case 'green':
|
||||||
color_code = '#00b894';
|
color_code = '#00b894';
|
||||||
@@ -34,31 +31,9 @@ export const Tier = ({ color, name, textColor }: TierProps) => {
|
|||||||
text_color_code = '#2d3436';
|
text_color_code = '#2d3436';
|
||||||
}
|
}
|
||||||
|
|
||||||
const [currentDragImage, setCurrentDragImage] = useState<tierImage | null>(null);
|
|
||||||
const [currentDragTier, setCurrentDragTier] = useState<string>('');
|
|
||||||
|
|
||||||
const onDragStart = (image: tierImage) => {
|
|
||||||
setCurrentDragImage(image);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className='w-full min-h-40 bg-[#2d3436] h-auto flex flex-row'>
|
||||||
className='w-full min-h-40 bg-[#2d3436] h-auto flex flex-row'
|
|
||||||
onDragEnd={() => {
|
|
||||||
// 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);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className='w-24 min-h-40 flex items-center justify-center'
|
className='w-24 min-h-40 flex items-center justify-center'
|
||||||
style={{
|
style={{
|
||||||
@@ -72,7 +47,7 @@ export const Tier = ({ color, name, textColor }: TierProps) => {
|
|||||||
{tierImages
|
{tierImages
|
||||||
.filter(image => image.category === name)
|
.filter(image => image.category === name)
|
||||||
.map((image, index) => (
|
.map((image, index) => (
|
||||||
<TierImage image={image} key={index} onDragStart={() => onDragStart(image)} />
|
<TierImage image={image} key={index} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { AppDispatch, RootState } from './store';
|
|
||||||
|
|
||||||
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
|
|
||||||
export const useAppSelector = useSelector.withTypes<RootState>();
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
|
import { DndContext } from '@dnd-kit/core';
|
||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import App from './App.tsx';
|
import App from './App.tsx';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import store from './store.ts';
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<Provider store={store}>
|
<DndContext>
|
||||||
<App />
|
<App />
|
||||||
</Provider>
|
</DndContext>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
);
|
);
|
||||||
|
|||||||
52
src/store.ts
52
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 {
|
export interface tierImage {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -6,34 +7,27 @@ export interface tierImage {
|
|||||||
category: string;
|
category: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tierImages = createSlice({
|
interface tierStore {
|
||||||
name: 'images',
|
images: tierImage[];
|
||||||
initialState: [] as tierImage[],
|
addTierImage: (image: tierImage) => void;
|
||||||
reducers: {
|
editTierImage: (image: tierImage, tier: string) => void;
|
||||||
addTierImage: (state, action: PayloadAction<tierImage>) => {
|
removeTierImage: (image: tierImage) => void;
|
||||||
state.push(action.payload);
|
}
|
||||||
},
|
|
||||||
removeTierImage: (state, action: PayloadAction<string>) => {
|
|
||||||
return state.filter(image => image.name !== action.payload);
|
|
||||||
},
|
|
||||||
changeTierImage: (state, action: PayloadAction<tierImage>) => {
|
|
||||||
return state.map(image => {
|
|
||||||
if (image.name == action.payload.name) return action.payload;
|
|
||||||
return image;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const { addTierImage, removeTierImage, changeTierImage } = tierImages.actions;
|
const useStore = create(
|
||||||
|
devtools<tierStore>(
|
||||||
const store = configureStore({
|
set => ({
|
||||||
reducer: {
|
images: [] as tierImage[],
|
||||||
tierImages: tierImages.reducer,
|
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' },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
export type RootState = ReturnType<typeof store.getState>;
|
export default useStore;
|
||||||
export type AppDispatch = typeof store.dispatch;
|
|
||||||
|
|
||||||
export default store;
|
|
||||||
|
|||||||
Reference in New Issue
Block a user