How do I set up a comment reply feature in react.js in these codes? - node.js

So, I am using react, nodejs and mongodb to build a basic blog application.
So far, I have been able to add the comment feature and users can create, delete and edit comments. But I wanted to add the ability to reply to a comment. I added a 'Reply' text inside the area where I mapped the array of comments in my react.js component. So, when you click on the 'Reply' it toggles the textbox for reply. That means on first click, the textbox to reply to that specific comment shows up, on second click, that textbox hides.
The problem now is that the toggle is working for all the mapped array of comments. I am trying to assign the specific '_id' to the 'Reply' text and pass it to the textbox for the user to write their reply to that specific comment using the '_id'. This should prevent the reply textbox from toggling for all the comments at the same time. How best can I get this done? Here are my codes:
The useState that hides and shows the textbox
const [showReply, setShowReply] = useState(false)
The function that toggles the useState
const handleShowReplyComment = (id) =>{
console.log(id)
if(id){
setShowReply(!showReply)
console.log(id)
}
}
This function picks the '_id' of the comment that I clicked. But how to pass that '_id' to the textbox is my challenge.
return (
<div className="comment">
<h5 className='users-comment'>Users comments</h5>
{comments.map((singleComment, index)=>{
console.log(singleComment)
const {author, commentdescription, _id, createdAt} = singleComment
return(
<>
{updateComment == _id ?
<div className='comment-div' key={_id} >
<textarea className='comment-wrapper' type='text'
onChange={(e) => setCommentDescription(e.target.value)} value={commentdescription2}>
</textarea>
<button className={isLoading ? 'comment-btn-no-cursor comment-btn': 'comment-btn'}onClick={() => handleCommentUpdate(_id)}>Update Post</button>
{error && <p>what happened?</p> }
</div>
:
<div className='displayed-comments'key={_id}>
<div className="commentPic">
<img className="user-pics" src={PF + singleComment.author.profilePicture} alt="" />
</div>
<div className="comment-info">
<div className="comment-author-div">
<div className='comment-author-date-info'>
<h4 className="comment-author">{singleComment.author.username}</h4>
<p className="comment-date">{new Date(singleComment.createdAt).toDateString()}
</p>
</div>
{
singleComment.author.username == user?.username && <div className="comment-edit-delete-div">
<i className="singlePostIcon fas fa-edit" onClick={() => {setUpdateComment(_id); setCommentDescription(commentdescription)}} ></i>
<i className={isLoading? "cursor-not-allowed singlePostIcon far fa-trash-alt":"singlePostIcon far fa-trash-alt" } onClick={() => handleCommentDelete(_id)} ></i>
</div>
}
</div>
<p className="comment-content">{singleComment.commentdescription}</p>
<div>
</div>
<h5 className="reply-comment" onClick={() => handleShowReplyComment(_id)}>Reply</h5> //this is the text with the toggle onClick function that toggles the useState called 'showReply'
{showReply && <div className='reply-div'>//this is the textbox with the useState 'showReply'.
<textarea className='comment-wrapper '>
</textarea>
</div>}
</div>
</div>
}
</>
)
})}
</div>
)

Related

How can I change the colour of a specific div based off the entry in my database? For a real-time parking lot map

I am not sure where to begin in regards to this type of development. I have developed my react-nodejs app which is successfully connected with my postgresql database.
An visual example UI of what I'm trying to attain
I would like to create a map that reflects a parking lot, and each parking spot should change colour based on the information in the database at that current time. For example, on Feb 9 at 9:25pm parking spot #4 is occupied, so my map will show the parking spot as red, meanwhile parking spot #5 is unoccupied, so the spot is green.
My frontend is made with react, and I have edited the elements with css.
For my database, right now I have my parking spot table, I have the current date, parking spot number, and the occupied column set as boolean. Does boolean make sense for the occupied column, in this regard?
The code for the table:
CREATE TABLE parking_spots (
parking_spot_id serial NOT NULL PRIMARY KEY,
parking_spot_number int serial NOT NULL,
occupancy boolean,
createdAt timestamp DEFAULT CURRENT_TIMESTAMP
);
The code for my parking lot is as follows:
const ParkingLot = () => {
// function abc(n) { console.log(n); }
const navigate = useNavigate(); // the navigation hook
const handleClick = event => {
event.preventDefault();
// navigate({value}); //redirects to the /home address
navigate('/')
}
const handleClickFwd = event => {
event.preventDefault();
// navigate({value}); //redirects to the /home address
navigate('/home/booking')
}
return (
<div className='flex-container'>
<div className='row'>
<div className="flex-container-accessories">
<div class="flex-accessories">
<div
className='backButton'
id="icon"
onClick={handleClick}
>
<ArrowBackIosIcon
className="icon"
sx={{fontSize: 'medium'}}
/>
</div>
<div
className='fwdButton'
id="icon"
onClick={handleClickFwd}
>
<ArrowForwardIosIcon
className="icon"
sx={{fontSize: 'medium'}}
/>
</div>
</div>
</div>
</div>
<div className='row'>
<header>
<div>
<h2> 1st Floor </h2>
<h2> 2 Spots Available </h2>
</div>
</header>
</div>
<div className="row">
<div className='flex-accessories'>
<div className='dropDown'>
<Selecter
className='dropDown'
/>
</div>
</div>
<div className="flex-accessories">
<div className='dropDownRight'>
<SelectType
className='dropDownRight'
/>
</div>
</div>
</div>
<div className='row'>
<ParkingMap/>
</div>
<div className="row">
<ParkingLegend/>
</div>
</div>
);
};
export default ParkingLot;
Any advice, guidance, or tutorials would be greatly appreciated.

In here, I want to preview image before update profile picture

Before updating profile picture, I want to preview it. So, here I use function to preview and submit it. But, this two of task can't be do in one fuction. If you know how to do it. Please help me.
<div class="mb-3">
<label for="formFile" class="form-label">
{" "}
<strong> Profile Picture</strong>{" "}
</label>
<div className="row">
<div className="col-sm-4">
<img className="img shadow" src={file} alt="select image" />
</div>
<div className="col-sm-8">
<input
class="form-control"
type="file"
id="file"
filename="file"
onChange={onChangeFile}
required
/>
</div>
</div>
</div>
this is the function i used
const onChangeFile = (e) => {
setfile(e.target.files[0]);
const [file] = e.target.files;
setfile(URL.createObjectURL(file));
// if (e.target.files && e.target.files[0]) {
// setfile(URL.createObjectURL(e.target.files[0]));
// setfile(e.target.files[0]);
// }
};
https://jakub-kozak.medium.com/how-to-open-the-native-camera-in-mobile-browsers-327820fa669a
This article explains how to do preview a photo you have uploaded / taken!

How to show a popup modal on page load in React js functional component

How to show a popup modal on page load in React js functional component.basically when the page loads the popup or modal should be visible automatically without any click
Most modals will have a prop to specify whether or not the modal should be open. You can simply set this to true on initialization.
Consider an example using a Dialog from the React UI library MUI:
const SimpleDialog = (props) =>
{
const [open, setOpen] = useState(true)
return (
<Dialog open = {open}>
<DialogTitle>Title</DialogTitle>
<DialogContent>...</DialogContent>
</Dialog>
)
}
The open prop of the Dialog is based on the value of the state variable, which is initialized as true. You can change this value as needed through various Dialog actions. To learn more about MUI Dialogs, see the docs.
For information on useState, see the React docs.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modalState: true
};
this.handleShow = this.handleShow.bind(this);
}
handleShow() {
this.setState({ modalState: !this.state.modalState });
}
render() {
return (
<div>
<div className={"modal fade" + (this.state.modalState ? " show d-block" : " d-none")} tabIndex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">My Profile</h5>
<button type="button" className="close" onClick={this.handleShow}>
<span>×</span>
</button>
</div>
<div className="modal-body">...</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" onClick={this.handleShow}>Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(, document.getElementById('root'));
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">

Cypress - how to get child of a specific parent element

I am stuck by finding a specific button within my list of items... The button exists 3 times with exact same data-testid, but the parent is different. And I end with
error: cy.click() can only be called on a single element. Your subject contained 3 elements. Pass { multiple: true } if you want to serially click each element.
HTML:
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
<div data-testid="list-item">
<div>
<div>
<span data-testid="status2">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
How can I select the details_button of either status1 or status2?
My attempt was:
cy.get('[data-testid=status1]')
.get('[data-testid="details_button"]').click()
cy.get('[data-testid=status1]')
.parent().parent()
.get('[data-testid="details_button"]').click()
Your first attempt is almost correct, but use .find() for the second step
cy.get('[data-testid=status1]')
.find('[data-testid="details_button"]') // find works here (same as .within())
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
<!-- span closing tag is missing -->
</div>
</div>
</div>
The reason that works is because the HTML posted is slightly invalid - the <span> has no closing tag.
Cypress thinks that the button is inside the span, so using .find() works.
However if that's a typo, you should change to your 2nd command using .parent() and also change .get() to .find()
cy.get('[data-testid=status1]')
.parent()
.find('[data-testid="details_button"]')
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1"></span>
<!-- span is closed, button is outside span so use .parent() command -->
<button data-testid="details_button">click</button>
</div>
</div>
</div>
You can use the siblings() method is cypress.
cy.get('[data-testid=status1]').siblings('[data-testid="details_button]').click()
cy.get('[data-testid=status2]').siblings('[data-testid="details_button]').click()
You can also use a combination of parent() and within(), something like:
cy.get('span[data-testid=status1]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})
cy.get('span[data-testid=status2]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})

Semantic UI: get current dropdown search input text

I'm trying to filter some results I will get from an api using Semantic UI's dropdown search component.
The issue is that I don't know how to get the text I'm typing in the input field
The dropdown search I have:
<div class="ui fluid search selection dropdown" id="user-dropdown">
<input id="user-dropdown-input" name="country" type="hidden">
<i class="dropdown icon"></i>
<div class="default text">Search...</div>
<div class="menu" id="user-dropdown-menu">
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
</div>
</div>
How dropdown is initialized:
$(document).ready(function () {
$('.ui.dropdown').dropdown({
clearable: true,
fullTextSearch: true
});
});
What I tried:
$('#user-dropdown').on('keyup', function () {
let input = $('#user-dropdown');
console.log('Val: ' + input.dropdown().val());
// also tried: $('#user-dropdown-input').val()
// $('#user-dropdown-input').html()
// $('#user-dropdown-input').text()
});
Basically what I want is if I type "abc" to print the value "abc" into the console, but I don't know how to get that value.
what worked for me was searching the input used for search that looks like:
<input class="search" autocomplete="off" tabindex="0">
and I added a type to this input
document.getElementsByClassName('search').type = 'text';
and then got the value by class on keyup
$('.search').keyup(function() {
console.log($(this).val());
});

Resources