Skip to content
41 changes: 29 additions & 12 deletions 3주차-NextJS/next-sns/components/Avatar.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,51 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Avatar from '@material-ui/core/Avatar';
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Avatar from "@material-ui/core/Avatar";

const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
'& > *': {
display: "flex",
"& > *": {
margin: theme.spacing(1),
},
},
small: {
width: theme.spacing(3),
height: theme.spacing(3),
},
medium: {
width: theme.spacing(7),
height: theme.spacing(7),
},
large: {
width: theme.spacing(13),
height: theme.spacing(13),
},
}));

export default function ImageAvatars() {
export default function ImageAvatars({ size }) {
const classes = useStyles();

return (
<div className={classes.root}>
<Avatar
alt='Remy Sharp'
src='/static/images/avatar/1.jpg'
className={classes.large}
/>
{size === 0 ? (
<Avatar
alt="Remy Sharp"
src="/static/images/avatar/1.jpg"
className={classes.small}
/>
) : size === 1 ? (
<Avatar
alt="Remy Sharp"
src="/static/images/avatar/1.jpg"
className={classes.medium}
/>
) : (
<Avatar
alt="Remy Sharp"
src="/static/images/avatar/1.jpg"
className={classes.large}
/>
)}
</div>
);
}
21 changes: 21 additions & 0 deletions 3주차-NextJS/next-sns/components/Comment.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import Avatar from "../components/Avatar";
import { Divider, Grid } from "@material-ui/core";

export default function Comment({ data }) {
const { username, comment } = data;
return (
<>
<Grid container wrap="nowrap" spacing={2}>
<Grid item>
<Avatar size={1} />
</Grid>
<Grid justifyContent="left" item xs zeroMinWidth>
<h4 style={{ margin: 0, textAlign: "left" }}>{username}</h4>
<p style={{ textAlign: "left" }}>{comment}</p>
</Grid>
</Grid>
<Divider variant="fullWidth" style={{ margin: "30px 0" }} />
</>
);
}
162 changes: 162 additions & 0 deletions 3주차-NextJS/next-sns/components/Feed.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React from "react";
import Link from "next/link";
import Avatar from "./Avatar";
import Comment from "./Comment";
import {
Paper,
TextField,
Grid,
CardHeader,
CardMedia,
CardContent,
Card,
CardActions,
Collapse,
IconButton,
Typography,
makeStyles,
} from "@material-ui/core";
import SendIcon from "@material-ui/icons/Send";
import FavoriteIcon from "@material-ui/icons/Favorite";
import ChatIcon from "@material-ui/icons/Chat";

const useStyles = makeStyles(() => ({
feed: {
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
},
root: {
marginTop: "55px",
maxWidth: "800px",
},
media: {
height: 0,
paddingTop: "56.25%", // 16:9
},
comment: {
width: "600px",
height: "75px",
},
commentItem: {
marginTop: "10px",
},
commentSend: {
display: "flex",
flexDirection: "row",
},
}));

export default function Feed({ comments, setComments }) {
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
const [liked, setLiked] = React.useState(false);
const [inputs, setInputs] = React.useState({
comment: "",
});

const handleExpandClick = () => {
setExpanded(!expanded);
};

const handleHeartClick = () => {
setLiked(!liked);
};

const handleTextChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};

const handleSendClick = () => {
const comment = {
id: comments.length + 1,
username: "aeuna",
comment: inputs.comment,
};
setComments([...comments, comment]);
setInputs({
comment: "",
});
};

return (
<div className={classes.feed}>
<Card className={classes.root}>
<CardHeader
avatar={<Avatar size={1} />}
title="aeuna"
subheader="May 14, 2020"
/>
<CardMedia
className={classes.media}
image="/images/test.jpeg"
title="food"
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text
ever since the 1500s.... (데이터 들어오면 몇자 이내로 자를 예정!)
</Typography>
<Link href="/">
<Typography variant="body1">더보기</Typography>
</Link>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites" onClick={handleHeartClick}>
{liked ? <FavoriteIcon color="secondary" /> : <FavoriteIcon />}
</IconButton>
<IconButton
aria-label="comment"
onClick={handleExpandClick}
aria-expanded={expanded}
>
<ChatIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Paper style={{ padding: "20px 20px" }}>
{comments.map((comment) => (
<Comment key={comment.id} data={comment} />
))}
<Grid container wrap="nowrap" spacing={2}>
<Grid item>
<Avatar size={1} />
</Grid>
<Grid
className={classes.commentItem}
justifyContent="left"
item
xs
zeroMinWidth
>
<h4 style={{ margin: 0, textAlign: "left" }}>aeuna</h4>
<div className={classes.commentSend}>
<TextField
name="comment"
multiline
placeholder="댓글을 입력해주세요..."
rowsMax={3}
className={classes.comment}
onChange={handleTextChange}
value={inputs.comment}
/>
<IconButton aria-label="send" onClick={handleSendClick}>
<SendIcon />
</IconButton>
</div>
</Grid>
</Grid>
</Paper>
</CardContent>
</Collapse>
</Card>
</div>
);
}
109 changes: 109 additions & 0 deletions 3주차-NextJS/next-sns/components/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from "react";
import Link from "next/link";
import {
makeStyles,
AppBar,
Toolbar,
IconButton,
Typography,
Badge,
MenuItem,
Menu,
} from "@material-ui/core";
import AccountCircle from "@material-ui/icons/AccountCircle";
import NotificationsIcon from "@material-ui/icons/Notifications";
import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline";

const useStyles = makeStyles((theme) => ({
fix: {
position: "fixed",
top: 0,
},
grow: {
flexGrow: 1,
},
title: {
display: "none",
[theme.breakpoints.up("sm")]: {
display: "block",
},
},
sectionDesktop: {
display: "none",
[theme.breakpoints.up("md")]: {
display: "flex",
},
},
}));

export default function Header() {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);

const isMenuOpen = Boolean(anchorEl);

const handleNotificationMenuOpen = (event) => {
setAnchorEl(event.currentTarget);
};

const handleMenuClose = () => {
setAnchorEl(null);
};

const menuId = "primary-account-menu";
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{ vertical: "top", horizontal: "right" }}
id={menuId}
keepMounted
transformOrigin={{ vertical: "top", horizontal: "right" }}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>알림 1</MenuItem>
<MenuItem onClick={handleMenuClose}>알림 2</MenuItem>
<MenuItem onClick={handleMenuClose}>알림 3</MenuItem>
</Menu>
);
return (
<div className={classes.grow}>
<AppBar className={classes.fix}>
<Toolbar>
<Typography className={classes.title} variant="h6" noWrap>
Sullivan-SNS
</Typography>
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
<Link href="/">
<IconButton aria-label="add feed" color="inherit">
<AddCircleOutlineIcon />
</IconButton>
</Link>
<Link href="/">
<IconButton
edge="end"
aria-label="account of user"
color="inherit"
>
<AccountCircle />
</IconButton>
</Link>
<IconButton
aria-label="show new notifications"
color="inherit"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleNotificationMenuOpen}
>
<Badge badgeContent={3} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
</div>
</Toolbar>
</AppBar>
{renderMenu}
</div>
);
}
Loading