Commit 69e22908 authored by 하찬균's avatar 하찬균
Browse files

initial

parent bb8c57a3
node_modules/
.npm
.next/
dist/
src/firebase.js
This diff is collapsed.
{
"name": "muibasic",
"version": "1.0.0",
"description": "muiBasic",
"main": "index.js",
"dependencies": {
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.60",
"firebase": "^8.7.1",
"next": "^11.0.1",
"swr": "^0.5.6"
},
"devDependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.14.6",
"@babel/plugin-proposal-class-properties": "^7.14.5",
"@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"webpack": "^5.45.1",
"webpack-cli": "^4.7.2"
},
"scripts": {
"dev": "next dev",
"build": "next build",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
import React from 'react';
const About = () => {
return <h3>About Me..</h3>
}
export default About;
\ No newline at end of file
import React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import theme from '../src/theme';
export default function MyApp(props) {
const { Component, pageProps } = props;
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<React.Fragment>
<Head>
<title>My page</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
pageProps: PropTypes.object.isRequired,
};
\ No newline at end of file
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/core/styles';
import theme from '../src/theme';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
import App from '../src/component/App';
const IndexPage = () => {
return <App/>;
}
export default IndexPage;
import React from 'react';
import Typography from '@material-ui/core/Typography';
import MuiLink from '@material-ui/core/Link';
export default function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<MuiLink color="inherit" href="https://material-ui.com/">
Your Website
</MuiLink>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
/* eslint-disable jsx-a11y/anchor-has-content */
import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { useRouter } from 'next/router';
import NextLink from 'next/link';
import MuiLink from '@material-ui/core/Link';
const NextComposed = React.forwardRef(function NextComposed(props, ref) {
const { as, href, ...other } = props;
return (
<NextLink href={href} as={as}>
<a ref={ref} {...other} />
</NextLink>
);
});
NextComposed.propTypes = {
as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
prefetch: PropTypes.bool,
};
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/#with-link
function Link(props) {
const {
href,
activeClassName = 'active',
className: classNameProps,
innerRef,
naked,
...other
} = props;
const router = useRouter();
const pathname = typeof href === 'string' ? href : href.pathname;
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName,
});
if (naked) {
return <NextComposed className={className} ref={innerRef} href={href} {...other} />;
}
return (
<MuiLink component={NextComposed} className={className} ref={innerRef} href={href} {...other} />
);
}
Link.propTypes = {
activeClassName: PropTypes.string,
as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
className: PropTypes.string,
href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
naked: PropTypes.bool,
onClick: PropTypes.func,
prefetch: PropTypes.bool,
};
export default React.forwardRef((props, ref) => <Link {...props} innerRef={ref} />);
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Link from '@material-ui/core/Link';
import SvgIcon from '@material-ui/core/SvgIcon';
import Typography from '@material-ui/core/Typography';
function LightBulbIcon(props) {
return (
<SvgIcon {...props}>
<path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z" />
</SvgIcon>
);
}
const useStyles = makeStyles((theme) => ({
root: {
margin: theme.spacing(6, 0, 3),
},
lightBulb: {
verticalAlign: 'middle',
marginRight: theme.spacing(1),
},
}));
export default function ProTip() {
const classes = useStyles();
return (
<Typography className={classes.root} color="textSecondary">
<LightBulbIcon className={classes.lightBulb} />
Pro tip: See more{' '}
<Link href="https://material-ui.com/getting-started/templates/">templates</Link> on the
Material-UI documentation.
</Typography>
);
}
\ No newline at end of file
import React from 'react';
//import './App.css';
//import PropTypes from 'prop-types';
//import { withStyles } from '@material-ui/core/styles';
//import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import AppBar from '@material-ui/core/AppBar';
//import Toolbar from '@material-ui/core/Toolbar';
//import MenuIcon from '@material-ui/icons/Menu';
//import IconButton from '@material-ui/core/IconButton';
//import ExitToApp from '@material-ui/icons/ExitToApp';
//import Drawer from '@material-ui/core/Drawer';
//import Forms from './Forms';
//import HomeIcon from '@material-ui/icons/Home';
import Typography from '@material-ui/core/Typography';
import MusicList from './MusicList';
import music_list from '../data';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
music_list : music_list
}
}
render () {
return (
<div>
<AppBar position="fixed">
<Typography align="center" variant="h3" color="inherit">Your Favorite Musics</Typography>
</AppBar>
<div style={{height: 60, width: '100%'}}></div>
<MusicList list={this.state.music_list}>
</MusicList>
</div>
);
}
}
\ No newline at end of file
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import {Card, CardContent, CardActions, Typography, IconButton} from '@material-ui/core';
import {Favorite, FavoriteBorder} from '@material-ui/icons';
import firebase from '../firebase';
import SnackbarMsg from './snackmsg';
const styles = theme => ({
content : {},
layout : {
display : 'flex',
justifyContent : 'center'
},
card: {
minWidth: 275,
maxWidth: 600,
marginBottom : 20,
marginLeft : 'auto',
marginRight : 'auto',
},
});
class MusicList extends React.Component {
constructor(props) {
super(props);
this.state = {
likes : {},
snackbar : {},
};
}
toggleFavorite = (id) => () => {
let {likes} = this.state;
console.log(id, likes[id]);
if(likes[id] == undefined) {
likes[id] = true;
}
else {
likes[id] = (likes[id]) ? false : true;
}
let db = firebase.firestore();
db.collection('likes').doc(String(id)).set({like : likes[id]});
/*
try {
let ref = db.collection('likes').doc(String(id));
ref.get().then((doc) => {
if (doc.exists) {
console.log('document data : ', doc.data());
}
else {
console.log('No Such Document')
}
}).catch((e) => {
console.log('Error while accessing Firestore : ' + e);
});
}
catch (e) {
console.log('Error Occurred : '+ e);
} */
this.setState({likes, snackbar : {open : true, msg : `id ${id} clicked`}});
}
handleSnackbarClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
this.setState({snackbar : {open : false, msg : ''}});
}
render () {
const {classes} = this.props;
return (
<div>
{this.props.list.results.map(item => {
return (
<Card key={item.collectionId} className={classes.card}>
<CardContent>
<Typography variant="subtitle1"> {item.artistName}</Typography>
<Typography variant="subtitle2"> {item.collectionCensoredName}</Typography>
</CardContent>
<CardActions>
<IconButton onClick={this.toggleFavorite(item.collectionId)}>
{this.state.likes[item.collectionId] ? <Favorite /> : <FavoriteBorder />}
</IconButton>
</CardActions>
</Card>)
})}
<SnackbarMsg open={this.state.snackbar.open} message={this.state.snackbar.msg} onClose={this.handleSnackbarClose}></SnackbarMsg>
</div>
);
}
}
export default withStyles(styles)(MusicList);
\ No newline at end of file
import React from 'react';
import {Snackbar} from '@material-ui/core';
import MuiAlert from '@material-ui/lab/Alert';
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
const SnackbarMsg = (props) => {
return (
<Snackbar open={props.open} autoHideDuration={3000} onClose={props.onClose} message={props.message}>
<Alert onClose={props.onClose} severity="success">{props.message}</Alert>
</Snackbar>
);
}
export default SnackbarMsg;
\ No newline at end of file
This diff is collapsed.
import firebase from 'firebase/app';
import 'firebase/firestore';
//import 'firebase/auth';
//import 'firebase/storage';
//var firebase = require("firebase");
// Initialize Firebase
/*
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.7.1/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.7.1/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "AIzaSyA-dgPz2St....",
authDomain: "practical-coding.firebaseapp.com",
projectId: "practical-coding",
storageBucket: "practical-coding.appspot.com",
messagingSenderId: "1107250.....",
appId: "1:110725080091:web:d6541c24969......",
measurementId: "G-Z6V6K...."
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
*/
// firebase 에서 WebApp을 추가하면 위와 같은 샘플을 준다.
// 그 데이터를 아래와 같이 변환한다.
var firebaseConfig = {
apiKey: "AIzaSyA-dgPz2St......",
authDomain: "practical-coding.firebaseapp.com",
projectId: "practical-coding",
storageBucket: "practical-coding.appspot.com",
messagingSenderId: "110725....",
appId: "1:110725080091:web:d6541c24969a9.....",
measurementId: "G-Z6V6K...."
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default firebase;
import { createTheme } from '@material-ui/core/styles';
import { red } from '@material-ui/core/colors';
// Create a theme instance.
const theme = createTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
background: {
default: '#fff',
},
},
});
export default theme;
\ No newline at end of file
const path = require('path');
module.exports = {
// enntry file
entry: './src/index.js',
// 컴파일 + 번들링된 js 파일이 저장될 경로와 이름 지정
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
include: [
path.resolve(__dirname, 'src')
],
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: ['@babel/plugin-proposal-class-properties']
}
}
}
]
},
devtool: 'source-map',
// https://webpack.js.org/concepts/mode/#mode-development
mode: 'development'
};
node_modules/
var express = require('express');
const logger = require('morgan');
const axios = require('axios');
const list = require('./data');
var app = express()
const port = 3000
app.use(express.json())
app.use(express.urlencoded({'extended' : true}));
app.use(logger('dev'));
app.use(express.static('public')); // html, image 등 정적파일 제공 폴더 지정
app.get('/', (req, res) => {
res.sendFile('index.html')
})
//curl localhost:3000/user/tommy
app.get('/user/:id', (req, res) => {
res.send(`User id is ${req.params.id}`); // Or res.send('User id is ' + req.params.id);
})
// In zsh, u should try curl "http://localhost:{port}/user?id={ur-id}" //curl "http://localhost:3000/user?id=tommy"
app.get('/user', (req, res) => {
res.send(`User id is ${req.query.id}`);
})
// curl -X POST localhost:3000/user -d '{"id" : "jyc", "name" : "Jae Young"}' -H "Content-Type: application/json"
app.post('/user', (req, res) => {
console.log(req.body.name);
res.send(req.body);
})
app.get('/music_list', (req,res) => {
res.json(list);
})
app.get('/musicSearch/:term', async (req, res) => {