From 582a50ab194e6c9b5464e363da698580861d03c4 Mon Sep 17 00:00:00 2001 From: Gabe Date: Mon, 6 Nov 2023 00:16:09 +0000 Subject: [PATCH] Version 1 done --- index.css | 43 ++++++++++++- index.html | 14 +++- main.js | 186 ++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 208 insertions(+), 35 deletions(-) diff --git a/index.css b/index.css index 0437da5..48ea7a6 100644 --- a/index.css +++ b/index.css @@ -8,6 +8,7 @@ --brown-light: #52391e; --blue: #05213f; --red: #EF3E36; + --red-dark: #d73831; --green: #08670a; --green-light: #217623; --purple: #750973; @@ -93,7 +94,7 @@ button:hover { color: var(--green); } -.subscriptions { +#subscriptions { width: 400px; } @@ -109,6 +110,7 @@ button:hover { } .no-subs-text { + color: var(--text-light); font-style: italic; font-size: 16px; text-align: center; @@ -117,6 +119,10 @@ button:hover { .sub-item-container:nth-child(odd) { background-color: white; } +.sub-item-container { + overflow-x:hidden; + position: relative; +} .sub-item { width: 350px; @@ -126,6 +132,21 @@ button:hover { margin: auto; } +.del-sub-button { + background-color: var(--red); + color: var(--main-bg); + border: none; + height: 100%; + width: 40px; + border-radius: 0px; + position: absolute; + right: -40px; + top: 0px; +} +.del-sub-button:hover { + background-color: var(--red-dark); +} + #add-sub-form * { margin: 5px 0px; } @@ -158,6 +179,9 @@ input:focus { #subPrice { width: 55px; } +#subName { + width: 200px; +} .ui-autocomplete { background-color: white; @@ -169,7 +193,7 @@ input:focus { padding: 0px; } .ui-autocomplete li { - padding: 10px 25px; + padding: 10px 0px 8px 25px; } .ui-autocomplete li:hover { cursor: pointer; @@ -179,4 +203,19 @@ input:focus { .error { border: 2px solid var(--red); +} + +.footer { + position: fixed; + bottom: 0px; + text-align: center; + font-size: 14px; + color: var(--text-light); + margin-bottom: 25px; + left: 50%; + transform: translate(-50%, 0); +} +.footer a { + font-style: italic; + color: inherit; } \ No newline at end of file diff --git a/index.html b/index.html index e919010..30958cb 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ @@ -21,6 +21,11 @@
+
+ So often you see in ads that their subscription is just the price of a coffee a week + or something similar. So just how many coffees a day are you really spending on all these + subscriptions? +

Cost in Coffee

See the true cost of your subscriptions in terms of cups of coffee a day.

@@ -31,7 +36,7 @@

cups of coffee a day.

That's $0.00 of coffee.

-
+

Your Subscriptions

@@ -47,6 +52,11 @@
+ + \ No newline at end of file diff --git a/main.js b/main.js index 1d218b0..2b4f64f 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,13 @@ +/* +* TODO: +* - (maybe) include coffee price somewhere +* - (maybe) coffee price selector +*/ + /********* CONSTANTS AND GLOBAL VARS *********/ + +// List of subscription services I can think of, for the +// form to auto-fill const SubList = [ 'LinkedIn Premium', 'Netflix', @@ -6,31 +15,106 @@ const SubList = [ 'Crunchyroll', 'Youtube Premium', 'Skillshare', + 'Max', + 'Spotify', + 'Tidal', + 'Paramount+', + 'Peacock', + 'Disney+', + 'Amazon Prime', + 'Audible', + 'Scribd', + 'Apple TV+', + 'Curiosity Stream', + 'Kindle Unlimited' ] +// list of prices to be auto-suggested in the form +const PriceList = [ + '$5', + '$10', + '$12', + '$15', + '$20', + '$40', +] + +// array of current subscriptions let subscriptions = [] +// pretty much just for IDing the HTML in the sub list. dunno why its global tbh let numSubs = 0 +// matches $40.00, 40.00, 40, but not €40, 4.000, 4., 50c, etc. const pricePattern = /^(\$)?(\d+(\.\d{1,2})?)$/ +// these two are for calculating the cost in coffee const avgDaysInMonth = 30.475 let costOfCoffee = 2.50 +// total cost of all the user's subscriptions let costTotal = 0 +// for opening/closing form let addFormOpen = false -const PriceList = [ - '$5', - '$10', - '$12', - '$15', - '$20' -] - /***************** FUNCTION DEFINITIONS **************/ +// rebuilds the sub list after one gets removed +// if we dont do this, the IDs in the HTML that we use for removing +// items starts to drift from the actual JS array +function updateSubList() { + numSubs = 0 + console.log('rebuilding sub list...') + for (let sub of subscriptions) { + // add subscription to page + $('#addSubFormContainer').after(` +
+
+

${sub.name}

+

${formatPrice(sub.price)}

+
+
`) + numSubs++ + } +} + +// handler for form +function addSubFormHandler() { + if (!validatePrice()) { + // disallow submit + console.log('nope') + return + } + + let price = processSubValue() + + addSubscription($('#subName').val(), price) + + subscriptions.push({ + name: $('#subName').val(), + price: price, + }) + localStorage.setItem('subscriptions', JSON.stringify(subscriptions)) + + $('#subPrice').val('') + $('#subName').val('') + + $('#addSubFormContainer').hide() + addFormOpen = !addFormOpen +} + +// updates the coffee and price displays +function updateDisplay() { + // update display + let dailyCost = costTotal / avgDaysInMonth + $('#cost-display').text(`${formatPrice(dailyCost)}`) + $('#coffee-count').text(`${(dailyCost / costOfCoffee).toFixed(2)}`) +} + +// handles logic for adding a new subscription +// note: not just UI logic, also updating total costs etc. function addSubscription(name, price) { + // make sure no sub text is hidden $('.no-subs-text').hide() - // inc. sub count - numSubs++ + + // add subscription to page $('#addSubFormContainer').after(`
@@ -38,14 +122,36 @@ function addSubscription(name, price) {

${formatPrice(price)}

`) + + // inc. sub count + numSubs++ + costTotal += price + updateDisplay() +} +// handles logic for removing a subscription +// note: not just UI logic, also updating total costs etc. +function removeSubscription(index) { + // get price from sub array + let price = subscriptions[index].price + // remove sub from array + subscriptions.splice(index, 1) + // if no subs are left, show no-sub text + if (subscriptions.length == 0) { + $('.no-subs-text').show() + } + // remove sub from localstorage + localStorage.setItem('subscriptions', JSON.stringify(subscriptions)) + // remove sub from ui + $(`#subscription-${index}`).remove() + // subtract price from totalcost + costTotal -= price // update display - let dailyCost = costTotal / avgDaysInMonth - $('#cost-display').text(`${formatPrice(dailyCost)}`) - $('#coffee-count').text(`${(dailyCost / costOfCoffee).toFixed(2)}`) + updateDisplay() } +// takes sub cost from form and returns it as an actual number function processSubValue() { let priceString = $('#subPrice').val() if (priceString[0] == '$') { @@ -54,10 +160,12 @@ function processSubValue() { return Number(priceString) } +// takes number and returns it as $X.XX string function formatPrice(num) { return '$' + (Math.round(num * 100) / 100).toFixed(2) } +// checks cost in form against regex, updates UI for error function validatePrice() { let priceString = $('#subPrice').val() if (!priceString.match(pricePattern)) { @@ -85,8 +193,12 @@ if (localStorage.getItem('subscriptions') != null) { $('#addSubButton').click(() => { if (!addFormOpen) { + $('#addSubButton').css('background-color', 'var(--brown)') + $('#addSubButton').css('color', 'var(--main-bg)') $('#addSubFormContainer').show() } else { + $('#addSubButton').css('background-color', '') + $('#addSubButton').css('color', '') $('#addSubFormContainer').hide() } addFormOpen = !addFormOpen @@ -95,13 +207,14 @@ $('#addSubButton').click(() => { $('#subName').autocomplete({ source: SubList, delay: 0, - minLength: 0, + autoFocus: true, }) $('#subPrice').autocomplete({ source: PriceList, delay: 0, minLength: 0, + autoFocus: true, }) $('#subPrice').on('focus', () => { @@ -109,25 +222,36 @@ $('#subPrice').on('focus', () => { }) $('#confirmSubButton').click(() => { - if (!validatePrice()) { - // disallow submit - console.log('nope') - return - } + addSubFormHandler() +}) - let price = processSubValue() - - addSubscription($('#subName').val(), price) +$('#add-sub-form').keypress((e) => { + if (e.which == 13) { + addSubFormHandler() + return false + } +}) - subscriptions.push({ - name: $('#subName').val(), - price: price, +// these two are UI logic for the remove subscription button +$('#subscriptions').on('mouseenter', '.sub-item-container', function() { + $(this).append(``); + $(`#${$(this).attr('id') + '-del'}`).animate({ + left: "-=40", + }, 200, function() { }) - localStorage.setItem('subscriptions', JSON.stringify(subscriptions)) - - $('#subPrice').val('') - $('#subName').val('') +}) +$('#subscriptions').on('mouseleave', '.sub-item-container', function() { + $(`#${$(this).attr('id') + '-del'}`).animate({ + left: "+=40", + }, 200, function() { + $(`#${$(this).attr('id') + '-del'}`).remove() + }) +}) - $('#addSubFormContainer').hide() - addFormOpen = !addFormOpen +$('#subscriptions').on('click', '.del-sub-button', function() { + // get index of sub to delete + let subIndex = $(this).attr('id').split('-')[1] + removeSubscription(subIndex) + $('.sub-item-container').remove() + updateSubList() })