Skip to content
48 changes: 48 additions & 0 deletions src/api/rooms/getBookPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { apiClient } from '../index';

// 책 페이지 정보 응답 데이터 타입
export interface BookPageData {
totalBookPage: number; // 책 전체 페이지 수
recentBookPage: number; // 최근 기록한 페이지 번호
isOverviewPossible: boolean; // 총평 작성 가능 여부
roomId: number; // 방 ID
}

// API 응답 타입
export interface BookPageResponse {
isSuccess: boolean;
code: number;
message: string;
data: BookPageData;
}

// 책 전체 페이지수 및 총평 작성 가능 여부 조회 API 함수
export const getBookPage = async (roomId: number): Promise<BookPageResponse> => {
try {
const response = await apiClient.get<BookPageResponse>(`/rooms/${roomId}/book-page`);
return response.data;
} catch (error) {
console.error('책 페이지 정보 조회 API 오류:', error);
throw error;
}
};

/*
사용 예시:
try {
const result = await getBookPage(1);
if (result.isSuccess) {
console.log("책 전체 페이지 수:", result.data.totalBookPage);
console.log("최근 기록한 페이지:", result.data.recentBookPage);
console.log("총평 작성 가능:", result.data.isOverviewPossible);
console.log("방 ID:", result.data.roomId);
// 성공 처리 로직
} else {
console.error("책 페이지 정보 조회 실패:", result.message);
// 실패 처리 로직
}
} catch (error) {
console.error("API 호출 오류:", error);
// 에러 처리 로직 (400: 파라미터 잘못, 403: 접근 권한 없음, 404: 방 없음)
}
*/
1 change: 1 addition & 0 deletions src/components/memory/MemoryContent/MemoryContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface MemoryContentProps {
selectedPageRange: { start: number; end: number } | null;
hasRecords: boolean;
showUploadProgress: boolean;
currentUserPage: number;
onTabChange: (tab: RecordType) => void;
onFilterChange: (filter: FilterType) => void;
onSortChange: (sort: SortType) => void;
Expand Down
1 change: 1 addition & 0 deletions src/components/recordwrite/PageRangeSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface PageRangeSectionProps {
isOverallEnabled: boolean;
onOverallToggle: () => void;
readingProgress: number;
isOverviewPossible: boolean;
}

const PageRangeSection = ({
Expand Down
156 changes: 75 additions & 81 deletions src/pages/memory/Memory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ const convertPostToRecord = (post: Post): Record => {
};
};

const addRecordIfNotExists = (prevRecords: Record[], newRecord: Record) => {
const exists = prevRecords.some(record => record.id === newRecord.id);
if (exists) {
return prevRecords;
}
return [newRecord, ...prevRecords];
};

const Memory = () => {
const navigate = useNavigate();
const location = useLocation();
Expand All @@ -76,13 +68,13 @@ const Memory = () => {
const [activeFilter, setActiveFilter] = useState<FilterType | null>(null);
const [selectedSort, setSelectedSort] = useState<SortType>('latest');
const [showSnackbar, setShowSnackbar] = useState(false);
const [readingProgress] = useState(70);
const [selectedPageRange, setSelectedPageRange] = useState<{ start: number; end: number } | null>(
null,
);

// API 관련 상태
const [error, setError] = useState<string | null>(null);
const [isOverviewEnabled, setIsOverviewEnabled] = useState(false);

// 업로드 프로그레스 상태
const [showUploadProgress, setShowUploadProgress] = useState(false);
Expand All @@ -96,112 +88,91 @@ const Memory = () => {
// 그룹 기록들을 별도로 관리
const [groupRecords, setGroupRecords] = useState<Record[]>([]);

// API 데이터 로드
// API 데이터 로드 함수
const loadMemoryPosts = useCallback(async () => {
// roomId가 없으면 기본값 1 사용 또는 API 호출 스킵
const currentRoomId = roomId || '1';
if (!roomId) return;

setError(null);

try {
// 정렬 타입 변환
let sortType: 'latest' | 'like' | 'comment' | undefined = undefined;
if (activeTab === 'group') {
if (selectedSort === 'latest') sortType = 'latest';
else if (selectedSort === 'popular') sortType = 'like';
else if (selectedSort === 'comments') sortType = 'comment';
}

// API 타입에 맞는 파라미터 구성
const requestParams: {
// API 파라미터 구성
const params: {
roomId: number;
type: 'group' | 'mine';
sort?: 'latest' | 'like' | 'comment';
pageStart?: number | null;
pageEnd?: number | null;
isOverview?: boolean;
isPageFilter?: boolean;
cursor?: string | null;
} = {
roomId: parseInt(currentRoomId),
type: activeTab === 'my' ? 'mine' : 'group',
pageStart: selectedPageRange ? selectedPageRange.start : null,
pageEnd: selectedPageRange ? selectedPageRange.end : null,
isOverview: activeFilter === 'overall' ? true : false,
isPageFilter: activeFilter === 'page' ? true : false,
cursor: null,
roomId: parseInt(roomId),
type: activeTab === 'group' ? 'group' : 'mine',
};

// sort는 group 타입일 때만 추가
if (activeTab === 'group' && sortType) {
requestParams.sort = sortType;
// 그룹 기록일 때만 정렬 파라미터 추가
if (activeTab === 'group') {
let sortType: 'latest' | 'like' | 'comment' = 'latest';
if (selectedSort === 'popular') sortType = 'like';
else if (selectedSort === 'comments') sortType = 'comment';

params.sort = sortType;
}

console.log('API 호출 파라미터:', requestParams);
// 일반 기록과 총평 기록을 모두 가져오기 위해 두 번 호출
const [generalResponse, overviewResponse] = await Promise.all([
getMemoryPosts(params), // 일반 기록 (isOverview: false 기본값)
getMemoryPosts({ ...params, isOverview: true }), // 총평 기록
]);

const response = await getMemoryPosts(requestParams);
if (generalResponse.isSuccess && overviewResponse.isSuccess) {
// 일반 기록과 총평 기록을 합치기
const allPosts = [...generalResponse.data.postList, ...overviewResponse.data.postList];
const convertedRecords = allPosts.map(convertPostToRecord);

if (response.isSuccess) {
const convertedRecords = response.data.postList.map(convertPostToRecord);
setIsOverviewEnabled(generalResponse.data.isOverviewEnabled);

if (activeTab === 'my') {
setMyRecords(convertedRecords);
} else {
if (activeTab === 'group') {
setGroupRecords(convertedRecords);
} else {
setMyRecords(convertedRecords);
}

setHasRecords(convertedRecords.length > 0);

console.log('API 응답 성공:', response.data);
} else {
setError(response.message);
console.error('API 응답 실패:', response.message);
setError(
generalResponse.message || overviewResponse.message || '기록을 불러오는데 실패했습니다.',
);
}
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : '기록을 불러오는 중 오류가 발생했습니다.';
setError(errorMessage);
console.error('API 호출 오류:', error);
} catch (err) {
console.error('기록 조회 API 오류:', err);
setError('기록을 불러오는 중 오류가 발생했습니다.');
}
}, [roomId, activeTab, selectedSort, selectedPageRange, activeFilter]);
}, [roomId, activeTab, selectedSort]);

// 컴포넌트 마운트 시 및 필터/탭 변경 시 데이터 로드
// 컴포넌트 마운트 시 및 탭 변경 시 데이터 로드
useEffect(() => {
loadMemoryPosts();
}, [loadMemoryPosts]);

// location.state에서 새로 추가된 기록 확인
// 새로운 기록이 추가되었을 때 처리 (작성 완료 후 돌아왔을 때)
useEffect(() => {
if (location.state?.newRecord) {
const { isUploading, ...recordData } = location.state.newRecord as Record & {
isUploading?: boolean;
};
const newRecord = location.state.newRecord as Record;
setShowUploadProgress(true);

if (isUploading) {
setShowUploadProgress(true);
const finalRecord: Record = recordData;
setMyRecords(prev => addRecordIfNotExists(prev, finalRecord));
setGroupRecords(prev => addRecordIfNotExists(prev, finalRecord));
if (activeTab === 'group') {
setGroupRecords(prev => [newRecord, ...prev]);
} else {
setMyRecords(prev => [newRecord, ...prev]);
}

setActiveTab('my');
navigate(location.pathname, { replace: true, state: null });
// 상태 정리
navigate(location.pathname, { replace: true });
}
}, [location.state?.newRecord, location.pathname, navigate]);

// 업로드 완료 처리
const handleUploadComplete = useCallback(() => {
setShowUploadProgress(false);
}, []);
}, [location.state, activeTab, navigate, location.pathname]);

// 현재 표시할 기록들
// 현재 탭에 따른 기록 목록 결정
const currentRecords = useMemo(() => {
if (activeTab === 'my') {
return myRecords;
} else {
return hasRecords ? groupRecords : [];
if (!hasRecords) {
return [];
}
}, [activeTab, myRecords, hasRecords, groupRecords]);
return activeTab === 'group' ? groupRecords : myRecords;
}, [activeTab, hasRecords, groupRecords, myRecords]);

// 정렬된 기록 목록
const sortedRecords = useMemo(() => {
Expand All @@ -210,8 +181,22 @@ const Memory = () => {

// 필터링된 기록 목록
const filteredRecords = useMemo(() => {
return sortedRecords;
}, [sortedRecords]);
const filtered = sortedRecords;

if (activeFilter === 'overall') {
const overallRecords = filtered.filter(record => record.recordType === 'overall');
return overallRecords;
} else if (activeFilter === 'page' && selectedPageRange) {
const pageRecords = filtered.filter(record => {
if (record.recordType === 'overall') return false;
const page = parseInt(record.pageRange || '0');
return page >= selectedPageRange.start && page <= selectedPageRange.end;
});
return pageRecords;
}

return filtered;
}, [sortedRecords, activeFilter, selectedPageRange]);

const handleBackClick = useCallback(() => {
if (roomId) {
Expand Down Expand Up @@ -246,6 +231,7 @@ const Memory = () => {

const handlePageRangeClear = useCallback(() => {
setSelectedPageRange(null);
setActiveFilter(null);
}, []);

const handlePageRangeSet = useCallback((range: { start: number; end: number }) => {
Expand All @@ -257,6 +243,13 @@ const Memory = () => {
setHasRecords(!hasRecords);
}, [hasRecords]);

const handleUploadComplete = useCallback(() => {
setShowUploadProgress(false);
}, []);

const readingProgress = isOverviewEnabled ? 85 : 70;
const currentUserPage = 350; // 임시로 350으로 설정 (나중에 API에서 가져올 것)

if (error) {
return (
<Container>
Expand Down Expand Up @@ -289,6 +282,7 @@ const Memory = () => {
selectedPageRange={selectedPageRange}
hasRecords={hasRecords}
showUploadProgress={showUploadProgress}
currentUserPage={currentUserPage}
onTabChange={handleTabChange}
onFilterChange={handleFilterChange}
onSortChange={handleSortChange}
Expand Down
Loading