Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project-music-releases-vite-estefanny #112

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,24 @@

# Music Releases

Replace this readme with your own information about your project.
This week we worked with React creating componets that gets data from Spotify
to transfer to its children's components using props, the requirements were to create components, displays album cover and name, and artist name, adding hover effects and icons, and make the names and albums linkables by clic on the names and it directs you to an external URL.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.

## Getting Started with the Project

### Dependency Installation & Startup Development Server
### The Problem

Once cloned, navigate to the project's root directory and this project uses npm (Node Package Manager) to manage its dependencies.
I used Node.js and npm to set up the development environment. The first step in building the Spotify mockup was installing the necessary packages via npm.

The command below is a combination of installing dependencies, opening up the project on VS Code and it will run a development server on your terminal.
There it was plenty of challenges, like with Node not recognizing the modules. I fixed these issues by reinstalling packages and ensuring the correct file paths.

```bash
npm i && code . && npm run dev
```
Since React helps in building user interfaces by breaking down web pages into smaller, reusable components, it helped me break down the music releases page into smaller parts like individual Album and ArtistName, etc. Instead of building one long HTML file, I made reusable components that dynamically change based on the data.

### The Problem
I got good help from blogs, stackoverflow (specially the section for this project) and chat gpt.

Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
If I had more time I would like to continue with the strech-goal.json (side bar/API)

### View it live

Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
https://splendid-semifreddo-330280.netlify.app/

## Instructions

Expand Down
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Music Releases</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<script type="module" src="./src/main.jsx"></script>
</body>
</html>
1 change: 1 addition & 0 deletions public/icons/dots.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/play.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions src/Album.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from "react";
import ArtistName from "./ArtistName"; // Import ArtistName component
import "./index.css";

const Album = ({ album }) => {

// Function to format the artist names based on the number of artists
const formatArtistNames = (artists) => {
if (artists.length === 2) {
// If there are only 2 artists, return them with "&"
return (
<>
<ArtistName artist={artists[0]} />
<span className="separator"> & </span>
<ArtistName artist={artists[1]} />
</>
);
} else if (artists.length > 2) {
// If more than 2, return all but the last two with commas, and the last two with "&"
return (
<>
{artists.slice(0, -2).map((artist, index) => (
<span key={artist.id}>
<ArtistName artist={artist} />
<span className="separator">, </span>
</span>
))}
<ArtistName artist={artists[artists.length - 2]} />
<span className="separator"> & </span>
<ArtistName artist={artists[artists.length - 1]} />
</>
);
} else {
// If there's only 1 artist, return just that artist
return <ArtistName artist={artists[0]} />;
}
};

return (
<div className="album-card">
{/* Album cover and controls */}
<div className="image-container">
<img className="album-image" src={album.images[1].url} alt={album.name} />

{/* Controls - Play, Heart, Dots */}
<div className="controls">
<img className="heart-btn" src="/icons/heart.svg" alt="Favorite" />
<img className="play-btn" src="/icons/play.svg" alt="Play" />
<img className="dots-btn" src="/icons/dots.svg" alt="More options" />
</div>
</div>

{/* Album name */}
<h3>
<a href={album.external_urls.spotify} target="_blank" rel="noreferrer">
{album.name}
</a>
</h3>

{/* Artists list with formatted commas and "&" */}
<div className="artists">
{formatArtistNames(album.artists)}
</div>
</div>
);
};

export default Album;
16 changes: 14 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import React from "react";
import data from "./data.json";
import Album from './Album.jsx';

console.log(data);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this console.log before handing in


export const App = () => {
return <div>Find me in src/app.jsx!</div>;
};
return (
<div>
<h1>Music Releases</h1>
{/* Mapping through the album data */}
<div className="album-list">
{data.albums.items.map((album) => (
<Album key={album.id} album={album} />
))}
</div>
</div>
);
};
13 changes: 13 additions & 0 deletions src/ArtistName.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

const ArtistName = ({ artist }) => {
return (
<span className="artist">
<a href={artist.external_urls.spotify} target="_blank" rel="noreferrer">
{artist.name}
</a>
</span>
);
};

export default ArtistName;
141 changes: 141 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,144 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

body {
background-color: rgb(0, 0, 0);
}

h1 {
color: #ffffff;
text-align: center;
font-size: 2.5rem;
margin-top: 20px;
}

h1:hover {
color: rgb(9, 53, 155);
}


.album-list {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 4 columns for desktop */
gap: 20px;
padding: 20px;
}

.album-card {
position: relative;
margin: 10px;
border-radius: 8px;
overflow: hidden;
background-color: #000000;
padding: 10px;
border-radius: 5px;
}

/* New wrapper for image and controls */
.image-container {
position: relative;
}

/* Controls centered relative to the image now */
.album-card .controls {
position: absolute;
top: 50%; /* Center vertically */
left: 40%;
right: 15%;
bottom: 50%; /* Center horizontally */
transform: translate(-50%, -50%);
display: flex;
justify-content: space-between; /* Add spacing between icons */
width: 140px; /* Adjust width for better spacing */
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
z-index: 2;
gap: 15px;
}

.album-card .controls > * {
margin: 0 5px; /* Adjust as needed */
}

/* Show controls ONLY when hovering on the image */
.image-container:hover .controls {
opacity: 1;
pointer-events: auto;
filter: brightness(0) invert(1);
}

/* Icon styling and hover effect */
.controls img {
width: 40px; /* General icon size */
height: 40px;
filter: brightness(0) invert(1);
transition: transform 0.3s ease;
cursor: pointer;
margin: 0 8px; /* Space between icons */
}

.controls .dots-btn {
width: 38px; /* Dots icon slightly smaller */
}

.controls img:hover {
transform: scale(1.4); /* Grow on hover */
filter: brightness(0) invert(1);
}

.album-card img {
width: 100%;
border-radius: 5px;
transition: opacity 0.3s ease, filter 0.3s ease;
}

.album-card img:hover {
filter: brightness(0.7);
}

.album-card h3 a {
font-size: 14px;
color: #fff;
text-decoration: none;
font-family: Arial, Helvetica, sans-serif;
}

.album-card h3 a:hover {
text-decoration: underline;
}

.artists {
margin-top: 10px;
}

.artist a {
color: #a0a0a0;
text-decoration: none;
font-family: Arial, Helvetica, sans-serif;
}

.artist a:hover {
color: #fff;
text-decoration: underline;
}

.separator {
color: #a0a0a0; /* Change the color of the separators */
}

/* Responsive styling */
@media (max-width: 768px) {
.album-list {
grid-template-columns: repeat(2, 1fr); /* 2 columns for tablets */
}
}

@media (max-width: 600px) {
.album-list {
grid-template-columns: repeat(1, 1fr); /* 1 column for mobile */
}

}