Skip to content

Commit

Permalink
Complete Code for the Meetup Project
Browse files Browse the repository at this point in the history
  • Loading branch information
anubhavbhatt authored May 24, 2021
1 parent aab8ed7 commit 99e8381
Show file tree
Hide file tree
Showing 20 changed files with 576 additions and 0 deletions.
40 changes: 40 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "may22reactapp",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {}
}
26 changes: 26 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Route, Switch } from "react-router-dom";

import AllMeetupsPage from "./pages/AllMeetups";
import FavoritesPage from "./pages/Favorites";
import NewMeetupPage from "./pages/NewMeetup";
import Layout from "./components/layout/Layout";

function App() {
return (
<Layout>
<Switch>
<Route path="/" exact={true}>
<AllMeetupsPage />
</Route>
<Route path="/favorite">
<FavoritesPage />
</Route>
<Route path="/new-meetup">
<NewMeetupPage />
</Route>
</Switch>
</Layout>
);
}

export default App;
13 changes: 13 additions & 0 deletions src/components/layout/Layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import MainNavigation from "./MainNavigation";
import classes from "./Layout.module.css";

function Layout(props) {
return (
<div>
<MainNavigation />
<main className={classes.main}>{props.children}</main>
</div>
);
}

export default Layout;
5 changes: 5 additions & 0 deletions src/components/layout/Layout.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.main {
margin: 3rem auto;
width: 90%;
max-width: 40rem;
}
34 changes: 34 additions & 0 deletions src/components/layout/MainNavigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useContext } from 'react';
import { Link } from "react-router-dom";
import FavoritesContext from "../../store/favorites-context";
import classes from "./MainNavigation.module.css";
function MainNavigation() {
const favoritesCtx = useContext(FavoritesContext);
return (
<header className={classes.header}>
<div className={classes.logo}>React MeetUps</div>
<nav>
<ul>
<li>
<Link to="/">All Meetups</Link>
</li>

<li>
<Link to="/new-meetup">Add New Meetup</Link>
</li>

<li>
<Link to="/favorite">
My Favorites
<span className={classes.badge}>
{favoritesCtx.totalFavorites}
</span>
</Link>
</li>
</ul>
</nav>
</header>
);
}

export default MainNavigation;
47 changes: 47 additions & 0 deletions src/components/layout/MainNavigation.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.header {
width: 100%;
height: 5rem;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #77002e;
padding: 0 10%;
}

.logo {
font-size: 2rem;
color: white;
font-weight: bold;
}

.header ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
align-items: baseline;
}

.header li {
margin-left: 3rem;
}

.header a {
text-decoration: none;
font-size: 1.5rem;
color: #fcb8d2;
}

.header a:hover,
.header a:active,
.header a.active {
color: white;
}

.badge {
background-color: #cc2062;
color: white;
border-radius: 12px;
padding: 0 1rem;
margin-left: 0.5rem;
}
47 changes: 47 additions & 0 deletions src/components/meetups/MeetupItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useContext } from 'react';

import Card from '../ui/Card';
import classes from './MeetupItem.module.css';
import FavoritesContext from '../../store/favorites-context';

function MeetupItem(props) {
const favoritesCtx = useContext(FavoritesContext);

const itemIsFavorite = favoritesCtx.itemIsFavorite(props.id);

function toggleFavoriteStatusHandler() {
if (itemIsFavorite) {
favoritesCtx.removeFavorite(props.id);
} else {
favoritesCtx.addFavorite({
id: props.id,
title: props.title,
description: props.description,
image: props.image,
address: props.address,
});
}
}

return (
<li className={classes.item}>
<Card>
<div className={classes.image}>
<img src={props.image} alt={props.title} />
</div>
<div className={classes.content}>
<h3>{props.title}</h3>
<address>{props.address}</address>
<p>{props.description}</p>
</div>
<div className={classes.actions}>
<button onClick={toggleFavoriteStatusHandler}>
{itemIsFavorite ? 'Remove from Favorites' : 'To Favorites'}
</button>
</div>
</Card>
</li>
);
}

export default MeetupItem;
46 changes: 46 additions & 0 deletions src/components/meetups/MeetupItem.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.item {
margin: 1rem 0;
}

.image {
width: 100%;
height: 20rem;
overflow: hidden;
border-top-right-radius: 6px;
border-top-left-radius: 6px;
}

.image img {
width: 100%;
object-fit: cover;
}

.content {
text-align: center;
padding: 1rem;
}

.content h3 {
font-size: 1.25rem;
color: #2c292b;
}

.actions {
padding: 1.5rem;
text-align: center;
}

.actions button {
font: inherit;
cursor: pointer;
color: #77002e;
border: 1px solid #77002e;
background-color: transparent;
padding: 0.5rem 1.5rem;
border-radius: 4px;
}

.actions button:hover,
.actions button:active {
background-color: #ffe2ed;
}
21 changes: 21 additions & 0 deletions src/components/meetups/MeetupList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import MeetupItem from "./MeetupItem";
import classes from "./MeetupList.module.css";

function MeetupList(props) {
return (
<ul className={classes.list}>
{props.meetups.map( (meetup) => (
<MeetupItem
key={meetup.id}
id={meetup.id}
image={meetup.image}
title={meetup.title}
address={meetup.address}
description={meetup.description}
/>
)
)}
</ul>
);
}
export default MeetupList;
6 changes: 6 additions & 0 deletions src/components/meetups/MeetupList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

.list {
list-style: none;
margin: 0;
padding: 0;
}
54 changes: 54 additions & 0 deletions src/components/meetups/NewMeetupForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Card from '../ui/Card';
import classes from './NewMeetupForm.module.css';
import { useRef } from 'react';

function NewMeetupForm(props){

const titleInputRef = useRef();
const imageInputRef = useRef();
const addressInputRef = useRef();
const descriptionInputRef = useRef();

function submitHandler(event){
event.preventDefault();

const enteredTitle = titleInputRef.current.value;
const enteredImage = imageInputRef.current.value;
const enteredAddress = addressInputRef.current.value;
const enteredDescription= descriptionInputRef.current.value;

const meetupData = {
title: enteredTitle,
image: enteredImage,
address: enteredAddress,
description: enteredDescription
};

props.onAddMeetup(meetupData);
}

return <Card>
<form className={classes.form} onSubmit={submitHandler}>
<div className={classes.control}>
<label htmlFor='title'>Meetup Title</label>
<input type='text' required id='title' ref={titleInputRef} />
</div>
<div className={classes.control}>
<label htmlFor='image'>Meetup Image</label>
<input type='url' required id='image' ref={imageInputRef} />
</div>
<div className={classes.control}>
<label htmlFor='address'>Meetup Address</label>
<input type='text' required id='address' ref={addressInputRef} />
</div>
<div className={classes.control}>
<label htmlFor='description'>Meetup Description</label>
<textarea required id='description' ref={descriptionInputRef} ></textarea>
</div>
<div className={classes.actions}>
<button>Add Meetup</button>
</div>
</form>
</Card>
}
export default NewMeetupForm;
Loading

0 comments on commit 99e8381

Please sign in to comment.