final project에서 내가 맡은 부분은 사장님들의 물류 관리 관련된 링크를 카드 형태로 모아두는 platform page이다.
내가 생각한
비즈니스 로직은 이렇다.
platform page는 사장님들이
편집하기를 눌렀을 때
위 update list를 조합해서 , 변경 전과 후를 비교해서 변경 된 것들만 data base에 update를 하고 싶다.
이럴 때 변경전, 후에 값을 비교할 때 사용 할 수 있는 도구는
platform card를 클릭시 useRef에 정보를 담고, 수정과 관련된 state를 만들어
수정버튼을 누르면 ref에 정보와 수정state의 정보를 비교해 변경됨이 없으면 버튼 클릭시에 return 시켜주고 하나라도 있으면
그 하나의 값만을 update
시킨다.
우선 알아둬야 할 점은 내 platform card의 비즈니스 로직 형태는 2가지 case가 있다.
이미지가 있고, link_url, title 있는 경우
이미지가 없고, link_url , title 있는 경우
그리고
이미지는 storage에서 img를 저장하고 img url을 받아 platform table의 row에 img_url
이라는 colum으로 저장해서
데이터를 받아 NEXT JS에서 제공하는 Image component
의 src에 바인딩 하는 로직이다.
수정 할 때 분기 처리를 해줘야 하는데
img 같은 경우에는 supabase에서 img_url로 데이터를 받아서 타입이 string이고 수정 할 때 이미지는 File
타입이므로
비교 할 시점에서 예외 처리를 해주어야 한다.
위 사진과 같이 case 별로 정리 하고
로직을 구현 하였다.
export interface EditFormType {
id: string;
name: string;
link_url: string;
store_id: string | null;
image_url?: string | null;
file?: File | null; // editTarget state에서 image 업로드 할 경우, 쓰일 타입
createdAt?: string;
}
const [isShowEditForm,setIsShowEditForm] = useState(false)// 수정 버튼을 클릭하면 true 로 바뀝니다.
const preDataRef = useRef<EditFormType | null>(); // 이전 값을 담아두는 ref
const [editTarget, setEditTarget] = useState<EditFormType>({
id: '',
name: '',
link_url: '',
store_id: storeId!,
image_url: preImage ?? null,
}); // 이전 데이터 값과 비교할 state
// 수정 할 카드의 정보를 담는 useEffect입니다.
useEffect(() => {
if (editRef.current) return;
editRef.current = { ...editTarget };
return () => {
editRef.current = null;
};
}, [isShowEditForm]);
위는 기본 필요한 로직이고
아래는 수정할 때 일어나는 함수 (main)이다.
const updatePlatForm = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const editData: EditFormType = {
...editTarget,
};
// object의 각 value 값을 비교해서 틀린 값만을 추출하기
let comparedData = Object.entries(editData).reduce((acc, [key, value]) => {
// 조금더 이해하기 위해 주석을 지우지 않았습니다.
// for (const key in editRef.current) {
// if (editRef.current[key as keyof EditFormType] !== value) {
// acc[key] = value;
// }
// }
if (editRef.current![key as keyof EditFormType] !== value) {
acc[key as keyof EditFormType] = value;
}
if (editRef.current!['image_url']) {
acc['image_url'] = editRef.current!['image_url'];
}
return acc;
}, new Object() as EditFormType);
if (isEmptyObject(comparedData) && editRef.current?.image_url === preImage) return;
// 나중에 refactoring하기
comparedData.id = editData.id;
comparedData.store_id = editData.store_id;
comparedData.createdAt;
// 기존이미지가 있고 이미지 변경 했을 때
if (editRef.current?.image_url && comparedData.file) {
comparedData.createdAt = moment().toISOString();
// 기존 이미지 삭제
await removePlatFormImage(editRef.current);
// 새로운 이미지 업로드
await uploadPlatFormImage(comparedData);
const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
comparedData = {
...comparedData,
image_url,
};
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
}
// 기존데이터에 이미지가 없을 때 이미지 등록을 할 때
if (!editRef.current?.image_url && comparedData.file) {
comparedData.createdAt = moment().toISOString();
await uploadPlatFormImage(comparedData);
const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
comparedData = {
...comparedData,
image_url,
};
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
}
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
const { platform, error } = await fetchPlatForm(storeId!);
setFecthDataList(platform);
setIsShowEditForm(false);
};
수정 할 때 이미지만 삭제 할 때 실행 되는 조건문이 필요하다 .
// 수정 할 때 이미지만 삭제 할 때 실행 되는 조건문
if (!preImage && !comparedData.link_url && !comparedData.name) {
await removePlatFormImage(comparedData);
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
const { platform, error } = await fetchPlatForm(storeId!);
setFecthDataList(platform);
setIsShowEditForm(false);
return;
}
const updatePlatForm = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const editData: EditFormType = {
...editTarget,
};
// object의 각 value 값을 비교해서 틀린 값만을 추출하기
let comparedData = Object.entries(editData).reduce((acc, [key, value]) => {
if (editRef.current![key as keyof EditFormType] !== value) {
acc[key as keyof EditFormType] = value;
}
if (editRef.current!['image_url']) {
acc['image_url'] = editRef.current!['image_url'];
}
return acc;
}, new Object() as EditFormType);
if (isEmptyObject(comparedData) && editRef.current?.image_url === preImage) return;
// 나중에 refactoring하기
comparedData.id = editData.id;
comparedData.store_id = editData.store_id;
comparedData.createdAt;
// 기존이미지가 있고 이미지 변경 했을 때
if (editRef.current?.image_url && comparedData.file) {
comparedData.createdAt = moment().toISOString();
// 기존 이미지 삭제
await removePlatFormImage(editRef.current);
// 새로운 이미지 업로드
await uploadPlatFormImage(comparedData);
const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
comparedData = {
...comparedData,
image_url,
};
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
}
// 기존데이터에 이미지가 없을 때 이미지 등록을 할 때
if (!editRef.current?.image_url && comparedData.file) {
comparedData.createdAt = moment().toISOString();
await uploadPlatFormImage(comparedData);
const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
comparedData = {
...comparedData,
image_url,
};
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
}
// 수정 할 때 이미지만 삭제 할 때 실행 되는 조건문
if (!preImage && !comparedData.link_url && !comparedData.name) {
await removePlatFormImage(comparedData);
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
const { platform, error } = await fetchPlatForm(storeId!);
setFecthDataList(platform);
setIsShowEditForm(false);
return;
}
const { file, createdAt, ...updateTarget } = comparedData;
await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
const { platform, error } = await fetchPlatForm(storeId!);
setFecthDataList(platform);
setIsShowEditForm(false);
};
user는
언제나 수정, 편집을 할 때 모든 것을 수정,편집하지 않기 때문이다.