Hi I am making a website front end (react) which talks to my back end (npm express/npm mssql)
I have made a page in which it uses a map function to render a separate component containing questions.
I have tried to implement a conditional render so that when question complete is set as true it then renders a new component but the new component will vanish after a second or so and will go back to its original state.
these are both in the same file so only one set of imports are required in this situation.
This is my display questions class using a .map to render the separate component.
import React from "react";
import { Link } from "react-router-dom";
import { Modal } from "react-bootstrap";
class DisplayQuestions extends React.Component {
constructor() {
super();
this.state = { questions: [], QuestionsAnswer: [], QuestionsSeverity: [] };
this.onSubmit = this.handleSubmit.bind(this);
}
// sets the questions form sql into state for questions
getItems() {
fetch("/user-questions")
.then(recordset => recordset.json())
.then(results => {
this.setState({ questions: results.recordset });
});
}
//when the component mounts make the sql questions the s
componentDidMount() {
this.setState({
questions: this.getItems()
});
}
handleSubmit(e) {
e.preventDefault();
const data = {
QuestionID: this.QuestionID,
QuestionsAnswer: this.state.QuestionsAnswer,
QuestionSeverity: this.state.QuestionsSeverity
};
try {
fetch("/Question-Response", {
method: "POST", // or 'PUT'
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
console.log("Success:", data);
})
.catch(error => {
console.error("Error:", error);
});
} catch (error) {}
}
refresh() {
window.location.reload();
}
render() {
var self = this;
console.log(this.state.questions);
return (
<div>
<h3 style={{ textAlign: "center" }}>
<u>Desk Assessment</u>
</h3>
<ul>
<button
disabled
className="btn btn-secondary"
style={{ float: "left " }}
>
Desk Assessment
</button>
<Link to="./user-history">
<button className="btn btn-secondary" style={{ float: "left " }}>
View History
</button>
</Link>
<br />
<br />
{this.state.questions &&
this.state.questions.map(function(questions, index) {
return (
<div >
<ul>
<WorkStations questions={questions}></WorkStations>
</ul>
</div>
);
})}
</ul>
</div>
);
}
}
export default DisplayQuestions;
This is my Questions component which is rendered
class WorkStations extends React.Component {
constructor(props) {
super(props);
console.log(props);
this.state = { ...props, show: false, QuestionAnswer: "", QuestionComplete: false };
this.QuestionDecline = this.QuestionDecline.bind(this);
this.QuestionOnChange = this.QuestionOnChange.bind(this);
this.OnCommit = this.OnCommit.bind(this);
}
QuestionDecline(e) {
e.preventDefault();
if (this.state.ShowInput) {
this.setState({ ShowInput: false });
alert(this.state.ShowInput);
} else if (!this.state.ShowInput) {
this.setState({ ShowInput: true });
alert(this.state.ShowInput);
}
}
QuestionOnChange(e) {
this.setState({ QuestionAnswer: e.target.value });
}
//////////////////////////////////////////////////////////// I believe its within here something is off
OnCommit(e) {
e.preventDefault();
alert(this.state.QuestionAnswer);
var today = new Date(),
date = `${today.getUTCFullYear()}-${today.getUTCMonth() +
1}-${today.getUTCDate()} ${today.getHours()}:${today.getMinutes()}:${today.getSeconds()}.${today.getMilliseconds()} `;
let User = window.localStorage.getItem("User")
const data = {
QuestionId: this.state.questions.QuestionId,
QuestionAnswer: this.state.QuestionAnswer,
date : date,
User
};
fetch("/question-response", {
method: "POST", // or 'PUT'
headers: {
Accept: "application/json,",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).then(response => {
console.log("response before it is broken down " + response);
// return response.json();
});
if (this.state.QuestionComplete) {
this.setState({ QuestionComplete: false });
alert(this.state.QuestionComplete);
} else if (!this.state.QuestionComplete) {
this.setState({ QuestionComplete: true });
alert(this.state.QuestionComplete);
}
window.location.reload();
}
////////////////////////////////////////////////
render() {
if (!this.state.QuestionComplete ){
if (!this.state.ShowInput && !this.state.QuestionComplete) {
return (
<div className="jumbotron">
<button
onClick={this.QuestionDecline}
className="btn btn-danger"
style={{ float: "right" }}
>
Decline
</button> <button
onClick={this.deleteQuestion}
className="btn btn-primary"
style={{ float: "right" }}
>
Accept
</button>
<br />
<li> Question ID: {this.state.questions.QuestionId}</li>
<li> Question:{this.state.questions.Question}</li>
</div>
);
} else if(this.state.ShowInput && !this.state.QuestionComplete) {
return (
<div className = "jumbotron">
<li>Question Id: {this.state.questions.QuestionId}</li>
<li>
<textarea
placeholder= "How can this be improved ?"
style={{ width: "100%" }}
onChange={this.QuestionOnChange}
/>
</li>
<button
style={{ float: "right", padding: "2px" }}
className="btn btn-primary"
onClick={this.OnCommit}
>
Submit
</button>
<button
onClick={this.EditQuestion}
style={{ float: "right", padding: "2px" }}
className="btn btn-secondary"
>
Revert
</button>
<br />
</div>
);
}
}else if (this.state.QuestionComplete) {
return(<h3> <li>Question Id: {this.state.questions.QuestionId}</li></h3>)
}
}
}
Related
The print statement in my if (this.props.currentNode.getAttribute("label").toLowerCase() === "data")
is being called infinite times which keeps on printing in modal and sending a post request until the modal is closed.
This does not happen when I put the post call in ComponentDidMount
Can anyone please explain why this is happening and what I can do to avoid this?
class ConfigurationModal extends React.Component {
constructor(props) {
super(props);
this.state = {
selectSource: [],
};
}
el = document.createElement("div");
componentDidMount() {
modalRoot.appendChild(this.el);
}
componentWillUnmount() {
modalRoot.removeChild(this.el);
}
jsonIsEmpty = (obj) => {
return obj === "[object Object]" ? true : false;
};
render() {
// The gray background
const backdropStyle = {
position: "fixed",
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: "rgba(0,0,0,0.3)",
padding: 50,
};
if (this.props.currentNode.getAttribute("label").toLowerCase() === "data") {
console.log("in modal")
http.post("configure_get_sources", {
headers: {
"content-type": "application/json",
},
})
.then((res) => {
this.setState({ selectSource: res.data });
});
var tempConfig = this.jsonIsEmpty(
this.props.currentNode.getAttribute("configuration")
)
? {}
: JSON.parse(this.props.currentNode.getAttribute("configuration"));
let renderedSources = this.state.selectSource.map((item, i) => {
return (
<option value={item} key={i} selected={item === tempConfig["Source"]}>
{item}
</option>
);
});
return ReactDOM.createPortal(
<div className="backdrop" style={backdropStyle}>
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Configure Node</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="container">
<div className="row">
<label className="col-md-4">Data Source: </label>
<select className="col-md-7" id="dataSelect">
{renderedSources}
</select>
</div>
<div className="row col-md-3"></div>
</div>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.props.onClose}>
Close
</Button>
<Button variant="primary" onClick={this.props.saveModal}>
Save changes
</Button>
</Modal.Footer>
</Modal.Dialog>
</div>,
this.el
);
}
return "";
}
}
export default ConfigurationModal;
You're modifying component's state inside render, this causing an infinity loop. Because of react re-rendering component after each props or state change. https://reactjs.org/docs/faq-state.html
I have an offer-adding feature in my app. my front end is on react js and the backend is on Laravel. I have created a route to update the data and called it using Axios but I don't know what I am doing wrong. Any type of Help will be appreciated Thank You!
this is my route in api.php
Route::put('offers/{id}', 'Api\Offer\OfferController#update');
This is my OfferController
public function update(Request $request, $id)
{
$offer = Offer::findOrFail($id);
$offer->update($request->all());
return $offer;
}
This is my API call function for update
export const updateItem = (offertitle,offerdescription,vid,id) => {
return axios
.put(
`/api/offers/${id}`,
{
offertitle:offertitle,
offerdescription:offerdescription,
vid:vid
},
{
headers: { 'Content-Type': 'application/json' }
}
)
.then(function (response) {
console.log(response)
})
}
OfferComponent
export default class Offer extends React.Component{
constructor() {
super()
this.state = {
offertitle: '',
offerdescription: '',
editDisabled: false,
offers: [],
redirect: false,
vid:'',
offerid:''
}
this.onSubmit = this.onSubmit.bind(this)
this.onChange = this.onChange.bind(this)
}
componentDidMount() {
this.getAll()
if (sessionStorage.getItem('user')) {
vendorprofile().then(res => {
this.setState({
vid: res.user.vid
})
})
}
else {
this.setState({ redirect: true });
}
}
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
getAll = () => {
getList().then(data => {
this.setState(
{
offertitle:'',
offerdescription:'',
offers: [...data]
},
() => {
console.log(this.state.offers)
}
)
})
}
onSubmit = e => {
e.preventDefault()
addItem({offertitle: this.state.offertitle, offerdescription: this.state.offerdescription,vid: this.state.vid}).then(() => {
this.getAll()
})
this.setState({
offertitle: '',
offerdescription:'',
vid:''
})
}
onUpdate = e => {
e.preventDefault()
updateItem({ offertitle: this.state.offertitle, offerdescription: this.state.offerdescription, offerid: this.state.offerid, vid: this.state.vid }).then(() => {
this.getAll()
})
this.setState({
offertitle: '',
offerdescription: '',
vid:'',
editDisabled: ''
})
this.getAll()
}
onEdit = (offerid, e) => {
e.preventDefault()
var data = [...this.state.offers]
data.forEach((offers,index) => {
if (offers.offerid === offerid) {
this.setState({
offerid: offers.offerid,
offertitle: offers.offertitle,
offerdescription: offers.offerdescription,
editDisabled: true
})
}
})
}
onDelete = (val, e) => {
e.preventDefault()
deleteItem(val)
var data = [...this.state.offers]
data.filter(function (offers, index) {
if (offers.offerid === val) {
data.splice(index, 1)
}
return true
})
this.setState({ offers: [...data] })
}
render() {
if (this.state.redirect) {
return (
<Redirect to="/stsignin" />
)
}
return (
<div>
<Pane />
<div className="container" style={{ marginTop : 150}}>
<form>
<div className="form-group">
<div className="row">
<div className="col-md-12">
<label>OFFER TITLE</label>
<input
type="text"
className="form-control"
id="offertitle"
name="offertitle"
value={this.state.offertitle || ''}
onChange={this.onChange.bind(this)}
/>
<label>OFFER DESCRIPTION</label>
<input
type="text"
className="form-control"
id="offerdescription"
name="offerdescription"
value={this.state.offerdescription || ''}
onChange={this.onChange.bind(this)}
/>
</div>
</div>
</div>
{!this.state.editDisabled ? (
<button
type="submit"
onClick={this.onSubmit.bind(this)}
className="btn btn-success btn-block"
>
Submit
</button>
) : (
''
)}
{this.state.editDisabled ? (
<button
type="submit"
onClick={this.onUpdate.bind(this)}
className="btn btn-primary btn-block"
>
Update
</button>
) : (
''
)}
</form>
<table className="table">
<tbody>
<tr>
<th>OFFER_TITLE</th>
<th>OFFER_DESCRIPTION</th>
</tr>
{this.state.offers.map((offers,index) => (
<tr key={index}>
<td className="text-left">{offers.offertitle}</td>
<td className="text-left">{offers.offerdescription}</td>
<td className="text-right">
<button
href=""
className="btn btn-info mr-1"
disabled={this.state.editDisabled}
onClick={this.onEdit.bind(
this,
offers.offerid
)}
>
Edit
</button>
<button
href=""
className="btn btn-danger"
disabled={this.state.editDisabled}
onClick={this.onDelete.bind(
this,
offers.offerid
)}
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}
}```
Error 404 Might mean that the offer specified in the link doesn't exist and thus can't be updated. Check if you have an order with the id that you are searching in the database. However, posting your entire response might show us more information. A simple 404 is pretty vague, you might want to copy paste that in.
That being said, i recommend using Eloquent for these kind of routes. You can basically change your route to /offers/{offer} and then instead of typing $id as a variable for that function and then finding the offer by id you can just simply query $offer->update(your_data) and it would work as expected. It is exactly the same thing but just keeps it cleaner and removes any basic mistakes
I'm trying to pass some data (response of fetch to API) from a component to another component, but I don't find the way to pass them.
In the Class AddresForm, I get the serialized data from form, this data is send to API with fecth method. The response has important information and I need use this information contained on response in another component.
class AddressForm extends React.Component{
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.validatePredio = this.validatePredio.bind(this);
this.state = {
isApartment: false,
required: false
};
this.cities = [];
this.cities.push(["11001" ,"XXX"]);
this.cities.push(["05001", "YYY"]);
this.cities.push(["76001", "ZZZ"]);
}
handleSubmit(event) {
event.preventDefault();
const data = serialize(event.target, { hash: true });
data['direccion'] = data['direccion']+"+"+data['num1']+"+"+data['num2']+"+"+data['num3'];
fetch('https://api.....', {
method: 'POST',
headers: header,
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((responseData) => {
console.log(responseData); // this data is needed in another component (MapSection)
});
}
And in this Class I need use the response of fetch from the previous component, exactly I need use some coordinates to render a Map.
export class MapSection extends React.Component{
constructor(props) {
super(props);
this.setState = this.setState.bind(this);
}
state = {
address: null
};
get googleMapDiv(){
return document.getElementById("mapa");
}
googleMapRef = createRef();
render(){
console.log(this.props,this.googleMapRef);
return(
<section className="hidden2" id="mapaSection">
<div className="container">
<div className="row mt-5">
<div className="col mt-5">
<h3>Confirma la ubicación de tu inmueble</h3>
<div className="row mt-5">
<div className="col">
<p id="direccionGeo"> {this.state.address !== null ? this.state.address : ""} </p>
</div>
</div>
<div id="mapa"
ref={this.googleMapRef}
style={{ width: 'auto', height: '55vh' }}
className="card-panel white map-holder"
/>
<div className="botonesMapa row mt-5">
<div className="col-6" align="center">
<button type="button" className="btn btn-info corregirBtn">Corregir dirección</button>
</div>
<div className="col-6" align="center">
<button type="button" className="btn btn-info confirmarBtn">Ubicación correcta</button>
</div>
</div>
</div>
</div>
</div>
</section>
)
}
componentDidMount() {
const self = this;
const googleMapScript = document.createElement('script');
googleMapScript.src = 'https://maps.googleapis.com/maps/api/js?key=yourKEY';
window.document.body.appendChild(googleMapScript);
googleMapScript.addEventListener('load',() => {
var coord = { lat: 4.6903289512, lng: -74.0522237222};
this.googleMap = this.createGoogleMap(coord);
this.marker = this.createMarker();
window.google.maps.event.addListener(this.marker, 'dragend', function(e) {
var request = {
"entrada": "address",
"mpio_ccdgo": "11001",
"lat": e.latLng.lat(),
"lng": e.latLng.lng()
};
fetch('https://api....', {
method: 'POST',
headers: header,
body: JSON.stringify(request),
}).then((response) => response.json())
.then(responseData => {
self.setState({
address: responseData.direccion_formato
});
});
});
});
}
createGoogleMap = ( data ) => {
return new window.google.maps.Map(this.googleMapRef.current, {
zoom: 16,
center:{
lat: data.lat, //4.6903289512
lng: data.lng//-74.0522237222
},
disableDefaultUI: true
});
};
createMarker = () => {
return new window.google.maps.Marker({
position: {lat: 4.6903289512, lng: -74.0522237222},
map: this.googleMap,
title: 'Avaluamos',
draggable: true
});
};
}
Finally I've a Class that join all components
class InitialForm extends React.Component{
constructor(props) {
super(props);
}
render(){
return(
<div>
<AddressForm />
<MapSection/>
<FeaturesForm/>
</div>
)
}
}
Many Thanks for your time and knowledge.
An idea would be to add a method to InitialForm that takes a string and saves it to InitialForm's state. You can pass this method as a prop to AddressForm and call it with the api response as an argument. Now you got the response in InitialForm and you can pass it down to MapSection.
Is that clear?
I am trying to generate expansion panels based on fetching API, which I have done successfully. The problem that I am having is that when I try to generate the data on the expansion panels, it shows all sets of data, where I want it to show one set of data per expansion panel. I used the Expansion Panel Component from material-ui
class FetchData extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false,
items: [],
}
}
componentDidMount() {
fetch(url , {
method: 'get',
mode: 'cors',
headers: {
'X-API-KEY': API_KEY,
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json,
})
})
};
render() {
const { classes } = this.props;
var{ isLoaded, items } = this.state;
if(!isLoaded) {
return <div>Loading...</div>
}
else{
return (
<div className="container">
<ul>
{items.map((item) => (
<li>
<ExpansionPanel />
</li>
))}
</ul>
</div>
);
}
}
}
export default FetchData;
Code for ExpansionPanel
function DetailedExpansionPanel(props) {
const { classes } = props;
return (
<div className={classes.root}>
<ExpansionPanel>
<ExpansionPanelSummary expandIcon={<img src={ExpandMoreIcon} alt="EMI"/>} >
<div className={classes.column}>
{this.item.props.device_id}
</div>
<div className={classes.column}>
</div>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={classes.details}>
<div className={classes.column} />
<div className={classes.column}>
<Chip label="Barbados" className={classes.chip} onDelete={() => {}} />
</div>
<div className={classNames(classes.column, classes.helper)}>
<Typography variant="caption">
Select your destination of choice
<br />
<a href="#sub-labels-and-columns" className={classes.link}>
Learn more
</a>
</Typography>
</div>
</ExpansionPanelDetails>
<Divider />
<ExpansionPanelActions>
<Button size="small">Cancel</Button>
<Button size="small" color="primary">
Save
</Button>
</ExpansionPanelActions>
</ExpansionPanel>
</div>
);
}
DetailedExpansionPanel.propTypes = {
classes: PropTypes.object.isRequired,
};
I have a "Nightlife Coordination" app (from the Free Code Camp curriculum) that allows a user to search by city and RSVP to a bar for that night. The app keeps a list of who has RSVP'd and who is going. It is built with React and Bootstrap v4 (and Node on the back end).
I have text under each bar location that, when clicked, allows a user to RSVP or unRSVP. There is also a button that shows how many people have RSVP'd and, if clicked, will display a Bootstrap popover of the list of people who have RSVP'd.
If a user RSVPs (or unRSVPs), I want the list to update. (Currently, the number on the button DOES update, but not the list.)
The following two images show the problem:
Upon initial load, all is correctly functional
When the user RSVPS or unRSVPs, the number on the button correctly updates, but the list does not
Here is my code.
The list is being generated in the data-content attribute in the second anchor tag in the render method.
Can anyone help?
One other hint is that in my React developer tools Chrome extension, it shows the data-content attribute correctly updating upon RSVP and unRSVP. Is it that perhaps Bootstrap saves the contents of the data-content attribute in its JS file upon initial render and does not update it?
const React = require('react');
class Bar extends React.Component {
constructor(props) {
super(props);
this.state = {
countMeIn: false, // coming from Mongo
numberGoing: this.props.user_namesArr.length,
user_id: this.props.twitter_id,
user_name: this.props.user_name,
yelp_id: this.props.yelp_id,
user_namesArr: this.props.user_namesArr
};
}
componentDidMount() { // need the same for DidMount and DidUpdate, in case user is signed in upon load (from previous session), or signs in after load
if (this.state.user_namesArr.includes(this.props.user_name) && !this.state.countMeIn) {
this.setState({
countMeIn: true
});
}
}
componentDidUpdate(prevProps, prevState) { // Need both in case user logs in after initial page load
console.log(this.state.user_namesArr);
if (this.state.user_namesArr.includes(this.props.user_name) && !prevState.countMeIn) {
this.setState({
countMeIn: true
});
}
$('[data-toggle="popover"]').popover();
}
rsvp() {
let url = '/rsvp/?&yelp_id=' + this.props.yelp_id + '&user_id=' + this.props.twitter_id + '&user_name=' + this.props.user_name;
fetch(url, { method: "POST" })
.then((res) => res.json())
.then((json) => {
let newArr = this.state.user_namesArr;
newArr.push(this.props.user_name);
this.setState({
numberGoing: this.state.numberGoing + 1,
countMeIn: true,
user_namesArr: newArr,
});
})
}
unrsvp() {
let url = '/unrsvp/?&yelp_id=' + this.props.yelp_id + '&user_id=' + this.props.twitter_id + '&user_name=' + this.props.user_name;
fetch(url, { method: "POST" })
.then((res) => res.json())
.then((json) => {
let ind = this.state.user_namesArr.indexOf(this.props.user_name);
let newArr = this.state.user_namesArr;
newArr.splice(ind, 1);
this.setState({
numberGoing: this.state.numberGoing - 1,
countMeIn: false,
user_namesArr: newArr,
});
})
}
render() {
return (
<div className="col-lg-4 onecomponent">
<a href={ this.props.bar_yelp_url } target="_blank">
<div className="barname text-center">
{ this.props.name }
</div>
<div className="priceline">
<img className="stars" src={ this.state.starsUrl } /> { this.props.review_count } reviews <span className="price">{ this.props.price }</span>
</div>
<div className="image">
<img class="mainimg" src={ this.props.image_url } />
</div>
<div className="address text-center">
{ this.props.loc[0] }., { this.props.loc[1] }
</div>
</a>
<hr/>
<div className="text-center">
<a tabindex="0" role="button" className="btn btn-success" data-toggle={ this.state.user_namesArr.length > 0 ? "popover" : "" } data-trigger="focus" title="Who's In?" data-content={ this.state.user_namesArr }>
{ this.state.numberGoing } going
</a>
{
this.props.loggedIn ?
this.state.countMeIn ?
<span className="going" onClick={ () => this.unrsvp() }>You're going!</span> : // if logged in and already RSVP'd
<span className="rsvpdetails" onClick={ () => this.rsvp() }>Count me in!</span> : // if logged in but not yet RSVP'd
<span> Please log in </span> // if not logged in
}
</div>
</div>
)
}
}
module.exports = Bar;
Maybe using ref could help ... but why not use reactstrap and more important why not react-popper ...? It's well known (https://github.com/FezVrasta/popper.js/#react-vuejs-angular-angularjs-emberjs-etc-integration) that many libraries doesn't work well with react or any other (virtual) DOM managers.
Do you really need jQuery?
Using react portals you can remove all theese dependencies.
It works with Reactstrap. I simply added reactstrap to my package.json file, and used the Reactstrap code.
const React = require('react');
import { Button, Popover, PopoverHeader, PopoverBody } from 'reactstrap';
class Bar extends React.Component {
constructor(props) {
super(props);
this.state = {
countMeIn: false, // coming from Mongo
numberGoing: this.props.user_namesArr.length,
user_id: this.props.twitter_id,
user_name: this.props.user_name,
yelp_id: this.props.yelp_id,
user_namesArr: this.props.user_namesArr,
popover: false
};
this.toggle = this.toggle.bind(this);
}
componentDidMount() { // need the same for DidMount and DidUpdate, in case user is signed in upon load (from previous session), or signs in after load
if (this.state.user_namesArr.includes(this.props.user_name) && !this.state.countMeIn) {
this.setState({
countMeIn: true
});
}
}
componentDidUpdate(prevProps, prevState) {
if (this.state.user_namesArr.includes(this.props.user_name) && !prevState.countMeIn) {
this.setState({
countMeIn: true
});
}
}
rsvp() {
let url = '/rsvp/?&yelp_id=' + this.props.yelp_id + '&user_id=' + this.props.twitter_id + '&user_name=' + this.props.user_name;
fetch(url, { method: "POST" })
.then((res) => res.json())
.then((json) => {
let newArr = this.state.user_namesArr;
newArr.push(this.props.user_name);
this.setState({
user_namesArr: newArr,
numberGoing: this.state.numberGoing + 1,
countMeIn: true
});
})
}
unrsvp() {
let url = '/unrsvp/?&yelp_id=' + this.props.yelp_id + '&user_id=' + this.props.twitter_id + '&user_name=' + this.props.user_name;
fetch(url, { method: "POST" })
.then((res) => res.json())
.then((json) => {
let ind = this.state.user_namesArr.indexOf(this.props.user_name);
let newArr = this.state.user_namesArr;
newArr.splice(ind, 1);
this.setState({
user_namesArr: newArr,
numberGoing: this.state.numberGoing - 1,
countMeIn: false
});
})
}
toggle() {
this.setState({
popover: !this.state.popover
});
}
render() {
return (
<div className="col-lg-4 onecomponent">
<a href={ this.props.bar_yelp_url } target="_blank">
<div className="barname text-center">
{ this.props.name }
</div>
<div className="priceline">
<img className="stars" src={ this.state.starsUrl } /> { this.props.review_count } reviews <span className="price">{ this.props.price }</span>
</div>
<div className="image">
<img class="mainimg" src={ this.props.image_url } />
</div>
<div className="address text-center">
{ this.props.loc[0] }., { this.props.loc[1] }
</div>
</a>
<hr/>
<div className="text-center">
{ /* For this to work, id must have leading letters, otherwise throws massive errors. See here: https://stackoverflow.com/questions/23898873/failed-to-execute-queryselectorall-on-document-how-to-fix */ }
<Button id={ "abc" + this.props.yelp_id } className="btn btn-success" onClick={ this.toggle }>{ this.state.numberGoing } going</Button>
<Popover placement="right" isOpen={ this.state.popover } target={ "abc" + this.props.yelp_id } toggle={ this.toggle }>
<PopoverHeader>Who's In?</PopoverHeader>
<PopoverBody>{ this.state.user_namesArr }</PopoverBody>
</Popover>
{
this.props.loggedIn ?
this.state.countMeIn ?
<span className="going" onClick={ () => this.unrsvp() }>You're going!</span> : // if logged in and already RSVP'd
<span className="rsvpdetails" onClick={ () => this.rsvp() }>Count me in!</span> : // if logged in but not yet RSVP'd
<span> Please log in </span> // if not logged in
}
</div>
</div>
)
}
}
module.exports = Bar;