Skip to content
Snippets Groups Projects
Commit 8dca0eed authored by Sumin Shin's avatar Sumin Shin
Browse files

Merge branch 'main' into 'master'

Main

See merge request !1
parents 589ee34a 8cc6f246
No related branches found
No related tags found
1 merge request!1Main
Pipeline #7946 passed
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
\ No newline at end of file
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
package-lock.json
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
{
"name": "muibasic_starterkit",
"version": "1.0.0",
"description": "Boiler plate for MaterialUI Development",
"main": "webpack.config.js",
"dependencies": {
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@mui/icons-material": "^5.13.7",
"@mui/material": "^5.8.6"
},
"devDependencies": {
"@babel/cli": "^7.18.6",
"@babel/core": "^7.18.6",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.13.2"
},
"scripts": {
"start": "webpack-dev-server --open --mode development --port 3000",
"build": "webpack --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Material",
"UI",
"ReactJS"
],
"author": "Su Min Shin",
"license": "MIT"
}
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="GitLab Pages">
<title>Plain HTML site using GitLab Pages</title>
<link rel="stylesheet" href="style.css">
<title> muiBasic </title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
</head>
<body>
<div class="navbar">
<a href="https://pages.gitlab.io/plain-html/">Plain HTML Example</a>
<a href="https://gitlab.com/pages/plain-html/">Repository</a>
<a href="https://gitlab.com/pages/">Other Examples</a>
</div>
<h1>Hello World!</h1>
<p>
This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.
</p>
<div id="app"></div>
<script src="./app.bundle.js" type="text/javascript"></script>
</body>
</html>
import React from 'react';
import {Box,Tabs,Tab, Typography, AppBar, CssBaseline} from "@mui/material";
import MusicList from "./MusicList";
import Favorites from './Favorites';
import music_list from "./data";
import SnackMsg from './SnackMsg';
import SearchPage from './SearchPage';
import { SettingsCellRounded } 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 handleTabChange = (event, newValue)=>{
setCurrentTab(newValue);
}
return (
<React.Fragment>
<AppBar position ="fixed">
<Typography align="center" variant="h3" color="inherit">Sumin's Favorite Music</Typography>
</AppBar>
<div style={{height:60, width:"100%"}}></div>
<Box sx={{borderBottom:1, borderColorl:"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 list={searchResult} onSearch={setSearchResult}/>}
{currentTab === 1 && <Favorites list={searchResult} likes={likes} />}
{currentTab == 2 && <Typography align="center" variant='h2'>More</Typography>}
</React.Fragment>
);
}
import React from 'react';
import { Typography } from '@mui/material';
import MusicList from './MusicList';
const Favorites = ({ list, likes }) => {
const favoriteList = list.filter(item => likes[item.collectionCensoredName]);
return (
<React.Fragment>
<Typography align="center" variant="h2">Favorites</Typography>
{favoriteList.length > 0 ? (
<MusicList list={favoriteList} />
) : (
<Typography align="center" variant="h4">No favorites yet.</Typography>
)}
</React.Fragment>
);
}
export default Favorites;
import React from "react";
import {Card, CardContent,CardActions, Typography,IconButton, Alert} from "@mui/material";
import {Favorite, FavoriteBorder} from "@mui/icons-material";
import SnackMsg from "./SnackMsg";
const styles={
content:{},
layout:{
display:"flex",
justifyContent:"center",
},
card:{
minWidth:275,
maxWidth:600,
marginBottom:"20pt",
marginLeft:"auto",
marginRight:"auto",
}
};
export default function MusicList ({list}){
const [likes,setLikes] = React.useState({});
let [snackState, setSnackState] = React.useState({open:false, msg:""});
const toggleFavorite=(id) => () => {
setLikes({...likes, [id]: !likes[id]});
setSnackState({...snackState, open :true, msg:`${id} is clicked`});
}
const handleSnackbarClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setSnackState({open : false, msg : ''});
}
return (
<div>{list.map(item =>{
return (
<Card sx={styles.card} key={item.collectionId}>
<CardContent>
<Typography variant="subtitle1">{item.artistName}</Typography>
<Typography variant="subtitle2">{item.collectionCensoredName}</Typography>
</CardContent>
<CardActions>
<IconButton onClick={toggleFavorite(item.collectionCensoredName)}>
{(likes[item.collectionCensoredName]===true)? <Favorite />:<FavoriteBorder />}
</IconButton>
</CardActions>
</Card>)
})}
<SnackMsg open ={snackState.open} message={snackState.msg} onClose={handleSnackbarClose} />
</div>
)
}
\ No newline at end of file
import React from "react";
import {Button, TextField} from "@mui/material";
import MusicList from "./MusicList";
export default function SearchPage ({list, onSearch}) {
const [searchWord, setSearchWord] = React.useState("");
const handleSearch = (event) => {
event.preventDefault();
console.log(searchWord);
setSearchWord("");
fetch(`http://itunes.apple.com/search?term=${searchWord}&entity=album`).then(r=>r.json()).then(r=>{
console.log(r);
onSearch(r.results);
setSearchWord("");
}).catch(e=>console.log("error when search musician"));
}
const handleSearchTextChange = (event)=>{
setSearchWord(event.target.value);
}
return (
<React.Fragment>
<form style={{display:"flex",marginTop:20, marginBottom:15}}>
<div style={{display:"flex", marginLeft:"auto", marginRight:"auto"}}>
<TextField variant="outlined" label="Music Album Search" type="serach" style={{width:450}}
onChange={handleSearchTextChange} value={searchWord}></TextField>
<Button variant="contained" color="primary" type="submit" onClick={handleSearch}
style={{marginLeft:20}}>
Search
</Button>
</div>
</form>
{/* <MusicList list={music_list}></MusicList> */}
<MusicList list={list}></MusicList>
</React.Fragment>
)
}
import React from "react";
import { Snackbar } from "@mui/material";
const SnackMsg = (props) => {
return (
<Snackbar
open={props.open}
anchorOrigin={{vertical:"bottom", horizontal:"right"}}
autoHideDuration={3000}
onClose={props.onClose}
message={props.message}>
</Snackbar>
)
}
export default SnackMsg;
\ No newline at end of file
This diff is collapsed.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App/>, document.getElementById('app'));
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'public')
},
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}]
},
devServer: {
hot: true,
allowedHosts: 'all',
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment