Skip to content

Commit

Permalink
Merge pull request #1 from softeerbootcamp4th/CC-85
Browse files Browse the repository at this point in the history
[Feat] 공통 컴포넌트인 Overlay구현
  • Loading branch information
Dunkkkk authored Jul 25, 2024
2 parents fd1adb8 + f1dfb69 commit c9119cb
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 53 deletions.
7 changes: 1 addition & 6 deletions Caecae/src/App/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import "./main.css";

// 임시 React component
const App = () => {
return (
<div>
<h2 className="text-blue-500 text-xl font-bold">Hello, React!</h2>
<p className="text-lg font-medium">Hello, Typescript!</p>
</div>
);
return <div></div>;
};

ReactDOM.createRoot(document.getElementById("root")!).render(<App />);
Empty file removed Caecae/src/Job/.gitkeep
Empty file.
54 changes: 54 additions & 0 deletions Caecae/src/Job/Overlay/OverlayWork.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { createState } from "../../Shared/Hyundux/State";
import { makePayLoad } from "../../Shared/Hyundux/Util/StoreUtil";
import Reducer from "../../Shared/Hyundux/Reducer";
import Action from "../../Shared/Hyundux/Actions";

const WORK_NAME = "Overlay";

// state type
interface OverlayPayLoad {
isShowing: boolean;
index: number;
isOnButton: boolean;
}

const initOverlayState = createState<OverlayPayLoad>(WORK_NAME, {
isShowing: false,
index: 0,
isOnButton: false,
});

// define reducer
const overlayReducer: Reducer<OverlayPayLoad> = {
type: WORK_NAME,
reducer: async function reducer(state, action) {
const payLoad = state.payload;
switch (action.actionName) {
case "toggleOverlay": {
return makePayLoad(state, { isShowing: !payLoad.isShowing });
}
case "nextPage": {
return makePayLoad(state, { index: payLoad.index + 1 });
}
default:
return state;
}
},
};
// actions
const action = {
toggleOverlay: (): Action => {
return {
type: WORK_NAME,
actionName: "toggleOverlay",
};
},
nextPage: (): Action => {
return {
type: WORK_NAME,
actionName: "nextPage",
};
},
};

export { action, initOverlayState, overlayReducer };
4 changes: 2 additions & 2 deletions Caecae/src/Shared/Hyundux/Example_Counter/ConuntUI.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import useBind from "../Hooks/Binding.tsx";
import useWork from "../Hooks/useWork.tsx";
import { action, initCountState, countReducer } from "./CountWorkFlow.tsx";
import store from "../Store.tsx";

const Counter = () => {
const state = useBind(initCountState, countReducer);
const state = useWork(initCountState, countReducer);

function temp1() {
store.dispatch(action.countUp());
Expand Down
16 changes: 0 additions & 16 deletions Caecae/src/Shared/Hyundux/Hooks/Binding.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions Caecae/src/Shared/Hyundux/Hooks/useWork.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useState } from "react";
import HState from "../State";
import store from "../Store";
import Reducer from "../Reducer";

function useWork<PayLoad>(
initialState: HState<PayLoad>,
reducer: Reducer<PayLoad>
): PayLoad {
const [state, setState] = useState<HState<PayLoad>>(initialState);
store.subscribe(state, reducer, (newState) => {
setState(newState);
});

return state.payload;
}

export default useWork;
79 changes: 50 additions & 29 deletions Caecae/src/Shared/Hyundux/Store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,56 @@ import removeFirst from "./Util/RemoveFirst";
import replaceFirst from "./Util/ReplaceFirst";

const store: {
states: State<unknown>[],
reducers: Reducer<unknown>[],
subscribe: <PayLoad>(initState: State<PayLoad>, reducer: Reducer<PayLoad>, cb: (state: State<PayLoad>) => void) => void,
dispatch: (action: Action) => void,
publish: <PayLoad>(state: State<PayLoad>) => void,
subscribeList: Map<string, <PayLoad>(state: State<PayLoad>) => void>,
states: State<unknown>[];
reducers: Reducer<unknown>[];
subscribe: <PayLoad>(
initState: State<PayLoad>,
reducer: Reducer<PayLoad>,
cb: (state: State<PayLoad>) => void
) => void;
dispatch: (action: Action) => void;
publish: <PayLoad>(state: State<PayLoad>) => void;
subscribeList: Map<string, <PayLoad>(state: State<PayLoad>) => void>;
} = {
states: [],
reducers: [],
subscribeList: new Map(),
dispatch: async function (action) {
const reducer = this.reducers.filter(reducer => reducer.type == action.type)[0].reducer
const { removed, newArray } = removeFirst(this.states, (state) => state.type == action.type)
const newState = await reducer(removed, action);
// 여기서 모든것을 바로 state를 적용하는것이 아니라 이게 다른 state도 propagation하는지도 확인해야함
this.states = [...newArray, newState];
this.publish(newState);
},
publish: function (state) {
const publishedCallBack = this.subscribeList.get(state.type);
if (publishedCallBack !== undefined) {
publishedCallBack(state);
}
},
subscribe: function <PayLoad>(state: State<PayLoad>, reducer: Reducer<PayLoad>, cb: (state: State<PayLoad>) => void) {
this.states = replaceFirst(this.states, state, (element) => element.type == state.type)
this.reducers = replaceFirst(this.reducers, reducer as Reducer<unknown>, (element) => element.type == state.type)
this.subscribeList.set(state.type, cb as (state: State<unknown>) => void);
states: [],
reducers: [],
subscribeList: new Map(),
dispatch: async function (action) {
const reducer = this.reducers.filter(
(reducer) => reducer.type == action.type
)[0].reducer;
const { removed, newArray } = removeFirst(
this.states,
(state) => state.type == action.type
);
const newState = await reducer(removed, action);
// 여기서 모든것을 바로 state를 적용하는것이 아니라 이게 다른 state도 propagation하는지도 확인해야함
this.states = [...newArray, newState];
this.publish(newState);
},
publish: function (state) {
const publishedCallBack = this.subscribeList.get(state.type);
if (publishedCallBack !== undefined) {
publishedCallBack(state);
}
}
},
subscribe: function <PayLoad>(
state: State<PayLoad>,
reducer: Reducer<PayLoad>,
cb: (state: State<PayLoad>) => void
) {
this.states = replaceFirst(
this.states,
state,
(element) => element.type == state.type
);
this.reducers = replaceFirst(
this.reducers,
reducer as Reducer<unknown>,
(element) => element.type == state.type
);
this.subscribeList.set(state.type, cb as (state: State<unknown>) => void);
},
};

export default store
export default store;
22 changes: 22 additions & 0 deletions Caecae/src/Shared/Util/FindChildrenElement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { isValidElement, ReactElement, ReactNode } from "react";

const findChildrenElement = (
elements: ReactNode,
checkFn: (element: ReactElement) => boolean
): ReactElement | null => {
let returnElement: ReactElement | null = null;
React.Children.forEach(elements, (element) => {
if (!isValidElement(element)) {
return;
}
if (element.type === React.Fragment) {
return;
}
if (checkFn(element)) {
returnElement = element.props.element;
}
});
return returnElement;
};

export default findChildrenElement;
3 changes: 3 additions & 0 deletions Caecae/src/Shared/assets/xButton.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions Caecae/src/Widget/Component/Overlay/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { ReactNode } from "react";
import useWork from "../../../Shared/Hyundux/Hooks/useWork";
import {
initOverlayState,
overlayReducer,
action,
} from "../../../Job/Overlay/OverlayWork";
import store from "../../../Shared/Hyundux/Store";
import findChildrenElement from "../../../Shared/Util/FindChildrenElement";

interface OverLayProps {
children: ReactNode;
}

const OverLay: React.FC<OverLayProps> = ({ children }) => {
const state = useWork(initOverlayState, overlayReducer);
const content = findChildrenElement(
children,
(element) =>
element.props.index !== undefined && element.props.index == state.index
);

if (state.isShowing) {
return (
<div className="absolute inset-0 bg-black opacity-50 flex flex-col items-center justify-center">
<div
className="relative bg-white shadow-lg z-10"
style={{ width: "62%", height: "71%" }}
>
<img
src="/src/Shared/assets/xButton.svg"
className="absolute right-10 top-10"
onClick={() => {
store.dispatch(action.toggleOverlay());
}}
/>
{content}
</div>
</div>
);
} else {
return null;
}
};

export default OverLay;
12 changes: 12 additions & 0 deletions Caecae/src/Widget/Component/Overlay/OverlayContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { ReactElement } from "react";

interface OverLayContentProps {
index: number;
element: ReactElement;
}

const OverLayContent: React.FC<OverLayContentProps> = () => {
return null;
};

export default OverLayContent;

0 comments on commit c9119cb

Please sign in to comment.