├── README.md ├── budget.js ├── chart.js ├── font ├── Gilroy-Bold.woff └── Gilroy-Regular.woff ├── full projects files ├── budget.js ├── chart.js ├── font │ ├── Gilroy-Bold.woff │ └── Gilroy-Regular.woff ├── icon │ ├── edit.png │ ├── plus.png │ └── trash.png ├── index.html └── style.css ├── icon ├── edit.png ├── plus.png └── trash.png ├── index.html └── style.css /README.md: -------------------------------------------------------------------------------- 1 | # Budget-App-JavaScript 2 | 3 | ​ @Code Explained Says Hi 4 | 5 | Today's project is the " Budget App" with vanilla JavaScript. 6 | 7 | In this tutorial, a JavaScript beginner can be able to create a beautiful and functional budget app using JavaScript. 8 | I will talk about the logic behind every line of code, before opening my text editor and start typing the code. 9 | it's a step by step tutorial, you won't get lost at any stage of this tutorial. 10 | 11 | Our app shows, the balance, the income and the outcome. it also has a dashboard where the user can add a new entry (an income or an expense), he can toggle between the income list (that show only all income entries) and the expenses list (that shows only the outcome entries) and all list that shows all the entries. 12 | The user can edit or delete an entry. 13 | Our app has a chart, so the user can easily compare the income and outcome. 14 | 15 | The user's income and expense entry list is stored in the local storage, so when he refreshes the page, or reboot his machine, he can always find his data there. 16 | 17 | to follow the tutorial step by step, when we get to the second part (when we type the code), you'll need to download the starter template. 18 | 19 | And then you can follow the tutorial on Youtube: https://youtu.be/SQbCwfGC7EM 20 | 21 | When you open the folder, you'll find all the files needed to get started, the CSS code is already typed (see style.css file), as we're not going to talk about CSS in our tutorial. we're going just to talk about HTML and JavaScript. 22 | -------------------------------------------------------------------------------- /budget.js: -------------------------------------------------------------------------------- 1 | /* www.youtube.com/CodeExplained */ -------------------------------------------------------------------------------- /chart.js: -------------------------------------------------------------------------------- 1 | /* www.youtube.com/CodeExplained */ -------------------------------------------------------------------------------- /font/Gilroy-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/font/Gilroy-Bold.woff -------------------------------------------------------------------------------- /font/Gilroy-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/font/Gilroy-Regular.woff -------------------------------------------------------------------------------- /full projects files/budget.js: -------------------------------------------------------------------------------- 1 | /* www.youtube.com/CodeExplained */ 2 | 3 | // SELECT ELEMENTS 4 | const balanceEl = document.querySelector(".balance .value"); 5 | const incomeTotalEl = document.querySelector(".income-total"); 6 | const outcomeTotalEl = document.querySelector(".outcome-total"); 7 | const incomeEl = document.querySelector("#income"); 8 | const expenseEl = document.querySelector("#expense"); 9 | const allEl = document.querySelector("#all"); 10 | const incomeList = document.querySelector("#income .list"); 11 | const expenseList = document.querySelector("#expense .list"); 12 | const allList = document.querySelector("#all .list"); 13 | 14 | // SELECT BTNS 15 | const expenseBtn = document.querySelector(".tab1"); 16 | const incomeBtn = document.querySelector(".tab2"); 17 | const allBtn = document.querySelector(".tab3"); 18 | 19 | // INPUT BTS 20 | const addExpense = document.querySelector(".add-expense"); 21 | const expenseTitle = document.getElementById("expense-title-input"); 22 | const expenseAmount = document.getElementById("expense-amount-input"); 23 | 24 | const addIncome = document.querySelector(".add-income"); 25 | const incomeTitle = document.getElementById("income-title-input"); 26 | const incomeAmount = document.getElementById("income-amount-input"); 27 | 28 | // VARIABLES 29 | let ENTRY_LIST; 30 | let balance = 0, income = 0, outcome = 0; 31 | const DELETE = "delete", EDIT = "edit"; 32 | 33 | // LOOK IF THERE IS SAVED DATA IN LOCALSTORAGE 34 | ENTRY_LIST = JSON.parse(localStorage.getItem("entry_list")) || []; 35 | updateUI(); 36 | 37 | // EVENT LISTENERS 38 | expenseBtn.addEventListener("click", function(){ 39 | show(expenseEl); 40 | hide( [incomeEl, allEl] ); 41 | active( expenseBtn ); 42 | inactive( [incomeBtn, allBtn] ); 43 | }) 44 | incomeBtn.addEventListener("click", function(){ 45 | show(incomeEl); 46 | hide( [expenseEl, allEl] ); 47 | active( incomeBtn ); 48 | inactive( [expenseBtn, allBtn] ); 49 | }) 50 | allBtn.addEventListener("click", function(){ 51 | show(allEl); 52 | hide( [incomeEl, expenseEl] ); 53 | active( allBtn ); 54 | inactive( [incomeBtn, expenseBtn] ); 55 | }) 56 | 57 | addExpense.addEventListener("click", function(){ 58 | // IF ONE OF THE INPUTS IS EMPTY => EXIT 59 | if(!expenseTitle.value || !expenseAmount.value ) return; 60 | 61 | // SAVE THE ENTRY TO ENTRY_LIST 62 | let expense = { 63 | type : "expense", 64 | title : expenseTitle.value, 65 | amount : parseInt(expenseAmount.value) 66 | } 67 | ENTRY_LIST.push(expense); 68 | 69 | updateUI(); 70 | clearInput( [expenseTitle, expenseAmount] ) 71 | }) 72 | 73 | addIncome.addEventListener("click", function(){ 74 | // IF ONE OF THE INPUTS IS EMPTY => EXIT 75 | if(!incomeTitle.value || !incomeAmount.value ) return; 76 | 77 | // SAVE THE ENTRY TO ENTRY_LIST 78 | let income = { 79 | type : "income", 80 | title : incomeTitle.value, 81 | amount : parseInt(incomeAmount.value) 82 | } 83 | ENTRY_LIST.push(income); 84 | 85 | updateUI(); 86 | clearInput( [incomeTitle, incomeAmount] ) 87 | }) 88 | 89 | incomeList.addEventListener("click", deleteOrEdit); 90 | expenseList.addEventListener("click", deleteOrEdit); 91 | allList.addEventListener("click", deleteOrEdit); 92 | 93 | // HELPERS 94 | 95 | function deleteOrEdit(event){ 96 | const targetBtn = event.target; 97 | 98 | const entry = targetBtn.parentNode; 99 | 100 | if( targetBtn.id == DELETE ){ 101 | deleteEntry(entry); 102 | }else if(targetBtn.id == EDIT ){ 103 | editEntry(entry); 104 | } 105 | } 106 | 107 | function deleteEntry(entry){ 108 | ENTRY_LIST.splice( entry.id, 1); 109 | 110 | updateUI(); 111 | } 112 | 113 | function editEntry(entry){ 114 | console.log(entry) 115 | let ENTRY = ENTRY_LIST[entry.id]; 116 | 117 | if(ENTRY.type == "income"){ 118 | incomeAmount.value = ENTRY.amount; 119 | incomeTitle.value = ENTRY.title; 120 | }else if(ENTRY.type == "expense"){ 121 | expenseAmount.value = ENTRY.amount; 122 | expenseTitle.value = ENTRY.title; 123 | } 124 | 125 | deleteEntry(entry); 126 | } 127 | 128 | function updateUI(){ 129 | income = calculateTotal("income", ENTRY_LIST); 130 | outcome = calculateTotal("expense", ENTRY_LIST); 131 | balance = Math.abs(calculateBalance(income, outcome)); 132 | 133 | // DETERMINE SIGN OF BALANCE 134 | let sign = (income >= outcome) ? "$" : "-$"; 135 | 136 | // UPDATE UI 137 | balanceEl.innerHTML = `${sign}${balance}`; 138 | outcomeTotalEl.innerHTML = `$${outcome}`; 139 | incomeTotalEl.innerHTML = `$${income}`; 140 | 141 | clearElement( [expenseList, incomeList, allList] ); 142 | 143 | ENTRY_LIST.forEach( (entry, index) => { 144 | if( entry.type == "expense" ){ 145 | showEntry(expenseList, entry.type, entry.title, entry.amount, index) 146 | }else if( entry.type == "income" ){ 147 | showEntry(incomeList, entry.type, entry.title, entry.amount, index) 148 | } 149 | showEntry(allList, entry.type, entry.title, entry.amount, index) 150 | }); 151 | 152 | updateChart(income, outcome); 153 | 154 | localStorage.setItem("entry_list", JSON.stringify(ENTRY_LIST)); 155 | } 156 | 157 | function showEntry(list, type, title, amount, id){ 158 | 159 | const entry = `
  • 160 |
    ${title}: $${amount}
    161 |
    162 |
    163 |
  • `; 164 | 165 | const position = "afterbegin"; 166 | 167 | list.insertAdjacentHTML(position, entry); 168 | } 169 | 170 | function clearElement(elements){ 171 | elements.forEach( element => { 172 | element.innerHTML = ""; 173 | }) 174 | } 175 | 176 | function calculateTotal(type, list){ 177 | let sum = 0; 178 | 179 | list.forEach( entry => { 180 | if( entry.type == type ){ 181 | sum += entry.amount; 182 | } 183 | }) 184 | 185 | return sum; 186 | } 187 | 188 | function calculateBalance(income, outcome){ 189 | return income - outcome; 190 | } 191 | 192 | function clearInput(inputs){ 193 | inputs.forEach( input => { 194 | input.value = ""; 195 | }) 196 | } 197 | function show(element){ 198 | element.classList.remove("hide"); 199 | } 200 | 201 | function hide( elements ){ 202 | elements.forEach( element => { 203 | element.classList.add("hide"); 204 | }) 205 | } 206 | 207 | function active(element){ 208 | element.classList.add("active"); 209 | } 210 | 211 | function inactive( elements ){ 212 | elements.forEach( element => { 213 | element.classList.remove("active"); 214 | }) 215 | } -------------------------------------------------------------------------------- /full projects files/chart.js: -------------------------------------------------------------------------------- 1 | /* www.youtube.com/CodeExplained */ 2 | 3 | // SELECT CHART ELEMENT 4 | const chart = document.querySelector(".chart"); 5 | 6 | // CREATE CANVAS ELEMMENT 7 | const canvas = document.createElement("canvas"); 8 | canvas.width = 50; 9 | canvas.height = 50; 10 | 11 | // APPEND CANVAS TO CHART ELEMENT 12 | chart.appendChild(canvas); 13 | 14 | // TO DRAW ON CANVAS, WE NEED TO GET CONTEXT OF CANVAS 15 | const ctx = canvas.getContext("2d"); 16 | 17 | // CHANGE THE LINE WIDTH 18 | ctx.lineWidth = 8; 19 | 20 | // CIRCLE RADIUS 21 | const R = 20; 22 | 23 | function drawCircle(color, ratio, anticlockwise){ 24 | 25 | ctx.strokeStyle = color; 26 | ctx.beginPath(); 27 | ctx.arc( canvas.width/2, canvas.height/2, R, 0, ratio * 2 * Math.PI, anticlockwise); 28 | ctx.stroke(); 29 | } 30 | 31 | function updateChart( income, outcome){ 32 | ctx.clearRect(0, 0, canvas.width, canvas.height); 33 | 34 | let ratio = income / (income+outcome); 35 | 36 | drawCircle("#FFFFFF", - ratio, true); 37 | drawCircle("#F0624D", 1 - ratio, false); 38 | } -------------------------------------------------------------------------------- /full projects files/font/Gilroy-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/full projects files/font/Gilroy-Bold.woff -------------------------------------------------------------------------------- /full projects files/font/Gilroy-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/full projects files/font/Gilroy-Regular.woff -------------------------------------------------------------------------------- /full projects files/icon/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/full projects files/icon/edit.png -------------------------------------------------------------------------------- /full projects files/icon/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/full projects files/icon/plus.png -------------------------------------------------------------------------------- /full projects files/icon/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/full projects files/icon/trash.png -------------------------------------------------------------------------------- /full projects files/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Budget App - JavaScript 8 | 9 | 10 | 11 |
    12 |
    13 | CodeExplained 14 |
    15 |
    16 |
    17 |
    18 | Balance 19 |
    20 |
    21 | $0 22 |
    23 |
    24 | 43 |
    44 |
    45 |
    Dashboard
    46 |
    47 |
    Expenses
    48 |
    Income
    49 |
    All
    50 |
    51 |
    52 |
      53 |
      54 | 55 | 56 |
      57 |
      58 |
      59 |
      60 |
        61 |
        62 | 63 | 64 |
        65 |
        66 |
        67 |
        68 |
          69 |
          70 |
          71 |
          72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /full projects files/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Gilroy'; 3 | src: url('font/Gilroy-Regular.woff') format('woff'); 4 | font-weight: bold; 5 | font-style: normal; 6 | } 7 | @font-face { 8 | font-family: 'Gilroy Bold'; 9 | src: url('font/Gilroy-Bold.woff') format('woff'); 10 | font-weight: bold; 11 | font-style: normal; 12 | } 13 | 14 | body{ 15 | background-color: #222; 16 | font-family: 'Gilroy'; 17 | } 18 | 19 | *{ 20 | font-family: 'Gilroy'; 21 | list-style: none; 22 | text-decoration: none; 23 | -webkit-user-select: none; 24 | -moz-user-select: none; 25 | -ms-user-select: none; 26 | user-select: none; 27 | } 28 | 29 | /* REMOVE SPINNERS FROM NUMBER INPUT */ 30 | /* Chrome, Safari, Edge, Opera */ 31 | input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { 32 | -webkit-appearance: none; 33 | margin: 0; 34 | } 35 | 36 | /* Firefox */ 37 | input[type=number] { 38 | -moz-appearance: textfield; 39 | } 40 | 41 | .budget-container{ 42 | position: absolute; 43 | width: 360px; 44 | height: 780px; 45 | top: 50%; 46 | left: 50%; 47 | transform: translateX(-50%) translateY(-50%); 48 | background-color: #34006a; 49 | } 50 | 51 | .budget-container .app-title{ 52 | margin-top: 45px; 53 | margin-left: 20px; 54 | } 55 | 56 | .budget-container .app-title a{ 57 | color: #FFF; 58 | } 59 | .budget-container .app-title a b{ 60 | font-family: 'Gilroy Bold'; 61 | } 62 | 63 | .budget-header{ 64 | 65 | } 66 | 67 | .budget-header .balance{ 68 | margin-top: 45px; 69 | margin-left: 20px; 70 | } 71 | 72 | .budget-header .balance .title{ 73 | color: #FFF; 74 | font-size: 1em; 75 | font-family: 'Gilroy Bold'; 76 | } 77 | 78 | .budget-header .balance .value{ 79 | color: #FFF; 80 | font-size: 2em; 81 | margin-top: 10px; 82 | font-family: 'Gilroy Bold'; 83 | } 84 | 85 | .budget-header .account{ 86 | display: block; 87 | width: 310px; 88 | margin: 35px auto 0; 89 | line-height: 1.7em; 90 | text-align: center; 91 | 92 | } 93 | 94 | .budget-header .account .income, .chart, .outcome{ 95 | height: 50px; 96 | display: inline-block; 97 | width: 100px; 98 | vertical-align: middle; 99 | } 100 | 101 | .budget-header .account .income .title{ 102 | color: #FFF; 103 | opacity: 0.5; 104 | } 105 | .budget-header .account .income .income-total{ 106 | color: #FFF; 107 | font-family: 'Gilroy Bold'; 108 | } 109 | 110 | .budget-header .account .outcome .title{ 111 | color: #FFF; 112 | opacity: 0.5; 113 | } 114 | .budget-header .account .outcome .outcome-total{ 115 | color: #f0624d; 116 | font-family: 'Gilroy Bold'; 117 | } 118 | 119 | /*///////////// DASHBOARD /////////////*/ 120 | .budget-dashboard{ 121 | display: block; 122 | width: 360px; 123 | height: 470px; 124 | background-color: #FFF; 125 | margin-top: 35px; 126 | border-radius: 30px 30px 0 0; 127 | } 128 | 129 | .budget-dashboard .dash-title{ 130 | display: inline-block; 131 | color: #1a0034; 132 | font-size: 1.7em; 133 | margin-left: 20px; 134 | margin-top: 30px; 135 | font-family: 'Gilroy Bold'; 136 | } 137 | 138 | .toggle{ 139 | display: block; 140 | margin-top: 30px; 141 | margin-left: 20px; 142 | } 143 | 144 | .toggle .tab1, .tab2, .tab3{ 145 | display: inline-block; 146 | cursor: pointer; 147 | font-size: 1.1em; 148 | color: #1a0034; 149 | font-family: 'Gilroy Bold'; 150 | opacity: 0.4; 151 | } 152 | 153 | .toggle .tab2, .tab3{ 154 | margin-left: 10px; 155 | } 156 | 157 | .active{ 158 | opacity : 1 !important; 159 | } 160 | 161 | .hide{ 162 | display: none; 163 | } 164 | 165 | .budget-dashboard input{ 166 | /* MAKE INPUT SELECTABLE */ 167 | -webkit-user-select: auto; 168 | -moz-user-select: auto; 169 | -ms-user-select: auto; 170 | user-select: auto; 171 | } 172 | 173 | /* ////////// ALL ///////////// */ 174 | .budget-dashboard #all{ 175 | width: 360px; 176 | height: 339px; 177 | position: relative; 178 | } 179 | .budget-dashboard #all ul{ 180 | width: 360px; 181 | height: 285px; 182 | list-style: none; 183 | margin: 0; 184 | padding: 0; 185 | margin-top:20px; 186 | overflow-x: auto; 187 | } 188 | 189 | .budget-dashboard #all ul.list li{ 190 | position: relative; 191 | font-size: 1em; 192 | } 193 | 194 | .budget-dashboard #all ul.list li *{ 195 | display: inline-block; 196 | height: 30px; 197 | vertical-align: middle; 198 | } 199 | 200 | .budget-dashboard #all ul.list li .entry{ 201 | width:250px; 202 | height: auto; 203 | padding-left: 20px; 204 | margin-bottom: 10px;; 205 | word-wrap: break-word; 206 | font-family: 'Gilroy Bold'; 207 | } 208 | 209 | .budget-dashboard #all ul.list li #edit{ 210 | visibility: hidden; 211 | } 212 | 213 | .budget-dashboard #all ul.list li #delete{ 214 | position: absolute; 215 | width:20px; 216 | height: 20px; 217 | right: 20px; 218 | cursor: pointer; 219 | background-image: url('icon/trash.png'); 220 | background-size: 20px 20px; 221 | background-repeat: no-repeat; 222 | } 223 | 224 | .budget-dashboard #all ul.list li.income{ 225 | 226 | } 227 | .budget-dashboard #all ul.list li.expense{ 228 | color: #f0624d; 229 | } 230 | 231 | /* //////// EXPENSE ////////// */ 232 | .budget-dashboard #expense{ 233 | width: 360px; 234 | height: 339px; 235 | position: relative; 236 | } 237 | 238 | .budget-dashboard #expense .input{ 239 | position: absolute; 240 | display: block; 241 | width: 360px; 242 | bottom: 0; 243 | border-top: 1px solid #ccc; 244 | } 245 | 246 | .budget-dashboard #expense .input *{ 247 | display: inline-block; 248 | vertical-align: middle; 249 | } 250 | 251 | .budget-dashboard #expense .input input#expense-title-input{ 252 | height: 40px; 253 | width : 150px; 254 | padding-left: 10px; 255 | font-size: 1.2em; 256 | font-family: 'Gilroy'; 257 | margin: 5px; 258 | margin-left: 10px; 259 | border-radius: 10px 0 0 10px; 260 | border: none; 261 | } 262 | 263 | .budget-dashboard #expense .input input#expense-amount-input{ 264 | height: 40px; 265 | width : 110px; 266 | padding-left: 10px; 267 | font-size: 1.2em; 268 | font-family: 'Gilroy'; 269 | margin: 5px; 270 | margin-left: -10px; 271 | border-radius: 0 10px 10px 0; 272 | border: none; 273 | } 274 | 275 | .budget-dashboard #expense .input .add-expense img{ 276 | width: 40px; 277 | height: 40px; 278 | cursor: pointer; 279 | } 280 | 281 | .budget-dashboard #expense ul{ 282 | width: 360px; 283 | height: 285px; 284 | list-style: none; 285 | margin: 0; 286 | padding: 0; 287 | margin-top:20px; 288 | overflow-x: auto; 289 | } 290 | 291 | .budget-dashboard #expense ul.list li{ 292 | position: relative; 293 | font-size: 1em; 294 | } 295 | 296 | .budget-dashboard #expense ul.list li *{ 297 | display: inline-block; 298 | height: 30px; 299 | vertical-align: middle; 300 | } 301 | 302 | .budget-dashboard #expense ul.list li .entry{ 303 | width:250px; 304 | height: auto; 305 | padding-left: 20px; 306 | margin-bottom: 10px;; 307 | word-wrap: break-word; 308 | font-family: 'Gilroy Bold'; 309 | color: #f0624d; 310 | } 311 | 312 | .budget-dashboard #expense ul.list li #edit{ 313 | position: absolute; 314 | width:20px; 315 | height: 20px; 316 | right: 50px; 317 | cursor: pointer; 318 | background-image: url("icon/edit.png"); 319 | background-size: 20px 20px; 320 | background-repeat: no-repeat; 321 | } 322 | 323 | .budget-dashboard #expense ul.list li #delete{ 324 | position: absolute; 325 | width:20px; 326 | height: 20px; 327 | right: 20px; 328 | cursor: pointer; 329 | background-image: url('icon/trash.png'); 330 | background-size: 20px 20px; 331 | background-repeat: no-repeat; 332 | } 333 | 334 | /* /////// INCOME //////// */ 335 | .budget-dashboard #income{ 336 | width: 360px; 337 | height: 339px; 338 | position: relative; 339 | } 340 | 341 | .budget-dashboard #income .input{ 342 | position: absolute; 343 | display: block; 344 | width: 360px; 345 | bottom: 0; 346 | border-top: 1px solid #ccc; 347 | } 348 | 349 | .budget-dashboard #income .input *{ 350 | display: inline-block; 351 | vertical-align: middle; 352 | } 353 | 354 | .budget-dashboard #income .input input#income-title-input{ 355 | height: 40px; 356 | width : 150px; 357 | padding-left: 10px; 358 | font-size: 1.2em; 359 | font-family: 'Gilroy'; 360 | margin: 5px; 361 | margin-left: 10px; 362 | border-radius: 10px 0 0 10px; 363 | border: none; 364 | } 365 | 366 | .budget-dashboard #income .input input#income-amount-input{ 367 | height: 40px; 368 | width : 110px; 369 | padding-left: 10px; 370 | font-size: 1.2em; 371 | font-family: 'Gilroy'; 372 | margin: 5px; 373 | margin-left: -10px; 374 | border-radius: 0 10px 10px 0; 375 | border: none; 376 | } 377 | 378 | .budget-dashboard #income .input .add-income img{ 379 | width: 40px; 380 | height: 40px; 381 | cursor: pointer; 382 | } 383 | 384 | .budget-dashboard #income ul{ 385 | width: 360px; 386 | height: 285px; 387 | list-style: none; 388 | margin: 0; 389 | padding: 0; 390 | margin-top:20px; 391 | overflow-x: auto; 392 | } 393 | 394 | .budget-dashboard #income ul.list li{ 395 | position: relative; 396 | font-size: 1em; 397 | } 398 | 399 | .budget-dashboard #income ul.list li *{ 400 | display: inline-block; 401 | height: 30px; 402 | vertical-align: middle; 403 | } 404 | 405 | .budget-dashboard #income ul.list li .entry{ 406 | width:250px; 407 | height: auto; 408 | padding-left: 20px; 409 | margin-bottom: 10px;; 410 | word-wrap: break-word; 411 | font-family: 'Gilroy Bold'; 412 | } 413 | 414 | .budget-dashboard #income ul.list li #edit{ 415 | position: absolute; 416 | width:20px; 417 | height: 20px; 418 | right: 50px; 419 | cursor: pointer; 420 | background-image: url("icon/edit.png"); 421 | background-size: 20px 20px; 422 | background-repeat: no-repeat; 423 | } 424 | 425 | .budget-dashboard #income ul.list li #delete{ 426 | position: absolute; 427 | width:20px; 428 | height: 20px; 429 | right: 20px; 430 | cursor: pointer; 431 | background-image: url('icon/trash.png'); 432 | background-size: 20px 20px; 433 | background-repeat: no-repeat; 434 | } -------------------------------------------------------------------------------- /icon/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/icon/edit.png -------------------------------------------------------------------------------- /icon/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/icon/plus.png -------------------------------------------------------------------------------- /icon/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Budget-App-JavaScript/b4087372367777b2bd495f2f635133b462b90a17/icon/trash.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Gilroy'; 3 | src: url('font/Gilroy-Regular.woff') format('woff'); 4 | font-weight: bold; 5 | font-style: normal; 6 | } 7 | @font-face { 8 | font-family: 'Gilroy Bold'; 9 | src: url('font/Gilroy-Bold.woff') format('woff'); 10 | font-weight: bold; 11 | font-style: normal; 12 | } 13 | 14 | body{ 15 | background-color: #222; 16 | font-family: 'Gilroy'; 17 | } 18 | 19 | *{ 20 | font-family: 'Gilroy'; 21 | list-style: none; 22 | text-decoration: none; 23 | -webkit-user-select: none; 24 | -moz-user-select: none; 25 | -ms-user-select: none; 26 | user-select: none; 27 | } 28 | 29 | /* REMOVE SPINNERS FROM NUMBER INPUT */ 30 | /* Chrome, Safari, Edge, Opera */ 31 | input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { 32 | -webkit-appearance: none; 33 | margin: 0; 34 | } 35 | 36 | /* Firefox */ 37 | input[type=number] { 38 | -moz-appearance: textfield; 39 | } 40 | 41 | .budget-container{ 42 | position: absolute; 43 | width: 360px; 44 | height: 780px; 45 | top: 50%; 46 | left: 50%; 47 | transform: translateX(-50%) translateY(-50%); 48 | background-color: #34006a; 49 | } 50 | 51 | .budget-container .app-title{ 52 | margin-top: 45px; 53 | margin-left: 20px; 54 | } 55 | 56 | .budget-container .app-title a{ 57 | color: #FFF; 58 | } 59 | .budget-container .app-title a b{ 60 | font-family: 'Gilroy Bold'; 61 | } 62 | 63 | .budget-header{ 64 | 65 | } 66 | 67 | .budget-header .balance{ 68 | margin-top: 45px; 69 | margin-left: 20px; 70 | } 71 | 72 | .budget-header .balance .title{ 73 | color: #FFF; 74 | font-size: 1em; 75 | font-family: 'Gilroy Bold'; 76 | } 77 | 78 | .budget-header .balance .value{ 79 | color: #FFF; 80 | font-size: 2em; 81 | margin-top: 10px; 82 | font-family: 'Gilroy Bold'; 83 | } 84 | 85 | .budget-header .account{ 86 | display: block; 87 | width: 310px; 88 | margin: 35px auto 0; 89 | line-height: 1.7em; 90 | text-align: center; 91 | 92 | } 93 | 94 | .budget-header .account .income, .chart, .outcome{ 95 | height: 50px; 96 | display: inline-block; 97 | width: 100px; 98 | vertical-align: middle; 99 | } 100 | 101 | .budget-header .account .income .title{ 102 | color: #FFF; 103 | opacity: 0.5; 104 | } 105 | .budget-header .account .income .income-total{ 106 | color: #FFF; 107 | font-family: 'Gilroy Bold'; 108 | } 109 | 110 | .budget-header .account .outcome .title{ 111 | color: #FFF; 112 | opacity: 0.5; 113 | } 114 | .budget-header .account .outcome .outcome-total{ 115 | color: #f0624d; 116 | font-family: 'Gilroy Bold'; 117 | } 118 | 119 | /*///////////// DASHBOARD /////////////*/ 120 | .budget-dashboard{ 121 | display: block; 122 | width: 360px; 123 | height: 470px; 124 | background-color: #FFF; 125 | margin-top: 35px; 126 | border-radius: 30px 30px 0 0; 127 | } 128 | 129 | .budget-dashboard .dash-title{ 130 | display: inline-block; 131 | color: #1a0034; 132 | font-size: 1.7em; 133 | margin-left: 20px; 134 | margin-top: 30px; 135 | font-family: 'Gilroy Bold'; 136 | } 137 | 138 | .toggle{ 139 | display: block; 140 | margin-top: 30px; 141 | margin-left: 20px; 142 | } 143 | 144 | .toggle .tab1, .tab2, .tab3{ 145 | display: inline-block; 146 | cursor: pointer; 147 | font-size: 1.1em; 148 | color: #1a0034; 149 | font-family: 'Gilroy Bold'; 150 | opacity: 0.4; 151 | } 152 | 153 | .toggle .tab2, .tab3{ 154 | margin-left: 10px; 155 | } 156 | 157 | .focus{ 158 | opacity : 1 !important; 159 | } 160 | 161 | .hide{ 162 | display: none; 163 | } 164 | 165 | .budget-dashboard input{ 166 | /* MAKE INPUT SELECTABLE */ 167 | -webkit-user-select: auto; 168 | -moz-user-select: auto; 169 | -ms-user-select: auto; 170 | user-select: auto; 171 | } 172 | 173 | /* ////////// ALL ///////////// */ 174 | .budget-dashboard #all{ 175 | width: 360px; 176 | height: 339px; 177 | position: relative; 178 | } 179 | .budget-dashboard #all ul{ 180 | width: 360px; 181 | height: 285px; 182 | list-style: none; 183 | margin: 0; 184 | padding: 0; 185 | margin-top:20px; 186 | overflow-x: auto; 187 | } 188 | 189 | .budget-dashboard #all ul.list li{ 190 | position: relative; 191 | font-size: 1em; 192 | } 193 | 194 | .budget-dashboard #all ul.list li *{ 195 | display: inline-block; 196 | height: 30px; 197 | vertical-align: middle; 198 | } 199 | 200 | .budget-dashboard #all ul.list li .entry{ 201 | width:250px; 202 | height: auto; 203 | padding-left: 20px; 204 | margin-bottom: 10px;; 205 | word-wrap: break-word; 206 | font-family: 'Gilroy Bold'; 207 | } 208 | 209 | .budget-dashboard #all ul.list li #edit{ 210 | visibility: hidden; 211 | } 212 | 213 | .budget-dashboard #all ul.list li #delete{ 214 | position: absolute; 215 | width:20px; 216 | height: 20px; 217 | right: 20px; 218 | cursor: pointer; 219 | background-image: url('icon/trash.png'); 220 | background-size: 20px 20px; 221 | background-repeat: no-repeat; 222 | } 223 | 224 | .budget-dashboard #all ul.list li.income{ 225 | 226 | } 227 | .budget-dashboard #all ul.list li.expense{ 228 | color: #f0624d; 229 | } 230 | 231 | /* //////// EXPENSE ////////// */ 232 | .budget-dashboard #expense{ 233 | width: 360px; 234 | height: 339px; 235 | position: relative; 236 | } 237 | 238 | .budget-dashboard #expense .input{ 239 | position: absolute; 240 | display: block; 241 | width: 360px; 242 | bottom: 0; 243 | border-top: 1px solid #ccc; 244 | } 245 | 246 | .budget-dashboard #expense .input *{ 247 | display: inline-block; 248 | vertical-align: middle; 249 | } 250 | 251 | .budget-dashboard #expense .input input#expense-title-input{ 252 | height: 40px; 253 | width : 150px; 254 | padding-left: 10px; 255 | font-size: 1.2em; 256 | font-family: 'Gilroy'; 257 | margin: 5px; 258 | margin-left: 10px; 259 | border-radius: 10px 0 0 10px; 260 | border: none; 261 | } 262 | 263 | .budget-dashboard #expense .input input#expense-amount-input{ 264 | height: 40px; 265 | width : 110px; 266 | padding-left: 10px; 267 | font-size: 1.2em; 268 | font-family: 'Gilroy'; 269 | margin: 5px; 270 | margin-left: -10px; 271 | border-radius: 0 10px 10px 0; 272 | border: none; 273 | } 274 | 275 | .budget-dashboard #expense .input .add-expense img{ 276 | width: 40px; 277 | height: 40px; 278 | cursor: pointer; 279 | } 280 | 281 | .budget-dashboard #expense ul{ 282 | width: 360px; 283 | height: 285px; 284 | list-style: none; 285 | margin: 0; 286 | padding: 0; 287 | margin-top:20px; 288 | overflow-x: auto; 289 | } 290 | 291 | .budget-dashboard #expense ul.list li{ 292 | position: relative; 293 | font-size: 1em; 294 | } 295 | 296 | .budget-dashboard #expense ul.list li *{ 297 | display: inline-block; 298 | height: 30px; 299 | vertical-align: middle; 300 | } 301 | 302 | .budget-dashboard #expense ul.list li .entry{ 303 | width:250px; 304 | height: auto; 305 | padding-left: 20px; 306 | margin-bottom: 10px;; 307 | word-wrap: break-word; 308 | font-family: 'Gilroy Bold'; 309 | color: #f0624d; 310 | } 311 | 312 | .budget-dashboard #expense ul.list li #edit{ 313 | position: absolute; 314 | width:20px; 315 | height: 20px; 316 | right: 50px; 317 | cursor: pointer; 318 | background-image: url("icon/edit.png"); 319 | background-size: 20px 20px; 320 | background-repeat: no-repeat; 321 | } 322 | 323 | .budget-dashboard #expense ul.list li #delete{ 324 | position: absolute; 325 | width:20px; 326 | height: 20px; 327 | right: 20px; 328 | cursor: pointer; 329 | background-image: url('icon/trash.png'); 330 | background-size: 20px 20px; 331 | background-repeat: no-repeat; 332 | } 333 | 334 | /* /////// INCOME //////// */ 335 | .budget-dashboard #income{ 336 | width: 360px; 337 | height: 339px; 338 | position: relative; 339 | } 340 | 341 | .budget-dashboard #income .input{ 342 | position: absolute; 343 | display: block; 344 | width: 360px; 345 | bottom: 0; 346 | border-top: 1px solid #ccc; 347 | } 348 | 349 | .budget-dashboard #income .input *{ 350 | display: inline-block; 351 | vertical-align: middle; 352 | } 353 | 354 | .budget-dashboard #income .input input#income-title-input{ 355 | height: 40px; 356 | width : 150px; 357 | padding-left: 10px; 358 | font-size: 1.2em; 359 | font-family: 'Gilroy'; 360 | margin: 5px; 361 | margin-left: 10px; 362 | border-radius: 10px 0 0 10px; 363 | border: none; 364 | } 365 | 366 | .budget-dashboard #income .input input#income-amount-input{ 367 | height: 40px; 368 | width : 110px; 369 | padding-left: 10px; 370 | font-size: 1.2em; 371 | font-family: 'Gilroy'; 372 | margin: 5px; 373 | margin-left: -10px; 374 | border-radius: 0 10px 10px 0; 375 | border: none; 376 | } 377 | 378 | .budget-dashboard #income .input .add-income img{ 379 | width: 40px; 380 | height: 40px; 381 | cursor: pointer; 382 | } 383 | 384 | .budget-dashboard #income ul{ 385 | width: 360px; 386 | height: 285px; 387 | list-style: none; 388 | margin: 0; 389 | padding: 0; 390 | margin-top:20px; 391 | overflow-x: auto; 392 | } 393 | 394 | .budget-dashboard #income ul.list li{ 395 | position: relative; 396 | font-size: 1em; 397 | } 398 | 399 | .budget-dashboard #income ul.list li *{ 400 | display: inline-block; 401 | height: 30px; 402 | vertical-align: middle; 403 | } 404 | 405 | .budget-dashboard #income ul.list li .entry{ 406 | width:250px; 407 | height: auto; 408 | padding-left: 20px; 409 | margin-bottom: 10px;; 410 | word-wrap: break-word; 411 | font-family: 'Gilroy Bold'; 412 | } 413 | 414 | .budget-dashboard #income ul.list li #edit{ 415 | position: absolute; 416 | width:20px; 417 | height: 20px; 418 | right: 50px; 419 | cursor: pointer; 420 | background-image: url("icon/edit.png"); 421 | background-size: 20px 20px; 422 | background-repeat: no-repeat; 423 | } 424 | 425 | .budget-dashboard #income ul.list li #delete{ 426 | position: absolute; 427 | width:20px; 428 | height: 20px; 429 | right: 20px; 430 | cursor: pointer; 431 | background-image: url('icon/trash.png'); 432 | background-size: 20px 20px; 433 | background-repeat: no-repeat; 434 | } --------------------------------------------------------------------------------