diff --git a/packages/xianeml/src/components/MenuItem.ts b/packages/xianeml/src/components/MenuItem.ts index 9da783e..6a0fcc5 100644 --- a/packages/xianeml/src/components/MenuItem.ts +++ b/packages/xianeml/src/components/MenuItem.ts @@ -1,13 +1,9 @@ import { Tstate } from '../types/store.js'; -import { getCategoryMenus } from '../utils/helper.js'; -const MenuItem = (state: Tstate) => { - const { menus, currentTab } = state; - const categoryMenus = getCategoryMenus(menus, currentTab); - - return categoryMenus +const MenuItem = ({ menus }: Tstate) => { + return menus .map( - menu => + (menu) => ``, +` ) .join(''); }; diff --git a/packages/xianeml/src/js/events.ts b/packages/xianeml/src/js/events.ts index cc3a26a..0ddb4e7 100644 --- a/packages/xianeml/src/js/events.ts +++ b/packages/xianeml/src/js/events.ts @@ -15,13 +15,15 @@ export const handleNavigation = (store: Tstore) => (e: Event) => { store.dispatch(setCurrentTab(categoryId)); }; -export const handleSubmitMenuForm = (store: Tstore) => (e: Event) => { +export const handleSubmitMenuForm = (store: Tstore) => async (e: Event) => { e.preventDefault(); const $menuInput = $('#espresso-menu-name') as HTMLInputElement; if (!$menuInput.value) return; - const { menus, currentTab } = store.getState(); + const state = await store.getState(); + const { menus, currentTab } = state; + if (menus && menus.length === 20) { return alert('메뉴는 20개까지 추가 가능합니다.'); } @@ -29,7 +31,7 @@ export const handleSubmitMenuForm = (store: Tstore) => (e: Event) => { $menuInput.value = ''; }; -export const handleMenuList = (e: Event, store: Tstore) => { +export const handleMenuList = (store: Tstore) => (e: Event) => { const target = e.target as HTMLElement; const targetMenuId = (target.parentElement as HTMLElement).id; diff --git a/packages/xianeml/src/js/renderViews.ts b/packages/xianeml/src/js/renderViews.ts index a524bca..77e7a87 100644 --- a/packages/xianeml/src/js/renderViews.ts +++ b/packages/xianeml/src/js/renderViews.ts @@ -3,13 +3,13 @@ import layoutView from '../components/layout/index.js'; import { Tstore } from '../types/store.js'; import { handleNavigation, handleSubmitMenuForm, handleMenuList } from './events.js'; -export const renderViews = (store: Tstore) => { - const state = store.getState(); +export const renderViews = async (store: Tstore) => { + const state = await store.getState(); $('#app').innerHTML = layoutView(state); const $menuForm = $('#espresso-menu-form'); const $menuList = $('#espresso-menu-list'); $('nav').addEventListener('click', handleNavigation(store)); $menuForm.addEventListener('submit', handleSubmitMenuForm(store)); - $menuList.addEventListener('click', (e: Event) => handleMenuList(e, store)); + $menuList.addEventListener('click', handleMenuList(store)); }; diff --git a/packages/xianeml/src/store/helper.ts b/packages/xianeml/src/store/helper.ts index a735825..4c696d5 100644 --- a/packages/xianeml/src/store/helper.ts +++ b/packages/xianeml/src/store/helper.ts @@ -1,4 +1,5 @@ import { Treducer, TmenuAction, Tlistener, Tstate, Tstore } from '../types/store.js'; +import { getMenus } from '../api/menu.js'; export const createStore = (reducer: Treducer): Tstore => { const initialState: Tstate = { @@ -15,19 +16,15 @@ export const createStore = (reducer: Treducer): Tstore => { const listeners: Tlistener[] = []; - const getState = () => { - return JSON.parse(localStorage.getItem('state') || '{}') as Tstate; + const getState = async () => { + const menus = await getMenus(initialState.currentTab.id); + const state = { ...initialState, menus }; + + return state; }; const dispatch = (action: TmenuAction) => { - const storageState = JSON.parse(localStorage.getItem('state') || '{}'); - - if (!storageState) { - localStorage.setItem('state', JSON.stringify(initialState)); - } else { - const newState = reducer(storageState, action); - localStorage.setItem('state', JSON.stringify(newState)); - } + reducer(initialState, action); publish(); }; diff --git a/packages/xianeml/src/store/menu.ts b/packages/xianeml/src/store/menu.ts index b37203b..56d046b 100644 --- a/packages/xianeml/src/store/menu.ts +++ b/packages/xianeml/src/store/menu.ts @@ -1,5 +1,6 @@ import { Tcategory, TmenuAction } from '../types/store.js'; import { Tstate } from '../types/store.js'; +import { createMenu } from '../api/menu.js'; /* 액션 타입 정의 */ const CREATE_MENU = 'CREATE_MENU' as const; @@ -47,24 +48,18 @@ export const setCurrentTab = (categoryId: string) => ({ }); // 리듀서는 새로운 상태를 생성하는 함수. -export default function reducer(state: Tstate, action: TmenuAction) { +export default async function reducer(state: Tstate, action: TmenuAction) { const { type, payload } = action; const { categoryId = '', menuId = '', menuName = '' } = payload; const { menus, categories } = state; switch (type) { case CREATE_MENU: { - const categoryMenus = menus.filter(menu => { - return menu.categoryId === categoryId; - }); - // TODO: 중복 가능성 의심, UUID 적용 - const id = `${categoryId}-menu-id-${categoryMenus.length}`; - const newMenu = { id, categoryId, menuName, inStock: true }; - const newMenuList = [...menus, newMenu]; - return { ...state, menus: newMenuList }; + await createMenu({ category: categoryId, name: menuName }); + break; } case EDIT_MENU: { - const newMenuList = menus.map(menu => { + const newMenuList = menus.map((menu) => { if (menu.id === menuId) { menu.menuName = menuName; } @@ -73,11 +68,11 @@ export default function reducer(state: Tstate, action: TmenuAction) { return { ...state, menus: newMenuList }; } case REMOVE_MENU: { - const newMenuList = menus.filter(menu => menu.id !== menuId); + const newMenuList = menus.filter((menu) => menu.id !== menuId); return { ...state, menus: newMenuList }; } case SOLD_OUT_MENU: { - const newMenuList = menus.map(menu => { + const newMenuList = menus.map((menu) => { if (menu.id === menuId) { menu.inStock = false; } diff --git a/packages/xianeml/src/types/api.ts b/packages/xianeml/src/types/api.ts index 7702729..426ba74 100644 --- a/packages/xianeml/src/types/api.ts +++ b/packages/xianeml/src/types/api.ts @@ -1,5 +1,17 @@ export type Tparams = { - category: string; + category?: string; menuId?: string; name?: string; }; + +export type TmenuResponse = { + menuId: string; + name: string; + isSoldOut: boolean; +}; + +export type TrequestConfig = { + url: string; + method: string; + data?: { name?: string }; +}; diff --git a/packages/xianeml/src/types/store.ts b/packages/xianeml/src/types/store.ts index c3f7faa..4c1989f 100644 --- a/packages/xianeml/src/types/store.ts +++ b/packages/xianeml/src/types/store.ts @@ -1,7 +1,7 @@ -export type Treducer = (state: Tstate, action: TmenuAction) => Tstate; +export type Treducer = (state: Tstate, action: TmenuAction) => Promise; export type Tstore = { - getState: () => Tstate; + getState: () => Promise; dispatch: (action: TmenuAction) => void; subscribe: (callback: Tlistener) => void; }; @@ -23,7 +23,6 @@ export type TmenuAction = { export type Tmenu = { id: string; - categoryId: string; menuName: string; inStock: boolean; }; diff --git a/packages/xianeml/src/utils/request.ts b/packages/xianeml/src/utils/request.ts index cbd261f..f3be841 100644 --- a/packages/xianeml/src/utils/request.ts +++ b/packages/xianeml/src/utils/request.ts @@ -1,26 +1,33 @@ import { SERVER_URL } from '../utils/constants/env.js'; +import { TmenuResponse, TrequestConfig } from '../types/api.js'; +import { Tmenu } from '../types/store.js'; -type Tconfig = { - url: string; - method: string; - data?: { name?: string }; -}; - -export default async (config: Tconfig) => { +export default async (config: TrequestConfig) => { const { url, method, data } = config; const requestUrl = SERVER_URL + url; + const headers = { + 'Content-Type': 'application/json', + }; + + try { + const response = await fetch(requestUrl, { + method, + headers, + body: JSON.stringify(data), + }); + + if (response.status !== 200) throw Error('요청 에러'); + if (method !== 'GET') return; - const response = await fetch(requestUrl, { - method, - body: JSON.stringify(data), - }); - console.log('요청정보? >>>> ', response); - const resData = await response.json(); + const resData = await response.json(); - if (response.status === 200) { - return resData; - } else { - throw new Error('서버요청 에러!!'); + return resData.map((data: TmenuResponse) => ({ + id: data.menuId, + menuName: data.name, + inStock: !data.isSoldOut, + })) as Tmenu[]; + } catch (e) { + console.error(e); } };