Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
idatt2106_2024_02_frontend
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
IDATT2106 - Gruppe 2
idatt2106_2024_02_frontend
Commits
d3c7a4b2
Commit
d3c7a4b2
authored
10 months ago
by
Malin Haugland Høli
Browse files
Options
Downloads
Patches
Plain Diff
refactor:
Update goal views with final design
parent
0ba974d4
No related branches found
Branches containing commit
No related tags found
3 merge requests
!66
Final merge
,
!50
fix(styling):
,
!4
Pipeline fix
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/views/ManageGoalView.vue
+156
-58
156 additions, 58 deletions
src/views/ManageGoalView.vue
src/views/UserGoalsView.vue
+19
-8
19 additions, 8 deletions
src/views/UserGoalsView.vue
src/views/ViewGoalView.vue
+25
-18
25 additions, 18 deletions
src/views/ViewGoalView.vue
with
200 additions
and
84 deletions
src/views/ManageGoalView.vue
+
156
−
58
View file @
d3c7a4b2
...
...
@@ -4,69 +4,94 @@ import { computed, onMounted, ref, watch } from 'vue'
import
type
{
Goal
}
from
'
@/types/goal
'
import
ProgressBar
from
'
@/components/ProgressBar.vue
'
import
authInterceptor
from
'
@/services/authInterceptor
'
import
ModalComponent
from
'
@/components/ModalComponent.vue
'
const
router
=
useRouter
()
const
selectedDate
=
ref
<
string
>
(
''
)
const
minDate
=
new
Date
(
new
Date
().
setDate
(
new
Date
().
getDate
()
+
1
)).
toISOString
().
slice
(
0
,
16
)
const
minDate
=
new
Date
(
new
Date
().
setDate
(
new
Date
().
getDate
()
+
1
)).
toISOString
().
slice
(
0
,
10
)
const
selectedDate
=
ref
<
string
>
(
minDate
)
const
modalMessage
=
ref
<
string
>
(
''
)
const
modalTitle
=
ref
<
string
>
(
''
)
const
errorModalOpen
=
ref
<
boolean
>
(
false
)
const
confirmModalOpen
=
ref
<
boolean
>
(
false
)
const
goalInstance
=
ref
<
Goal
>
({
title
:
''
,
saved
:
0
,
target
:
10
0
,
target
:
0
,
description
:
''
,
due
:
''
})
watch
(
()
=>
goalInstance
.
value
.
saved
,
(
newVal
)
=>
{
goalInstance
.
value
.
saved
=
Math
.
max
(
0
,
Math
.
min
(
goalInstance
.
value
.
target
,
newVal
))
watch
(
selectedDate
,
(
newDate
)
=>
{
goalInstance
.
value
.
due
=
newDate
;
});
const
isEdit
=
computed
(()
=>
router
.
currentRoute
.
value
.
name
===
'
edit-goal
'
)
const
pageTitle
=
computed
(()
=>
(
isEdit
.
value
?
'
Rediger sparemål🎨
'
:
'
Nytt sparemål🎨
'
))
const
submitButton
=
computed
(()
=>
(
isEdit
.
value
?
'
Oppdater
'
:
'
Opprett
'
))
const
completion
=
computed
(()
=>
(
goalInstance
.
value
.
saved
/
goalInstance
.
value
.
target
)
*
100
)
function
validateInputs
()
{
const
errors
=
[];
goalInstance
.
value
.
due
=
selectedDate
.
value
+
'
T23:59:59.999Z
'
;
if
(
!
goalInstance
.
value
.
title
)
{
errors
.
push
(
'
Tittel må fylles ut
'
);
}
if
(
!
goalInstance
.
value
.
target
)
{
errors
.
push
(
'
Målbeløp må fylles ut
'
);
}
if
(
!
goalInstance
.
value
.
due
)
{
errors
.
push
(
'
Forfallsdato må fylles ut
'
);
}
)
watch
(
()
=>
goalInstance
.
value
.
target
,
(
newVal
)
=>
{
goalInstance
.
value
.
target
=
Math
.
max
(
Math
.
max
(
goalInstance
.
value
.
saved
,
1
),
newVal
)
if
(
goalInstance
.
value
.
target
<
1
)
{
errors
.
push
(
'
Målbeløp må være større enn 0
'
);
}
)
watch
(
()
=>
selectedDate
.
value
,
(
newVal
)
=>
{
if
(
newVal
<
minDate
)
selectedDate
.
value
=
minDate
goalInstance
.
value
.
due
=
newVal
+
'
:00.000Z
'
if
(
goalInstance
.
value
.
saved
<
0
)
{
errors
.
push
(
'
Sparebeløp kan ikke være negativt
'
);
}
)
const
isEdit
=
computed
(()
=>
router
.
currentRoute
.
value
.
name
===
'
edit-goal
'
)
const
pageTitle
=
computed
(()
=>
(
isEdit
.
value
?
'
Rediger sparemål
'
:
'
Nytt sparemål
'
))
const
submitButton
=
computed
(()
=>
(
isEdit
.
value
?
'
Oppdater
'
:
'
Opprett
'
))
const
completion
=
computed
(()
=>
(
goalInstance
.
value
.
saved
/
goalInstance
.
value
.
target
)
*
100
)
if
(
goalInstance
.
value
.
saved
>
goalInstance
.
value
.
target
)
{
errors
.
push
(
'
Sparebeløp kan ikke være større enn målbeløp
'
);
}
const
isInputValid
=
computed
(()
=>
{
return
(
goalInstance
.
value
.
title
.
length
>
0
&&
goalInstance
.
value
.
title
.
length
<=
20
&&
goalInstance
.
value
.
description
.
length
<=
280
&&
goalInstance
.
value
.
target
>
0
&&
goalInstance
.
value
.
due
!==
''
)
})
return
errors
;
const
submitAction
=
()
=>
{
if
(
!
isInputValid
.
value
)
{
return
()
=>
alert
(
'
Fyll ut alle feltene
'
)
}
const
submitAction
=
async
()
=>
{
const
errors
=
validateInputs
();
if
(
errors
.
length
>
0
)
{
const
formatErrors
=
errors
.
join
(
'
\n
'
);
modalTitle
.
value
=
'
Oops! Noe er feil med det du har fylt ut🚨
'
;
modalMessage
.
value
=
formatErrors
.
replace
(
/
\n
/g
,
"
<br>
"
)
errorModalOpen
.
value
=
true
;
return
;
}
if
(
isEdit
.
value
)
{
updateGoal
()
}
else
{
createGoal
()
try
{
if
(
isEdit
.
value
)
{
updateGoal
();
}
else
{
createGoal
();
}
}
catch
(
error
)
{
console
.
error
(
error
);
modalTitle
.
value
=
'
Systemfeil
'
;
modalMessage
.
value
=
'
En feil oppstod under lagring av utfordringen.
'
;
errorModalOpen
.
value
=
true
;
}
}
watch
(
selectedDate
,
(
newDate
)
=>
{
console
.
log
(
newDate
)
})
onMounted
(
async
()
=>
{
if
(
isEdit
.
value
)
{
const
goalId
=
router
.
currentRoute
.
value
.
params
.
id
...
...
@@ -75,12 +100,14 @@ onMounted(async () => {
await
authInterceptor
(
`/goals/
${
goalId
}
`
)
.
then
((
response
)
=>
{
goalInstance
.
value
=
response
.
data
selectedDate
.
value
=
response
.
data
.
due
.
slice
(
0
,
1
6
)
selectedDate
.
value
=
response
.
data
.
due
.
slice
(
0
,
1
0
)
})
.
catch
((
error
)
=>
{
console
.
error
(
error
)
router
.
push
({
name
:
'
goals
'
})
})
}
else
{
goalInstance
.
value
.
due
=
selectedDate
.
value
}
})
...
...
@@ -116,6 +143,24 @@ const deleteGoal = () => {
console
.
error
(
error
)
})
}
function
cancelCreation
()
{
if
(
goalInstance
.
value
.
title
!==
''
||
goalInstance
.
value
.
description
!==
''
||
goalInstance
.
value
.
target
!==
0
||
selectedDate
.
value
!==
''
)
{
modalTitle
.
value
=
'
Du er i ferd med å avbryte redigeringen🚨
'
;
modalMessage
.
value
=
'
Er du sikker på at du vil avbryte?
'
;
confirmModalOpen
.
value
=
true
;
}
else
{
router
.
push
({
name
:
'
goals
'
})
}
}
const
confirmCancel
=
()
=>
{
router
.
push
({
name
:
'
goals
'
})
confirmModalOpen
.
value
=
false
;
}
</
script
>
<
template
>
...
...
@@ -128,7 +173,7 @@ const deleteGoal = () => {
</div>
<div
class=
"flex flex-col"
>
<p
class=
"mx-4"
>
Beskrivelse
</p>
<p
class=
"mx-4"
>
Beskrivelse
(valgfri)
</p>
<textarea
v-model=
"goalInstance.description"
class=
"w-80 h-20 no-rezise"
...
...
@@ -138,18 +183,17 @@ const deleteGoal = () => {
<div
class=
"flex flex-col sm:flex-row gap-3"
>
<div
class=
"flex flex-col"
>
<p
class=
"mx-4"
>
Kroner spart
...
</p>
<p
class=
"mx-4"
>
Kroner spart
💸
</p>
<input
v-model=
"goalInstance.saved"
class=
"w-40 text-right"
min=
"0"
placeholder=
"Sparebeløp"
type=
"number"
/>
</div>
<div
class=
"flex flex-col"
>
<p
class=
"mx-4"
>
Av målbeløp
...
*
</p>
<p
class=
"mx-4"
>
Av målbeløp
💯
*
</p>
<input
v-model=
"goalInstance.target"
class=
"w-40 text-right"
...
...
@@ -160,31 +204,85 @@ const deleteGoal = () => {
</div>
<ProgressBar
:completion=
"completion"
/>
<div
class=
"flex flex-col"
>
<p
class=
"mx-4"
>
Forfallsdato*
</p>
<input
:min=
"minDate"
v-model=
"selectedDate"
placeholder=
"Forfallsdato"
type=
"datetime-local"
/>
<div
class=
"flex flex-row gap-4"
>
<div
class=
"flex flex-col"
>
<p
class=
"mx-4"
>
Forfallsdato*
</p>
<input
:min=
"minDate"
v-model=
"selectedDate"
placeholder=
"Forfallsdato"
type=
"date"
/>
</div>
<div
class=
"flex flex-col"
>
<p>
Last opp ikon for utfordringen📸
</p>
<button
class=
"mt-2 font-bold cursor-pointer transition-transform duration-300 ease-in-out hover:scale-110 hover:opacity-90"
>
💾
</button>
</div>
</div>
<div
class=
"flex flex-row justify-between w-full"
>
<button
:disabled=
"!isInputValid"
@
click=
"submitAction"
v-text=
"submitButton"
/>
<button
v-if=
"isEdit"
class=
"ml-2
bg-button-
danger"
class=
"ml-2
primary
danger"
@
click=
"deleteGoal"
v-text=
"'Slett'"
/>
<button
v-else
class=
"ml-2
bg-button-oth
er"
@
click=
"
router.push(
{ name: 'goals' })
"
class=
"ml-2
primary dang
er"
@
click=
"
cancelCreation
"
v-text=
"'Avbryt'"
/>
<button
class=
"primary"
@
click=
"submitAction"
v-text=
"submitButton"
/>
</div>
<ModalComponent
:title=
"modalTitle"
:message=
"modalMessage"
:isModalOpen=
"errorModalOpen"
@
close=
"errorModalOpen = false"
>
<template
v-slot:input
>
<div
class=
"flex justify-center items-center"
>
<div
class=
"flex flex-col gap-5"
>
<button
class=
"primary"
@
click=
"errorModalOpen = false"
>
Lukk
</button>
</div>
</div>
</
template
>
</ModalComponent>
<ModalComponent
:title=
"modalTitle"
:message=
"modalMessage"
:isModalOpen=
"confirmModalOpen"
@
close=
"confirmModalOpen = false"
>
<
template
v-slot:input
>
<div
class=
"flex justify-center items-center"
>
<div
class=
"flex flex-col gap-5"
>
<button
class=
"primary"
@
click=
"confirmCancel"
>
Bekreft
</button>
<button
class=
"primary danger"
@
click=
"confirmModalOpen = false"
>
Avbryt
</button>
</div>
</div>
</
template
>
</ModalComponent>
</div>
</div>
</template>
...
...
@@ -193,4 +291,4 @@ const deleteGoal = () => {
.no-rezise
{
resize
:
none
;
}
</
style
>
</
style
>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/views/UserGoalsView.vue
+
19
−
8
View file @
d3c7a4b2
...
...
@@ -60,8 +60,10 @@ const changeOrder = async () => {
<
template
>
<div
class=
"flex flex-col gap-5 items-center"
>
<h1
class=
"font-bold m-0"
>
Dine sparemål
</h1>
<button
@
click=
"router.push(
{ name: 'new-goal' })">Opprett et nytt sparemål
</button>
<h2
class=
"font-thin m-0"
>
Aktive sparemål
</h2>
<button
class=
"primary"
@
click=
"router.push(
{ name: 'new-goal' })">Opprett et nytt sparemål
</button>
<h2
class=
"font-bold m-0"
>
Aktive sparemål🚀
</h2>
<p
v-if=
"activeGoals.length === 0"
>
Du har ingen aktive sparemål
</p>
<draggable
v-else
...
...
@@ -75,20 +77,28 @@ const changeOrder = async () => {
:key=
"index"
:class=
"[
{ 'cursor-move shadow-xl -translate-y-2 duration-300': isDraggable },
{ 'border-4 border-green-500': index === 0 }
{ 'border-2 border-lime-400': index === 0 },
{ 'border-2 border-slate-200 hover:bg-slate-50': index !== 0 }
]"
:goal-instance="element"
:is-clickable="!isDraggable"
/>
</
template
>
</draggable>
<button
:disabled=
"activeGoals.length === 0"
@
click=
"changeOrder()"
>
<button
class=
"primary secondary"
:disabled=
"activeGoals.length === 0"
@
click=
"changeOrder()"
>
{{ isDraggable ? 'Lagre rekkefølge' : 'Endre rekkefølge' }}
</button>
<h2
class=
"font-
thin
m-0"
>
Fullførte sparemål
</h2>
<p
v-if=
"completedGoals.length === 0"
>
Du har ingen fullførte sparemål
</p>
<h2
class=
"font-
bold
m-0"
>
Fullførte sparemål
💯
</h2>
<p
v-if=
"completedGoals.length === 0"
>
Du har ingen fullførte sparemål
😢
</p>
<div
v-else
class=
"flex flex-row flex-wrap justify-center gap-10"
>
<CardGoal
v-for=
"goal in completedGoals"
:key=
"goal.id"
:goal-instance=
"goal"
/>
<CardGoal
class=
"border-2 border-slate-200 hover:bg-slate-50"
v-for=
"goal in completedGoals"
:key=
"goal.id"
:goal-instance=
"goal"
/>
</div>
<PageControl
:current-page=
"currentPage"
...
...
@@ -98,4 +108,5 @@ const changeOrder = async () => {
</div>
</template>
<
style
scoped
></
style
>
<
style
scoped
>
</
style
>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/views/ViewGoalView.vue
+
25
−
18
View file @
d3c7a4b2
...
...
@@ -73,29 +73,36 @@ const completeGoal = () => {
<div
class=
"flex flex-row flex-wrap items-center justify-center gap-10"
>
<div
class=
"flex flex-col gap-5 max-w-96"
>
<button
class=
"w-min"
@
click=
"router.push(
{ name: 'goals', params: { id: goalInstance.id } })"
class=
"w-min
bg-transparent rounded-lg font-bold left-10 cursor-pointer transition-transform duration-200 ease-in-out hover:scale-110 hover:opacity-100 justify-start
"
@
click=
"router.push(
{ name: 'goals', params: { id: goalInstance.id } })"
>
Oversikt
👈
Oversikt
</button>
<div
class=
"flex flex-col justify-center border-
4 border-black
rounded-3xl align-middle p-5 card-shadow overflow-hidden w-full"
class=
"flex flex-col justify-center border-
2
rounded-3xl align-middle p-5 card-shadow overflow-hidden w-full"
>
<h2
class=
"my-0"
>
Sparemål:
</h2>
<h2
class=
"font-light"
>
{{
goalInstance
.
title
}}
</h2>
<p
class=
"text-wrap break-words"
>
{{
goalInstance
.
description
}}
</p>
<div
class=
"flex flex-row gap-4 justify-center"
>
<p
class=
"text-wrap break-words"
>
{{
goalInstance
.
description
}}
</p>
<div>
<img
class=
"w-20 h-20"
src=
"https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png"
alt=
"Profilbilde"
/>
</div>
</div>
<br
/>
<p
class=
"text-center"
>
Du har spart
{{
goalInstance
.
saved
}}
kr av
{{
goalInstance
.
target
}}
kr
</p>
<ProgressBar
:completion=
"completion"
/>
</div>
<div
class=
"flex flex-row justify-between gap-2 w-full"
>
<button
<button
class=
"primary secondary mt-6"
v-if=
"!isCompleted"
@
click=
"
router.push(
{
...
...
@@ -106,15 +113,8 @@ const completeGoal = () => {
>
Rediger
</button>
<button
v-if=
"!isCompleted"
@
click=
"completeGoal"
v-text=
"'Marker målet som ferdig'"
/>
<button
class=
"
bg-button-danger hover:bg-button-danger
"
class=
"
danger mt-2 rounded-2xl p-1
"
@
click=
"
authInterceptor
.delete(`/goals/$
{goalInstance.id}`)
...
...
@@ -124,9 +124,16 @@ const completeGoal = () => {
>
Slett
</button>
<button
class=
"primary mt-4"
v-if=
"!isCompleted"
@
click=
"completeGoal"
v-text=
"'Marker målet som ferdig'"
/>
</div>
</div>
<InteractiveSpare
:png-size=
"10"
:speech=
"motivation"
direction=
"left"
/>
<div>
</div>
<InteractiveSpare
:png-size=
"10"
:speech=
"motivation"
direction=
"left"
/>
</div>
</
template
>
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment