-
-
+
diff --git a/projects/month-calender/index.js b/projects/month-calender/index.js
new file mode 100644
index 0000000..30ee25d
--- /dev/null
+++ b/projects/month-calender/index.js
@@ -0,0 +1,41 @@
+const monthEl = document.querySelector(".date h1");
+const fullDateEl = document.querySelector(".date p");
+const daysEl = document.querySelector(".days");
+
+const monthInx = new Date().getMonth();
+const lastDay = new Date(new Date().getFullYear(), monthInx + 1, 0).getDate();
+const firstDay = new Date(new Date().getFullYear(), monthInx, 1).getDay() - 1;
+
+
+const months = [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+];
+
+monthEl.innerText = months[monthInx];
+fullDateEl.innerText = new Date().toDateString();
+
+let days = "";
+
+for (let i = firstDay; i > 0; i--) {
+ days += `
`;
+}
+for (let i = 1; i <= lastDay; i++) {
+ if (i === new Date().getDate()) {
+ days += `
`;
+ }
+}
+
+daysEl.innerHTML = days;
diff --git a/projects/month-calender/script.js b/projects/month-calender/script.js
deleted file mode 100644
index d24ec17..0000000
--- a/projects/month-calender/script.js
+++ /dev/null
@@ -1,42 +0,0 @@
-const date = new Date();
-
-const monthDays = document.querySelector(".days");
-
-const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
-
-const firstDayIndex = date.getDay();
-
-const months = [
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December",
-];
-
-document.querySelector(".date h1").innerText = months[date.getMonth()];
-
-document.querySelector(".date p").innerText = new Date().toDateString();
-
-let days = "";
-
-for (let i = firstDayIndex - 1; i > 0; i--) {
- days += `
`;
-}
-
-for (let i = 1; i <= lastDay; i++) {
- if (i === new Date().getDate() && date.getMonth() === new Date().getMonth()) {
- days += `
`;
- }
-}
-
-monthDays.innerHTML = days;
diff --git a/projects/month-calender/style.css b/projects/month-calender/style.css
index c0d4745..61fde6e 100644
--- a/projects/month-calender/style.css
+++ b/projects/month-calender/style.css
@@ -1,97 +1,87 @@
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- font-family: sans-serif;
+*{
+ margin: 0;
+ padding: 0;
+ font-family: sans-serif;
+ box-sizing: border-box;
}
-.container {
- width: 100%;
- height: 100vh;
- background-color: salmon;
- color: lightgray;
- display: flex;
- justify-content: center;
- align-items: center;
+.container{
+ width: 100%;
+ height: 100vh;
+ background-color: salmon;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
-.calendar {
- width: 450px;
- height: 520px;
- background-color: black;
- box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.4);
- border-radius: 10px;
+.calender{
+ background-color: black;
+ color: lightgray;
+ width: 450px;
+ height: 520px;
+ border-radius: 10px;
+ box-shadow: 4px 4px 8px rgba(0, 0, 0, .4);
}
-.month {
- width: 100%;
- height: 120px;
- background-color: lightseagreen;
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 0 20px;
- text-align: center;
- border-radius: 10px 10px 0 0;
+.month{
+ width: 100%;
+ height: 120px;
+ background-color: lightseagreen;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ border-radius: 10px 10px 0 0;
}
-.month i {
- font-size: 25px;
- cursor: pointer;
+.month h1{
+ font-size: 30px;
+ font-weight: 400;
+ text-transform: uppercase;
}
-.month h1 {
- font-size: 30px;
- font-weight: 400;
- text-transform: uppercase;
- letter-spacing: 2px;
- margin-bottom: 1px;
+.month p{
+ font-size: 16px;
}
-.month p {
- font-size: 16px;
-
-}
-
-.weekdays {
- width: 100%;
- height: 50px;
- display: flex;
+.weekdays{
+ width: 100%;
+ height: 50px;
+ display: flex;
}
-.weekdays div {
- font-size: 15px;
- font-weight: bold;
- letter-spacing: 1px;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
+.weekdays div{
+ font-size: 15px;
+ font-weight: bold;
+ letter-spacing: 1px;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
-.days {
- width: 100%;
- display: flex;
- flex-wrap: wrap;
- padding: 2px;
+.days{
+ width: 100%;
+ display: flex;
+ flex-wrap: wrap;
+ padding: 2px;
}
-.days div {
- font-size: 14px;
- margin: 3px;
- width: 57.5px;
- height: 50px;
- display: flex;
- justify-content: center;
- align-items: center;
+.days div{
+ font-size: 14px;
+ margin: 3px;
+ width: 57.5px;
+ height: 50px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
-.days div:hover:not(.empty) {
- border: 2px solid gray;
- cursor: pointer;
+.days div:hover:not(.empty){
+ border: 2px solid gray;
+ cursor: pointer;
}
-.today {
- background-color: lightseagreen;
-
-}
+.today{
+ background-color: lightseagreen;
+}
\ No newline at end of file
diff --git a/projects/music-player/index.html b/projects/music-player/index.html
new file mode 100644
index 0000000..20b6976
--- /dev/null
+++ b/projects/music-player/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/projects/music-player/pause.png b/projects/music-player/pause.png
new file mode 100644
index 0000000..3c877cc
Binary files /dev/null and b/projects/music-player/pause.png differ
diff --git a/projects/music-player/play.png b/projects/music-player/play.png
new file mode 100644
index 0000000..7019bf1
Binary files /dev/null and b/projects/music-player/play.png differ
diff --git a/projects/music-player/script.js b/projects/music-player/script.js
new file mode 100644
index 0000000..c037a17
--- /dev/null
+++ b/projects/music-player/script.js
@@ -0,0 +1,90 @@
+const playlist = [
+ { title: "Song 1", src: "songs/song1.m4a" },
+ { title: "Song 2", src: "songs/song2.m4a" },
+ { title: "Song 3", src: "songs/song3.m4a" },
+];
+
+const links = document.querySelectorAll(".playlist__item a");
+
+links.forEach((link) => {
+ link.addEventListener("click", function (e) {
+ e.preventDefault();
+ const source = this.getAttribute("data-src");
+ document.querySelector("#player").setAttribute("src", source);
+ playSong();
+
+ // Remove active class from all links
+ links.forEach((link) => {
+ link.classList.remove("active-song");
+ });
+
+ // Add active class to clicked link
+ this.classList.add("active-song");
+ });
+});
+
+function playSong() {
+ const player = document.querySelector("#player");
+ const playButton = document.querySelector(".player__button--play");
+ const pauseButton = document.querySelector(".player__button--pause");
+ const progressBar = document.querySelector(".player__progress-bar");
+
+ if (player.paused) {
+ player.play();
+ playButton.classList.remove("active");
+ pauseButton.classList.add("active");
+ } else {
+ player.pause();
+ playButton.classList.add("active");
+ pauseButton.classList.remove("active");
+ }
+
+ player.addEventListener("timeupdate", function () {
+ const progress = (player.currentTime / player.duration) * 100;
+ progressBar.style.width = `${progress}%`;
+ });
+
+ progressBar.addEventListener("click", function (e) {
+ const progressWidth = this.offsetWidth;
+ const clickedWidth = e.offsetX;
+ const percent = (clickedWidth / progressWidth) * 100;
+ player.currentTime = (player.duration / 100) * percent;
+ progressBar.style.width = `${percent}%`;
+ });
+}
+
+function playFirstSong() {
+ const firstSong = playlist[0].src;
+ document.querySelector("#player").setAttribute("src", firstSong);
+ playSong();
+}
+
+const playButton = document.querySelector(".player__button--play");
+const pauseButton = document.querySelector(".player__button--pause");
+
+playButton.addEventListener("click", function () {
+ const player = document.querySelector("#player");
+ player.play();
+ playButton.classList.remove("active");
+ pauseButton.classList.add("active");
+});
+
+pauseButton.addEventListener("click", function () {
+ const player = document.querySelector("#player");
+ player.pause();
+ playButton.classList.add("active");
+ pauseButton.classList.remove("active");
+});
+
+const player = document.querySelector("#player");
+player.addEventListener("play", function () {
+ playButton.classList.remove("active");
+ pauseButton.classList.add("active");
+});
+
+player.addEventListener("pause", function () {
+ playButton.classList.add("active");
+ pauseButton.classList.remove("active");
+});
+
+playFirstSong();
diff --git a/projects/music-player/songs/song1.m4a b/projects/music-player/songs/song1.m4a
new file mode 100644
index 0000000..90842b1
Binary files /dev/null and b/projects/music-player/songs/song1.m4a differ
diff --git a/projects/music-player/songs/song2.m4a b/projects/music-player/songs/song2.m4a
new file mode 100644
index 0000000..13c7c3d
Binary files /dev/null and b/projects/music-player/songs/song2.m4a differ
diff --git a/projects/music-player/songs/song3.m4a b/projects/music-player/songs/song3.m4a
new file mode 100644
index 0000000..02ba7a4
Binary files /dev/null and b/projects/music-player/songs/song3.m4a differ
diff --git a/projects/music-player/style.css b/projects/music-player/style.css
new file mode 100644
index 0000000..038d0b1
--- /dev/null
+++ b/projects/music-player/style.css
@@ -0,0 +1,90 @@
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ font-family: Arial, sans-serif;
+ background-color: #f2f2f2;
+}
+
+.container {
+ max-width: 600px;
+ margin: 0 auto;
+ padding: 0 20px;
+}
+
+.title {
+ text-align: center;
+ margin-top: 50px;
+ margin-bottom: 50px;
+}
+
+.player {
+ margin-bottom: 50px;
+}
+
+.player__controls {
+ display: flex;
+ justify-content: center;
+ margin-bottom: 20px;
+}
+
+.player__button {
+ width: 50px;
+ height: 50px;
+ background-color: #fff;
+ border: none;
+ cursor: pointer;
+ margin-right: 10px;
+ background-image: url("play.png");
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 60%;
+}
+
+.player__button--pause {
+ background-image: url("pause.png");
+}
+
+.player__button.active {
+ background-color: #0074d9;
+ color: #fff;
+}
+
+.player__progress {
+ height: 5px;
+ background-color: #f5f5f5;
+ position: relative;
+}
+
+.player__progress-bar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: #0074d9;
+ width: 0%;
+}
+
+.playlist__item {
+ margin-bottom: 10px;
+}
+
+.playlist__item a {
+ display: block;
+ padding: 10px;
+ background-color: #fff;
+ color: #333;
+ text-decoration: none;
+}
+
+.playlist__item a:hover {
+ background-color: #f5f5f5;
+}
+
+.playlist__item a.active-song {
+ background-color: #0074d9;
+ color: #fff;
+}
diff --git a/projects/navbar/index.html b/projects/navbar/index.html
new file mode 100644
index 0000000..78fd71b
--- /dev/null
+++ b/projects/navbar/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
diff --git a/projects/Navbar-project/index.js b/projects/navbar/index.js
similarity index 100%
rename from projects/Navbar-project/index.js
rename to projects/navbar/index.js
diff --git a/projects/Navbar-project/logo.svg b/projects/navbar/logo.svg
similarity index 100%
rename from projects/Navbar-project/logo.svg
rename to projects/navbar/logo.svg
diff --git a/projects/Navbar-project/styles.css b/projects/navbar/styles.css
similarity index 100%
rename from projects/Navbar-project/styles.css
rename to projects/navbar/styles.css
diff --git a/projects/new-year-countdown/index.html b/projects/new-year-countdown/index.html
index c4c0578..3638291 100644
--- a/projects/new-year-countdown/index.html
+++ b/projects/new-year-countdown/index.html
@@ -9,7 +9,7 @@
00
00
diff --git a/projects/new-year-countdown/index.js b/projects/new-year-countdown/index.js
index 1a89f36..3ee8cd0 100644
--- a/projects/new-year-countdown/index.js
+++ b/projects/new-year-countdown/index.js
@@ -3,7 +3,7 @@ const hourEl = document.getElementById("hour");
const minuteEl = document.getElementById("minute");
const secondEl = document.getElementById("second");
-const newYearTime = new Date("Jan 1, 2022 00:00:00").getTime();
+const newYearTime = new Date("Jan 1, 2024 00:00:00").getTime();
updateCountdown();
diff --git a/projects/note-app/index.html b/projects/note-app/index.html
new file mode 100644
index 0000000..f61a1bd
--- /dev/null
+++ b/projects/note-app/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
Document
+
+
+
+
Note App
+
Double click on a note to remove it
+
+
+
+ +
+
+
+
+
diff --git a/projects/note-app/index.js b/projects/note-app/index.js
new file mode 100644
index 0000000..c3b33e9
--- /dev/null
+++ b/projects/note-app/index.js
@@ -0,0 +1,64 @@
+const btnEl = document.getElementById("btn");
+const appEl = document.getElementById("app");
+
+getNotes().forEach((note) => {
+ const noteEl = createNoteEl(note.id, note.content);
+ appEl.insertBefore(noteEl, btnEl);
+});
+
+function createNoteEl(id, content) {
+ const element = document.createElement("textarea");
+ element.classList.add("note");
+ element.placeholder = "Empty Note";
+ element.value = content;
+
+ element.addEventListener("dblclick", () => {
+ const warning = confirm("Do you want to delete this note?");
+ if (warning) {
+ deleteNote(id, element);
+ }
+ });
+
+ element.addEventListener("input", () => {
+ updateNote(id, element.value);
+ });
+
+ return element;
+}
+
+function deleteNote(id, element) {
+ const notes = getNotes().filter((note)=>note.id != id)
+ saveNote(notes)
+ appEl.removeChild(element)
+}
+
+function updateNote(id, content) {
+ const notes = getNotes();
+ const target = notes.filter((note) => note.id == id)[0];
+ target.content = content;
+ saveNote(notes);
+}
+
+function addNote() {
+ const notes = getNotes();
+ const noteObj = {
+ id: Math.floor(Math.random() * 100000),
+ content: "",
+ };
+ const noteEl = createNoteEl(noteObj.id, noteObj.content);
+ appEl.insertBefore(noteEl, btnEl);
+
+ notes.push(noteObj);
+
+ saveNote(notes);
+}
+
+function saveNote(notes) {
+ localStorage.setItem("note-app", JSON.stringify(notes));
+}
+
+function getNotes() {
+ return JSON.parse(localStorage.getItem("note-app") || "[]");
+}
+
+btnEl.addEventListener("click", addNote);
diff --git a/projects/note-app/style.css b/projects/note-app/style.css
new file mode 100644
index 0000000..47154de
--- /dev/null
+++ b/projects/note-app/style.css
@@ -0,0 +1,68 @@
+body {
+ margin: 0;
+ background: linear-gradient(to left, lightblue, lightgreen);
+ font-family: "Courier New", Courier, monospace;
+}
+
+.heading {
+ color: darkblue;
+ text-align: center;
+ padding-top: 10px;
+ font-size: 35px;
+}
+
+.info-text {
+ text-align: center;
+ color: darkblue;
+ font-size: 18px;
+}
+
+.app {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, 300px);
+ gap: 40px;
+ justify-content: center;
+ padding: 50px;
+}
+
+.note {
+ padding: 17px;
+ border-radius: 15px;
+ resize: none;
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
+ font-size: 18px;
+ height: 200px;
+ color: darkblue;
+ border: none;
+ outline: none;
+ background: rgba(255, 255, 255, 0.1);
+ box-sizing: border-box;
+}
+
+.note::placeholder {
+ color: gray;
+ opacity: 30%;
+}
+
+.note:hover,
+.note:focus {
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+ transition: all 300ms ease;
+}
+
+.btn{
+ height: 200px;
+ border-color: rgba(255, 255, 255, 0.37);
+ background: rgba(255, 255, 255, 0.27);
+ border-radius: 15px;
+ font-size: 70px;
+ font-weight: 700;
+ color: rgba(0, 0, 0, 0.3);
+ cursor: pointer;
+}
+
+.btn:hover{
+ background: rgba(255, 255, 255, 0.55);
+ color: rgba(0, 0, 0, 0.6);
+ transition: all 300ms ease;
+}
diff --git a/projects/photo-gallery/index.html b/projects/photo-gallery/index.html
new file mode 100644
index 0000000..f0a8e39
--- /dev/null
+++ b/projects/photo-gallery/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
Photo Gallery
+
+
+
+
+
Photo Gallery
+
Enter the number of photos
+
+
Error Message
+
Get Photos
+
+
+
+
+
diff --git a/projects/photo-gallery/index.js b/projects/photo-gallery/index.js
new file mode 100644
index 0000000..024848b
--- /dev/null
+++ b/projects/photo-gallery/index.js
@@ -0,0 +1,48 @@
+const btnEl = document.getElementById("btn");
+const errorMessageEl = document.getElementById("errorMessage");
+const galleryEl = document.getElementById("gallery");
+
+async function fetchImage() {
+ const inputValue = document.getElementById("input").value;
+
+ if (inputValue > 10 || inputValue < 1) {
+ errorMessageEl.style.display = "block";
+ errorMessageEl.innerText = "Number should be between 0 and 11";
+ return;
+ }
+
+ imgs = "";
+
+ try {
+ btnEl.style.display = "none";
+ const loading = `
`;
+ galleryEl.innerHTML = loading;
+ await fetch(
+ `https://api.unsplash.com/photos?per_page=${inputValue}&page=${Math.round(
+ Math.random() * 1000
+ )}&client_id=B8S3zB8gCPVCvzpAhCRdfXg_aki8PZM_q5pAyzDUvlc`
+ ).then((res) =>
+ res.json().then((data) => {
+ if (data) {
+ data.forEach((pic) => {
+ imgs += `
+
+ `;
+ galleryEl.style.display = "block";
+ galleryEl.innerHTML = imgs;
+ btnEl.style.display = "block";
+ errorMessageEl.style.display = "none";
+ });
+ }
+ })
+ );
+ } catch (error) {
+ console.log(error);
+ errorMessageEl.style.display = "block";
+ errorMessageEl.innerHTML = "An error happened, try again later";
+ btnEl.style.display = "block";
+ galleryEl.style.display = "none";
+ }
+}
+
+btnEl.addEventListener("click", fetchImage);
diff --git a/projects/photo-gallery/spinner.svg b/projects/photo-gallery/spinner.svg
new file mode 100644
index 0000000..c59456b
--- /dev/null
+++ b/projects/photo-gallery/spinner.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/photo-gallery/styles.css b/projects/photo-gallery/styles.css
new file mode 100644
index 0000000..c4270f4
--- /dev/null
+++ b/projects/photo-gallery/styles.css
@@ -0,0 +1,75 @@
+
+body{
+ margin: 0;
+ font-family: 'Courier New', Courier, monospace;
+ background: linear-gradient(to bottom, lightgreen, lightblue);
+ display: flex;
+ min-height: 100vh;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+}
+
+.container{
+ background-color: aliceblue;
+ padding: 20px;
+ border-radius: 5px;
+ box-shadow: 0 10px 20px rgba(0,0,0,0.3);
+ width: 90%;
+ margin: 10px;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+}
+
+h2{
+ font-weight: 400;
+}
+
+.input{
+ padding: 20px 10px;
+ font-size: 18px;
+ background-color: white;
+ border-radius: 5px;
+ text-align: center;
+ width: 100px;
+}
+
+.errorMessage{
+ color: red;
+ font-weight: 600;
+ margin: 10px;
+ display: none;
+}
+
+.btn{
+ text-transform: uppercase;
+ width: 250px;
+ height: 45px;
+ margin: 20px 0;
+ font-size: 18px;
+ border-radius: 5px;
+ background-color: black;
+ color: aliceblue;
+
+}
+
+.btn:hover{
+ color: aliceblue;
+ background-color: green;
+ cursor: pointer;
+ transition: background-color 300ms ease-in-out;
+}
+.gallery img{
+ width: 400px;
+ height: 250px;
+ object-fit: cover;
+ border-radius: 5px;
+ margin: 5px;
+}
+
+.gallery{
+ display: none;
+}
\ No newline at end of file
diff --git a/projects/pomodoro-timer/index.html b/projects/pomodoro-timer/index.html
new file mode 100644
index 0000000..7cfe584
--- /dev/null
+++ b/projects/pomodoro-timer/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
Pomodoro Timer
+
+
+
+
+
Pomodoro Timer
+
25:00
+
+ Start
+ Stop
+ Reset
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/pomodoro-timer/index.js b/projects/pomodoro-timer/index.js
new file mode 100644
index 0000000..22b4ede
--- /dev/null
+++ b/projects/pomodoro-timer/index.js
@@ -0,0 +1,42 @@
+const startEl = document.getElementById("start");
+const stopEl = document.getElementById("stop");
+const resetEl = document.getElementById("reset");
+const timerEl = document.getElementById("timer");
+
+let interval;
+let timeLeft = 1500;
+
+function updateTimer() {
+ let minutes = Math.floor(timeLeft / 60);
+ let seconds = timeLeft % 60;
+ let formattedTime = `${minutes.toString().padStart(2, "0")}:${seconds
+ .toString()
+ .padStart(2, "0")}`;
+
+ timerEl.innerHTML = formattedTime;
+}
+
+function startTimer() {
+ interval = setInterval(() => {
+ timeLeft--;
+ updateTimer();
+ if (timeLeft === 0) {
+ clearInterval(interval);
+ alert("Time's up!");
+ timeLeft = 1500;
+ updateTimer();
+ }
+ }, 1000);
+}
+function stopTimer() {
+ clearInterval(interval);
+}
+function resetTimer() {
+ clearInterval(interval);
+ timeLeft = 1500;
+ updateTimer();
+}
+
+startEl.addEventListener("click", startTimer);
+stopEl.addEventListener("click", stopTimer);
+resetEl.addEventListener("click", resetTimer);
diff --git a/projects/pomodoro-timer/style.css b/projects/pomodoro-timer/style.css
new file mode 100644
index 0000000..0e6970b
--- /dev/null
+++ b/projects/pomodoro-timer/style.css
@@ -0,0 +1,47 @@
+.container {
+ margin: 0 auto;
+ max-width: 400px;
+ text-align: center;
+ padding: 20px;
+ font-family: "Roboto", sans-serif;
+}
+
+.title {
+ font-size: 36px;
+ margin-bottom: 10px;
+ color: #2c3e50;
+}
+
+.timer {
+ font-size: 72px;
+ color: #2c3e50;
+}
+
+button {
+ font-size: 18px;
+ padding: 10px 20px;
+ margin: 10px;
+ color: white;
+
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ text-transform: uppercase;
+ transition: opacity 0.3s ease-in-out;
+}
+
+button:hover {
+ opacity: 0.7;
+}
+
+#start {
+ background-color: #27ae60;
+}
+
+#stop {
+ background-color: #c0392b;
+}
+
+#reset {
+ background-color: #7f8c8d;
+}
diff --git a/projects/Q&A-section/app.js b/projects/q-and-a-section/app.js
similarity index 100%
rename from projects/Q&A-section/app.js
rename to projects/q-and-a-section/app.js
diff --git a/projects/Q&A-section/index.html b/projects/q-and-a-section/index.html
similarity index 100%
rename from projects/Q&A-section/index.html
rename to projects/q-and-a-section/index.html
diff --git a/projects/Q&A-section/styles.css b/projects/q-and-a-section/styles.css
similarity index 100%
rename from projects/Q&A-section/styles.css
rename to projects/q-and-a-section/styles.css
diff --git a/projects/random-emoji/index.html b/projects/random-emoji/index.html
new file mode 100644
index 0000000..74b24cc
--- /dev/null
+++ b/projects/random-emoji/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
Random Emoji
+
+
+
Random Emoji
+
+
+
+
\ No newline at end of file
diff --git a/projects/random-emoji/index.js b/projects/random-emoji/index.js
new file mode 100644
index 0000000..a768eb0
--- /dev/null
+++ b/projects/random-emoji/index.js
@@ -0,0 +1,27 @@
+const btnEl = document.getElementById("btn");
+const emojiNameEl = document.getElementById("emoji-name");
+
+const emoji = [];
+
+async function getEmoji() {
+ let response = await fetch(
+ "https://emoji-api.com/emojis?access_key=773b58f681fb786fafdb8392e8b8a75ddc177fd1"
+ );
+
+ data = await response.json();
+
+ for (let i = 0; i < 1500; i++) {
+ emoji.push({
+ emojiName: data[i].character,
+ emojiCode: data[i].unicodeName,
+ });
+ }
+}
+
+getEmoji();
+
+btnEl.addEventListener("click", () => {
+ const randomNum = Math.floor(Math.random() * emoji.length);
+ btnEl.innerText = emoji[randomNum].emojiName;
+ emojiNameEl.innerText = emoji[randomNum].emojiCode;
+});
diff --git a/projects/random-emoji/style.css b/projects/random-emoji/style.css
new file mode 100644
index 0000000..37b110b
--- /dev/null
+++ b/projects/random-emoji/style.css
@@ -0,0 +1,41 @@
+body{
+ padding: 0;
+ margin: 0;
+ background: salmon;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ height: 100vh;
+ align-items: center;
+ font-family: 'Courier New', Courier, monospace;
+}
+
+h2{
+ font-size: 2rem;
+ color: aliceblue;
+}
+
+.section{
+ text-align: center;
+}
+
+.btn{
+ font-size: 5rem;
+ border: none;
+ background: rgb(255,255,255,.2);
+ border-radius: 10px;
+ padding: 15px;
+ filter: grayscale();
+ transition: filter .2s ease-in-out;
+ cursor: pointer;
+
+}
+
+.btn:hover{
+ filter: grayscale(0);
+}
+
+.emoji-name{
+ font-weight: 600;
+ color: darkblue;
+}
\ No newline at end of file
diff --git a/projects/random-quote-generator/index.html b/projects/random-quote-generator/index.html
new file mode 100644
index 0000000..04cd199
--- /dev/null
+++ b/projects/random-quote-generator/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
Random Quote Generator
+
+
+
+
+
+
Random Quote Generator
+
+
+ Quote
+
+
+
+
~ Author
+
Get a quote
+
+
+
+
\ No newline at end of file
diff --git a/projects/random-quote-generator/index.js b/projects/random-quote-generator/index.js
new file mode 100644
index 0000000..801cc29
--- /dev/null
+++ b/projects/random-quote-generator/index.js
@@ -0,0 +1,33 @@
+const btnEl = document.getElementById("btn");
+const quoteEl = document.getElementById("quote");
+const authorEl = document.getElementById("author");
+
+const apiURL = "https://api.quotable.io/random";
+
+async function getQuote() {
+ try {
+ btnEl.innerText = "Loading...";
+ btnEl.disabled = true;
+ quoteEl.innerText = "Updating...";
+ authorEl.innerText = "Updating...";
+ const response = await fetch(apiURL);
+ const data = await response.json();
+ const quoteContent = data.content;
+ const quoteAuthor = data.author;
+ quoteEl.innerText = quoteContent;
+ authorEl.innerText = "~ " + quoteAuthor;
+ btnEl.innerText = "Get a quote";
+ btnEl.disabled = false;
+ console.log(data);
+ } catch (error) {
+ console.log(error);
+ quoteEl.innerText = "An error happened, try again later";
+ authorEl.innerText = "An error happened";
+ btnEl.innerText = "Get a quote";
+ btnEl.disabled = false;
+ }
+}
+
+getQuote()
+
+btnEl.addEventListener("click", getQuote);
diff --git a/projects/random-quote-generator/style.css b/projects/random-quote-generator/style.css
new file mode 100644
index 0000000..e67e3f5
--- /dev/null
+++ b/projects/random-quote-generator/style.css
@@ -0,0 +1,54 @@
+body {
+ margin: 0;
+ display: flex;
+ min-height: 100vh;
+ justify-content: center;
+ align-items: center;
+ font-family: "Courier New", Courier, monospace;
+ background: linear-gradient(to left bottom, lightgreen, lightblue);
+}
+
+.container {
+ background-color: rgba(255, 255, 255, 0.1);
+ box-shadow: 0 6px 10px rgba(0, 0, 0, 0.3);
+ padding: 30px;
+ border-radius: 15px;
+ width: 90%;
+ margin: 10px;
+ text-align: center;
+}
+
+.heading {
+ font-size: 35px;
+ font-weight: 700;
+}
+
+.quote {
+ font-size: 30px;
+ font-weight: 600;
+}
+
+.author {
+ font-size: 25px;
+ margin: 10px;
+ font-style: italic;
+}
+
+.btn {
+ font-size: 18px;
+ border-radius: 5px;
+ cursor: pointer;
+ padding: 10px;
+ margin-top: 15px;
+ background-color: rgba(255, 255, 255, 0.3);
+ border-color: rgba(255, 255, 255, 0.6);
+ text-transform: uppercase;
+ width: 300px;
+}
+
+.btn:hover{
+ background-color: rgba(255,255,255,.6);
+ box-shadow: 0 4px 4px rgba(0,0,0,.3);
+ transition: all 300ms ease-in-out;
+ color: green;
+}
diff --git a/projects/recipe-book-app/index.html b/projects/recipe-book-app/index.html
new file mode 100644
index 0000000..b93360d
--- /dev/null
+++ b/projects/recipe-book-app/index.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
Document
+
+
+
+
+
+
+
+
+
diff --git a/projects/recipe-book-app/index.js b/projects/recipe-book-app/index.js
new file mode 100644
index 0000000..d35b3b8
--- /dev/null
+++ b/projects/recipe-book-app/index.js
@@ -0,0 +1,50 @@
+const API_KEY = "275d58779ccf4e22af03e792e8819fff";
+const recipeListEl = document.getElementById("recipe-list");
+
+function displayRecipes(recipes) {
+ recipeListEl.innerHTML = "";
+ recipes.forEach((recipe) => {
+ const recipeItemEl = document.createElement("li");
+ recipeItemEl.classList.add("recipe-item");
+ recipeImageEl = document.createElement("img");
+ recipeImageEl.src = recipe.image;
+ recipeImageEl.alt = "recipe image";
+
+ recipeTitleEl = document.createElement("h2");
+ recipeTitleEl.innerText = recipe.title;
+
+ recipeIngredientsEl = document.createElement("p");
+ recipeIngredientsEl.innerHTML = `
+
Ingredients: ${recipe.extendedIngredients
+ .map((ingredient) => ingredient.original)
+ .join(", ")}
+ `;
+
+ recipeLinkEl = document.createElement("a");
+ recipeLinkEl.href = recipe.sourceUrl;
+ recipeLinkEl.innerText = "View Recipe";
+
+ recipeItemEl.appendChild(recipeImageEl);
+ recipeItemEl.appendChild(recipeTitleEl);
+ recipeItemEl.appendChild(recipeIngredientsEl);
+ recipeItemEl.appendChild(recipeLinkEl);
+ recipeListEl.appendChild(recipeItemEl);
+ });
+}
+
+async function getRecipes() {
+ const response = await fetch(
+ `https://api.spoonacular.com/recipes/random?number=10&apiKey=${API_KEY}`
+ );
+
+ const data = await response.json();
+
+ return data.recipes;
+}
+
+async function init() {
+ const recipes = await getRecipes();
+ displayRecipes(recipes);
+}
+
+init();
diff --git a/projects/recipe-book-app/style.css b/projects/recipe-book-app/style.css
new file mode 100644
index 0000000..9e56d02
--- /dev/null
+++ b/projects/recipe-book-app/style.css
@@ -0,0 +1,104 @@
+body {
+ margin: 0;
+ padding: 0;
+ font-family: Arial, sans-serif;
+}
+
+header {
+ background: #0c2461;
+ color: #fff;
+ padding: 20px;
+ text-align: center;
+}
+
+h1 {
+ margin: 0;
+ font-size: 36px;
+}
+
+.container {
+ margin: 0 auto;
+ max-width: 1200px;
+ padding: 20px;
+}
+
+.recipe-list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.recipe-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 20px;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ overflow: hidden;
+}
+
+.recipe-item img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.recipe-item h2 {
+ margin: 0;
+ font-size: 20px;
+ padding: 10px;
+ min-width: 200px;
+}
+
+.recipe-item p {
+ margin: 0;
+ padding: 10px;
+ color: #777;
+}
+
+.recipe-item a {
+ background: #0c2461;
+ color: #fff;
+ min-width: 150px;
+ padding: 10px;
+ text-decoration: none;
+ text-transform: uppercase;
+ font-size: 14px;
+ transition: background 0.3s ease;
+}
+
+.recipe-item a:hover {
+ background: #1e3799;
+}
+
+@media screen and (max-width: 768px) {
+ .container {
+ max-width: 90%;
+ }
+ .recipe-item {
+ flex-direction: column;
+ }
+
+ .recipe-item img {
+ width: 100%;
+ height: auto;
+ margin-bottom: 10px;
+ }
+
+ .recipe-item h2 {
+ font-size: 20px;
+ padding: 0;
+ margin-bottom: 10px;
+ }
+
+ .recipe-item p {
+ font-size: 14px;
+ margin-bottom: 10px;
+ }
+
+ .recipe-item a {
+ width: 100%;
+ text-align: center;
+ }
+}
diff --git a/projects/rock-paper-scissors-game/index.html b/projects/rock-paper-scissors-game/index.html
new file mode 100644
index 0000000..c458606
--- /dev/null
+++ b/projects/rock-paper-scissors-game/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
Rock Paper Scissors Game
+
+
+
+
Rock Paper Scissors Game
+
Choose your move:
+
+ 👊
+ 🖐
+ ✌
+
+
+
+ Your score: 0
+ Computer score: 0
+
+
+
+
\ No newline at end of file
diff --git a/projects/rock-paper-scissors-game/index.js b/projects/rock-paper-scissors-game/index.js
new file mode 100644
index 0000000..4944f3e
--- /dev/null
+++ b/projects/rock-paper-scissors-game/index.js
@@ -0,0 +1,42 @@
+const buttons = document.querySelectorAll("button");
+
+const resultEl = document.getElementById("result");
+
+const playerScoreEl = document.getElementById("user-score");
+
+const computerScoreEl = document.getElementById("computer-score");
+
+let playerScore = 0;
+let computerScore = 0;
+
+buttons.forEach((button) => {
+ button.addEventListener("click", () => {
+ const result = playRound(button.id, computerPlay());
+ resultEl.textContent = result;
+
+ });
+});
+
+function computerPlay() {
+ const choices = ["rock", "paper", "scissors"];
+ const randomChoice = Math.floor(Math.random() * choices.length);
+ return choices[randomChoice];
+}
+
+function playRound(playerSelection, computerSelection) {
+ if (playerSelection === computerSelection) {
+ return "It's a tie!";
+ } else if (
+ (playerSelection === "rock" && computerSelection === "scissors") ||
+ (playerSelection === "paper" && computerSelection === "rock") ||
+ (playerSelection === "scissors" && computerSelection === "paper")
+ ) {
+ playerScore++;
+ playerScoreEl.textContent = playerScore;
+ return "You win! " + playerSelection + " beats " + computerSelection;
+ } else {
+ computerScore++;
+ computerScoreEl.textContent = computerScore;
+ return "You lose! " + computerSelection + " beats " + playerSelection;
+ }
+}
diff --git a/projects/rock-paper-scissors-game/style.css b/projects/rock-paper-scissors-game/style.css
new file mode 100644
index 0000000..940eff4
--- /dev/null
+++ b/projects/rock-paper-scissors-game/style.css
@@ -0,0 +1,58 @@
+body {
+ background-color: #f1f1f1;
+ font-family: "Arial", sans-serif;
+ margin: 0;
+ padding: 0;
+}
+
+h1 {
+ font-size: 2rem;
+ text-align: center;
+ padding-top: 100px;
+}
+
+p {
+ font-size: 1.5rem;
+ font-weight: 600;
+ text-align: center;
+ margin-bottom: 0.5rem;
+}
+
+.buttons {
+ display: flex;
+ justify-content: center;
+}
+
+button {
+ border: none;
+ font-size: 3rem;
+ margin: 0 0.5rem;
+ padding: 0.5rem;
+ cursor: pointer;
+ border-radius: 5px;
+ transition: all 0.3s ease-in-out;
+}
+
+button:hover {
+ opacity: 0.7;
+}
+
+#rock {
+ background-color: #ff0000;
+}
+
+#paper {
+ background-color: #2196f3;
+}
+
+#scissors {
+ background-color: #4caf50;
+}
+
+#user-score {
+ color: #2196f3;
+}
+
+#computer-score {
+ color: #ff0000;
+}
diff --git a/projects/Sidebar-project/index.html b/projects/sidebar/index.html
similarity index 100%
rename from projects/Sidebar-project/index.html
rename to projects/sidebar/index.html
diff --git a/projects/Sidebar-project/index.js b/projects/sidebar/index.js
similarity index 100%
rename from projects/Sidebar-project/index.js
rename to projects/sidebar/index.js
diff --git a/projects/Sidebar-project/logo.svg b/projects/sidebar/logo.svg
similarity index 100%
rename from projects/Sidebar-project/logo.svg
rename to projects/sidebar/logo.svg
diff --git a/projects/Sidebar-project/styles.css b/projects/sidebar/styles.css
similarity index 100%
rename from projects/Sidebar-project/styles.css
rename to projects/sidebar/styles.css
diff --git a/projects/stopwatch/index.html b/projects/stopwatch/index.html
new file mode 100644
index 0000000..05d8b2b
--- /dev/null
+++ b/projects/stopwatch/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
Stopwatch
+
+
+
+
+
00:00:00
+
+ Start
+ Stop
+ Reset
+
+
+
+
\ No newline at end of file
diff --git a/projects/stopwatch/index.js b/projects/stopwatch/index.js
new file mode 100644
index 0000000..0cbd647
--- /dev/null
+++ b/projects/stopwatch/index.js
@@ -0,0 +1,54 @@
+const timerEl = document.getElementById("timer");
+const startButtonEl = document.getElementById("start");
+const stopButtonEl = document.getElementById("stop");
+const resetButtonEl = document.getElementById("reset");
+
+let startTime = 0;
+let elapsedTime = 0;
+let timerInterval;
+
+function startTimer() {
+ startTime = Date.now() - elapsedTime;
+
+ timerInterval = setInterval(() => {
+ elapsedTime = Date.now() - startTime;
+ timerEl.textContent = formatTime(elapsedTime);
+ }, 10);
+
+ startButtonEl.disabled = true;
+ stopButtonEl.disabled = false;
+}
+
+function formatTime(elapsedTime) {
+ const milliseconds = Math.floor((elapsedTime % 1000) / 10);
+ const seconds = Math.floor((elapsedTime % (1000 * 60)) / 1000);
+ const minutes = Math.floor((elapsedTime % (1000 * 60 * 60)) / (1000 * 60));
+ const hours = Math.floor(elapsedTime / (1000 * 60 * 60));
+ return (
+ (hours ? (hours > 9 ? hours : "0" + hours) : "00") +
+ ":" +
+ (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") +
+ ":" +
+ (seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") +
+ "." +
+ (milliseconds > 9 ? milliseconds : "0" + milliseconds)
+ );
+}
+function stopTimer() {
+ clearInterval(timerInterval);
+ startButtonEl.disabled = false;
+ stopButtonEl.disabled = true;
+}
+function resetTimer() {
+ clearInterval(timerInterval);
+
+ elapsedTime = 0;
+ timerEl.textContent = "00:00:00";
+
+ startButtonEl.disabled = false;
+ stopButtonEl.disabled = true;
+}
+
+startButtonEl.addEventListener("click", startTimer);
+stopButtonEl.addEventListener("click", stopTimer);
+resetButtonEl.addEventListener("click", resetTimer);
diff --git a/projects/stopwatch/style.css b/projects/stopwatch/style.css
new file mode 100644
index 0000000..cf0859d
--- /dev/null
+++ b/projects/stopwatch/style.css
@@ -0,0 +1,61 @@
+body {
+ background-color: #f0f0f0;
+ font-family: "Poppins", sans-serif;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ min-height: 100vh;
+ overflow: hidden;
+ align-items: center;
+}
+
+#timer {
+ font-size: 7rem;
+ font-weight: 700;
+ text-shadow: 2px 2px #f8a5c2;
+ color: #f92672;
+ width: 600px;
+ text-align: center;
+ margin: 40px auto;
+}
+
+#buttons {
+ display: flex;
+ justify-content: center;
+}
+
+button {
+ background-color: #f92672;
+ color: white;
+ border: none;
+ font-size: 2rem;
+ font-weight: bold;
+ padding: 1.5rem 4rem;
+ margin: 1rem;
+ border-radius: 30px;
+ cursor: pointer;
+ box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3);
+ transition: all 0.2s;
+}
+
+button:hover {
+ background-color: #f44583;
+ box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5);
+}
+
+button[disabled] {
+ opacity: 0.5;
+ cursor: default;
+}
+
+@media (max-width: 800px) {
+ #timer {
+ font-size: 4rem;
+ width: 350px;
+ }
+
+ button {
+ font-size: 1.5rem;
+ padding: 1rem 2rem;
+ }
+}
diff --git a/projects/temperature-converter/index.html b/projects/temperature-converter/index.html
new file mode 100644
index 0000000..dd23f99
--- /dev/null
+++ b/projects/temperature-converter/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
Temperature Converter
+
+
+
+
+
+
+
diff --git a/projects/temperature-converter/index.js b/projects/temperature-converter/index.js
new file mode 100644
index 0000000..e2dfcf3
--- /dev/null
+++ b/projects/temperature-converter/index.js
@@ -0,0 +1,24 @@
+const celsiusEl = document.getElementById("celsius");
+const fahrenheitEl = document.getElementById("fahrenheit");
+const kelvinEl = document.getElementById("kelvin");
+
+function computeTemp(event) {
+ const currentValue = +event.target.value;
+
+ switch (event.target.name) {
+ case "celsius":
+ kelvinEl.value = (currentValue + 273.32).toFixed(2);
+ fahrenheitEl.value = (currentValue * 1.8 + 32).toFixed(2);
+ break;
+ case "fahrenheit":
+ celsiusEl.value = ((currentValue - 32) / 1.8).toFixed(2);
+ kelvinEl.value = ((currentValue - 32) / 1.8 + 273.32).toFixed(2);
+ break;
+ case "kelvin":
+ celsiusEl.value = (currentValue - 273.32).toFixed(2);
+ fahrenheitEl.value = ((currentValue - 273.32) * 1.8 + 32).toFixed(2);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/projects/temperature-converter/style.css b/projects/temperature-converter/style.css
new file mode 100644
index 0000000..ea02485
--- /dev/null
+++ b/projects/temperature-converter/style.css
@@ -0,0 +1,51 @@
+body {
+ margin: 0;
+ background: linear-gradient(to left bottom, lightgreen, lightblue);
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-family: monospace;
+ color: darkcyan;
+}
+
+.container {
+ background: rgba(255, 255, 255, 0.3);
+ padding: 20px;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
+ border-radius: 10px;
+ width: 85%;
+ max-width: 450px;
+ min-width: 350px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.heading {
+ font-size: 32px;
+}
+
+.temp-container {
+ width: 100%;
+ padding: 15px;
+ font-weight: bold;
+ font-size: 18px;
+}
+
+.input {
+ width: 220px;
+ font-family: monospace;
+ padding: 5px;
+ float: right;
+ outline: none;
+ background: rgba(255, 255, 255, 0.3);
+ border-color: rgba(255, 255, 255, 0.5);
+ color: darkgreen;
+ font-size: 18px;
+}
+
+
+.input::placeholder{
+ color: darkgray;
+}
diff --git a/projects/tip-calculator/index.html b/projects/tip-calculator/index.html
new file mode 100644
index 0000000..029457b
--- /dev/null
+++ b/projects/tip-calculator/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
Tip Calculator
+
+
+
+
+
Tip Calculator
+
Enter the bill amount and tip percentage to calculate the total.
+
Bill amount:
+
+
+
Tip percentage:
+
+
+
Calculate
+
+
Total:
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/tip-calculator/index.js b/projects/tip-calculator/index.js
new file mode 100644
index 0000000..98cb079
--- /dev/null
+++ b/projects/tip-calculator/index.js
@@ -0,0 +1,13 @@
+const btnEl = document.getElementById("calculate");
+const billInput = document.getElementById("bill");
+const tipInput = document.getElementById("tip");
+const totalSpan = document.getElementById("total");
+
+function calculateTotal() {
+ const billValue = billInput.value;
+ const tipValue = tipInput.value;
+ const totalValue = billValue * (1 + tipValue / 100);
+ totalSpan.innerText = totalValue.toFixed(2);
+}
+
+btnEl.addEventListener("click", calculateTotal);
diff --git a/projects/tip-calculator/style.css b/projects/tip-calculator/style.css
new file mode 100644
index 0000000..786e129
--- /dev/null
+++ b/projects/tip-calculator/style.css
@@ -0,0 +1,53 @@
+* {
+ box-sizing: border-box;
+}
+
+body {
+ background-color: #f2f2f2;
+ font-family: "Helvetica", sans-serif;
+}
+
+.container {
+ background-color: white;
+ max-width: 600px;
+ margin: 100px auto;
+ padding: 20px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ border-radius: 10px;
+}
+
+h1 {
+ margin-top: 0;
+ text-align: center;
+}
+
+input {
+ padding: 10px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ margin: 10px 0;
+ width: 100%;
+}
+
+button {
+ background-color: #4caf50;
+ color: white;
+ padding: 10px;
+ border: none;
+ cursor: pointer;
+ margin: 10px 0;
+ width: 100%;
+ font-size: 18px;
+ text-transform: uppercase;
+ transition: background-color 0.2s ease;
+}
+
+button:hover {
+ background-color: #45a049;
+}
+
+#total {
+ font-size: 24px;
+ font-weight: bold;
+ margin-top: 10px;
+}
diff --git a/projects/weather-app/index.html b/projects/weather-app/index.html
new file mode 100644
index 0000000..7fe9e3a
--- /dev/null
+++ b/projects/weather-app/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
Weather App
+
+
+
+
+
+
+
diff --git a/projects/weather-app/index.js b/projects/weather-app/index.js
new file mode 100644
index 0000000..f773a49
--- /dev/null
+++ b/projects/weather-app/index.js
@@ -0,0 +1,58 @@
+const apikey = "46f80a02ecae410460d59960ded6e1c6";
+
+const weatherDataEl = document.getElementById("weather-data");
+
+const cityInputEl = document.getElementById("city-input");
+
+const formEl = document.querySelector("form");
+
+formEl.addEventListener("submit", (event) => {
+ event.preventDefault();
+ const cityValue = cityInputEl.value;
+ getWeatherData(cityValue);
+});
+
+async function getWeatherData(cityValue) {
+ try {
+ const response = await fetch(
+ `https://api.openweathermap.org/data/2.5/weather?q=${cityValue}&appid=${apikey}&units=metric`
+ );
+
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+
+ const data = await response.json();
+
+ const temperature = Math.round(data.main.temp);
+
+ const description = data.weather[0].description;
+
+ const icon = data.weather[0].icon;
+
+ const details = [
+ `Feels like: ${Math.round(data.main.feels_like)}`,
+ `Humidity: ${data.main.humidity}%`,
+ `Wind speed: ${data.wind.speed} m/s`,
+ ];
+
+ weatherDataEl.querySelector(
+ ".icon"
+ ).innerHTML = `
`;
+ weatherDataEl.querySelector(
+ ".temperature"
+ ).textContent = `${temperature}°C`;
+ weatherDataEl.querySelector(".description").textContent = description;
+
+ weatherDataEl.querySelector(".details").innerHTML = details
+ .map((detail) => `
${detail}
`)
+ .join("");
+ } catch (error) {
+ weatherDataEl.querySelector(".icon").innerHTML = "";
+ weatherDataEl.querySelector(".temperature").textContent = "";
+ weatherDataEl.querySelector(".description").textContent =
+ "An error happened, please try again later";
+
+ weatherDataEl.querySelector(".details").innerHTML = "";
+ }
+}
diff --git a/projects/weather-app/style.css b/projects/weather-app/style.css
new file mode 100644
index 0000000..2030f24
--- /dev/null
+++ b/projects/weather-app/style.css
@@ -0,0 +1,94 @@
+body {
+ margin: 0;
+ font-family: "Montserrat", sans-serif;
+ background-color: #f7f7f7;
+}
+
+.container {
+ background-color: #fff;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
+ margin: 0 auto;
+ margin-top: 50px;
+ text-align: center;
+ max-width: 600px;
+ border-radius: 5px;
+ padding: 20px;
+}
+
+form {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 20px;
+}
+
+form input[type="text"] {
+ padding: 10px;
+ border: none;
+ outline: none;
+ font-size: 18px;
+ width: 60%;
+}
+
+form input[type="submit"] {
+ background-color: #007bff;
+ color: #fff;
+ border: none;
+ padding: 10px 20px;
+ border-radius: 5px;
+ font-size: 18px;
+ cursor: pointer;
+ outline: none;
+ transition: background-color 0.3s ease;
+}
+
+form input[type="submit"]:hover {
+ background-color: #0062cc;
+}
+
+.icon img {
+ width: 100px;
+ height: 100px;
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+
+.temperature {
+ font-size: 48px;
+ font-weight: bold;
+ margin: 20px 0;
+}
+
+.description{
+ font-size: 24px;
+ margin-bottom: 20px;
+}
+
+.details{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.details > div{
+ padding: 20px;
+ background-color: #f1f1f1;
+ margin: 10px;
+ flex: 1;
+ border-radius: 5px;
+ text-align: center;
+ min-height: 45px;
+}
+
+@media (max-width: 768px){
+ form {
+ flex-direction: column;
+ }
+
+ form input[type="text"]{
+ width: 100%;
+ margin-bottom: 10px;
+ }
+}
diff --git a/projects/weight-converter/index.html b/projects/weight-converter/index.html
new file mode 100644
index 0000000..d441ffd
--- /dev/null
+++ b/projects/weight-converter/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
Weight Converter
+
+
+
+
+
Weight Converter
+
+ Pounds:
+
+
+
Your weight in kg is:
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/weight-converter/index.js b/projects/weight-converter/index.js
new file mode 100644
index 0000000..faf2a44
--- /dev/null
+++ b/projects/weight-converter/index.js
@@ -0,0 +1,24 @@
+const inputEl = document.getElementById("input");
+const errorEl = document.getElementById("error");
+const resultEl = document.getElementById("result");
+let errorTime;
+let resultTime;
+function updateResults() {
+ if (inputEl.value <= 0 || isNaN(inputEl.value)) {
+ errorEl.innerText = "Please enter a valid number!";
+ clearTimeout(errorTime);
+ errorTime = setTimeout(() => {
+ errorEl.innerText = "";
+ inputEl.value = "";
+ }, 2000);
+ } else {
+ resultEl.innerText = (+inputEl.value / 2.2).toFixed(2);
+ clearTimeout(resultTime);
+ resultTime = setTimeout(() => {
+ resultEl.innerText = "";
+ inputEl.value = "";
+ }, 10000);
+ }
+}
+
+inputEl.addEventListener("input", updateResults);
diff --git a/projects/weight-converter/style.css b/projects/weight-converter/style.css
new file mode 100644
index 0000000..e69936b
--- /dev/null
+++ b/projects/weight-converter/style.css
@@ -0,0 +1,42 @@
+body{
+ margin: 0;
+ background: linear-gradient(to left top, yellow, lightblue, yellow);
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-family: 'Courier New', Courier, monospace;
+ color: darkcyan;
+}
+
+.container{
+ background: rgba(255,255,255,0.3);
+ padding: 20px;
+ box-shadow: 0 4px 10px rgba(0,0,0,.3);
+ border-radius: 10px;
+ width: 85%;
+ max-width: 450px;
+}
+
+.input-container{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 18px;
+ font-weight: 700;
+}
+
+.input{
+ padding: 10px;
+ width: 70%;
+ background: rgba(255,255,255,0.3);
+ border-color: rgba(255,255,255,0.5);
+ font-size: 18px;
+ border-radius: 10px;
+ color: darkgreen;
+ outline: none;
+}
+
+.error{
+ color: red;
+}
\ No newline at end of file