Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ad4db1c
followed react router tutorial, specified routes (home, search, libra…
mvlofthus Jan 20, 2021
2a815d2
wrote code for VideoLibrary to be called by App, crashing server at t…
mvlofthus Jan 20, 2021
af54942
axios get request pulls through, deleted node.module to prevent local…
mvlofthus Jan 20, 2021
2a7de31
libraryentry subcomponent of library component setup
scottzec Jan 21, 2021
fc34f08
display sorted list of movies under Video Library. Next step is to f…
mvlofthus Jan 21, 2021
2e1b0b2
starting callback function for videolibrary
mvlofthus Jan 21, 2021
021089f
setup callback function and button for video library
scottzec Jan 21, 2021
ce403ee
library page working with clickable buttons
scottzec Jan 21, 2021
dd4634b
return text to user with selected video
scottzec Jan 21, 2021
d17e816
created customer and search component setup
scottzec Jan 21, 2021
fe83718
list of customer buttons returned now for List Customers
scottzec Jan 21, 2021
c5ff81f
added images to buttons
mvlofthus Jan 22, 2021
55e7c93
search form works and pulls up list of movies
mvlofthus Jan 22, 2021
f5f04d6
axios post
scottzec Jan 22, 2021
12519b2
search sort of works on more than one request now, though I do not lo…
mvlofthus Jan 22, 2021
bf49ecc
Merge pull request #1 from mvlofthus/leah-customer
scottzec Jan 22, 2021
6528a54
Merge branch 'master' into video-search
mvlofthus Jan 22, 2021
54caeee
Merge pull request #2 from mvlofthus/video-search
mvlofthus Jan 22, 2021
4aea486
Made search not a button for current completion:
mvlofthus Jan 22, 2021
3c27b97
display selected customer, improve customer list aesthetic
scottzec Jan 22, 2021
f476ee6
css touchup
scottzec Jan 22, 2021
3a7857b
additional info for search page
mvlofthus Jan 22, 2021
33b4b84
returned to full year, substring failed
mvlofthus Jan 22, 2021
31d7500
checkout works
mvlofthus Jan 22, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

yarn.lock
41,591 changes: 34,096 additions & 7,495 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
"version": "0.1.1",
"private": true,
"dependencies": {
"axios": "^0.21.1",
"moment": "^2.29.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1"
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1",
"react-select": "^3.2.0"
},
"devDependencies": {
"gh-pages": "^3.1.0",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.3",
"@testing-library/user-event": "^12.6.0"
"@testing-library/user-event": "^12.6.0",
"gh-pages": "^3.1.0"
},
"scripts": {
"start": "PORT=3001 react-scripts start",
Expand Down
29 changes: 29 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,32 @@
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}

ul {
list-style: none;
}

button {
background-color: white;
border-color: black;
}

nav ul {
list-style: none;
display: flex;
background-color: black;
margin-bottom: 20px;
}

nav ul li {
padding: 20px;
}

nav ul li a {
color: white;
text-decoration: none;
}

.current {
border-bottom: 4px solid white;
}
120 changes: 105 additions & 15 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,111 @@
import React, { Component } from 'react';
import React, { Component, useState } from 'react';
import logo from './logo.svg';
import './App.css';
import { NavLink, Switch, Route } from 'react-router-dom';
import VideoLibrary from './components/VideoLibrary';
import VideoSearch from './components/VideoSearch';
import CustomerList from './components/CustomerList';
import PostToRails from './components/PostToRails';

class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}

const App = () => {
const [selectedVideoID, setSelectedVideoID] = useState('');
const [selectedVideoTitle, setSelectedVideoTitle] = useState('');

const [selectedCustomerID, setSelectedCustomerID] = useState('');
const [selectedCustomerName, setSelectedCustomerName] = useState('');

const [message, setMessage] = useState('');



// 1. pass down function all the way to entry
// 2. make button to be able to select them
// 3. pass data back
const onClickLibraryCallback = (video) => {
setSelectedVideoID(video.id);
setSelectedVideoTitle(video.title);
console.log('onClickLibraryCallback was called')
}

const onClickCustomerListCallback = (customer) => {
setSelectedCustomerID(customer.id);
setSelectedCustomerName(customer.name);
console.log('onClickCustomerListCallback called')
}

const onSuccessfulRental = () => {
setMessage('');
setSelectedCustomerID('');
setSelectedCustomerName('');
setSelectedVideoID('');
setSelectedVideoTitle('');
setMessage(`You successfully checked out!`)
}

const onFailedRental = () =>{
setMessage('Rental incomplete. Make sure to select a video and customer.')
}


const Navigation = () => (
<nav>
<ul>
<li><NavLink exact activeClassName="current" to='/'>Home</NavLink></li>
<li><NavLink exact activeClassName="current" to='/search'>Video Search</NavLink></li>
<li><NavLink exact activeClassName="current" to='/library'>Video Library</NavLink></li>
<li><NavLink exact activeClassName="current" to='/customers'>List Customers</NavLink></li>
</ul>
</nav>
);

const Main = () => (
<Switch>
<Route exact path='/' component={Home}></Route>
<Route exact path='/search' component={Search}></Route>
<Route exact path='/library' component={Library}></Route>
<Route exact path='/customers' component={Customers}></Route>
</Switch>
);

const Home = () => (
<div className='home'>
<h1>Welcome to Video Store</h1>
<PostToRails video={selectedVideoTitle} customer={selectedCustomerID} onSuccessfulRental={onSuccessfulRental} onFailedRental={onFailedRental}/>
</div>
);

const Search = () => (
<div className='search'>
<h1>Search for a new video</h1>
<VideoSearch />
</div>
);


const Library = () => (
<div className = 'library'>
<h1>Peruse our video library</h1>
<VideoLibrary libraryCallback={onClickLibraryCallback}/>
</div>
);

const Customers = () => (
<div className = 'customers'>
<h1>List of customers</h1>
<CustomerList listCallback={onClickCustomerListCallback}/>
</div>
);

return( <div className='app'>
<h1>Leah and Mackenzie's Video Store</h1>
<h3> {selectedVideoTitle !== '' ? `Selected Video: ${selectedVideoTitle}` : null} </h3>
<h3> {selectedCustomerName !== '' ? `Selected Customer: ${selectedCustomerName}` : null} </h3>
<h3> {message !== '' ? message : null} </h3>
<Navigation />
<Main />
</div>
)
}

export default App;
34 changes: 34 additions & 0 deletions src/components/CustomerEntry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import PropTypes from 'prop-types';

// This returns an entry in the customer list.
// name, id and account credit

const CustomerEntry = (props) => {
return (
<div>
<button
onClick={() => {props.listCallback(
{id: props.id,
name: props.name,
accountCredit: props.accountCredit}
)
}
}>
{props.name}
</button>
<p> </p>
</div>
)
}

// For callback, need to have id & account credit come back up so it can be passed to rails
// or put acct credit logic in backend?

CustomerEntry.propTypes = {
name: PropTypes.string,
id: PropTypes.number,
listCallback: PropTypes.func.isRequired
}

export default CustomerEntry;
46 changes: 46 additions & 0 deletions src/components/CustomerList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import CustomerEntry from './CustomerEntry'

const CustomerList = (props) => {
const fullUrl = 'http://localhost:3000/customers';

const [customers, setCustomers] = useState([]);
const [errors, setErrors] = useState(null);

useEffect ( () => {
axios.get(fullUrl)
.then((response) => {
const customerList = response.data;
console.log(customerList);
setCustomers(customerList);
})
.catch((error) => {
setErrors(error.message);
console.log(error.message);
})
}, [])


// SORT?

return (
<div className='customerList'>
<ul>
{customers.map((customer) => {
// ADD WHAT IS PASSED TO CUSTOMER ENTRY in the return
return (<li key={customer.id}>{<CustomerEntry id={customer.id} name={customer.name} listCallback={props.listCallback}/>}</li>);
})
}
</ul>
</div>
)

}

CustomerList.propTypes = {
listCallback: PropTypes.func.isRequired
}

export default CustomerList;
37 changes: 37 additions & 0 deletions src/components/LibraryEntry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { Component, useEffect, useState } from 'react';
import PropTypes from 'prop-types';

// This returns an entry in the video library: title and id

const LibraryEntry = (props) => {
return (
<div>

<p>
<button
onClick={() => {props.libraryCallback(
{id: props.id,
title: props.title}
)
}
}
>
<img src={props.image_url} alt={props.title}/>
<p>Select {props.title}</p>
</button>
<p> </p>
</p>
</div>
)
}

// for callback, need to have id come back up so we can pass it to rails
// hold onto it (setState) then pass it
LibraryEntry.propTypes = {
title: PropTypes.string,
id: PropTypes.number,
libraryCallback: PropTypes.func.isRequired
}


export default LibraryEntry;
79 changes: 79 additions & 0 deletions src/components/PosttoRails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { Component, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import Moment from 'moment';
import axios from 'axios';

// TESTING AREA


Date.prototype.addDays = function(interval) {
this.setDate(this.getDate() + interval);
return this;
};


const PostToRails = (props) => {

const checkoutUrl = 'http://localhost:3000/rentals/';

const [checkouts, setCheckouts] = useState([]);
const [errors, setErrors] = useState(null);


const checkout = () => {
const currentDate = new Date();
// to add 6 days to current date
const dueDate = currentDate.addDays(7);

console.log(dueDate);

const dd = dueDate.getDate();
const mm = dueDate.getMonth() + 1;
const yyyy = dueDate.getFullYear();

let formattedDueDate = yyyy + '-'+ mm + '-'+ dd;
if (mm < 10) {
formattedDueDate = yyyy + '-'+ 0 + mm + '-'+ dd;
}



console.log(formattedDueDate);

// where does this go to get video & customer
// axios, 2nd parameter takes the payload, pass in obj with all those values

axios.post(`${checkoutUrl}${props.video}/check-out?customer_id=${props.customer}&due_date=${formattedDueDate}`)
.then((response) => {
console.log(response);
props.onSuccessfulRental();

})
.catch((error) => {
setErrors(error.message);
console.log(error.message);
props.onFailedRental();
})
}

/////..

return (
<button onClick={checkout}>
Check Out {props.video} To Customer
</button>
)


}


// axios.get maeks a get request to that url, but checkin/checkout make post request
// instead of making that request to customers, should be whatever url you associate with checkin/checkout

PostToRails.propTypes = {

}


export default PostToRails;
Loading