-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added: Time Capsule Center(VanillaJS) (#749)
* Added: Time Capsule Center(VanillaJS) * Review changes
- Loading branch information
1 parent
0efddae
commit f6c1fde
Showing
6 changed files
with
516 additions
and
1 deletion.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
Vanilla-JS-Projects/Intermediate/Time-Capsule-Center/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<h1 align='center'><b>💥 Time Capsule Center 💥</b></h1> | ||
|
||
<!-- -------------------------------------------------------------------------------------------------------------- --> | ||
|
||
<h3 align='center'>Tech Stack Used 🎮</h3> | ||
<!-- enlist all the technologies used to create this project from them (Remove comment using 'ctrl+z' or 'command+z') --> | ||
|
||
<div align='center'> | ||
|
||
![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white) | ||
![CSS3](https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white) | ||
<!-- ![Bootstrap](https://img.shields.io/badge/bootstrap-%238511FA.svg?style=for-the-badge&logo=bootstrap&logoColor=white) --> | ||
![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E) | ||
<!-- ![jQuery](https://img.shields.io/badge/jquery-%230769AD.svg?style=for-the-badge&logo=jquery&logoColor=white) --> | ||
<!-- ![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) --> | ||
<!-- ![Redux](https://img.shields.io/badge/redux-%23593d88.svg?style=for-the-badge&logo=redux&logoColor=white) --> | ||
<!-- ![TailwindCSS](https://img.shields.io/badge/tailwindcss-%2338B2AC.svg?style=for-the-badge&logo=tailwind-css&logoColor=white) --> | ||
<!-- ![Web3.js](https://img.shields.io/badge/web3.js-F16822?style=for-the-badge&logo=web3.js&logoColor=white) --> | ||
<!-- ![Express.js](https://img.shields.io/badge/express.js-%23404d59.svg?style=for-the-badge&logo=express&logoColor=%2361DAFB) --> | ||
<!-- ![Angular.js](https://img.shields.io/badge/angular.js-%23E23237.svg?style=for-the-badge&logo=angularjs&logoColor=white) --> | ||
<!-- ![Next JS](https://img.shields.io/badge/Next-black?style=for-the-badge&logo=next.js&logoColor=white) --> | ||
<!-- ![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) --> | ||
<!-- ![Vue.js](https://img.shields.io/badge/vuejs-%2335495e.svg?style=for-the-badge&logo=vuedotjs&logoColor=%234FC08D) --> | ||
<!-- ![MongoDB](https://img.shields.io/badge/MongoDB-%234ea94b.svg?style=for-the-badge&logo=mongodb&logoColor=white) --> | ||
</div> | ||
|
||
![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847) | ||
|
||
<!-- -------------------------------------------------------------------------------------------------------------- --> | ||
|
||
## :zap: Description 📃 | ||
|
||
- A web application to help you store memories in terms of time capsules for future. | ||
|
||
<!-- -------------------------------------------------------------------------------------------------------------- --> | ||
|
||
## :zap: How to run it? 🕹️ | ||
|
||
<!-- add the steps how to run the project --> | ||
- Fork this repository. | ||
- Clone the forked repository. | ||
- Open index.html in your web browser to start your culinary exploration. | ||
|
||
<!-- -------------------------------------------------------------------------------------------------------------- --> | ||
|
||
## :zap: Screenshots 📸 | ||
<!-- add the screenshot of the project (Mandatory) --> | ||
|
||
![Screenshot 2024-08-07 011353](https://github.com/user-attachments/assets/800ed567-67fa-476f-891c-34331e916477) | ||
![Screenshot 2024-08-07 011805](https://github.com/user-attachments/assets/939c3a3c-0046-41f4-b74f-3e5ec4c564fc) | ||
![Screenshot 2024-08-07 011851](https://github.com/user-attachments/assets/8bdb336d-948c-4547-a3da-e07f9dfb9abb) | ||
|
||
|
||
![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847) | ||
|
||
|
||
<!-- -------------------------------------------------------------------------------------------------------------- --> | ||
|
||
<h4 align='center'>Developed By <b><i>Kosuri Indu</i></b> </h4> | ||
<p align='center'> | ||
<a href='https://github.com/kosuri-indu'> | ||
<img src='https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white' /> | ||
</a> | ||
</p> | ||
|
||
<h4 align='center'>Happy Coding 🧑💻</h4> | ||
|
||
<h3 align="center">Show some ❤️ by 🌟 this repository!</h3> |
77 changes: 77 additions & 0 deletions
77
Vanilla-JS-Projects/Intermediate/Time-Capsule-Center/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Time Capsule Center</title> | ||
<link rel="stylesheet" href="style.css"> | ||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet"> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<header> | ||
<h1>Time Capsule Center</h1> | ||
<nav> | ||
<ul> | ||
<li><a href="#addCapsule" class="nav-link">Add Time Capsule</a></li> | ||
<li><a href="#statistics" class="nav-link">Statistics</a></li> | ||
<li><a href="#capsuleStorage" class="nav-link">Capsule Storage</a></li> | ||
</ul> | ||
</nav> | ||
</header> | ||
<!-- Form to add a time capsule --> | ||
<section id="addCapsule" class="page"> | ||
<h2>Add Time Capsule</h2> | ||
<form id="timeCapsuleForm"> | ||
<label for="capsuleName">Capsule Name:</label> | ||
<input type="text" id="capsuleName" name="capsuleName" required> | ||
<label for="openDate">Open Date:</label> | ||
<input type="date" id="openDate" name="openDate" required> | ||
<label for="tags">Tags:</label> | ||
<input type="text" id="tags" name="tags" placeholder="Enter tags separated by commas"> | ||
<label for="message">Message:</label> | ||
<textarea id="message" name="message" required></textarea> | ||
<label for="image">Image (optional):</label> | ||
<input type="file" id="image" name="image" accept="image/*"> | ||
<label for="video">Video (optional):</label> | ||
<input type="file" id="video" name="video" accept="video/*"> | ||
<button type="submit">Create Capsule</button> | ||
</form> | ||
</section> | ||
<section id="statistics" class="page"> | ||
<h2>Statistics</h2> | ||
<div id="overallStatistics" class="statistics-item"> | ||
<h3>Overall Statistics</h3> | ||
<p id="totalCapsules">Total Capsules: 0</p> | ||
<p id="totalMessages">Total Messages: 0</p> | ||
<p id="totalImages">Total Images: 0</p> | ||
<p id="totalVideos">Total Videos: 0</p> | ||
</div> | ||
<div id="recentActivity" class="statistics-item"> | ||
<h3>Recent Activity</h3> | ||
<ul id="recentCapsules"></ul> | ||
</div> | ||
<div id="upcomingCapsules" class="statistics-item"> | ||
<h3>Upcoming Capsules</h3> | ||
<ul id="upcomingCapsuleList"></ul> | ||
</div> | ||
</section> | ||
<section id="capsuleStorage" class="page"> | ||
<h2>Capsule Storage</h2> | ||
<input type="text" id="searchBar" placeholder="Search capsules by name or tags"> | ||
<div id="capsuleList"></div> | ||
</section> | ||
</div> | ||
<div id="capsuleModal" class="modal"> | ||
<div class="modal-content"> | ||
<span class="close">×</span> | ||
<h2 id="modalCapsuleName"></h2> | ||
<p id="modalCapsuleMessage"></p> | ||
<img id="modalCapsuleImage" src="" alt="Capsule Image" style="display:none;"> | ||
<video id="modalCapsuleVideo" controls style="display:none;"></video> | ||
</div> | ||
</div> | ||
<div id="notification" class="notification"></div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
Binary file not shown.
214 changes: 214 additions & 0 deletions
214
Vanilla-JS-Projects/Intermediate/Time-Capsule-Center/script.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
document.addEventListener('DOMContentLoaded', () => { | ||
const form = document.getElementById('timeCapsuleForm'); | ||
const capsuleList = document.getElementById('capsuleList'); | ||
const searchBar = document.getElementById('searchBar'); | ||
const notification = document.getElementById('notification'); | ||
const statisticsContainer = document.getElementById('statisticsContainer'); | ||
let capsules = []; | ||
|
||
form.addEventListener('submit', (e) => { | ||
e.preventDefault(); | ||
|
||
const capsuleName = document.getElementById('capsuleName').value; | ||
const openDate = new Date(document.getElementById('openDate').value); | ||
const tags = document.getElementById('tags').value.split(',').map(tag => tag.trim()); | ||
const message = document.getElementById('message').value; | ||
const image = document.getElementById('image').files[0]; | ||
const video = document.getElementById('video').files[0]; | ||
|
||
const capsule = { | ||
name: capsuleName, | ||
openDate: openDate, | ||
tags: tags, | ||
message: message, | ||
image: image ? URL.createObjectURL(image) : null, | ||
video: video ? URL.createObjectURL(video) : null, | ||
}; | ||
|
||
capsules.push(capsule); | ||
updateDashboard(); | ||
updateStatistics(); | ||
showNotification('New capsule added successfully!'); | ||
form.reset(); | ||
}); | ||
|
||
searchBar.addEventListener('input', updateDashboard); | ||
|
||
function updateDashboard() { | ||
capsuleList.innerHTML = ''; | ||
const searchQuery = searchBar.value.toLowerCase(); | ||
const filteredCapsules = capsules.filter(capsule => | ||
capsule.name.toLowerCase().includes(searchQuery) || | ||
capsule.tags.some(tag => tag.toLowerCase().includes(searchQuery)) | ||
); | ||
|
||
filteredCapsules.forEach((capsule, index) => { | ||
const capsuleItem = document.createElement('div'); | ||
capsuleItem.classList.add('capsule-item'); | ||
|
||
const nameSpan = document.createElement('span'); | ||
nameSpan.textContent = capsule.name; | ||
capsuleItem.appendChild(nameSpan); | ||
|
||
const dateSpan = document.createElement('span'); | ||
dateSpan.textContent = capsule.openDate.toDateString(); | ||
capsuleItem.appendChild(dateSpan); | ||
|
||
const tagsSpan = document.createElement('span'); | ||
tagsSpan.textContent = capsule.tags.join(', '); | ||
capsuleItem.appendChild(tagsSpan); | ||
|
||
const countdownSpan = document.createElement('span'); | ||
countdownSpan.id = `countdown${index}`; | ||
capsuleItem.appendChild(countdownSpan); | ||
|
||
const editButton = document.createElement('button'); | ||
editButton.classList.add('edit-btn'); | ||
editButton.textContent = 'Delete'; | ||
editButton.addEventListener('click', () => editCapsule(index)); | ||
capsuleItem.appendChild(editButton); | ||
|
||
capsuleItem.addEventListener('click', (e) => { | ||
if (e.target.tagName !== 'BUTTON') { | ||
showCapsuleDetails(capsule); | ||
} | ||
}); | ||
|
||
capsuleList.appendChild(capsuleItem); | ||
updateCountdown(capsule, index); | ||
}); | ||
} | ||
|
||
function updateCountdown(capsule, index) { | ||
const countdownElement = document.getElementById(`countdown${index}`); | ||
const interval = setInterval(() => { | ||
const now = new Date(); | ||
const distance = capsule.openDate - now; | ||
|
||
if (distance < 0) { | ||
clearInterval(interval); | ||
countdownElement.textContent = 'Available to open'; | ||
return; | ||
} | ||
|
||
const days = Math.floor(distance / (1000 * 60 * 60 * 24)); | ||
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); | ||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); | ||
const seconds = Math.floor((distance % (1000 * 60)) / 1000); | ||
|
||
countdownElement.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`; | ||
}, 1000); | ||
} | ||
|
||
function showCapsuleDetails(capsule) { | ||
const modal = document.getElementById('capsuleModal'); | ||
const modalCapsuleName = document.getElementById('modalCapsuleName'); | ||
const modalCapsuleMessage = document.getElementById('modalCapsuleMessage'); | ||
const modalCapsuleImage = document.getElementById('modalCapsuleImage'); | ||
const modalCapsuleVideo = document.getElementById('modalCapsuleVideo'); | ||
const closeBtn = document.querySelector('.close'); | ||
|
||
if (new Date() < capsule.openDate) { | ||
alert('This capsule cannot be opened yet.'); | ||
return; | ||
} | ||
|
||
modalCapsuleName.textContent = capsule.name; | ||
modalCapsuleMessage.textContent = capsule.message; | ||
|
||
if (capsule.image) { | ||
modalCapsuleImage.style.display = 'block'; | ||
} else { | ||
modalCapsuleImage.style.display = 'none'; | ||
} | ||
|
||
if (capsule.video) { | ||
modalCapsuleVideo.style.display = 'block'; | ||
} else { | ||
modalCapsuleVideo.style.display = 'none'; | ||
} | ||
|
||
modal.style.display = 'block'; | ||
|
||
closeBtn.onclick = function () { | ||
modal.style.display = 'none'; | ||
}; | ||
|
||
window.onclick = function (event) { | ||
if (event.target == modal) { | ||
modal.style.display = 'none'; | ||
} | ||
}; | ||
} | ||
|
||
function editCapsule(index) { | ||
const capsule = capsules[index]; | ||
document.getElementById('capsuleName').value = capsule.name; | ||
document.getElementById('openDate').value = capsule.openDate.toISOString().split('T')[0]; | ||
document.getElementById('tags').value = capsule.tags.join(', '); | ||
document.getElementById('message').value = capsule.message; | ||
capsules.splice(index, 1); | ||
updateDashboard(); | ||
updateStatistics(); | ||
} | ||
|
||
function showNotification(message) { | ||
notification.textContent = message; | ||
notification.style.display = 'block'; | ||
setTimeout(() => { | ||
notification.style.display = 'none'; | ||
}, 3000); | ||
} | ||
|
||
function updateStatistics() { | ||
const totalCapsules = capsules.length; | ||
const tagCounts = capsules.reduce((acc, capsule) => { | ||
capsule.tags.forEach(tag => { | ||
acc[tag] = (acc[tag] || 0) + 1; | ||
}); | ||
return acc; | ||
}, {}); | ||
|
||
const mostCommonTags = Object.entries(tagCounts) | ||
.sort((a, b) => b[1] - a[1]) | ||
.slice(0, 5) | ||
.map(([tag, count]) => `${tag} (${count})`) | ||
.join(', '); | ||
|
||
const dateCounts = capsules.reduce((acc, capsule) => { | ||
const date = capsule.openDate.toDateString(); | ||
acc[date] = (acc[date] || 0) + 1; | ||
return acc; | ||
}, {}); | ||
|
||
const distribution = Object.entries(dateCounts) | ||
.map(([date, count]) => `${date}: ${count}`) | ||
.join('<br>'); | ||
|
||
statisticsContainer.innerHTML = ''; | ||
const statsTitle = document.createElement('h3'); | ||
statsTitle.textContent = 'Capsule Statistics'; | ||
statisticsContainer.appendChild(statsTitle); | ||
|
||
const totalCapsulesP = document.createElement('p'); | ||
totalCapsulesP.textContent = `Total Capsules: ${totalCapsules}`; | ||
statisticsContainer.appendChild(totalCapsulesP); | ||
|
||
const mostCommonTagsP = document.createElement('p'); | ||
mostCommonTagsP.textContent = `Most Common Tags: ${mostCommonTags}`; | ||
statisticsContainer.appendChild(mostCommonTagsP); | ||
|
||
const distributionP = document.createElement('p'); | ||
distributionP.innerHTML = `Distribution by Opening Date:<br>${distribution}`; | ||
statisticsContainer.appendChild(distributionP); | ||
} | ||
|
||
document.querySelectorAll('.nav-link').forEach(link => { | ||
link.addEventListener('click', function () { | ||
document.querySelectorAll('.page').forEach(page => page.classList.remove('active')); | ||
document.querySelector(this.getAttribute('href')).classList.add('active'); | ||
}); | ||
}); | ||
|
||
document.getElementById('addCapsule').classList.add('active'); | ||
}); |
Oops, something went wrong.