diff --git a/Calculator/cal.css b/Calculator/cal.css index 25bad49..42733f1 100644 --- a/Calculator/cal.css +++ b/Calculator/cal.css @@ -1,64 +1,161 @@ -body{ - background-image: url(c10.jpg); - background-repeat: no-repeat; - height: 100%; - width: 100%; - overflow: hidden; - background-position: center; - background-size: cover; +/* General body */ +body { + font-family: "Segoe UI", Arial, sans-serif; + background: #f5f5f5; + color: #333; + display: flex; + justify-content: center; + align-items: flex-start; + height: 100vh; + margin: 0; + transition: background 0.3s, color 0.3s; } -button{ - width: 200px; - height: 50px; - margin: 2px 2px; - background-color: blue; - color: #fff4a7; + +/* Container */ +#outside { + background: #ffffff; + padding: 30px; border-radius: 20px; - font-weight: bolder; - font-style: italic; - font-size: larger; + text-align: center; + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.2); + width: 420px; + margin-top: 40px; + transition: background 0.3s, box-shadow 0.3s; +} + +/* Header */ +.header { + display: flex; + justify-content: space-between; + align-items: center; } -#outside{ - color: white; - border-radius: 5px; - margin: auto; - margin-top: 100px; - width: 1000px; - height: 600px; - padding: 5px; + +/* Heading */ +#heading { + font-size: 2rem; + color: #ff9800; } -#heading{ - margin: auto; - width: 412px; - font-size: xxx-large; + +/* Theme toggle */ +.switch { + position: relative; + display: inline-block; + width: 50px; + height: 26px; } -#btn{ - margin: auto; - margin-top: 20px; - width: 815px; +.switch input { opacity: 0; width: 0; height: 0; } +.slider { + position: absolute; + cursor: pointer; + top: 0; left: 0; right: 0; bottom: 0; + background-color: #ccc; + border-radius: 26px; + transition: 0.4s; } -.btn-inside{ - width: 900px; +.slider:before { + position: absolute; + content: ""; + height: 20px; width: 20px; + left: 3px; bottom: 3px; + background-color: white; + border-radius: 50%; + transition: 0.4s; } -#val{ - /* border: 2px solid red; */ - height: 55px; - width: 783px; - margin-left: 100px; - color: white; - padding-left: 37px; - padding-top: 20px; - font-weight: bolder; +input:checked + .slider { background-color: #2196f3; } +input:checked + .slider:before { transform: translateX(24px); } + +/* Display */ +#val { + width: 100%; + height: 70px; + font-size: 1.8rem; + text-align: right; + margin-bottom: 10px; + padding: 12px; + border-radius: 12px; + border: 1px solid #ccc; + background: #fff; + color: #000; + box-shadow: inset 0 2px 5px rgba(0,0,0,0.1); + transition: background 0.3s, color 0.3s; } -#res{ - /* border: 2px solid red; */ - height: 50px; - width: 783px; - margin-left: 100px; - color: white; - padding-left: 37px; - padding-top: 25px; - font-weight: bolder; - font-size: x-large; + +#res { + font-size: 1.3rem; + margin-bottom: 20px; + text-align: right; + color: #ff5722; + min-height: 20px; + transition: color 0.3s; +} + +/* Buttons grid */ +#btn { display: grid; grid-gap: 12px; } +.btn-inside { display: flex; justify-content: center; gap: 12px; } + +/* Buttons - adaptive color */ +button { + flex: 1; + padding: 18px; + font-size: 1.3rem; + font-weight: bold; + border: none; + border-radius: 12px; + cursor: pointer; + background: #1976d2; + color: #fff; + box-shadow: 0 4px 8px rgba(0,0,0,0.2); + transition: 0.2s all; +} +button:hover { background: #1565c0; transform: scale(1.05); } +button:active { transform: scale(0.95); } + +/* History side panel */ +.history-panel { + position: fixed; + top: 0; right: -250px; + width: 250px; + height: 100%; + background: #ffffff; + border-left: 1px solid #ccc; + box-shadow: -4px 0 12px rgba(0,0,0,0.2); + padding: 20px; + transition: right 0.3s; + overflow-y: auto; + z-index: 100; +} +.history-panel h3 { margin-top: 0; } +.history-panel ul { padding-left: 0; list-style: none; } +.history-panel li { + padding: 8px 5px; + border-bottom: 1px solid #eee; + cursor: pointer; +} +.history-panel li:hover { background: #f0f0f0; } + +/* History button */ +.history-btn { + position: fixed; + top: 20px; right: 20px; + padding: 10px 15px; + font-size: 1.2rem; + background: #ff9800; + color: #fff; + border: none; + border-radius: 8px; + cursor: pointer; + box-shadow: 0 4px 8px rgba(0,0,0,0.2); + z-index: 101; + transition: 0.2s all; } +.history-btn:hover { background: #fb8c00; } +/* Dark mode */ +body.dark { background: #1e1e2f; color: #fff; } +body.dark #outside { background: #2b2b3c; box-shadow: 0 12px 30px rgba(0,0,0,0.6); } +body.dark #val { background: #1e1e2f; color: #fff; } +body.dark #res { color: #b3e5fc; } +body.dark button { background: #64b5f6; color: #000; } +body.dark button:hover { background: #42a5f5; } +body.dark .history-panel { background: #2b2b3c; color: #fff; border-left: 1px solid #555; } +body.dark .history-panel li:hover { background: #3a3a4d; } diff --git a/Calculator/cal.html b/Calculator/cal.html index 84a65f1..c69dd9e 100644 --- a/Calculator/cal.html +++ b/Calculator/cal.html @@ -1,54 +1,68 @@ - - - - - - Calculator + + + Calculator + - -
-

🖩CALCULATOR🖩

-
-
-

-
-
-

-
-
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
- -
-
+
+
+

🖩 CALCULATOR 🖩

+ +
- - - \ No newline at end of file + + +

+ + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + +
+
+
+ + +
+

History

+ +
+ + + + + + + diff --git a/Calculator/cal.js b/Calculator/cal.js index 1699f4c..7cb992f 100644 --- a/Calculator/cal.js +++ b/Calculator/cal.js @@ -1,42 +1,104 @@ -let valEl = document.getElementById("val") -let resEl = document.getElementById("res") -function clearer(){ - valEl.innerText = "" - resEl.innerText = "" +let valEl = document.getElementById("val"); +let resEl = document.getElementById("res"); +let historyEl = document.getElementById("history"); +let historyPanel = document.getElementById("history-panel"); +let historyToggle = document.getElementById("history-toggle"); +let themeToggle = document.getElementById("theme-toggle"); + +// Load history from localStorage +let calcHistory = JSON.parse(localStorage.getItem("calcHistory") || "[]"); +updateHistory(); + +// ------------------ Calculator Functions ------------------ + +// Clear display +function clearer() { + valEl.value = ""; + resEl.innerText = ""; } -function adder(k){ - valEl.innerText += k - if(k=='*' || k=='+' || k=='-' || k=='/'){ - compute(0) + +// Add number/operator +function adder(k) { + let lastChar = valEl.value.slice(-1); + if ("+-*/".includes(k) && "+-*/".includes(lastChar)) { + valEl.value = valEl.value.slice(0, -1) + k; + } else { + valEl.value += k; } } -function compute(is){ - let temp = valEl.innerText, i - let t = temp[temp.length-1]; - for(i=0;i 20) calcHistory.pop(); // keep last 20 + localStorage.setItem("calcHistory", JSON.stringify(calcHistory)); + updateHistory(); +} + +// Update history panel +function updateHistory() { + historyEl.innerHTML = ""; + calcHistory.forEach(item => { + let li = document.createElement("li"); + li.textContent = item; + li.onclick = () => { + valEl.value = item.split('=')[0].trim(); + resEl.innerText = ""; + }; + historyEl.appendChild(li); + }); +} + +// Toggle history panel +historyToggle.addEventListener("click", () => { + if (historyPanel.style.right === "0px") { + historyPanel.style.right = "-250px"; + } else { + historyPanel.style.right = "0px"; + } +}); + +// ------------------ Theme Toggle ------------------ +themeToggle.addEventListener("change", () => { + document.body.classList.toggle("dark"); +}); + +// ------------------ Optional: Keyboard support ------------------ +document.addEventListener("keydown", (e) => { + if ((e.key >= '0' && e.key <= '9') || "+-*/.".includes(e.key)) { + adder(e.key); + } else if (e.key === "Enter") { + computeFinal(); + } else if (e.key === "Backspace") { + backspace(); + } else if (e.key === "Escape") { + clearer(); } -} \ No newline at end of file +}); diff --git a/Clock/index.css b/Clock/index.css index 81c1a15..c70a248 100644 --- a/Clock/index.css +++ b/Clock/index.css @@ -1,37 +1,132 @@ -#clockContainer{ +/* --- General Body and Theme Styling --- */ +body { + background-color: #f4f4f4; + color: #333; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100vh; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + transition: background-color 0.3s, color 0.3s; +} + +body.dark-mode { + background-color: #1a1a1a; + color: #f0f0f0; +} + +/* --- Analog Clock --- */ +#clockContainer { position: relative; - margin: auto; - height: 40vw; - width: 40vw; + margin: 20px auto; + height: 40vmin; /* Using vmin for better responsiveness */ + width: 40vmin; background: url(clock.png) no-repeat; background-size: 100%; + transition: filter 0.3s; } -#hour, #minute, #second{ +body.dark-mode #clockContainer { + filter: invert(1); +} + +#hour, #minute, #second { position: absolute; background: black; - border-radius: 10px; + border-radius: 10px; transform-origin: bottom; } -#hour{ - width: 1.8%; - height: 25%; - top: 25%; - left: 48.85%; - opacity: 0.8; -} -#minute{ - width: 1.6%; - height: 30%; - top: 19%; - left: 48.9%; - opacity: 0.8; -} -#second{ - width: 1%; - height: 40%; - top: 9%; - left: 49.25%; - opacity: 0.8; - -} \ No newline at end of file + +#hour { width: 1.8%; height: 25%; top: 25%; left: 49.1%; } +#minute { width: 1.6%; height: 35%; top: 15%; left: 49.2%; } +#second { width: 1%; height: 40%; top: 10%; left: 49.5%; background-color: red; } + + +/* --- Digital Clock and Date --- */ +#digital-display { + text-align: center; + margin-top: 20px; +} + +#digital-time { + font-size: 3rem; + font-weight: 600; +} + +#date-display { + font-size: 1.2rem; + margin-top: 5px; +} + + +/* --- Top Controls (Toggle & Timezone) --- */ +.controls-container { + position: absolute; + top: 20px; + right: 20px; + display: flex; + align-items: center; + gap: 20px; +} + +#timezone-selector { + padding: 8px; + border-radius: 5px; + border: 1px solid #ccc; + font-size: 1rem; +} + +body.dark-mode #timezone-selector { + background-color: #333; + color: #f0f0f0; + border-color: #555; +} + +/* Fancy Toggle Switch */ +.switch { position: relative; display: inline-block; width: 60px; height: 34px; } +.switch input { opacity: 0; width: 0; height: 0; } +.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 34px; } +.slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; } +input:checked + .slider { background-color: #4CAF50; } +input:checked + .slider:before { transform: translateX(26px); } + + +/* --- Stopwatch --- */ +#stopwatch-container { + margin-top: 30px; + padding: 20px; + border: 1px solid #ccc; + border-radius: 10px; + text-align: center; + width: 300px; +} + +body.dark-mode #stopwatch-container { + border-color: #555; +} + +#stopwatch-display { + font-size: 2rem; + font-family: 'Courier New', Courier, monospace; + margin: 10px 0 20px 0; +} + +.stopwatch-controls button { + padding: 10px 20px; + margin: 0 5px; + font-size: 1rem; + cursor: pointer; + border: none; + border-radius: 5px; + color: white; + transition: background-color 0.2s; +} + +#startBtn { background-color: #4CAF50; /* Green */ } +#stopBtn { background-color: #f44336; /* Red */ } +#resetBtn { background-color: #555; /* Grey */ } + +#startBtn:hover { background-color: #45a049; } +#stopBtn:hover { background-color: #da190b; } +#resetBtn:hover { background-color: #333; } \ No newline at end of file diff --git a/Clock/index.html b/Clock/index.html index 13664bd..70355bd 100644 --- a/Clock/index.html +++ b/Clock/index.html @@ -3,15 +3,48 @@ - Clock Using Pure JS + Enhanced JS Clock - + +
+ + + +
+
+ +
+
00:00:00
+
Date
+
+ +
+

Stopwatch

+
00:00:00.000
+
+ + + +
+
+ + \ No newline at end of file diff --git a/Clock/index.js b/Clock/index.js index 835800b..4df53a1 100644 --- a/Clock/index.js +++ b/Clock/index.js @@ -1,13 +1,95 @@ -setInterval(() => { - d = new Date(); - htime = d.getHours(); - mtime = d.getMinutes(); - stime = d.getSeconds(); - hrotation = 30*htime + mtime/2; - mrotation = 6*mtime; - srotation = 6*stime; - - hour.style.transform = `rotate(${hrotation}deg)`; - minute.style.transform = `rotate(${mrotation}deg)`; - second.style.transform = `rotate(${srotation}deg)`; -}, 1000); \ No newline at end of file +// Wait for the DOM to be fully loaded before running the script +document.addEventListener('DOMContentLoaded', () => { + + // --- Element Selection --- + const hourHand = document.getElementById('hour'); + const minuteHand = document.getElementById('minute'); + const secondHand = document.getElementById('second'); + const digitalTime = document.getElementById('digital-time'); + const dateDisplay = document.getElementById('date-display'); + const timezoneSelector = document.getElementById('timezone-selector'); + const themeToggle = document.getElementById('theme-toggle'); + + // --- Theme Toggle Logic --- + themeToggle.addEventListener('change', () => { + document.body.classList.toggle('dark-mode'); + }); + + // --- Clock and Date Update Function --- + function updateClocks() { + const selectedTimezone = timezoneSelector.value; + const now = new Date(); + + // Use Intl.DateTimeFormat for robust timezone handling + const timeOptions = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: selectedTimezone }; + const timeString = new Intl.DateTimeFormat('en-US', timeOptions).format(now); + const [h, m, s] = timeString.split(':').map(Number); + + const dateOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: selectedTimezone }; + const dateString = new Intl.DateTimeFormat('en-US', dateOptions).format(now); + + // Analog Clock Rotation + const hrotation = 30 * h + m / 2; + const mrotation = 6 * m; + const srotation = 6 * s; + + hourHand.style.transform = `rotate(${hrotation}deg)`; + minuteHand.style.transform = `rotate(${mrotation}deg)`; + secondHand.style.transform = `rotate(${srotation}deg)`; + + // Digital Clock and Date Display + digitalTime.textContent = timeString; + dateDisplay.textContent = dateString; + } + + // Update the clock immediately and then every second + updateClocks(); + setInterval(updateClocks, 1000); + + // Update clocks when timezone changes + timezoneSelector.addEventListener('change', updateClocks); + + + // --- Stopwatch Logic --- + const stopwatchDisplay = document.getElementById('stopwatch-display'); + const startBtn = document.getElementById('startBtn'); + const stopBtn = document.getElementById('stopBtn'); + const resetBtn = document.getElementById('resetBtn'); + + let startTime; + let elapsedTime = 0; + let stopwatchInterval; + + function formatTime(ms) { + const date = new Date(ms); + const minutes = String(date.getUTCMinutes()).padStart(2, '0'); + const seconds = String(date.getUTCSeconds()).padStart(2, '0'); + const milliseconds = String(date.getUTCMilliseconds()).padStart(3, '0'); + return `${minutes}:${seconds}.${milliseconds}`; + } + + function startStopwatch() { + if (!stopwatchInterval) { // Prevent multiple intervals + startTime = Date.now() - elapsedTime; + stopwatchInterval = setInterval(() => { + elapsedTime = Date.now() - startTime; + stopwatchDisplay.textContent = formatTime(elapsedTime); + }, 10); // Update every 10ms for smooth milliseconds + } + } + + function stopStopwatch() { + clearInterval(stopwatchInterval); + stopwatchInterval = null; + } + + function resetStopwatch() { + stopStopwatch(); + elapsedTime = 0; + stopwatchDisplay.textContent = '00:00:00.000'; + } + + startBtn.addEventListener('click', startStopwatch); + stopBtn.addEventListener('click', stopStopwatch); + resetBtn.addEventListener('click', resetStopwatch); +}); \ No newline at end of file diff --git a/Password Generator/index.css b/Password Generator/index.css index b8bbf74..a0b7b62 100644 --- a/Password Generator/index.css +++ b/Password Generator/index.css @@ -1,136 +1,113 @@ -body{ +body { box-sizing: border-box; - font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: #1F2937; + color: #D5D4D8; + display: flex; + justify-content: center; + align-items: flex-start; + padding-top: 5vh; + min-height: 100vh; } -.container{ - margin-left: 20%; - margin-right: 10%; +.container { + width: 90%; + max-width: 550px; + background-color: #1F2937; + padding: 20px; +} + +#headline1 { + margin-top: 0; + color: aliceblue; + font-weight: 800; + margin-bottom: 0; + font-size: 2.5rem; } -#headline { - color:#10B981; +#headline2 { + margin-top: 0; + margin-bottom: 0; + font-size: 2.5rem; + color: #55F991; } -#btn { +#line { color: #D5D4D8; } + +.main-btn { background-color: #10B981; - padding:.7em; + padding: .8em 1.2em; color: white; - font-size: medium; + font-size: 1rem; font-weight: 500; border: none; margin-bottom: 1em; margin-top: 1em; cursor: pointer; - border-radius:.5rem; -} - -hr{ - color: #273549; - position: absolute; - - width: 30rem; -} - -#PassContainer{ - border: 2px solid; - margin-top: 1.5em; - margin-right: 2em; - padding-bottom: 2.5rem; - width: 17em; - height: 3em; - line-height: normal; - display: block; border-radius: .5rem; - background-color: #273549; - color:#000000; + transition: background-color 0.2s; } -.Password1{ - color:#55F991; -} -.Password2{ - color:#55F991; -} - -#headline1{ - margin-top: 2em; - color: aliceblue; - font-weight: 800; - margin-bottom: 0; - font-size: 2.5rem; -} - -#headline2{ - margin-top: 0em; - margin-bottom: 0; - font-size: 2.5em; - color:#55F991; +.main-btn:hover { background-color: #0c9f6d; } +.secondary-btn { background-color: #4A5567; } +.secondary-btn:hover { background-color: #394251; } +.action-buttons { display: flex; gap: 15px; } -} -#line{ - color: #D5D4D8; +hr { + border: none; + border-top: 1px solid #273549; + margin: 2em 0; } -.password-container{ +/* Password Display & Copy */ +.password-display-container { display: flex; - -} - -.switch{ - margin-top: 1em; - margin-left:.5em; - position: relative; - display: inline-block; - width: 60px; - height: 34px; -} - -.switch input { - opacity: 0; - width: 0; - height: 0; + align-items: center; + gap: 10px; + margin-top: 1.5em; } - -.slider{ - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; +#passwordOutput { + flex-grow: 1; background-color: #273549; - -webkit-transition:.4s; - transition: .4s; -} - -.slider:before { - position: absolute; - content: ""; - height: 26px; - width: 26px; - left: 4px; - bottom: 4px; - background-color: white; - -webkit-transition: .4s; - transition: .4s; -} - -input:checked + .slider{ - background-color: #10B981; + color: #55F991; + border: none; + border-radius: .5rem; + padding: .8em; + font-size: 1.2rem; + font-family: 'Courier New', Courier, monospace; } - - -input:checked + .slider:before { - -webkit-transform: translateX(26px); - -ms-transform: translateX(26px); - transform: translateX(26px); +#copyBtn { + background-color: #4A5567; + color: white; + border: none; + border-radius: .5rem; + padding: .8em; + font-size: 1.2rem; + cursor: pointer; } +#copyBtn:active { transform: scale(0.95); } -.slider.round { - border-radius: 34px; -} +/* Settings */ +.settings-container { display: flex; flex-direction: column; gap: 1.5em; } +.setting { display: flex; align-items: center; flex-wrap: wrap; gap: 15px; } +.setting label { user-select: none; } +#lengthSlider { flex-grow: 1; } +.checkboxes { flex-direction: column; align-items: flex-start; gap: 10px; } -.slider.round:before{ - border-radius: 50%; -} \ No newline at end of file +/* Security Feedback */ +.security-feedback { margin-top: 2em; } +.strength-meter { + height: 10px; + width: 100%; + background-color: #273549; + border-radius: 5px; + overflow: hidden; +} +#strengthBar { + height: 100%; + width: 0%; + border-radius: 5px; + transition: width 0.3s ease, background-color 0.3s ease; +} +#strengthText { font-weight: bold; margin-top: 10px; } +#crackTimeText { font-size: 0.9em; color: #a0aec0; } +#securityNote { font-size: 0.8em; color: #6B7280; text-align: center; margin-top: 2em; } \ No newline at end of file diff --git a/Password Generator/index.html b/Password Generator/index.html index 4e75e50..b6aa9c2 100644 --- a/Password Generator/index.html +++ b/Password Generator/index.html @@ -1,30 +1,55 @@ - + Password Generator - - + + +
-

Generate a

-

random password

-

Never use an insecure password

- -
-
-
- - +

Generate a

+

random password

+

Never use an insecure password

+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ + 16 + +
+
+ + + + +
+
+ +
+
+
+
+

+

+

Passwords are generated in your browser and are never saved.

+
+
- - - + + + + \ No newline at end of file diff --git a/Password Generator/index.js b/Password Generator/index.js index da55d4a..c1ec248 100644 --- a/Password Generator/index.js +++ b/Password Generator/index.js @@ -1,49 +1,121 @@ -let mode = document.querySelector("#modeChanger"); -let headline = document.getElementById("headline1"); -let body = document.querySelector("body"); -let line = document.querySelector("#line"); -let hr = document.querySelector("hr"); -let headline2 = document.querySelector("#headline2"); - -mode.addEventListener("change", () => { - if (mode.checked) { - headline.style.color = "#000000"; - body.style.backgroundColor = "#ECFDF5" - line.style.color = "#6B7280" - hr.style.color = "#E8E7E9" - headline2.style.color = "#10B981" +document.addEventListener('DOMContentLoaded', () => { + // --- Element Selectors --- + const passwordOutput = document.getElementById('passwordOutput'); + const copyBtn = document.getElementById('copyBtn'); + const generatePasswordBtn = document.getElementById('generatePasswordBtn'); + const generatePassphraseBtn = document.getElementById('generatePassphraseBtn'); + const lengthSlider = document.getElementById('lengthSlider'); + const lengthValue = document.getElementById('lengthValue'); - } else { - headline2.style.color = "#55F991" - headline.style.color = "aliceblue"; - body.style.backgroundColor = "#1F2937" - hr.style.color = "#273549" - } -}); - - -const lowercaseChars = "abcdefghijklmnopqrstuvwxyz"; -const uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const numberChars = "0123456789"; -const specialChars = "!@#$%^&*"; - -const generatePassword = (length) => { - const allChars = `${lowercaseChars}${uppercaseChars}${numberChars}${specialChars}`; - let password = ""; - - for (let i = 0; i < length; i++) { - const randomIndex = Math.floor(Math.random() * allChars.length); - password += allChars.charAt(randomIndex); - } - return password; -}; - -const displayPassword = () => { - let dPassword1 = document.querySelector(".Password1"); - dPassword1.textContent = generatePassword(13); - let dPassword2 = document.querySelector(".Password2"); - dPassword2.textContent = generatePassword(12); -}; - -document.getElementById("btn").addEventListener("click", displayPassword); + const includeUppercase = document.getElementById('includeUppercase'); + const includeLowercase = document.getElementById('includeLowercase'); + const includeNumbers = document.getElementById('includeNumbers'); + const includeSymbols = document.getElementById('includeSymbols'); + + const strengthBar = document.getElementById('strengthBar'); + const strengthText = document.getElementById('strengthText'); + const crackTimeText = document.getElementById('crackTimeText'); + + const charSets = { + uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + lowercase: "abcdefghijklmnopqrstuvwxyz", + numbers: "0123456789", + symbols: "!@#$%^&*" + }; + + // --- Wordlist for Passphrase --- + const wordList = ["Apple", "Banana", "River", "Mountain", "Ocean", "Forest", "Sunshine", "Moonlight", "Coffee", "Guitar", "Computer", "Journey", "Silence", "Whisper", "Velocity", "Galaxy"]; + + // --- Main Functions --- + + function generatePassword() { + let characterPool = ""; + if (includeUppercase.checked) characterPool += charSets.uppercase; + if (includeLowercase.checked) characterPool += charSets.lowercase; + if (includeNumbers.checked) characterPool += charSets.numbers; + if (includeSymbols.checked) characterPool += charSets.symbols; + + if (characterPool === "") { + passwordOutput.value = "Select at least one character set!"; + updateSecurityFeedback(""); + return; + } + + let password = ""; + const length = lengthSlider.value; + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characterPool.length); + password += characterPool.charAt(randomIndex); + } + + passwordOutput.value = password; + updateSecurityFeedback(password); + } + + function generatePassphrase() { + let passphrase = []; + const length = 4; // Generate a 4-word passphrase + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * wordList.length); + passphrase.push(wordList[randomIndex]); + } + const finalPassphrase = passphrase.join('-'); + passwordOutput.value = finalPassphrase; + updateSecurityFeedback(finalPassphrase); + } + + function updateSecurityFeedback(password) { + if (!password) { + strengthBar.style.width = '0%'; + strengthText.textContent = ''; + crackTimeText.textContent = ''; + return; + } + + const result = zxcvbn(password); + const strength = result.score; // Score from 0 (worst) to 4 (best) + + const strengthLevels = { + 0: { width: '10%', color: '#ef4444', text: 'Very Weak' }, + 1: { width: '25%', color: '#f97316', text: 'Weak' }, + 2: { width: '50%', color: '#facc15', text: 'Moderate' }, + 3: { width: '75%', color: '#84cc16', text: 'Strong' }, + 4: { width: '100%', color: '#22c55e', text: 'Very Strong' } + }; + + strengthBar.style.width = strengthLevels[strength].width; + strengthBar.style.backgroundColor = strengthLevels[strength].color; + strengthText.textContent = `Strength: ${strengthLevels[strength].text}`; + crackTimeText.textContent = `Estimated time to crack: ${result.crack_times_display.offline_slow_hashing_1e4_per_second}`; + } + + function copyToClipboard() { + if (passwordOutput.value) { + navigator.clipboard.writeText(passwordOutput.value) + .then(() => { + copyBtn.textContent = '✅'; + setTimeout(() => { copyBtn.textContent = '📋'; }, 2000); + }) + .catch(err => alert("Failed to copy password.")); + } + } + + // --- Event Listeners --- + lengthSlider.addEventListener('input', () => { + lengthValue.textContent = lengthSlider.value; + generatePassword(); // Regenerate on slider change + }); + + // Regenerate password if any checkbox is changed + document.querySelectorAll('.checkboxes input').forEach(checkbox => { + checkbox.addEventListener('change', generatePassword); + }); + + generatePasswordBtn.addEventListener('click', generatePassword); + generatePassphraseBtn.addEventListener('click', generatePassphrase); + copyBtn.addEventListener('click', copyToClipboard); + + // Initial generation on page load + generatePassword(); +}); \ No newline at end of file diff --git a/TODO-LIST/src/App.css b/TODO-LIST/src/App.css index 85771d2..f916268 100644 --- a/TODO-LIST/src/App.css +++ b/TODO-LIST/src/App.css @@ -1,121 +1,310 @@ -.home { - min-height: 100vh; - background-color: white; +/* Reset and Base */ +*, *::after, *::before { + box-sizing: border-box; + margin: 0; + padding: 0; } +body { + margin: 0; + font-family: 'Open Sans', sans-serif; + background-color: #f0f6ff; /* light blue background */ + color: #222; +} + +/* Container */ .container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - padding: 15px; + max-width: 600px; + margin: 40px auto; + padding: 0 15px; } +/* Form */ .todo-form { display: flex; - align-items: center; - justify-content: space-between; - width: 300px; + gap: 10px; + margin-bottom: 20px; + justify-content: center; + flex-wrap: wrap; +} + +.todo-form input[type="text"], +.todo-form textarea { + flex: 1; padding: 10px; - background-color: #E1F0F7; + border: 1px solid #1DA1F2; border-radius: 6px; - gap: 5px; + font-size: 1rem; + outline: none; + transition: border 0.2s ease; } -input{ - padding: 7px; - width: 98%; +.todo-form input[type="text"]:focus, +.todo-form textarea:focus { + border-color: #0d8ddb; + box-shadow: 0 0 0 3px rgba(29,161,242,0.2); +} + +.todo-form textarea { + resize: none; + min-height: 40px; +} + +.todo-form .btn-addTodo { + padding: 10px 18px; + background: #1DA1F2; border: none; border-radius: 6px; - outline: none; + color: white; + font-weight: 600; + cursor: pointer; + transition: background 0.2s ease, transform 0.1s ease; } -input:focus{ - box-shadow: 0 0 0 2px #2cb0ee; + +.todo-form .btn-addTodo:hover { + background: #0d8ddb; } -.btn-addTodo{ - padding: 6px; - border: none; - border-radius: 4px; - outline: none; - background-color: #1DA1F2; + +.todo-form .btn-addTodo:active { + transform: scale(0.95); +} + +/* Filter Buttons */ +.filters { + display: flex; + justify-content: center; + align-items: center; + gap: 8px; + margin-bottom: 20px; + flex-wrap: wrap; +} + +.filters button { + padding: 6px 14px; + background: #fff; + border: 1px solid #1DA1F2; + border-radius: 6px; + color: #1DA1F2; + font-weight: 600; cursor: pointer; - color: white; - font-weight: 700; - font-size: 14px; - width: 70px; + transition: all 0.2s ease; } -.todo { - width: 300px; - padding: 10px; - background-color: #E1F0F7; +.filters button:hover { + background: #1DA1F2; + color: #fff; +} + +.filters button.active { + background: #1DA1F2; + color: #fff; + box-shadow: 0 0 6px rgba(29,161,242,0.4); +} + +/* Date input for custom filter */ +.filters input[type="date"] { + padding: 6px 10px; + border: 1px solid #1DA1F2; border-radius: 6px; - margin-top: 10px; + font-size: 0.9rem; + cursor: pointer; + outline: none; + transition: border 0.2s ease; +} + +.filters input[type="date"]:focus { + border-color: #0d8ddb; + box-shadow: 0 0 0 3px rgba(29,161,242,0.2); +} + +/* Todo Card */ +.todo { + background: #fff; + border: 1px solid #d6e9ff; + border-radius: 8px; + padding: 15px; + margin-bottom: 15px; + box-shadow: 0 2px 6px rgba(0,0,0,0.05); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.todo:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.08); +} + +/* Completed Task */ +.todo.completed h3, +.todo.completed .desc { + text-decoration: line-through; + color: #777; +} + +/* Task Layout */ +.task-main { display: flex; - align-items: center; justify-content: space-between; + align-items: flex-start; } -.text { - font-size: 16px; - font-weight: 700; - margin-right: auto; - overflow: hidden; - overflow-wrap: break-word; +/* Todo Title */ +.todo h3 { + font-size: 1.1rem; + color: #1DA1F2; + margin-bottom: 6px; +} + +/* Task Description */ +.todo .desc { + font-size: 0.9rem; + color: #444; + background: #f7fbff; + border-left: 3px solid #1DA1F2; + padding: 6px 10px; + border-radius: 4px; + margin-bottom: 10px; + line-height: 1.4; } -.utils{ +/* Timestamp */ +.todo small { + display: block; + font-size: 0.8rem; + color: #777; + margin-bottom: 6px; +} + +/* Task Actions (right side buttons) */ +.task-actions { display: flex; + gap: 12px; align-items: center; - gap: 8px; + font-size: 1.2rem; } -.go-up { - width: 0; - height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #1DA1F2; +/* Tick (Complete) */ +.task-actions .tick { + color: green; + font-size: 1.3rem; cursor: pointer; + transition: transform 0.2s ease; } -.go-down{ - width: 0; - height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 6px solid #1DA1F2; +.task-actions .tick:hover { + transform: scale(1.2); +} + +/* Edit button */ +.task-actions .edit { cursor: pointer; + font-size: 1.2rem; + color: #f39c12; + transition: transform 0.2s ease; +} + +.task-actions .edit:hover { + transform: scale(1.2); } -.remove{ +/* Remove button */ +.task-actions .remove { + width: 18px; + height: 18px; + border: 2px solid #e63946; + border-radius: 50%; position: relative; - width: 20px; - height: 20px; cursor: pointer; + transition: transform 0.2s ease; +} + +.task-actions .remove:hover { + transform: scale(1.2); } -.remove::after { +.task-actions .remove::before, +.task-actions .remove::after { + content: ""; position: absolute; - content:''; - width: 100%; + top: 50%; + left: 50%; + width: 10px; height: 2px; - background-color: black; - top:0; - left:0; - border-radius: 999px; - transform: translateY(10px) rotate(-45deg); + background: #e63946; + transform: translate(-50%, -50%) rotate(45deg); } -.remove::before { - position: absolute; - content:''; +.task-actions .remove::after { + transform: translate(-50%, -50%) rotate(-45deg); +} + +/* Edit Mode */ +.edit-mode { + display: flex; + flex-direction: column; + gap: 8px; +} + +.edit-mode input, +.edit-mode textarea { width: 100%; - height: 2px; - background-color: black; - top:100%; - left:0; - border-radius: 999px; - transform: translateY(-10px) rotate(45deg); -} \ No newline at end of file + padding: 8px 10px; + border: 1px solid #1DA1F2; + border-radius: 6px; + font-size: 0.95rem; + outline: none; +} + +.edit-mode input:focus, +.edit-mode textarea:focus { + border-color: #0d8ddb; + box-shadow: 0 0 0 3px rgba(29,161,242,0.2); +} + +.edit-mode textarea { + min-height: 60px; + resize: vertical; +} + +.edit-actions { + display: flex; + gap: 10px; +} + +.edit-actions button { + padding: 8px 12px; + border: none; + border-radius: 6px; + background: #1DA1F2; + color: #fff; + font-size: 0.9rem; + font-weight: 600; + cursor: pointer; + transition: background 0.2s ease, transform 0.1s ease; +} + +.edit-actions button:hover { + background: #0d8ddb; +} + +.edit-actions button:active { + transform: scale(0.96); +} + +.edit-actions button:last-child { + background: #ccc; + color: #333; +} + +.edit-actions button:last-child:hover { + background: #999; + color: #fff; +} + +/* No tasks text */ +.no-tasks { + text-align: center; + margin-top: 20px; + font-weight: bold; + font-size: 1rem; + color: #555; +} diff --git a/TODO-LIST/src/components/Todo.jsx b/TODO-LIST/src/components/Todo.jsx index a1bee9e..484375c 100644 --- a/TODO-LIST/src/components/Todo.jsx +++ b/TODO-LIST/src/components/Todo.jsx @@ -1,17 +1,66 @@ -import React from 'react' +import React, { useState } from 'react' -const Todo = ({ todo,deleteTodo,moveUp,moveDown,total,index}) => { - - return ( -
-

{todo.text}

-
-
moveUp(todo.id)}>
-
moveDown(todo.id)}>
-
deleteTodo(todo.id)}>
-
+const Todo = ({ todo, deleteTodo, editTodo, moveUp, moveDown, total, index }) => { + const [isEditing, setIsEditing] = useState(false) + const [newTitle, setNewTitle] = useState(todo.title) + const [newDesc, setNewDesc] = useState(todo.desc) + + const handleSave = () => { + if (newTitle.trim()) { + editTodo(todo.id, newTitle, newDesc) + setIsEditing(false) + } + } + + return ( +
+ {isEditing ? ( +
+ setNewTitle(e.target.value)} + placeholder="Edit title" + /> +