Skip to content
Snippets Groups Projects
Commit 051debc2 authored by Jens Christian Aanestad's avatar Jens Christian Aanestad
Browse files

feat/Created new budget view component

parent cce63f99
No related branches found
No related tags found
1 merge request!34Feat/budget
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#FFFFFF" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="20px" height="20px" viewBox="0 0 494.936 494.936"
xml:space="preserve">
<g>
<g>
<path d="M389.844,182.85c-6.743,0-12.21,5.467-12.21,12.21v222.968c0,23.562-19.174,42.735-42.736,42.735H67.157
c-23.562,0-42.736-19.174-42.736-42.735V150.285c0-23.562,19.174-42.735,42.736-42.735h267.741c6.743,0,12.21-5.467,12.21-12.21
s-5.467-12.21-12.21-12.21H67.157C30.126,83.13,0,113.255,0,150.285v267.743c0,37.029,30.126,67.155,67.157,67.155h267.741
c37.03,0,67.156-30.126,67.156-67.155V195.061C402.054,188.318,396.587,182.85,389.844,182.85z"/>
<path d="M483.876,20.791c-14.72-14.72-38.669-14.714-53.377,0L221.352,229.944c-0.28,0.28-3.434,3.559-4.251,5.396l-28.963,65.069
c-2.057,4.619-1.056,10.027,2.521,13.6c2.337,2.336,5.461,3.576,8.639,3.576c1.675,0,3.362-0.346,4.96-1.057l65.07-28.963
c1.83-0.815,5.114-3.97,5.396-4.25L483.876,74.169c7.131-7.131,11.06-16.61,11.06-26.692
C494.936,37.396,491.007,27.915,483.876,20.791z M466.61,56.897L257.457,266.05c-0.035,0.036-0.055,0.078-0.089,0.107
l-33.989,15.131L238.51,247.3c0.03-0.036,0.071-0.055,0.107-0.09L447.765,38.058c5.038-5.039,13.819-5.033,18.846,0.005
c2.518,2.51,3.905,5.855,3.905,9.414C470.516,51.036,469.127,54.38,466.61,56.897z"/>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#FFF" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<g>
<g>
<path d="M435.2,153.6H320v25.6h102.4v307.2H89.6V179.2H192v-25.6H76.8c-7.066,0-12.8,5.734-12.8,12.8v332.8
c0,7.066,5.734,12.8,12.8,12.8h358.4c7.066,0,12.8-5.734,12.8-12.8V166.4C448,159.334,442.266,153.6,435.2,153.6z"/>
</g>
</g>
<g>
<g>
<path d="M341.956,234.249c-4.941-5.052-13.056-5.146-18.099-0.205L268.8,287.898V12.8C268.8,5.734,263.066,0,256,0
c-7.066,0-12.8,5.734-12.791,12.8v275.089l-55.057-53.854c-5.043-4.941-13.158-4.847-18.099,0.205
c-4.941,5.06-4.855,13.158,0.205,18.099l76.8,75.128c5.043,4.949,13.158,4.855,18.099-0.188l76.595-74.931
C346.803,247.407,346.897,239.309,341.956,234.249z"/>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#FFFFFF" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="20px" height="20px" viewBox="0 0 408.483 408.483"
xml:space="preserve">
<g>
<g>
<path d="M87.748,388.784c0.461,11.01,9.521,19.699,20.539,19.699h191.911c11.018,0,20.078-8.689,20.539-19.699l13.705-289.316
H74.043L87.748,388.784z M247.655,171.329c0-4.61,3.738-8.349,8.35-8.349h13.355c4.609,0,8.35,3.738,8.35,8.349v165.293
c0,4.611-3.738,8.349-8.35,8.349h-13.355c-4.61,0-8.35-3.736-8.35-8.349V171.329z M189.216,171.329
c0-4.61,3.738-8.349,8.349-8.349h13.355c4.609,0,8.349,3.738,8.349,8.349v165.293c0,4.611-3.737,8.349-8.349,8.349h-13.355
c-4.61,0-8.349-3.736-8.349-8.349V171.329L189.216,171.329z M130.775,171.329c0-4.61,3.738-8.349,8.349-8.349h13.356
c4.61,0,8.349,3.738,8.349,8.349v165.293c0,4.611-3.738,8.349-8.349,8.349h-13.356c-4.61,0-8.349-3.736-8.349-8.349V171.329z"/>
<path d="M343.567,21.043h-88.535V4.305c0-2.377-1.927-4.305-4.305-4.305h-92.971c-2.377,0-4.304,1.928-4.304,4.305v16.737H64.916
c-7.125,0-12.9,5.776-12.9,12.901V74.47h304.451V33.944C356.467,26.819,350.692,21.043,343.567,21.043z"/>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -70,6 +70,10 @@ function toHome() {
router.push('/')
}
function toBudget() {
router.push('/budget-overview')
}
function toSavingGoals() {
router.push('/roadmap')
}
......
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter();
const props = defineProps({
title: {
......@@ -27,10 +29,14 @@ onMounted(() => {
}
})
const onBudgetContainerPressed = () => {
router.push('/budget')
}
</script>
<template>
<div class="container-fluid row">
<div class="container-fluid row" @click="onBudgetContainerPressed">
<div class="col-12">
<div class="title-container">
<h2>{{title}}</h2>
......@@ -77,14 +83,15 @@ onMounted(() => {
}
.container-fluid {
border: 4px solid #4747ce;
border: 4px solid #5959ea;
min-height: 90px;
border-radius: 15px;
transition: transform 150ms ease-in-out;
transition: transform 150ms ease-in-out, border 200ms ease-in-out;
cursor: pointer;
}
.container-fluid:hover {
border: 4px solid #0000f1;
transform: scale(1.03);
}
......
<script setup lang="ts">
import Button1 from '@/components/Buttons/Button1.vue'
import { type CreateAppFunction, ref } from 'vue'
const emit = defineEmits(['deleteEvent', 'editEvent']);
const props = defineProps({
index: {
type: Number,
default: 0
},
description: {
type: String,
default: ''
},
amount: {
type: Number,
default: 0
}
})
let editDescription = ref('')
let editAmount = ref('')
const emitDeleteEvent = () => {
emit('deleteEvent', props.index)
}
const emitEditEvent = () => {
emit('editEvent', props.index, editDescription.value, editAmount.value)
}
</script>
<template>
<div class="expense-container">
<p>{{index + 1}}</p>
<p>{{description}}</p>
<p>{{amount}} kr</p>
<button class="btn btn-success" data-bs-toggle="collapse" :data-bs-target="'#' + index" aria-expanded="false" aria-controls="editBudgetCollapse">
<img src="../../assets/icons/edit-button.svg" alt="Edit" height="18" width="18">
Edit
</button>
<button class="btn btn-danger" @click="emitDeleteEvent">
<img src="../../assets/icons/trash-can.svg" alt="Edit" height="18" width="18">
Delete
</button>
</div>
<div class="collapse" :id="index">
<div class="container collapse-container">
<form @submit.prevent="emitEditEvent">
<div class="input-group">
<span class="input-group-text">Edit expense #{{ index+1 }}: </span>
<input type="text" class="form-control" placeholder="Expense description" required v-model="editDescription">
<input type="number" min="0" class="form-control" placeholder="Amount (kr)" required v-model="editAmount">
<button type="submit" class="btn btn-primary" data-bs-toggle="collapse" :data-bs-target="'#' + index">Confirm</button>
</div>
</form>
</div>
</div>
</template>
<style scoped>
.expense-container {
padding: 0 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr .6fr .6fr;
border-radius: 10px;
background-color: #2a2a34;
align-content: center;
justify-self: center;
margin: 10px 5px;
}
.expense-container p {
color: white;
align-self: center;
margin: 0;
}
.expense-container button {
margin: 5px;
padding: 0;
}
</style>
\ No newline at end of file
<script setup lang="ts">
</script>
<template>
</template>
<style scoped>
</style>
\ No newline at end of file
......@@ -37,6 +37,7 @@ const onChangedChallengeEvent = (value) => {
else {
chosenChallenges.value = chosenChallenges.value.filter(item => item !== value[0]);
}
console.log(chosenChallenges.value)
}
/**
......
......@@ -53,10 +53,15 @@ const routes = [
name: 'profile',
component: UserProfileView
},
{
path: '/budget-overview',
name: 'budget overview',
component: () => import('@/views/BudgetOverview.vue'),
},
{
path: '/budget',
name: 'budget',
component: () => import('@/views/BudgetOverview.vue'),
component: () => import('@/views/BudgetView.vue'),
},
{
path: 'friends',
......
<script setup lang="ts">
import Button1 from '@/components/Buttons/Button1.vue'
import Budget from '@/components/Budget/BudgetBox.vue'
import BudgetBox from '@/components/Budget/BudgetBox.vue'
</script>
<template>
<div class="container">
<h1 class="text-center">Your Budgets</h1>
<button1 id="createBudgetButton" button-text="Create new budget" lass="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample"/>
<button1 id="createBudgetButton" button-text="Create new budget" class="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample"/>
<div class="collapse" id="collapseExample">
<div class="container collapse-container">
<div class="input-group row">
<input id="collapseInput" class="col-5" type="text" placeholder="Enter name of budget">
<input id="collapseInput" class="col-5 form-control" type="text" placeholder="Enter name of budget">
<button1 id="collapseButton" class="col-1" button-text="Create" data-bs-dismiss="modal"/>
</div>
</div>
</div>
<ul class="budgetContainer">
<li><budget title="April 2024" budget="1000" expenses="908700"></budget></li>
<li><budget title="Mai 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="Juni 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="Juli 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="August 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="September 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="Oktober 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="November 2024" budget="1000" expenses="87"></budget></li>
<li><budget title="Desember 2024" budget="1000" expenses="87"></budget></li>
<li><budget-box title="April 2024" budget="1000" expenses="908700"></budget-box></li>
<li><budget-box title="Mai 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="Juni 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="Juli 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="August 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="September 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="Oktober 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="November 2024" budget="1000" expenses="87"></budget-box></li>
<li><budget-box title="Desember 2024" budget="1000" expenses="87"></budget-box></li>
</ul>
<nav id="navbar" aria-label="Page navigation example">
......
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import Button1 from '@/components/Buttons/Button1.vue'
import ExpenseBox from '@/components/Budget/ExpenseBox.vue'
import router from '@/router'
// TODO Need endpoint in order to retrieve budget
// Mocked values
let title = ref('Mai 2024');
let budget = ref(10000);
let expenses = ref(0);
let balance = ref(budget.value - expenses.value);
let expenseJSONObject = ref({
"expenses": [
{
"title": "Ost",
"value": 30
},
{
"title": "Skinke",
"value": 20
},
{
"title": "Bread",
"value": 15
}
]
});
for (let expense of expenseJSONObject.value.expenses) {
expenses.value += expense.value
}
// Reactive input values
let budgetTitle = ref('')
let budgetValue = ref()
let expenseDescription = ref('')
let expenseAmount = ref()
const iRef = ref()
onMounted(() => {
if (balance.value >= 0) {
iRef.value.style.backgroundColor = 'rgba(34, 231, 50, 0.43)';
}
balance.value = budget.value - expenses.value
})
const updateBalance = () => {
expenses.value = 0
for (let expense of expenseJSONObject.value.expenses) {
expenses.value += expense.value
}
balance.value = budget.value - expenses.value
if (balance.value >= 0) {
iRef.value.style.backgroundColor = 'rgba(34, 231, 50, 0.43)';
} else {
iRef.value.style.backgroundColor= 'rgba(232, 14, 14, 0.43)';
}
}
const calculateNewBudget = (newBudget: number) => {
budget.value = newBudget
updateBalance()
}
const addNewExpense = (expenseDescription: string, expenseValue: number) => {
expenseJSONObject.value.expenses.push({
"title": expenseDescription,
"value": expenseValue
});
updateBalance()
}
const editBudgetTitle = (newTitle: string) => {
title.value = newTitle
}
const deleteExpense = (index: number) => {
expenseJSONObject.value.expenses.splice(index, 1);
updateBalance()
}
const editExpense = (index: number, newDescription: string, newAmount: number) => {
console.log('Reached')
expenseJSONObject.value.expenses[index].title = newDescription
expenseJSONObject.value.expenses[index].value = newAmount
updateBalance()
}
// TODO add delete functionality
const onDeleteBudgetPressed = () => {
router.push('/budget-overview')
}
</script>
<template>
<div class="container">
<h1 class="text-center">{{ title }}</h1>
<div class="button-container">
<button1 id="optionButton" button-text="Options" data-bs-toggle="modal"
data-bs-target="#modal"/>
<button1 id="saveChanges" button-text="Save changes"/>
</div>
<div class="modal fade" id="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3>Options</h3>
<button class="btn btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<button id="importButton" class="btn btn-primary"><img src="../assets/icons/import.svg" height="20" width="20">Import budget</button>
<button id="editBudget" class="btn btn-primary" data-bs-toggle="collapse" data-bs-target="#editBudgetCollapse" aria-expanded="false" aria-controls="editBudgetCollapse"><img src="../assets/icons/edit-button.svg" alt="editButton">Rename budget</button>
<div class="collapse" id="editBudgetCollapse">
<div class="container collapse-container">
<form @submit.prevent="editBudgetTitle(budgetTitle)">
<div class="input-group">
<input id="collapseInput" class="col-5 form-control" type="text" placeholder="Enter new name of budget" v-model="budgetTitle">
<button1 id="collapseButton" type="submit" button-text="Edit" data-bs-dismiss="modal" />
</div>
</form>
</div>
</div>
<button id="deleteButton" class="btn btn-primary" data-bs-toggle="modal" @click="onDeleteBudgetPressed"><img src="../assets/icons/trash-can.svg" height="20" width="20">Delete budget</button>
</div>
</div>
</div>
</div>
<div class="budget-info-container">
<div class="info budget-container">
<i><img src="../assets/icons/money2.svg" width="48px" height="48px"></i>
<div class="budget-text-container">
<h5>{{budget}} kr</h5>
<p>Budget</p>
</div>
</div>
<div class="info expenses-container">
<i><img src="../assets/icons/credit-card.svg" width="48px" height="48px"></i>
<div class="expenses-text-container">
<h5>{{expenses}} kr</h5>
<p>Expenses</p>
</div>
</div>
<div class="info balance-container">
<i ref="iRef"><img src="../assets/icons/scale.svg" width="48px" height="48px"></i>
<div class="balance-text-container">
<h5>{{balance}} kr</h5>
<p>Balance</p>
</div>
</div>
</div>
<div class="budget-content-container">
<form class="budget-from" @submit.prevent="calculateNewBudget(budgetValue)">
<div class="input-group">
<span class="input-group-text">Your budget: </span>
<input type="text" class="form-control" placeholder="Enter your budget" required v-model="budgetValue">
<button type="submit" class="btn btn-primary">Calculate</button>
</div>
</form>
<form class="expenses-form" @submit.prevent="addNewExpense(expenseDescription, expenseAmount)">
<div class="input-group">
<span class="input-group-text">Add new expense: </span>
<input type="text" class="form-control" placeholder="Name of expense" required v-model="expenseDescription">
<input type="number" min="0" class="form-control" placeholder="Amount (kr)" required v-model="expenseAmount">
<button type="submit" class="btn btn-primary">Calculate</button>
</div>
</form>
</div>
<div class="expenses-details-container">
<h3>Expenses details</h3>
<div class="expense-box-container">
<expense-box v-for="(expense, index) in expenseJSONObject.expenses"
:key="index"
:index="index"
:description="expense.title"
:amount="expense.value"
@deleteEvent="deleteExpense"
@editEvent="editExpense"
/>
</div>
</div>
</div>
</template>
<style scoped>
.button-container {
display: flex;
gap: 10px;
}
.container.collapse-container {
padding: 0;
margin: 0;
}
.modal-header {
display: flex;
}
.modal-body {
display: grid;
gap: 10px
}
div.budget-info-container {
margin-top: 2rem;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
justify-content: center;
gap: 1rem;
}
div.info {
display: flex;
flex-direction: row;
background-color: rgba(221, 221, 224, 0.5);
border-radius: 10px;
padding: 10px;
transition: transform 150ms ease-in-out;
}
div.info:hover {
transform: scale(1.03);
}
i {
display: grid;
justify-content: center;
align-content: center;
margin: 5px;
border-radius: 7px;
min-width: 90px;
}
.budget-container i {
background-color: rgba(78, 107, 239, 0.43);
}
.expenses-container i {
background-color: rgba(238, 191, 43, 0.43);
}
.balance-container i {
background-color: rgba(232, 14, 14, 0.43);
}
.budget-content-container {
margin: 2rem 0;
display: grid;
gap: 5px;
}
.budget-content-container label {
display: flex;
align-items: center;
}
.expenses-details-container {
margin: 1rem 0;
min-height: 80px;
border-radius: 8px;
background-color: rgba(234, 234, 234, 0.8);
}
.expenses-details-container h3 {
margin-top: 1rem;
padding: 10px;
}
.expense-box-container {
overflow-y: auto;
overflow-x: hidden;
max-height: 100vh;
}
</style>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment