Steps to Setup The Frontend
Step 1: Run the command to create a new React app using create-react-app:
npx create-react-app music-discovery-app
Step 2: Navigate to App Directory:
cd music-discovery-app
Step 3: Install the necessary packages/libraries in your project using the following commands.
npm install axios
Project Structure:
The updated dependencies in package.json file will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
Example: Implementation to setup the frontend for the music discovery app.
/* App.css */
body {
font-family: Arial, sans-serif;
background: linear-gradient(
179.4deg, rgb(12, 20, 69) -16.9%, rgb(71, 30, 84) 119.9%);
color: #ffffff;
margin: 2%
}
h1 {
text-align: center;
margin-bottom: 20px;
}
form {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-bottom: 20px;
}
input {
padding: 8px;
margin: 4px;
border: 1px solid #ffffff;
border-radius: 4px;
background-color: rgba(244, 239, 239, 0.1);
color: #000000;
}
button {
padding: 8px 16px;
margin: 4px;
border: none;
border-radius: 4px;
background-color: #ffffff;
color: #2c5d63;
cursor: pointer;
}
.music-item {
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
padding: 10px;
}
.playing {
background: linear-gradient(
to right, rgb(173, 83, 137), rgb(60, 16, 83)) !important;
/* Light blue background color for playing song */
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 8px;
}
li strong {
font-weight: bold;
}
.music-list {
display: flex;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}
.music-item {
width: 600px;
border: 1px solid #ffffff;
border-radius: 8px;
padding: 20px;
background-color: rgba(255, 255, 255, 0.1);
}
input {
color: white;
}
.music-info h3 {
margin-bottom: 10px;
}
.music-info p {
margin: 5px 0;
}
.search-container {
margin-top: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.search-container input[type="text"] {
padding: 8px;
margin-right: 10px;
border: 1px solid #ffffff;
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.1);
color: #ffffff;
}
.search-container button {
padding: 8px 16px;
border: none;
border-radius: 4px;
background-color: #ffffff;
color: #2c5d63;
cursor: pointer;
}
//App.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';
function App() {
const [musicList, setMusicList] = useState([]);
const [newMusic, setNewMusic] =
useState({
title: '', artist: '',
genre: '', releaseDate: '',
songUrl: ''
});
const [searchTerm, setSearchTerm] = useState('');
const [currentSong, setCurrentSong] = useState(null);
const [audioPlayer, setAudioPlayer] = useState(null);
// Track playing state
const [isPlaying, setIsPlaying] = useState(false);
useEffect(() => {
axios.get('http://localhost:3001/api/music')
.then(response => setMusicList(response.data))
.catch(error =>
console.error('Error fetching music:', error));
}, []);
const handleSearch = () => {
// Trim whitespace from search term
let searchQuery = searchTerm.trim();
if (searchQuery === '') {
// If search query is empty, fetch all songs
axios.get('http://localhost:3001/api/music')
.then(response =>
setMusicList(response.data))
.catch(error =>
console.error('Error fetching music:', error));
} else {
// Otherwise, perform search with non-empty query
axios.get(
`http://localhost:3001/api/music?search=${searchQuery}`)
.then(response => setMusicList(response.data))
.catch(error =>
console.error('Error searching music:', error));
}
};
const handleInputChange = e => {
const { name, value } = e.target;
setNewMusic(
prevState => ({ ...prevState, [name]: value }));
};
const handleSubmit = e => {
e.preventDefault();
if (!newMusic.title ||
!newMusic.artist ||
!newMusic.genre ||
!newMusic.releaseDate ||
!newMusic.songUrl) {
console.error('Please fill in all fields.');
return;
}
axios.post('http://localhost:3001/api/music', newMusic)
.then(response => {
setMusicList(
prevState => [...prevState, response.data]);
setNewMusic({
title: '', artist: '',
genre: '', releaseDate: '',
songUrl: ''
});
console.log('Music added successfully.');
})
.catch(error =>
console.error('Error adding music:', error));
};
const handleEdit = (id, currentMusic) => {
let updatedTitle =
prompt("Enter updated title:", currentMusic.title);
let updatedArtist =
prompt("Enter updated artist:", currentMusic.artist);
let updatedGenre =
prompt("Enter updated genre:", currentMusic.genre);
let updatedReleaseDate =
prompt("Enter updated release date (YYYY-MM-DD):",
currentMusic.releaseDate);
let updatedSongUrl =
prompt("Enter updated song URL:",
currentMusic.songUrl);
// Check if any field is null or undefined
if (updatedTitle === null || updatedTitle === undefined ||
updatedArtist === null || updatedArtist === undefined ||
updatedGenre === null || updatedGenre === undefined ||
updatedReleaseDate === null ||
updatedReleaseDate === undefined ||
updatedSongUrl === null || updatedSongUrl === undefined) {
console.error('Please fill in all fields.');
return;
}
// Construct updatedMusic object
const updatedMusic = {
title: updatedTitle,
artist: updatedArtist,
genre: updatedGenre,
releaseDate: updatedReleaseDate,
songUrl: updatedSongUrl
};
axios.put(
`http://localhost:3001/api/music/${id}`, updatedMusic)
.then(response => {
const updatedList =
musicList.map(music =>
(music._id === id ? response.data : music));
setMusicList(updatedList);
console.log('Music edited successfully.');
})
.catch(error =>
console.error('Error editing music:', error));
};
const handleDelete = id => {
axios.delete(`http://localhost:3001/api/music/${id}`)
.then(() => {
const updatedList =
musicList.filter(
music => music._id !== id);
setMusicList(updatedList);
console.log('Music deleted successfully.');
})
.catch(error =>
console.error('Error deleting music:', error));
};
const playSong = (songUrl) => {
if (audioPlayer) {
// Check if audio is paused before attempting to play
if (audioPlayer.paused) {
audioPlayer.src = songUrl;
audioPlayer.load();
audioPlayer.play();
setIsPlaying(true); // Update playing state
setCurrentSong(songUrl); // Set current song
}
}
};
useEffect(() => {
if (audioPlayer) {
audioPlayer.onended = () => {
setCurrentSong(null);
setIsPlaying(false); // Update playing state
};
}
}, [audioPlayer]);
return (
<div className="App">
<h1>Music Discovery App</h1>
<form onSubmit={handleSubmit}>
<input type="text" name="title"
placeholder="Title" value={newMusic.title}
onChange={handleInputChange} />
<input type="text" name="artist"
placeholder="Artist" value={newMusic.artist}
onChange={handleInputChange} />
<input type="text" name="genre"
placeholder="Genre" value={newMusic.genre}
onChange={handleInputChange} />
<input type="date" name="releaseDate"
value={newMusic.releaseDate}
onChange={handleInputChange} />
<input type="text" name="songUrl"
placeholder="Song URL" value={newMusic.songUrl}
onChange={handleInputChange} />
<button type="submit">Add Music</button>
</form>
<div className="search-container">
<input type="text" placeholder="Search music..."
value={searchTerm} onChange={
(e) => setSearchTerm(e.target.value)} />
<button onClick={handleSearch}>Search</button>
</div>
<div className="music-list">
{musicList.map(music => (
<div className={
`music-item ${currentSong === music.songUrl ? 'playing' : ''}`}
key={music._id}>
<div className="music-info">
<h3>{music.title}</h3>
<p>Artist: {music.artist}</p>
<p>Genre: {music.genre}</p>
<p>
Release Date: {new Date(music.releaseDate).toLocaleDateString()}
</p>
{currentSong === music.songUrl ? (
<button onClick={() => {
audioPlayer.pause();
setIsPlaying(false);
setCurrentSong(null);
}}>Pause</button>
) : (
<button onClick={() => {
playSong(music.songUrl);
setCurrentSong(music.songUrl);
}}>
{isPlaying && currentSong === music.songUrl ? 'Pause' : 'Play'}
</button>
)}
</div>
<div className="music-actions">
<button onClick={
() => handleEdit(music._id,
{ title: 'Updated Title' })}>
Edit
</button>
<button onClick={
() => handleDelete(music._id)}>
Delete
</button>
</div>
</div>
))}
</div>
<audio ref={(ref) => setAudioPlayer(ref)} />
</div>
);
}
export default App;
Step to Run Application: Run the application using the following command from the root directory of the project
npm start
Output: Your project will be shown in the URL http://localhost:3000/
Music Discovery App with MERN Stack
In today’s digital age, music discovery has become an integral part of our lives. With the rise of streaming platforms and personalized recommendations, users are constantly seeking new music experiences. In this article, we’ll delve into the creation of a Music Discovery App using the MERN stack (MongoDB, Express.js, React.js, Node.js). This comprehensive guide will walk you through the process of building a feature-rich web application for exploring and discovering music.
Output Preview:
Contact Us