Select Git revision
App.js 5.60 KiB
import React, { useEffect } from 'react';
import SearchPage from './SearchPage';
import Favorites from './Favorites';
import MusicList from './MusicList';
import SnackMsg from './SnackMsg';
import {Box, Tabs, Tab, Typography, AppBar} from '@mui/material';
import { LineAxisOutlined } from '@mui/icons-material';
export default function App () {
const [currentTab, setCurrentTab] = React.useState(0);//탭
const [searchResult, setSearchResult] = React.useState([]);//서치결과
const [likes, setLikes] = React.useState({});//좋아요결과
const [snackState, setSnackState] = React.useState({open: false, msg:''})//스낵바열림결과
const [favorites, setFavorites] = React.useState([]);//재검색해도 Favorites목록이 리셋되는 것을 막기 위해 Favorites 모아놓은 상태변수 만듦
//여기에 useEffect로 favorites랑 likes관리?
//사이트 처음 들어갈 때 좋아요 목록이랑 좋아요 표시가 잘 나타나도록
useEffect(() => {
fetch(`/likes`, {method:'GET'})
.then((r) => r.json())
.then((r) => {setFavorites(r), setLikes(r);})
.catch((error) => {
console.error("Error fetching favorites:", error);
});
}, []);
const handleTabChange = (event, newValue) => {//탭
setCurrentTab(newValue);
}
const toggleFavorite = (id, name) => {//좋아요와 스낵바 상태 업데이트
setSnackState({open: true, msg: `${name} is clicked`})
if (likes[id]) {//이미 좋아요를 한 item이라면
fetch(`/likes/${id}`, {method: "DELETE"})//fetch 기능을 사용하여 서버에 대한 네트워크 요청을 보냄
.then((r)=>r.json())
.then((r)=>{
console.log(r);
console.log("DELETE");
setLikes(prevLikes => ({...prevLikes, [id]: !prevLikes[id]}));//기존의 모든 키-값 쌍을 복사한다음 뒤에 써져있는대로 업데이트함
setFavorites(prevFavorites => prevFavorites.filter(item => item.collectionId !== id));
})
.catch((error) => {
console.error('Error deleting likes:', error);
});
}
//참고 코드
/*
@GetMapping(value="/likes")
public List<FavoriteMusic> getLikes() {
return service.getLikes();
}
@PostMapping(value="/likes")
public int postLikes(@RequestBody FavoriteMusicRequestDto favorite) {
return service.saveFavorite(favorite);
}
@DeleteMapping(value="/likes/{id}")
public int deleteLikes(@PathVariable String id) {
return service.deleteFavorite(id);
}
*/
/*
fetch(`/musicSearch/${searchWord}`)//fetch 기능을 사용하여 서버에 대한 네트워크 요청을 보냄
.then(r => r.json()).then(r => {
console.log(r);
onSearch(r.results);
setSearchWord('');//searchWord 변수 값을 다시 빈 문자열로 초기화
}).catch(e => console.log('error when search musician));
*/
else {//좋아요가 아직 안 되어있는 item이라면
const selectedItem = searchResult.find(item => item.collectionId === id);
if (selectedItem) {
fetch(`/likes`, {method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(item)})//fetch 기능을 사용하여 서버에 대한 네트워크 요청을 보냄
.then((r)=>r.json())
.then((r)=>{
console.log(r);
console.log("POST");
setLikes(prevLikes => ({ ...prevLikes, [id]: !prevLikes[id] }));
setFavorites(prevFavorites => [...prevFavorites, selectedItem]);
})
.catch((error) => {
console.error('Error posting likes:', error);
});
}
}
}
const handleSnackbarClose = (event, reason)=> {//스낵바 닫기
if(reason === 'clickaway'){
return;
}
setSnackState({open: false, msg: ''});
}
return (
<React.Fragment>
<AppBar positions = "fixed">
<Typography align = "center" variant = "h3" color = "inherit">Hyunjin's Favorite Music</Typography>
</AppBar>
<div style = {{height: 60, width: '100%'}}></div>
<Box sx = {{borderBottom: 1, borderColor: 'divider'}}>
<Tabs value = {currentTab} onChange = {handleTabChange} aria-label = "basic tabs" centered>
<Tab label = "Search Music" value = {0}/>
<Tab label = "Favorites" value = {1}/>
<Tab label = "More Contents" value = {2}/>
</Tabs>
</Box>
{currentTab == 0 &&
<>
<SearchPage onSearch = {setSearchResult}/>
<MusicList list = {searchResult} likes = {likes} toggleFavorite = {toggleFavorite}/>
</>
}
{currentTab == 1 &&
<>
<Typography align = "center" variant = "h5"> Favorites </Typography>
<Favorites list = {favorites} likes = {likes} toggleFavorite = {toggleFavorite}/>
</>}
{currentTab == 2 && <Typography align = "center" variant = "h5"> More Contents </Typography>}
<SnackMsg open = {snackState.open} message = {snackState.msg} onClose = {handleSnackbarClose}/>
</React.Fragment>
)
}