모달창에서 입력폼이 있는데, 추가로 옵션이라는 항목이 생기게 됐다.
기존엔 모든 옵션들이 입력하고 확인하면 끝나는데 이 옵션값은 한단계 더 들어가야하기에 생각할게 많았다.
그 모달에서 저장이 바로 되도 안되고, 확인 후 이전 모달에서 저장된 값이 보이고 그 후에 모든 내용이 저장되야 했다.
기술적 어려움보다 로직을 생각하기가 어려웠다.
일단 기존의 추가되있을 수 있던 옵션들이나 1번 모달에서 삭제할 수 있는 로직을 짰다
// 옵션 삭제시 필터링
const removerOptionHandler = () => {
const missingInMenuOptions = origineMenuOptions.filter(item =>
menuOptions.some(menu => menu.menu_id === item.menu_id),
);
const missingItems = missingInMenuOptions.filter(item => !menuOptions.some(menu => menu.id === item.id));
if (missingItems.length > 0) {
missingItems.forEach(async item => {
removeChangeMenuOptionsStore(item);
await removeMenuOption(item.id);
});
}
};
그리고 제일 중요한 옵션들을 먼저 정리하기 전에 팀원분의 가이드를 토대로 로직을 짰다.
가이드는 다음과 같다.
// 1. option정보를 담는 state를 3개 만든다.
menuOption, originalMenuOption, changedMenuOption
// 2 . 옵션 데이터를 불러온 후 두 state에 똑같이 담는다.
setMenuOption(data), setOriginalMenuOption(data)
// 3. 변경 사항은 menuOption state에 업데이트 한다.
// 4. 변경 사항 저장시 두 state를 비교하며 값이 다른게 하나라도 있는 것은 changedMenuOption에 담는다.
// 5. menu_option을 뽑아 menu_option에 upsert를 한다.
// 6-1. state에서 뽑은 menu_option에 id가 없는 경우는 DB에 들어가지 않은 경우이므로 upsert후 id를 받은 후 menu_option_detail을 뽑아 upsert를 한다.
// 6-2. state에서 뽑은 menu_option에 id가 있는 경우는 그 id를 이용해 menu_option_detail을 upsert한다.
이 내용을 토대로 짠 코드는 다음과 같다.
const filterOptionHandler = () => {
const differences = findDifferences(menuOptions, origineMenuOptions);
differences.map(async item => {
if (item.id === '') {
// 옵션 항목 supabase에 추가
const newOption = {
name: item.name,
is_use: item.is_use,
max_detail_count: item.max_detail_count,
menu_id: item.menu_id,
};
const { data: optionData } = await addMenuOption(newOption);
// 해당 data 받아서 그 option_id로 detail들 추가
item.menu_option_detail.map(async option => {
const addOptionForm: Omit<Tables<'menu_option_detail'>, 'id'> = {
name: option.name,
option_id: optionData[0].id,
price: option.price,
};
await addUpsertMenuOptionDetail(addOptionForm);
});
const newOptionList: MenuOptionWithDetail = {
id: optionData[0].id,
name: optionData[0].name,
is_use: optionData[0].is_use,
max_detail_count: optionData[0].max_detail_count,
menu_id: optionData[0].menu_id,
menu_option_detail: item.menu_option_detail,
};
setChangeMenuOptions([...changeMenuOptions, { ...newOptionList }]);
} else {
// 옵션은 있는거니까 해당 detail을 옵션 아이디로 supabase 추가
await updateMenuOption(item);
const newOptionList: MenuOptionWithDetail = {
id: item.id,
name: item.name,
is_use: item.is_use,
max_detail_count: item.max_detail_count,
menu_id: item.menu_id,
menu_option_detail: [],
};
// 디테일 있는것도 있고 없는것도 있으니까 upsert
item.menu_option_detail.map(async option => {
const addOptionForm: Omit<Tables<'menu_option_detail'>, 'id'> | Tables<'menu_option_detail'> = {
name: option.name,
option_id: newOptionList.id,
price: option.price,
};
if (option.id !== '') (addOptionForm as Tables<'menu_option_detail'>).id = option.id;
await addUpsertMenuOptionDetail(addOptionForm);
});
updateChangeMenuOptionsStore(prevMenuOptions =>
prevMenuOptions.map(option =>
option.id === item.id
? {
...item,
name: item.name ?? '',
is_use: item.is_use ?? false,
max_detail_count: item.max_detail_count ?? 1,
}
: item,
),
);
}
});
};
생각보다 가진 기능에 비해 로직이 길어서 맘에 썩 들진 않지만, 시간이 된다면 이 부분도 리팩토링 기간을 가지고 싶다
'TIL' 카테고리의 다른 글
[TIL][24.01.24] Project - react 직접 drag and drop 구현 (0) | 2024.01.25 |
---|---|
[TIL][24.01.23] project - magic pos QA (1) | 2024.01.23 |
[TIL][24.01.19] Project - useMutate에서 값 가져오기 (0) | 2024.01.20 |
[TIL][24.01.18] zustand 작업, query hooks로 빼기 (1) | 2024.01.19 |
[TIL] [24.01.17] zustand에서 state와 action을 분리하기 (0) | 2024.01.18 |
모달창에서 입력폼이 있는데, 추가로 옵션이라는 항목이 생기게 됐다.
기존엔 모든 옵션들이 입력하고 확인하면 끝나는데 이 옵션값은 한단계 더 들어가야하기에 생각할게 많았다.
그 모달에서 저장이 바로 되도 안되고, 확인 후 이전 모달에서 저장된 값이 보이고 그 후에 모든 내용이 저장되야 했다.
기술적 어려움보다 로직을 생각하기가 어려웠다.
일단 기존의 추가되있을 수 있던 옵션들이나 1번 모달에서 삭제할 수 있는 로직을 짰다
// 옵션 삭제시 필터링
const removerOptionHandler = () => {
const missingInMenuOptions = origineMenuOptions.filter(item =>
menuOptions.some(menu => menu.menu_id === item.menu_id),
);
const missingItems = missingInMenuOptions.filter(item => !menuOptions.some(menu => menu.id === item.id));
if (missingItems.length > 0) {
missingItems.forEach(async item => {
removeChangeMenuOptionsStore(item);
await removeMenuOption(item.id);
});
}
};
그리고 제일 중요한 옵션들을 먼저 정리하기 전에 팀원분의 가이드를 토대로 로직을 짰다.
가이드는 다음과 같다.
// 1. option정보를 담는 state를 3개 만든다.
menuOption, originalMenuOption, changedMenuOption
// 2 . 옵션 데이터를 불러온 후 두 state에 똑같이 담는다.
setMenuOption(data), setOriginalMenuOption(data)
// 3. 변경 사항은 menuOption state에 업데이트 한다.
// 4. 변경 사항 저장시 두 state를 비교하며 값이 다른게 하나라도 있는 것은 changedMenuOption에 담는다.
// 5. menu_option을 뽑아 menu_option에 upsert를 한다.
// 6-1. state에서 뽑은 menu_option에 id가 없는 경우는 DB에 들어가지 않은 경우이므로 upsert후 id를 받은 후 menu_option_detail을 뽑아 upsert를 한다.
// 6-2. state에서 뽑은 menu_option에 id가 있는 경우는 그 id를 이용해 menu_option_detail을 upsert한다.
이 내용을 토대로 짠 코드는 다음과 같다.
const filterOptionHandler = () => {
const differences = findDifferences(menuOptions, origineMenuOptions);
differences.map(async item => {
if (item.id === '') {
// 옵션 항목 supabase에 추가
const newOption = {
name: item.name,
is_use: item.is_use,
max_detail_count: item.max_detail_count,
menu_id: item.menu_id,
};
const { data: optionData } = await addMenuOption(newOption);
// 해당 data 받아서 그 option_id로 detail들 추가
item.menu_option_detail.map(async option => {
const addOptionForm: Omit<Tables<'menu_option_detail'>, 'id'> = {
name: option.name,
option_id: optionData[0].id,
price: option.price,
};
await addUpsertMenuOptionDetail(addOptionForm);
});
const newOptionList: MenuOptionWithDetail = {
id: optionData[0].id,
name: optionData[0].name,
is_use: optionData[0].is_use,
max_detail_count: optionData[0].max_detail_count,
menu_id: optionData[0].menu_id,
menu_option_detail: item.menu_option_detail,
};
setChangeMenuOptions([...changeMenuOptions, { ...newOptionList }]);
} else {
// 옵션은 있는거니까 해당 detail을 옵션 아이디로 supabase 추가
await updateMenuOption(item);
const newOptionList: MenuOptionWithDetail = {
id: item.id,
name: item.name,
is_use: item.is_use,
max_detail_count: item.max_detail_count,
menu_id: item.menu_id,
menu_option_detail: [],
};
// 디테일 있는것도 있고 없는것도 있으니까 upsert
item.menu_option_detail.map(async option => {
const addOptionForm: Omit<Tables<'menu_option_detail'>, 'id'> | Tables<'menu_option_detail'> = {
name: option.name,
option_id: newOptionList.id,
price: option.price,
};
if (option.id !== '') (addOptionForm as Tables<'menu_option_detail'>).id = option.id;
await addUpsertMenuOptionDetail(addOptionForm);
});
updateChangeMenuOptionsStore(prevMenuOptions =>
prevMenuOptions.map(option =>
option.id === item.id
? {
...item,
name: item.name ?? '',
is_use: item.is_use ?? false,
max_detail_count: item.max_detail_count ?? 1,
}
: item,
),
);
}
});
};
생각보다 가진 기능에 비해 로직이 길어서 맘에 썩 들진 않지만, 시간이 된다면 이 부분도 리팩토링 기간을 가지고 싶다
'TIL' 카테고리의 다른 글
[TIL][24.01.24] Project - react 직접 drag and drop 구현 (0) | 2024.01.25 |
---|---|
[TIL][24.01.23] project - magic pos QA (1) | 2024.01.23 |
[TIL][24.01.19] Project - useMutate에서 값 가져오기 (0) | 2024.01.20 |
[TIL][24.01.18] zustand 작업, query hooks로 빼기 (1) | 2024.01.19 |
[TIL] [24.01.17] zustand에서 state와 action을 분리하기 (0) | 2024.01.18 |