diff --git a/Saurabh-1785/README.md b/Saurabh-1785/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/Saurabh-1785/assets/css.png b/Saurabh-1785/assets/css.png new file mode 100644 index 000000000..626e620df Binary files /dev/null and b/Saurabh-1785/assets/css.png differ diff --git a/Saurabh-1785/assets/html.png b/Saurabh-1785/assets/html.png new file mode 100644 index 000000000..0f5ea8892 Binary files /dev/null and b/Saurabh-1785/assets/html.png differ diff --git a/Saurabh-1785/assets/js.png b/Saurabh-1785/assets/js.png new file mode 100644 index 000000000..22c812007 Binary files /dev/null and b/Saurabh-1785/assets/js.png differ diff --git a/Saurabh-1785/assets/main.png b/Saurabh-1785/assets/main.png new file mode 100644 index 000000000..ecb071c06 Binary files /dev/null and b/Saurabh-1785/assets/main.png differ diff --git a/Saurabh-1785/index.html b/Saurabh-1785/index.html new file mode 100644 index 000000000..142192452 --- /dev/null +++ b/Saurabh-1785/index.html @@ -0,0 +1,89 @@ + + + + + + INTERACTIVE TIP CALCULATOR + + + + +
+

Interactive Tip Calculator

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

Select Tip Percentage

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

Tip Amount

+ / person + +
+ +
+ + ₹ 0.00 +
+ +
+ +
+ +
+ +

Total

+ / person + +
+ +
+ + ₹ 0.00 + +
+ +
+ + + +
+ +
+ + + + \ No newline at end of file diff --git a/Saurabh-1785/script.js b/Saurabh-1785/script.js new file mode 100644 index 000000000..2f3dc771d --- /dev/null +++ b/Saurabh-1785/script.js @@ -0,0 +1,202 @@ +const billInput = document.getElementById('bill'); + +const tipButtons = document.querySelectorAll('.tip-percent-btn'); + +const customTipInput = document.getElementById('custom-tip'); + +const peopleInput = document.getElementById('num-people'); + +const tipAmountDisplay = document.getElementById('tip-amount-display'); + +const totalAmountDisplay = document.getElementById('total-amount-display'); + +const resetButton = document.getElementById('reset-button'); + +//Event Listeners + +billInput.addEventListener('input', calculateTip); + +tipButtons.forEach((button) => { + button.addEventListener('click', (event) =>{ + const clickedButton = event.target; + const tipPercentage = clickedButton.dataset.tip; + tipButtons.forEach(btn => btn.classList.remove('active')); + clickedButton.classList.add('active'); + customTipInput.value = ''; + calculateTip(); + }); +}); + +customTipInput.addEventListener('input', () => { + tipButtons.forEach(btn => btn.classList.remove('active')); + + calculateTip(); + +}); + +peopleInput.addEventListener('input', calculateTip); + +resetButton.addEventListener('click',resetCalculator); + + + +//FUNCTION FOR CALCULATION LOGIC + +function calculateTip() { + + + // --- 1. Retrieve Input Values (Strings) --- + const billValueStr = billInput.value; //stores in string type + const peopleValueStr = peopleInput.value; + const customTipValueStr = customTipInput.value; + let selectedButtonTipStr = null; + const activeButton = document.querySelector('.tip-percent-btn.active'); + + if (activeButton) { + selectedButtonTipStr = activeButton.dataset.tip; + } + + // --- 2. Convert to Numbers --- + const billAmount = parseFloat(billValueStr); + const numberOfPeople = parseFloat(peopleValueStr); + const customTipPercent = parseFloat(customTipValueStr); + // Convert selected button tip only if a button is actually active (selectedButtonTipStr is not null) + const selectedButtonTipPercent = selectedButtonTipStr ? parseFloat(selectedButtonTipStr) : null; + //if selectedButtonTipStr is not null(its active), it will convert the string to number, else it will asssign selectedButtonTipPercent=null + + + // --- 3. INPUT VALIDATION SECTION --- + + // Check if billAmount is a valid number AND is not negative. + const isBillValid = !isNaN(billAmount) && billAmount >= 0; + + let isTipValid = false; // Placeholder + + const isPeopleValid = !isNaN(numberOfPeople) && numberOfPeople > 0 && Number.isInteger(numberOfPeople); + + const isCustomTipInputValid = customTipValueStr === '' || (!isNaN(customTipPercent) && customTipPercent >= 0); + + + + // --- 4. Determine Tip Percentage to Use --- + let actualTipPercent = 0; + + if (customTipValueStr !== '' && !isNaN(customTipPercent) && customTipPercent >= 0) { // Prioritize valid custom input + actualTipPercent = customTipPercent; + } else if (customTipValueStr === '') { // If custom input is empty, check buttons + const activeButton = document.querySelector('.tip-percent-btn.active'); + if (activeButton) { + const selectedButtonTipPercent = parseFloat(activeButton.dataset.tip); + if (!isNaN(selectedButtonTipPercent) && selectedButtonTipPercent >= 0) { + actualTipPercent = selectedButtonTipPercent; + } + } + } + + isTipValid = !isNaN(actualTipPercent) && actualTipPercent >= 0; + + + // --- 5. Calculate Total Tip --- + let totalTipPercent = 0; + + if (!isNaN(billAmount) && billAmount >= 0) { + totalTipAmount = billAmount * (actualTipPercent / 100); + } + + // --- 6. Calculate Total Bill --- + let totalBillAmount = 0; + + if (isBillValid) { + totalBillAmount = billAmount + totalTipAmount; + } + + // --- 7. Calculate Per Person Amount (with Validation) --- + let tipAmountPerPerson = 0; + let totalAmountPerPerson = 0; + + + if (isBillValid && isTipValid && isPeopleValid) { + if (!isNaN(totalBillAmount)) { + tipAmountPerPerson = totalTipAmount / numberOfPeople; + totalAmountPerPerson = totalBillAmount / numberOfPeople; + }else { + tipAmountPerPerson = 0; + totalAmountPerPerson = 0; + } + } + + // --- 8. Format Results for Display --- + const formattedTipAmount = tipAmountPerPerson.toFixed(2); + const formattedTotalAmount = totalAmountPerPerson.toFixed(2); + const displayTipAmount = `\u20B9${formattedTipAmount}`; + const displayTotalAmount = `\u20B9${formattedTotalAmount}`; + + // --- 9. Update DOM Text Content --- + + tipAmountDisplay.textContent = displayTipAmount; + + totalAmountDisplay.textContent = displayTotalAmount; + + billInput.classList.toggle('error', !isBillValid); + + peopleInput.classList.toggle('error', !isPeopleValid); + + customTipInput.classList.toggle('error', !isCustomTipInputValid); + + +} + +function resetCalculator() { + + // 1. Set the value of the bill input to empty. + + billInput.value = ''; + + + // 2. Clear the custom tip input value. + + customTipInput.value = ''; + + + // 3. Deselect any active tip percentage buttons. + + if (tipButtons && tipButtons.length > 0) { + tipButtons.forEach(button => { + button.classList.remove('active'); + }); + } + + // 4. Set the value of the number of people input to empty. + + peopleInput.value = ''; + + + // 5. Reset the text content of the tip amount/person display to '0.00'. + if (tipAmountDisplay) { + tipAmountDisplay.textContent = '\u20B9 0.00'; + } + + // 6. Reset the text content of the total/person display to '0.00'. + if (totalAmountDisplay) { + totalAmountDisplay.textContent = '\u20B9 0.00'; + } + + // 7. Remove any validation error styling from input fields. + + if (billInput) { + billInput.classList.remove('error'); + } + if (customTipInput) { + customTipInput.classList.remove('error'); + } + if (peopleInput) { + peopleInput.classList.remove('error'); + } + +} + + +document.addEventListener('DOMContentLoaded', () =>{ + calculateTip() +}); +//It runs your code as soon as the DOM (all HTML elements) is ready to be accessed. \ No newline at end of file diff --git a/Saurabh-1785/style.css b/Saurabh-1785/style.css new file mode 100644 index 000000000..cf20196b6 --- /dev/null +++ b/Saurabh-1785/style.css @@ -0,0 +1,237 @@ +body{ + background-color: #a5d8a6; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /*for different os, default size*/ + color: #003400; + line-height: 1.6; + margin: 0; +} + +header h1{ + display: flex; + justify-content: center; + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + font-size: clamp(20px, 4vw, 50px); +} + +.calculator-container { + background-color: #FFFFFF; + padding: 32px; + border-radius: 15px; + max-width: 800px; + width: 90%; + /* + For viewports narrower than what max-width would allow (effectively, viewports narrower than 800px / 0.90 = ~889px), the calculator will take up 90% of the available width. This ensures it scales down gracefully on smaller screens and doesn't touch the edges of the viewport immediately. + */ + margin: 50px auto; + box-shadow: 10px 15px 50px rgba(4, 52, 15, 0.4); + /* x y blur color*/ + box-sizing: border-box; + display: flex; + gap: 30px; +} + +.input-section, +.output-section{ + flex: 1; +} + +.input-field{ + width: 100%; + padding: 10px 12px; + margin: 0 0 16px 0; /*top right bottom left*/ + border: 1px solid #098f07; + border-radius: 4px; + font-size: 1rem; /* 1rem usually matches body font size */ + background-color: #fff; + box-sizing: border-box; + +} + +label, +.form-control p{ + display: block; + font-size: 1rem;/* Makes labels slightly smaller than input text (1rem) */ + font-weight: 600; + color: #095d16; + margin-bottom: 10px; + +} + +.tip-buttons-container{ + display: grid; + grid-template-columns: repeat(3,1fr); + gap: 10px; + margin-bottom: 16px; +} + +.tip-percent-btn{ + padding: 10px; + /* width: 100%; */ + background-color: #003400; + color: #fff; + border: none; + border-radius: 4px; + font-size: 1.1rem; /* Slightly larger font size for button text */ + font-weight: 700; + text-align: center; + cursor: pointer; + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;/* [Property to animate] [duration] [type], [another prop] .... */ + +} + +.tip-percent-btn:hover{ + background-color: #a5d8a6; + color: #003400; + transform: translateY(-2px)scale(1.05); +} + +.tip-percent-btn.active { /*target button which is active in javascript*/ + background-color: #a5d8a6; + color: #0a5e03; +} + +#custom-tip { + padding: 10px; + border: 1px solid #00474b; + border-radius: 4px; + font-size: 1rem; + font-weight: 700; + text-align: center; + cursor: pointer; +} + +.output-section{ + background-color: #003400; + padding: 30px 25px; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 20px; + +} + +.result-line{ + display: flex; + justify-content: space-between; + align-items: center; +} + +.result-label p{ + color: #ffffff; + font-size: 1rem; + margin: 0; + font-weight: 600; + +} + +.result-label span{ + color: #7fa8a9; + font-size: 1rem; + display: block; +} + +.result-value span { + color: #a5d8a6; + font-size: 2.2rem; + font-weight: 700; + /* display: block; */ + text-align: right; +} + +.reset-btn { + + width: 100%; + padding: 12px; + background-color: #a5d8a6; + color: #003400; + border: none; + border-radius: 4px; + font-size: 1.1rem; + font-weight: 700; + text-transform: uppercase;/* Makes "RESET" text more prominent and command-like */ + text-align: center; + cursor: pointer; + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; +} + +.reset-btn:hover { + background-color: #ffffff; + color: #00474B; +} + +.reset-btn:active { + background-color: #003400; + color: #a5d8a6; +} + + +@media screen and (max-width: 600px) { + + .calculator-container { + flex-direction: column; + align-items: stretch; + padding: 15px; + } + + .inputs-section, + .outputs-section { + width: 100%; + margin-left: 0; + margin-right: 0; + margin-bottom: 20px; + } + .outputs-section { + margin-bottom: 0; + } + + .input-label { + font-size: 0.875rem; + margin-bottom: 6px; + } + + input[type="number"]#bill-input, + input[type="number"]#custom-tip-input, + input[type="number"]#people-input { + font-size: 1rem; + padding: 10px 12px; + } + + .input-field-group { + margin-bottom: 16px; + } + + .tip-percent-btn { + font-size: 0.9rem; + padding: 10px 8px; + } + + .output-description .per-person-label { + font-size: 0.8rem; + } + + label { + font-size: 0.9rem; + } + + #reset-button { + font-size: 1rem; + padding: 10px; + width: 100%; + margin-top: 20px; + } + + .result-value, + #tip-amount-display, + #total-amount-display { + font-size: 1.75rem; + } + + .input-group { + margin-bottom: 15px; + } + + .output-label { + font-size: 0.85rem; + } +} \ No newline at end of file