Skip to content

Commit

Permalink
Change data structure (primarily for budget object)
Browse files Browse the repository at this point in the history
  • Loading branch information
forevermatt committed Jun 5, 2020
1 parent 4e835d9 commit 7157ffc
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 80 deletions.
2 changes: 1 addition & 1 deletion assets/bundle.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import ErrorMessage from './components/ErrorMessage.svelte'
import { loadAccounts } from './data/accounts'
import { loadBudgets } from './data/budgets'
import { loadBudget } from './data/budget'
import { loadCategories } from './data/categories'
import { onMount } from 'svelte'
import Router from 'svelte-spa-router'
Expand All @@ -10,7 +10,7 @@ import routes from './views/routes'
onMount(async () => {
loadAccounts()
loadCategories()
loadBudgets()
loadBudget()
})
</script>

Expand Down
20 changes: 8 additions & 12 deletions src/components/BudgetOverview.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
<script>
import CategoryGraph from './CategoryGraph.svelte'
import { getBudgetFor, sortPlanByCategory } from '../data/budgets'
import { budget, sortBudgetByCategory } from '../data/budget'
import { categories } from '../data/categories'
import { getCurrentYearMonthString } from '../helpers/dates'
import { dangerIfNegative, formatAmount, formatAmountAsWholeNumber } from '../helpers/numbers'
export let params = {} // URL parameters provided by router
let yearMonth = params.yearMonth || getCurrentYearMonthString()
$: budget = getBudgetFor(yearMonth)
$: alphabetizedPlan = sortPlanByCategory(budget.plan, $categories)
$: sortedBudget = sortBudgetByCategory($budget, $categories)
</script>

<style>
Expand Down Expand Up @@ -52,18 +48,18 @@ $: alphabetizedPlan = sortPlanByCategory(budget.plan, $categories)

<table class="category-list table table-sm">
<tbody>
{#each alphabetizedPlan as {budgeted, spent, category} }
{#each sortedBudget as {budgeted, remaining, name, uuid} }
<tr>
<td class="category-name width-10">
<a href="#/category/{ category.uuid }"
class="btn btn-outline-secondary">{ category.name }</a>
<a href="#/category/{ uuid }"
class="btn btn-outline-secondary">{ name }</a>
</td>
<td class="width-80">
<CategoryGraph {category} />
<CategoryGraph {budgeted} {remaining} />
</td>
<td class="category-amount width-10">
<div class="category-available { dangerIfNegative(budgeted - spent) }">
<sup>$</sup>{ formatAmount(budgeted - spent) }
<div class="category-available { dangerIfNegative(remaining) }">
<sup>$</sup>{ formatAmount(remaining) }
</div>
<div class="category-budgeted"><span>/ { formatAmountAsWholeNumber(budgeted) }</span></div>
</td>
Expand Down
9 changes: 5 additions & 4 deletions src/components/CategoryGraph.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script>
import { dangerIfNegative } from '../helpers/numbers'
export let category
export let budgeted
export let remaining
const getStatus = (remaining, total) => {
if (remaining == undefined) {
Expand Down Expand Up @@ -54,7 +55,7 @@ const calculageWidth = (remaining, total) => {
}
</style>

<div class="category-graph { dangerIfNegative(category.remaining) }">
<div class="category-graph-line { getStatus(category.remaining, category.amount) }"
style="width: { calculageWidth(category.remaining, category.budgetedAmount) }%;"></div>
<div class="category-graph { dangerIfNegative(remaining) }">
<div class="category-graph-line { getStatus(remaining, budgeted) }"
style="width: { calculageWidth(remaining, budgeted) }%;"></div>
</div>
65 changes: 65 additions & 0 deletions src/data/budget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { getCategoryFrom } from './categories'
import { addToList, updateInObject } from '../helpers/data-store-helpers'
import { getCurrentYearMonthString } from '../helpers/dates'
import { getObjectFromStorage, saveToStorage } from './storage'
import { get, writable } from 'svelte/store'

const BUDGET = 'budget'

const budgetStore = writable({})
export {budgetStore as budget}

const addCategoryToBudget = (categoryUuid, budgeted) => {
updateBudget(categoryUuid, {
budgeted: budgeted,
remaining: budgeted,
refilled: getCurrentYearMonthString()
})
}

const isExistingCategory = uuid => get(budgetStore).hasOwnProperty(uuid)

export const loadBudget = () => {
budgetStore.set(getObjectFromStorage(BUDGET))
}

const saveBudget = () => saveToStorage(BUDGET, get(budgetStore))

export const setBudgetedForCategory = (uuid, budgeted) => {
const budget = get(budgetStore)
if (isExistingCategory(uuid)) {
updateBudgetedForExistingCategory(uuid, budgeted)
} else {
addCategoryToBudget(uuid, budgeted)
}
}

export const sortBudgetByCategory = (budget, categories) => {
let list = []
for (var uuid in budget) {
if (budget.hasOwnProperty(uuid)) {
let category = getCategoryFrom(uuid, categories)
list.push({
budgeted: budget[uuid].budgeted,
remaining: budget[uuid].remaining,
name: category.name,
uuid: category.uuid,
});
}
}
return list.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
}

export const updateBudget = (categoryUuid, changes) => {
updateInObject(categoryUuid, changes, budgetStore)
saveBudget()
}

const updateBudgetedForExistingCategory = (categoryUuid, budgeted) => {
const budget = get(budgetStore)
let categoryAmounts = budget[categoryUuid]
let previousBudgeted = categoryAmounts.budgeted
let previousRemaining = categoryAmounts.remaining
let remaining = previousRemaining + (budgeted - previousBudgeted)
updateBudget(categoryUuid, {budgeted, remaining})
}
56 changes: 0 additions & 56 deletions src/data/budgets.js

This file was deleted.

4 changes: 4 additions & 0 deletions src/data/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const createCategory = name => {
}
}

export const getCategoryFrom = (uuid, list) => {
return list.find(item => item.uuid === uuid) || {}
}

export const loadCategories = () => {
categories.set(getListFromStorage(CATEGORIES))
}
Expand Down
15 changes: 12 additions & 3 deletions src/data/storage.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
const isArray = Array.isArray

export const getListFromStorage = listName => {
const stringFromStorage = localStorage.getItem(listName)
const dataFromStorage = JSON.parse(stringFromStorage)
return isArray(dataFromStorage) ? dataFromStorage : []
const list = parseJsonFromStorage(listName)
return isArray(list) ? list : []
}

export const getObjectFromStorage = objectName => {
const data = parseJsonFromStorage(objectName)
return (data !== null) ? data : {}
}

const parseJsonFromStorage = itemName => {
const stringFromStorage = localStorage.getItem(itemName)
return JSON.parse(stringFromStorage)
}

export const saveToStorage = (name, data) => {
Expand Down
17 changes: 17 additions & 0 deletions src/helpers/data-store-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,30 @@ export const updateInList = (idField, id, changes, store) => {
const itemToUpdate = list.find(item => item[idField] === id)
const updatedItem = Object.assign({}, itemToUpdate, changes)

let found = false;
for (let i = 0; i < list.length; i++) {
if (list[i][idField] === id) {
found = true
list[i] = updatedItem
break
}
}

if (!found) {
list.push(updatedItem)
}

return list
})
}

export const updateInObject = (property, changes, store) => {
store.update(data => {
if (data.hasOwnProperty(property)) {
data[property] = Object.assign(data[property], changes)
} else {
data[property] = changes
}
return data
})
}
4 changes: 2 additions & 2 deletions src/views/CategoryAmount.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import AmountInput from '../components/AmountInput.svelte'
import { setCurrentBudgetForCategory } from '../data/budgets'
import { setBudgetedForCategory } from '../data/budget'
import { categories } from '../data/categories'
import { push } from 'svelte-spa-router'
Expand All @@ -12,7 +12,7 @@ $: initialAmount = category.amount || 0
function onSubmit(event) {
let amount = event.detail
setCurrentBudgetForCategory(uuid, amount)
setBudgetedForCategory(uuid, amount)
push(`/budget`)
}
</script>
Expand Down

0 comments on commit 7157ffc

Please sign in to comment.