From d52227f1a7c09c05c76132589db64f16f45065a2 Mon Sep 17 00:00:00 2001 From: Suvansh Tembe Date: Fri, 24 Oct 2025 01:12:59 +0530 Subject: [PATCH 1/2] added new project Tip calculator --- data/projects.json | 12 +- projects/Tip Calculator/index.html | 83 +++++++++++ projects/Tip Calculator/main.js | 67 +++++++++ projects/Tip Calculator/styles.css | 229 +++++++++++++++++++++++++++++ 4 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 projects/Tip Calculator/index.html create mode 100644 projects/Tip Calculator/main.js create mode 100644 projects/Tip Calculator/styles.css diff --git a/data/projects.json b/data/projects.json index baecccc..a39be6f 100644 --- a/data/projects.json +++ b/data/projects.json @@ -196,7 +196,7 @@ "title": "Password Generator", "slug": "password-generator", "description": "Generate secure passwords with customizable options.", - "category": "Productivity", + "category": "Productivity", "categoryKey": "productivity", "difficulty": "easy" }, @@ -204,8 +204,16 @@ "title": "Simon Says", "slug": "simon-says", "description": "Play Simon Says", - "category": "Small Games", + "category": "Small Games", "categoryKey": "games", "difficulty": "easy" + }, + { + "title": "Tip Calculator", + "slug": "Tip Calculator", + "description": "Calculate tips and divide bills accurately in seconds", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" } ] diff --git a/projects/Tip Calculator/index.html b/projects/Tip Calculator/index.html new file mode 100644 index 0000000..50c1aaf --- /dev/null +++ b/projects/Tip Calculator/index.html @@ -0,0 +1,83 @@ + + + + + + Tip Calculator + + + + +

Tip Calculator

+ +
+ + + +

Select tip percentage:

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

Tip Amount: Rs0.00

+

Total Bill: Rs0.00

+

Total per Person: Rs0.00

+
+
+ + + + diff --git a/projects/Tip Calculator/main.js b/projects/Tip Calculator/main.js new file mode 100644 index 0000000..074efb4 --- /dev/null +++ b/projects/Tip Calculator/main.js @@ -0,0 +1,67 @@ +const billInput = document.querySelector(".bill"); +const splitInput = document.querySelector(".split"); +const tipButtons = document.querySelectorAll(".tip-btn"); +const customTipInput = document.getElementById("custom-tip"); +const tipAmountDisplay = document.getElementById("tip-amount"); +const totalBillDisplay = document.getElementById("total-bill"); +const perPersonDisplay = document.getElementById("per-person"); + +let tipPercentage = 0; + +tipButtons.forEach(btn => { + btn.addEventListener("click", () => { + tipPercentage = Number(btn.dataset.tip); + customTipInput.value = ""; // clear custom tip + tipButtons.forEach(b => b.classList.remove("active")); + btn.classList.add("active"); + calculateTotals(); + }); +}); + + +[billInput, splitInput, customTipInput].forEach(input => { + input.addEventListener("input", () => calculateTotals()); +}); + + +function calculateTotals() { + const bill = parseFloat(billInput.value); + const people = parseInt(splitInput.value) || 1; + const customTip = parseFloat(customTipInput.value); + + // Use custom tip if entered + const tipPercent = customTip > 0 ? customTip : tipPercentage; + + // Prevent calculation for empty bill + if (isNaN(bill) || bill <= 0) { + updateDisplay(0, 0, 0); + return; + } + + const tipAmount = (bill * tipPercent) / 100; + const totalBill = bill + tipAmount; + const perPerson = totalBill / people; + + updateDisplay(tipAmount, totalBill, perPerson); +} + +function updateDisplay(tip, total, perPerson) { + tipAmountDisplay.textContent = `Rs${tip.toFixed(2)}`; + totalBillDisplay.textContent = `Rs${total.toFixed(2)}`; + perPersonDisplay.textContent = `Rs${perPerson.toFixed(2)}`; +} + +const themeToggle = document.getElementById("themeToggle"); +const body = document.body; + +const currentTheme = localStorage.getItem("theme") || "light"; +if (currentTheme === "dark") { + body.classList.add("dark-mode"); +} + +themeToggle.addEventListener("click", () => { + body.classList.toggle("dark-mode"); + + const theme = body.classList.contains("dark-mode") ? "dark" : "light"; + localStorage.setItem("theme", theme); +}); diff --git a/projects/Tip Calculator/styles.css b/projects/Tip Calculator/styles.css new file mode 100644 index 0000000..ab664c8 --- /dev/null +++ b/projects/Tip Calculator/styles.css @@ -0,0 +1,229 @@ +:root { + /* Light Theme */ + --bg: #f9fafb; + --card: #ffffff; + --muted: #6b7280; + --accent: #2563eb; + --text: #111827; + --border: #e5e7eb; +} + +body.dark-mode { +/* dark mode */ + --bg: #0f172a; + --card: #1e293b; + --muted: #9ca3af; + --accent: #60a5fa; + --text: #f1f5f9; + --border: #334155; +} + + +html, body { + height: 100%; + margin: 0; + padding: 0; +} + +body { + font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; + background: var(--bg); + color: var(--text); + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + min-height: 100vh; + padding: 2rem; + transition: background 0.4s ease, color 0.4s ease; +} + +* { + box-sizing: border-box; + transition: background 0.4s ease, color 0.4s ease, border-color 0.3s ease; +} + + +.container { + background: var(--card); + padding: 2rem; + border-radius: 16px; + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); + + + width: 32vw; + max-width: 100%; + min-width: 320px; + + margin-top: 0.1rem; +} + +h1 { + text-align: center; + margin-bottom: 1.6rem; + font-size: 2rem; + font-weight: 600; + color: var(--text); +} + + +label { + display: block; + margin-top: 1rem; + font-size: 0.95rem; + color: var(--muted); + font-weight: 500; +} + +input[type="number"] { + width: 100%; + padding: 0.75rem; + margin-top: 0.5rem; + font-size: 1rem; + border: 1px solid var(--border); + border-radius: 8px; + background: var(--bg); + color: var(--text); + transition: border 0.3s ease, box-shadow 0.3s ease; +} + +input[type="number"]:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15); +} + +.tip-buttons { + display: flex; + gap: 0.75rem; + margin-top: 1rem; + flex-wrap: wrap; +} + +.tip-btn { + flex: 1 1 30%; + padding: 0.75rem; + font-size: 1rem; + font-weight: 500; + border: 1px solid var(--border); + background: var(--card); + color: var(--text); + border-radius: 8px; + cursor: pointer; + transition: all 0.3s ease; +} + +.tip-btn:hover { + background: var(--accent); + color: #ffffff; + border-color: var(--accent); +} + +.tip-btn.active { + background: var(--accent); + color: #ffffff; + border-color: var(--accent); +} + + +.results { + margin-top: 2rem; + background: rgba(0, 0, 0, 0.03); + padding: 1rem 1.25rem; + border-radius: 10px; + border: 1px solid var(--border); +} + +body.dark-mode .results { + background: rgba(255, 255, 255, 0.05); +} + +.results h3 { + margin-bottom: 0.75rem; + font-size: 1.1rem; + display: flex; + justify-content: space-between; + align-items: center; + color: var(--text); +} + +.results span { + font-weight: bold; + color: var(--accent); +} + +/* Theme toggle */ +.theme-toggle { + background: var(--card); + border: 2px solid var(--border); + border-radius: 50%; + width: 45px; + height: 45px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: scale(1.1); +} + +.theme-toggle .sun-icon { + display: none; +} + +body.dark-mode .theme-toggle .sun-icon { + display: block; +} + +body.dark-mode .theme-toggle .moon-icon { + display: none; +} + +/* Responsive */ +@media (max-width: 768px) { + body { + padding: 1.5rem; + } + + .container { + margin-top: 1rem; + padding: 1.5rem; + } + + h1 { + font-size: 1.7rem; + } +} + +@media (max-width: 480px) { + .tip-buttons { + flex-direction: column; + } + + .tip-btn { + flex: 1 1 100%; + } + + .container { + padding: 1.25rem; + } + + h1 { + font-size: 1.5rem; + } +} +/* Remove (arrows that appear for input type number ( to inc and dec value) */ +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} \ No newline at end of file From 0519f6e78e82d5516258e9f58311893d6efd454a Mon Sep 17 00:00:00 2001 From: Suvansh Tembe Date: Fri, 24 Oct 2025 01:26:52 +0530 Subject: [PATCH 2/2] added project-tip-calculator to projects.json --- data/projects.json | 441 +++++++++++++++++++++++---------------------- 1 file changed, 224 insertions(+), 217 deletions(-) diff --git a/data/projects.json b/data/projects.json index a39be6f..51370b2 100644 --- a/data/projects.json +++ b/data/projects.json @@ -1,219 +1,226 @@ [ - { - "title": "Snake Game", - "slug": "snake", - "description": "Classic snake with keyboard controls, speed levels, and scoring.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Memory Match", - "slug": "memory-match", - "description": "Flip cards to find pairs. Extend with themes and sounds.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Tic-Tac-Toe", - "slug": "tic-tac-toe", - "description": "Two-player tic-tac-toe. Extend with AI and themes.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Whack-a-Mole", - "slug": "whack-a-mole", - "description": "Click moles before they disappear. Add levels and effects.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Maze Solver", - "slug": "maze", - "description": "Generate a random maze and navigate through it.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "medium" - }, - { - "title": "Todo List", - "slug": "todo", - "description": "Task tracker with localStorage, sorting, and themes.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - }, - { - "title": "Notes App", - "slug": "notes", - "description": "Notes with categories, search, and dark mode.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - }, - { - "title": "Pomodoro Timer", - "slug": "pomodoro", - "description": "Pomodoro timer with notifications and custom intervals.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - }, - { - "title": "Expense Tracker", - "slug": "expense-tracker", - "description": "Track expenses and visualize charts in pure JS.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "medium" - }, - { - "title": "Markdown Editor", - "slug": "markdown", - "description": "Live Markdown editor and previewer.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "medium" - }, - { - "title": "Theme Switcher", - "slug": "theme-switcher", - "description": "Generate color palettes and apply themes.", - "category": "Fun UI / Visual", - "categoryKey": "visual", - "difficulty": "easy" - }, - { - "title": "Image Slider", - "slug": "image-slider", - "description": "Simple carousel with autoplay and responsive behavior.", - "category": "Fun UI / Visual", - "categoryKey": "visual", - "difficulty": "easy" - }, - { - "title": "Animated Clock", - "slug": "animated-clock", - "description": "Smooth clock using requestAnimationFrame.", - "category": "Fun UI / Visual", - "categoryKey": "visual", - "difficulty": "easy" - }, - { - "title": "Weather Widget", - "slug": "weather", - "description": "Fetch weather from a public API and update UI dynamically.", - "category": "Fun UI / Visual", - "categoryKey": "visual", - "difficulty": "medium" - }, - { - "title": "Typing Speed Test", - "slug": "typing-test", - "description": "Measure typing speed and accuracy.", - "category": "Fun UI / Visual", - "categoryKey": "visual", - "difficulty": "medium" - }, - { - "title": "Quiz App", - "slug": "quiz", - "description": "Multiple-choice trivia with score tracking.", - "category": "Mini Data", - "categoryKey": "data", - "difficulty": "easy" - }, - { - "title": "Currency Converter", - "slug": "currency", - "description": "Offline rate-based converter with local overrides.", - "category": "Mini Data", - "categoryKey": "data", - "difficulty": "easy" - }, - { - "title": "BMI Calculator", - "slug": "bmi", - "description": "Compute BMI with validation and simple history.", - "category": "Mini Data", - "categoryKey": "data", - "difficulty": "easy" - } - , - { - "title": "Number Guessing Game", - "slug": "number-guessing-game", - "description": "Guess a random number with feedback and attempt tracking.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Text Encryption / Decryption Tool", - "slug": "text-encryption-decryption", - "description": "Encrypt and decrypt text using simple algorithms.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - }, - { - "title": "Rock-Paper-Scissors Game", - "slug": "rock-paper-scissors", - "description": "Play rock-paper-scissors against the computer with score tracking.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "QR Code Generator & Scanner", - "slug": "qr-code-generator-scanner", - "description": "Generate and scan QR codes from text or images.", - "category": "Mini Data", - "categoryKey": "data", - "difficulty": "medium" - }, - { - "title": "Quiz", - "slug": "quiz", - "description": "A dynamic quiz app using Open Trivia API with a timer and scoring.", - "category": "Fun UI", - "categoryKey": "fun", - "difficulty": "intermediate" - }, - { - "title": "2048", - "slug": "game-2048", - "description": "Simple game with powers of 2.", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "intermediate" - }, - { - "title": "Password Generator", - "slug": "password-generator", - "description": "Generate secure passwords with customizable options.", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - }, - { - "title": "Simon Says", - "slug": "simon-says", - "description": "Play Simon Says", - "category": "Small Games", - "categoryKey": "games", - "difficulty": "easy" - }, - { - "title": "Tip Calculator", - "slug": "Tip Calculator", - "description": "Calculate tips and divide bills accurately in seconds", - "category": "Productivity", - "categoryKey": "productivity", - "difficulty": "easy" - } + { + "title": "Snake Game", + "slug": "snake", + "description": "Classic snake with keyboard controls, speed levels, and scoring.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Memory Match", + "slug": "memory-match", + "description": "Flip cards to find pairs. Extend with themes and sounds.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Tic-Tac-Toe", + "slug": "tic-tac-toe", + "description": "Two-player tic-tac-toe. Extend with AI and themes.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Whack-a-Mole", + "slug": "whack-a-mole", + "description": "Click moles before they disappear. Add levels and effects.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Maze Solver", + "slug": "maze", + "description": "Generate a random maze and navigate through it.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "medium" + }, + { + "title": "Todo List", + "slug": "todo", + "description": "Task tracker with localStorage, sorting, and themes.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + }, + { + "title": "Notes App", + "slug": "notes", + "description": "Notes with categories, search, and dark mode.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + }, + { + "title": "Pomodoro Timer", + "slug": "pomodoro", + "description": "Pomodoro timer with notifications and custom intervals.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + }, + { + "title": "Expense Tracker", + "slug": "expense-tracker", + "description": "Track expenses and visualize charts in pure JS.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "medium" + }, + { + "title": "Markdown Editor", + "slug": "markdown", + "description": "Live Markdown editor and previewer.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "medium" + }, + { + "title": "Theme Switcher", + "slug": "theme-switcher", + "description": "Generate color palettes and apply themes.", + "category": "Fun UI / Visual", + "categoryKey": "visual", + "difficulty": "easy" + }, + { + "title": "Image Slider", + "slug": "image-slider", + "description": "Simple carousel with autoplay and responsive behavior.", + "category": "Fun UI / Visual", + "categoryKey": "visual", + "difficulty": "easy" + }, + { + "title": "Animated Clock", + "slug": "animated-clock", + "description": "Smooth clock using requestAnimationFrame.", + "category": "Fun UI / Visual", + "categoryKey": "visual", + "difficulty": "easy" + }, + { + "title": "Weather Widget", + "slug": "weather", + "description": "Fetch weather from a public API and update UI dynamically.", + "category": "Fun UI / Visual", + "categoryKey": "visual", + "difficulty": "medium" + }, + { + "title": "Typing Speed Test", + "slug": "typing-test", + "description": "Measure typing speed and accuracy.", + "category": "Fun UI / Visual", + "categoryKey": "visual", + "difficulty": "medium" + }, + { + "title": "Quiz App", + "slug": "quiz", + "description": "Multiple-choice trivia with score tracking.", + "category": "Mini Data", + "categoryKey": "data", + "difficulty": "easy" + }, + { + "title": "Currency Converter", + "slug": "currency", + "description": "Offline rate-based converter with local overrides.", + "category": "Mini Data", + "categoryKey": "data", + "difficulty": "easy" + }, + { + "title": "BMI Calculator", + "slug": "bmi", + "description": "Compute BMI with validation and simple history.", + "category": "Mini Data", + "categoryKey": "data", + "difficulty": "easy" + }, + { + "title": "Number Guessing Game", + "slug": "number-guessing-game", + "description": "Guess a random number with feedback and attempt tracking.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Text Encryption / Decryption Tool", + "slug": "text-encryption-decryption", + "description": "Encrypt and decrypt text using simple algorithms.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + }, + { + "title": "Rock-Paper-Scissors Game", + "slug": "rock-paper-scissors", + "description": "Play rock-paper-scissors against the computer with score tracking.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "QR Code Generator & Scanner", + "slug": "qr-code-generator-scanner", + "description": "Generate and scan QR codes from text or images.", + "category": "Mini Data", + "categoryKey": "data", + "difficulty": "medium" + }, + { + "title": "Quiz", + "slug": "quiz", + "description": "A dynamic quiz app using Open Trivia API with a timer and scoring.", + "category": "Fun UI", + "categoryKey": "fun", + "difficulty": "intermediate" + }, + { + "title": "2048", + "slug": "game-2048", + "description": "Simple game with powers of 2.", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "intermediate" + }, + { + "title": "Password Generator", + "slug": "password-generator", + "description": "Generate secure passwords with customizable options.", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + }, + { + "title": "Simon Says", + "slug": "simon-says", + "description": "Play Simon Says", + "category": "Small Games", + "categoryKey": "games", + "difficulty": "easy" + }, + { + "title": "Contributors Page", + "slug": "contributor", + "description": "See the contributions of people", + "category": "contributor", + "categoryKey": "contributor", + "difficulty": "easy" + }, + { + "title": "Tip Calculator", + "slug": "Tip Calculator", + "description": "Calculate tips and divide bills accurately in seconds", + "category": "Productivity", + "categoryKey": "productivity", + "difficulty": "easy" + } ]