Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix/#58]: 과목 편집 문제 해결 #89

Merged
merged 10 commits into from
Aug 26, 2024
13 changes: 9 additions & 4 deletions api/subjectFormApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ export const subjectFormApi = async (payload: SubjectPayload) => {
addedSubjects: [], // 기본값으로 빈 배열 설정
deletedSubjects: [], // 기본값으로 빈 배열 설정
};
console.log('API 요청 데이터:', payload);

// 추가된 과목이 있으면 requestBody에 추가
if (payload.addedSubjects.length > 0) {
// 추가된 과목이 있으면 requestBody에 추가, 빈 배열일 때는 빈 배열만 전송
if (payload.addedSubjects.length >= 0) {
requestBody.addedSubjects = payload.addedSubjects;
}

// 삭제된 과목이 있으면 requestBody에 추가
if (payload.deletedSubjects.length > 0) {
// 삭제된 과목이 있으면 requestBody에 추가, 빈 배열일 때는 빈 배열만 전송
if (payload.deletedSubjects.length >= 0) {
requestBody.deletedSubjects = payload.deletedSubjects;
}

Expand All @@ -35,6 +36,10 @@ export const subjectFormApi = async (payload: SubjectPayload) => {
return { success: false, message: '요청을 처리하는 중 오류가 발생했습니다. 나중에 다시 시도해 주세요.' };
}

if (requestBody.addedSubjects.length === 0 && requestBody.deletedSubjects.length === 0) {
return { success: true }; // 변경 사항이 없으므로 성공으로 처리
}

return { success: true };
} catch (error) {
console.error('subjectFormApi 에러:', error);
Copy link
Member

@Kong-E Kong-E Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error code에 따라 메시지를 다르게 전달했으면 좋겠어요~

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영하겠습니다!!

Expand Down
2 changes: 1 addition & 1 deletion components/ranking/topLanking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function TopRankings({ rankings, activeTab }: TopRankingsProps) {
modifiedRankings.slice(0, 3).map((student, index) => {
const sizeClass = index === 1 ? styles.ranking_box_size_large : styles.ranking_box_size_small;
const medalImage = index === 0 ? rankingTwo : index === 1 ? rankingOne : rankingThird;
const medalSizeClass = index === 1 ? styles.medal_image_large : styles.medal_image_small;
const medalSizeClass = index === 0 ? styles.medal_image_large : styles.medal_image_small;

// 시간 포맷팅
const formattedStudyTime = formatTime(student.studyTime);
Expand Down
60 changes: 40 additions & 20 deletions components/study/SubjectEditForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
import { Text } from '@radix-ui/themes';
import styles from './SubjectForm.module.css';
import { useSubjectStore } from '@/store/subjectStore';
import { subjectFormApi } from '@/api/subjectFormApi'; // API 함수 임포트
import { subjectFormApi } from '@/api/subjectFormApi';
import { fetchSubjects } from '@/api/subjectFormApi';
import useSWR from 'swr';

Expand Down Expand Up @@ -36,36 +36,55 @@ export default function SubjectEditForm({
setSubjects,
} = useSubjectStore();

// SWR을 사용하여 과목 데이터를 가져오고 동기화
// SWR을 사용하여 과목 데이터를 가져오고 동기화 - 마이페이지 새로 고침 시 저장
const { data, error } = useSWR('subjects', fetchSubjects, {
onSuccess: (data) => {
setSubjects(data.subjects);
if (addedSubjects.length === 0 && deletedSubjects.length === 0) {
setSubjects(data.subjects);
}
},
});

if (error) {
console.error('Failed to load subjects:', error);
}

// 과목 편집 저장 버튼
const handleAddSubject = () => {
if (newSubjectName.trim() !== '') {
const newSubject = { id: Date.now(), name: newSubjectName }; // 예시로 새로운 ID 생성
addSubject(newSubject);
setNewSubjectName('');
if (newSubjectName.trim() === '') {
return;
}

// 중복 체크
const isDuplicate = subjects.some((subject) => subject.name === newSubjectName.trim());
if (isDuplicate) {
alert('이 과목은 이미 존재합니다.');
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복 체크 해주는거 좋은것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굳굳

}

const newSubject = { id: Date.now(), name: newSubjectName }; // 예시로 새로운 ID 생성
addSubject(newSubject);
setNewSubjectName('');
};

const handleCancelEditing = () => {
revertChanges(); // 취소 시 초기 상태로 되돌리기
setEditing(false); // 편집 모드 종료
revertChanges();
setEditing(false);
};

const handleSaveEditing = async () => {
const payload = {
addedSubjects: addedSubjects,
deletedSubjects: deletedSubjects,
addedSubjects: addedSubjects.map((subject) => subject.name), // 이름만 추출
deletedSubjects: deletedSubjects.map((subject) => subject.id), // ID만 추출
};

// 추가된 과목과 삭제된 과목이 모두 비어있는 경우
if (payload.addedSubjects.length === 0 && payload.deletedSubjects.length === 0) {
alert('변경된 과목이 없습니다.');
setEditing(false);
return;
}

try {
const response = await subjectFormApi(payload);
if (response.success) {
Expand All @@ -76,19 +95,18 @@ export default function SubjectEditForm({

// 삭제된 ID와 추가된 과목명을 알림으로 표시
alert(
`삭제한 과목 ID는 ${deletedSubjects.join(', ')} 입니다\n` +
`추가된 과목은 ${addedSubjects.join(', ')} 입니다`,
`삭제한 과목 ID는 ${deletedSubjects.map((subject) => subject.id).join(', ')} 입니다\n` +
`추가된 과목은 ${addedSubjects.map((subject) => subject.name).join(', ')} 입니다`,
);

// 부모 컴포넌트에 저장 완료를 알림
onSaveEditing();
} else {
console.error('Failed to update subjects:', response.message);
alert(`업데이트 실패: ${response.message}`); // 오류 메시지를 사용자에게 표시
alert(`업데이트 실패: ${response.message}`);
}
} catch (error) {
console.error('Error sending request:', error);
alert('요청을 처리하는 중 오류가 발생했습니다.'); // 오류 처리
alert('요청을 처리하는 중 오류가 발생했습니다.');
}
};

Expand All @@ -114,10 +132,12 @@ export default function SubjectEditForm({
</div>
<div className={styles.subject_choice_box} style={subjectChoiceBoxStyle}>
{subjects?.map((subject) => (
<div key={subject.id} className={styles.subject_item}>
<Text as="p" size="3" className={styles.subject_item_text}>
{subject.name}
</Text>
<div key={subject.id} className={styles.subject_item_wrapper}>
<div className={styles.subject_item}>
<Text as="p" size="3" className={styles.subject_item_text}>
{subject.name}
</Text>
</div>
<button className={styles.delete_button} onClick={() => deleteSubject(subject.id)}>
-
</button>
Expand Down
69 changes: 44 additions & 25 deletions components/study/SubjectForm.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,14 @@
}

/* 과목 박스 전체 */
.subject_select_choice_box {
max-height: 400px !important;
}

.subject_choice_box {
position: relative;
background-color: white;
max-height: 350px;
max-height: 330px;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
Expand All @@ -135,6 +140,13 @@
row-gap: 15px;
overflow-y: auto;
overflow-x: hidden;
padding-right: 10px;
}

.subject_item_wrapper {
position: relative;
display: inline-block;
max-width: 99%;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

왜 최대 넓이를 99%만 줬는지 궁금합니다~!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100%로 하면 (-)삭제 버튼이 살짝 짤리던데 width값을 줄이는 거 말고 다른 방법이 있을까요?!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflow-x 때문인데 전에도 overflow-y 때문에 감싸고 있는 박스에 padding-top:5px을 줬었죠~ 마찬가지로 하면 됩니다^_^
그런데 padding-right를 주면 좌우여백이 조금 달라지니 margin-right:-5px로 당겨주면 더더더 좋겠습니다~

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 다시 해봤을 때 max-width:100%로 해도 큰 문제가 없는 것 같아서 100%로 수정했습니다,,!

}

.subject_item {
Expand All @@ -150,10 +162,41 @@
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
white-space: nowrap;
flex: 0 1 auto;
}

.subject_item_text {
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
}

/* 삭제버튼 */

.delete_button {
position: absolute;
top: -5px;
right: -5px;
background: rgb(247, 83, 83);
color: white;
border: none;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 20px;
text-align: center;
z-index: 2;
/* 버튼이 항상 위에 표시되도록 설정 */
}

.delete_button:hover {
background-color: darkred;
}

.subject_item.selected {
Expand Down Expand Up @@ -233,30 +276,6 @@
font-weight: 500;
}

/* 삭제버튼 */

.delete_button {
position: absolute;
top: -5px;
right: -5px;
background: rgb(247, 83, 83);
color: white;
border: none;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 20px;
text-align: center;
}

.delete_button:hover {
background-color: darkred;
}

/* 브라우저 화면일 때 숨기기 */
@media (min-width: 769px) {
.backButton {
Expand Down
6 changes: 3 additions & 3 deletions components/study/SubjectSelectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ export default function SubjectSelectForm({ onEditClick, onSaveClick }: SubjectS
과목 선택
</Text>
</div>
<div className={styles.subject_choice_box}>
<div className={`${styles.subject_select_choice_box} ${styles.subject_choice_box}`}>
{subjects?.map((subject) => (
<div
key={subject.id}
className={`${styles.subject_item} ${selectedSubjects.includes(subject.name) ? styles.selected : ''}`}
onClick={() => selectSubject(subject.name)}
className={`${styles.subject_item} ${selectedSubjects.some((s) => s.id === subject.id) ? styles.selected : ''}`}
onClick={() => selectSubject(subject)}
>
<Text as="p" size="3" className={styles.subject_item_text}>
{subject.name}
Expand Down
46 changes: 30 additions & 16 deletions store/subjectStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ interface Subject {

interface SubjectStoreState {
subjects: Subject[];
initialSelectedSubjects: string[];
initialSelectedSubjects: Subject[];
initialSubjects: Subject[];
selectedSubjects: string[];
addedSubjects: string[];
selectedSubjects: Subject[];
addedSubjects: Subject[]; // Store as objects
isEditing: boolean;
deletedSubjects: number[];
deletedSubjects: Subject[]; // Store as objects
setInitialSubjects: () => void;
addSubject: (subject: Subject) => void;
deleteSubject: (subjectId: number) => void;
selectSubject: (subjectName: string) => void;
selectSubject: (subject: Subject) => void;
setEditing: (isEditing: boolean) => void;
saveSelected: () => void;
saveEditing: () => void;
Expand All @@ -30,10 +30,10 @@ export const useSubjectStore = create<SubjectStoreState>((set, get) => ({
subjects: [],
initialSubjects: [],
selectedSubjects: [],
addedSubjects: [],
addedSubjects: [], // Store as objects
initialSelectedSubjects: [],
isEditing: false,
deletedSubjects: [],
deletedSubjects: [], // Store as objects

setInitialSubjects: () => set({ initialSubjects: get().subjects, initialSelectedSubjects: get().selectedSubjects }),

Expand All @@ -45,32 +45,46 @@ export const useSubjectStore = create<SubjectStoreState>((set, get) => ({
deletedSubjects: [],
})),

addSubject: (subject) =>
addSubject: (subject: Subject) =>
set((state) => ({
subjects: [...state.subjects, subject],
addedSubjects: [...state.addedSubjects, subject.name],
addedSubjects: [...state.addedSubjects, subject],
})),

deleteSubject: (subjectId) =>
set((state) => {
const subjectIndex = state.subjects.findIndex((s) => s.id === subjectId);
const subjectToDelete = state.subjects.find((s) => s.id === subjectId);

// 추가된 과목인지 확인
const isAddedSubject = state.addedSubjects.some((subject) => subject.id === subjectId);

// 만약 추가된 과목이라면, 삭제 목록에 포함시키지 않고, 단순히 addedSubjects에서 제거
const newAddedSubjects = isAddedSubject
? state.addedSubjects.filter((subject) => subject.id !== subjectId)
: state.addedSubjects;

return {
subjects: state.subjects.filter((s) => s.id !== subjectId),
selectedSubjects: state.selectedSubjects.filter((s) => s !== state.subjects[subjectIndex]?.name),
deletedSubjects: subjectIndex !== -1 ? [...state.deletedSubjects, subjectId] : state.deletedSubjects,
selectedSubjects: state.selectedSubjects.filter((s) => s.id !== subjectId),
deletedSubjects:
!isAddedSubject && subjectIndex !== -1 && subjectToDelete
? [...state.deletedSubjects, subjectToDelete]
: state.deletedSubjects,
addedSubjects: newAddedSubjects,
};
}),

selectSubject: (subjectName) =>
selectSubject: (subject) =>
set((state) => ({
selectedSubjects: state.selectedSubjects.includes(subjectName)
? state.selectedSubjects.filter((s) => s !== subjectName)
: [...state.selectedSubjects, subjectName],
selectedSubjects: state.selectedSubjects.includes(subject)
? state.selectedSubjects.filter((s) => s.id !== subject.id)
: [...state.selectedSubjects, subject],
})),

saveSelected: () => {
const { selectedSubjects } = get();
alert(`선택한 과목이 저장되었습니다: ${selectedSubjects.join(', ')}`);
alert(`선택한 과목이 저장되었습니다: ${selectedSubjects.map((s) => s.name).join(', ')}`);
},

setEditing: (isEditing) => set({ isEditing }),
Expand Down
Loading