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

Merge remote-tracking branch 'origin/main'

parents 3c6d37e3 4f7ee2e5
No related branches found
No related tags found
1 merge request!84Refactor/navbar
Pipeline #283492 passed with warnings
......@@ -2383,6 +2383,10 @@
"type": "integer",
"format": "int64"
},
"bannerImage": {
"type": "integer",
"format": "int64"
},
"email": {
"type": "string"
},
......@@ -2395,6 +2399,14 @@
},
"subscriptionLevel": {
"type": "string"
},
"checkingAccountBBAN": {
"type": "integer",
"format": "int64"
},
"savingsAccountBBAN": {
"type": "integer",
"format": "int64"
}
}
},
......@@ -2606,9 +2618,21 @@
"type": "integer",
"format": "int64"
},
"bannerImage": {
"type": "integer",
"format": "int64"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"totalPoints": {
"type": "integer",
"format": "int32"
},
"currentStreak": {
"type": "integer",
"format": "int32"
}
}
},
......
......@@ -7,6 +7,9 @@ export type ProfileDTO = {
firstName?: string;
lastName?: string;
profileImage?: number;
bannerImage?: number;
createdAt?: string;
totalPoints?: number;
currentStreak?: number;
};
......@@ -7,9 +7,12 @@ export type UserDTO = {
firstName?: string;
lastName?: string;
profileImage?: number;
bannerImage?: number;
email?: string;
createdAt?: string;
role?: string;
subscriptionLevel?: string;
checkingAccountBBAN?: number;
savingsAccountBBAN?: number;
};
src/assets/loadingPig.png

61.8 KiB

src/assets/savingPigRun.png

215 KiB

......@@ -2,18 +2,21 @@
import SavingGoalList from "@/components/SavingGoal/SavingGoalList.vue";
import SavingGoalRoadmap from "@/components/SavingGoal/SavingGoalRoadmap.vue";
import SavingGoalCreate from "@/components/SavingGoal/SavingGoalCreate.vue";
import SavingGoalDefault from "@/components/SavingGoal/SavingGoalDefault.vue";
import type {GoalDTO} from "@/api";
import {GoalService} from "@/api";
export default {
components: {SavingGoalCreate, SavingGoalRoadmap, SavingGoalList},
components: {SavingGoalDefault, SavingGoalCreate, SavingGoalRoadmap, SavingGoalList},
data() {
return {
bluePanelMaxHeight: 'auto' as string,
createClicked: true as boolean,
createClicked: false as boolean,
savingGoalClicked: false as boolean,
selectedGoal: [] as any,
createdGoal: [] as any,
key: 0 as number,
keyForList: 0 as number,
};
},
mounted() {
......@@ -26,7 +29,8 @@ export default {
if (timelineElement instanceof HTMLElement) {
// Calculate the max-height based on the height of the timeline
const timelineHeight = timelineElement.offsetHeight;
this.bluePanelMaxHeight = '700px';
console.log(timelineHeight)
this.bluePanelMaxHeight = (timelineHeight * 1.5)+'px';
} else {
this.bluePanelMaxHeight = '700px';
}
......@@ -36,16 +40,24 @@ export default {
},
async goToSavingGoal(savingGoal: GoalDTO) {
this.$emit('goToSavingGoal', savingGoal);
let response = await GoalService.getGoal({id: savingGoal.id as number});
console.log(response)
this.selectedGoal = response
this.selectedGoal = await GoalService.getGoal({id: savingGoal.id as number})
this.createClicked = false;
this.savingGoalClicked = true;
this.key++
setTimeout(() => {
this.calculateBluePanelMaxHeight()
}, 500);
},
createSavingGoal(savingGoal: GoalDTO) {
this.$emit('createSavingGoal', savingGoal)
this.createdGoal = savingGoal;
this.createClicked = false;
async handleCreateGoalClicked(savingGoal: GoalDTO) {
this.$emit('goToSavingGoal', savingGoal);
let response = await GoalService.getGoal({id: savingGoal.id as number});
setTimeout(() => {
this.selectedGoal = response
this.createClicked = false;
this.key++
this.savingGoalClicked = true;
this.keyForList++
}, 100);
}
},
};
......@@ -55,15 +67,16 @@ export default {
<div class="cont">
<div class="row">
<div class="col-lg-4 blue-background overflow-scroll" :style="{ 'max-height': bluePanelMaxHeight }">
<h3 style="color: white; margin-bottom: 16px">Your saving goals</h3>
<h2>Dine sparemål</h2>
<div>
<button class="btn btn-success btn-lg" style="font-weight: 600; margin-bottom: 20px" @click="createGoal">Create new saving goal</button>
<button class="btn btn-success btn-lg" style="font-weight: 600; margin-bottom: 20px" @click="createGoal">+ Lag et nytt sparemål</button>
</div>
<saving-goal-list @goToSavingGoal="goToSavingGoal"></saving-goal-list>
<saving-goal-list :key="keyForList" @goToSavingGoal="goToSavingGoal"></saving-goal-list>
</div>
<div class="spacer"/>
<saving-goal-create @createGoalClick="createSavingGoal" v-if="createClicked"></saving-goal-create>
<saving-goal-roadmap :key="key" :selected-goal="selectedGoal" v-else></saving-goal-roadmap>
<saving-goal-create @createGoalClicked="handleCreateGoalClicked" v-if="createClicked"></saving-goal-create>
<saving-goal-roadmap :key="key" :selected-goal="selectedGoal" v-else-if="savingGoalClicked"></saving-goal-roadmap>
<saving-goal-default v-else></saving-goal-default>
</div>
</div>
</template>
......@@ -82,11 +95,18 @@ export default {
padding: 12px;
background-color: #003A58;
width: 27%;
border-radius: 0 2em 2em 0;
border-radius: 0 1em 1em 0;
}
.spacer {
width: 10%;
background-color: transparent;
}
h2 {
color: white;
margin-bottom: 16px;
font-weight: 600;
}
</style>
\ No newline at end of file
<script setup lang="ts">
import {GoalService, type CreateGoalDTO, type GoalDTO} from "@/api"
import {ref} from "vue";
import {ref, defineProps, defineEmits} from "vue";
const emits = defineEmits(['createGoalClicked']);
const name = ref("")
const desc = ref("")
......@@ -10,13 +12,6 @@ const createdConfirm = ref("");
const errorMessage = ref("")
const createGoalClick = async () => {
console.log("create goal clicked")
console.log(name.value)
console.log(desc.value)
console.log(date.value)
console.log(amount.value)
const createGoalPayload: CreateGoalDTO = {
name: name.value,
description: desc.value,
......@@ -28,8 +23,9 @@ const createGoalClick = async () => {
try {
let response = await GoalService.createGoal({ requestBody: createGoalPayload });
if(response.name != "") {
createdConfirm.value = "Your goal has been created! Refresh the page to se it in the list"
createdConfirm.value = "Your goal has been created!"
errorMessage.value = ""
emits('createGoalClicked', response)
}
} catch (error: any) {
console.log(error.message);
......@@ -41,36 +37,37 @@ const createGoalClick = async () => {
<template>
<div class="col-lg-8">
<h1>Create a new saving goal!</h1>
<h1>Lag et nytt sparemål!</h1>
<br>
<p>Create a name for this saving goal </p>
<p>Gi sparemålet et navn </p>
<div class="input-group mb-3">
<span class="input-group-text" id="basic-addon1">Name</span>
<input v-model="name" type="text" class="form-control" placeholder="Name of Saving Goal" aria-label="Username" aria-describedby="basic-addon1" required>
<span class="input-group-text" id="basic-addon1">Navn</span>
<input v-model="name" type="text" class="form-control" placeholder="Navn på sparemålet"
aria-label="Username" aria-describedby="basic-addon1" required>
</div>
<p>Add a description to this saving goal </p>
<p>Legg til en beskrivelse for sparemålet </p>
<div class="input-group mb-3">
<span class="input-group-text" id="basic-addon2">Description</span>
<span class="input-group-text" id="basic-addon2">Beskrivelse</span>
<textarea v-model="desc" class="form-control" aria-label="With textarea"></textarea>
</div>
<!--Change this to date picker?-->
<p>When should this saving goal end?</p>
<p>Når skal pengene være spart?</p>
<div class="input-group mb-3">
<input v-model="date" type="date" class="form-control" aria-label="Amount of days" placeholder="Amount of days (as number)" required>
<input v-model="date" type="date" class="form-control" aria-label="Amount of days" required>
</div>
<p>How much do you want to save during this saving goal? </p>
<p>Hvor mye vil du spare?</p>
<div class="input-group">
<input v-model="amount" type="number" class="form-control" aria-label="" placeholder="NOK (as number)" required>
<input v-model="amount" type="number" class="form-control" aria-label="NOK" required>
<span class="input-group-text">NOK</span>
</div>
<br>
<button class="btn btn-primary btn-lg" @click="createGoalClick">Create goal!</button>
<div style="color: green; font-size: 32px">
<div class="confirmMessage">
{{ createdConfirm }}
</div>
......@@ -87,4 +84,10 @@ const createGoalClick = async () => {
padding-right: 56px;
padding-bottom: 28px;
}
.confirmMessage {
color: green;
font-size: 32px;
min-height: 100px;
}
</style>
\ No newline at end of file
<script setup lang="ts">
</script>
<template>
<section id="hero" class="hero section">
<div class="col-lg-8">
<div class="container text-center">
<div class="d-flex flex-column justify-content-center align-items-center">
<h1 class="">Velkommen til <span>SpareSti</span></h1>
<br>
<p class="">Kom i økonomisk form: Ta på deg våre spareutfordringer!<br></p>
<img src="../../assets/savingPigRun.png" alt="SpareSti-logo">
</div>
</div>
</div>
</section>
</template>
<style scoped>
.col-lg-8 {
width: 100%;
margin-top: 50px;
padding-right: 56px;
padding-bottom: 28px;
}
.hero {
width: 63%;
min-height: 70vh;
overflow: hidden;
}
.hero img {
inset: 0;
display: block;
width: 60%;
height: 60%;
object-fit: cover;
z-index: 1;
}
.hero .container {
position: relative;
z-index: 3;
}
.hero h1 {
margin: 0;
font-size: 56px;
font-weight: 700;
line-height: 56px;
}
.hero h1 span {
color: white;
background-color: #003A58;
padding: 4px 24px 14px 24px;
border-radius: 6px;
}
.hero p {
color: #003A58;
margin: 5px 0 30px 0;
font-size: 28px;
font-weight: 400;
}
.hero .btn-watch-video i {
color: #003A58;
font-size: 32px;
transition: 0.3s;
line-height: 0;
margin-right: 8px;
}
.hero .btn-watch-video:hover i {
color: #003A58;
}
@media (max-width: 640px) {
.hero h1 {
font-size: 28px;
line-height: 36px;
}
.hero p {
font-size: 18px;
line-height: 24px;
margin-bottom: 30px;
}
.hero img {
inset: 0;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
}
</style>
\ No newline at end of file
<script setup lang="ts">
import {ref, onMounted} from "vue";
import {GoalService, type GoalDTO, type CreateGoalDTO} from "@/api"
import {GoalService, type GoalDTO, type ChallengeDTO} from "@/api"
const savingGoalList = ref([] as any)
defineProps()
const savingGoalList = ref(null as any)
const oldSavingGoalList = ref(null as any)
const getGoals = async () => {
try {
let response = await GoalService.getGoals();
savingGoalList.value = response
savingGoalList.value = []
oldSavingGoalList.value = []
const date = new Date()
response.forEach((goal: GoalDTO) => {
if(goal.targetDate) {
const targetDate = new Date(goal.targetDate)
if(targetDate < date) {
console.log("old")
oldSavingGoalList.value.push(goal)
} else {
console.log("current")
savingGoalList.value.push(goal)
}
}
})
} catch (error: any) {
console.log(error.message);
}
......@@ -26,19 +39,70 @@ const goToSavingGoal = (savingGoal: GoalDTO) => {
const deleteSavingGoal = () => {
};
function calculateSavedSoFar (goal: GoalDTO) {
console.log("hehe")
let savedSoFar = 0; // Reset savedSoFar before calculating again
if(goal.challenges){
console.log("hehehe")
goal.challenges.forEach((challenge: ChallengeDTO) => {
// Check if progressList exists before accessing its elements
if (challenge.progressList) {
challenge.progressList.forEach((progress: any) => {
// Assuming 'amount' is the property you want to add from progressList
savedSoFar += progress.amount;
console.log("he")
});
}
});
}
return savedSoFar
}
function formatDate(date: string) {
const date1 = new Date(date);
return date1.toISOString().split('T')[0]
}
</script>
<template>
<div v-for="(savingGoal, index) in savingGoalList" :key="index" class="card bg-body">
<div class="card-header">
Saving goal {{ index + 1 }}
<div v-if="savingGoalList">
<div v-if="oldSavingGoalList.lenght > 0">
<h3>Current:</h3>
</div>
<div class="card-body">
<h5 class="card-title">{{ savingGoal.goalName }}</h5>
<p class="card-text">{{ savingGoal.description }}</p>
<a href="#" class="btn btn-primary" @click="goToSavingGoal(savingGoal)">Go to saving goal</a>
<a href="#" class="btn btn-danger" @click="deleteSavingGoal" style="margin-left: 8px">Delete</a>
<div v-for="(savingGoal, index) in savingGoalList" :key="index" class="card bg-body">
<div class="card-header">
Sparemål {{ index + 1 }}
</div>
<div class="card-body">
<h5 class="card-title">{{ savingGoal.name }}</h5>
<p class="card-text">{{ savingGoal.description }}</p>
<p class="card-text">Spart: {{calculateSavedSoFar(savingGoal)}}/{{savingGoal.targetAmount}} Kr</p>
<p class="card-text">Avsluttes: {{formatDate(savingGoal.targetDate)}} </p>
<a class="btn btn-primary" @click="goToSavingGoal(savingGoal)">Gå til sparemål</a>
<a class="btn btn-danger" @click="deleteSavingGoal" style="margin-left: 8px">
<img src="../../assets/icons/trash-can.svg"> Slett</a>
</div>
</div>
<div v-if="oldSavingGoalList.lenght > 0">
<h3>Old:</h3>
<div v-for="(savingGoal, index) in oldSavingGoalList" :key="index" class="card bg-body">
<div class="card-header">
Sparemål {{ index + 1 }}
</div>
<div class="card-body">
<h5 class="card-title">{{ savingGoal.name }}</h5>
<p class="card-text">{{ savingGoal.description }}</p>
<p class="card-text">{{calculateSavedSoFar(savingGoal)}}/{{savingGoal.targetAmount}}</p>
<a class="btn btn-primary" @click="goToSavingGoal(savingGoal)">Gå til sparemål</a>
<a class="btn btn-danger" @click="deleteSavingGoal" style="margin-left: 8px">Slett</a>
</div>
</div>
</div>
</div>
<div class="loading" v-else>
Laster...
<img src="../../assets/loadingPig.png" alt="loadingPig">
</div>
</template>
......@@ -63,4 +127,19 @@ const deleteSavingGoal = () => {
margin-bottom: 20px;
border: none;
}
.loading {
color: white;
font-size: 40px;
font-weight: 500;
}
.loading img {
width: 50%;
height: 50%;
}
h3 {
color: white;
}
</style>
\ No newline at end of file
<script lang="ts">
import {CategoryScale, Chart as ChartJS, Legend, LinearScale, LineElement, PointElement, Title, Tooltip} from 'chart.js'
import {Line} from 'vue-chartjs'
import type {ChallengeDTO, GoalDTO, MarkChallengeDTO} from "@/api";
import type {ChallengeDTO, CreateGoalDTO, GoalDTO, MarkChallengeDTO} from "@/api";
import {GoalService} from '@/api'
import {useUserInfoStore} from "@/stores/UserStore";
ChartJS.register(
CategoryScale,
......@@ -23,6 +24,8 @@ export default {
return {
image: 'https://th.bing.com/th/id/OIG3.NMbdxmKYKVnxYGLOa0Z0?w=1024&h=1024&rs=1&pid=ImgDetMain' as string,
altImage: 'https://th.bing.com/th/id/OIG4.gVWUC.rwCb8faTNx31yU?w=1024&h=1024&rs=1&pid=ImgDetMain' as string,
failedImage: 'https://cdn-icons-png.flaticon.com/512/6659/6659895.png' as string,
successImage: 'https://static-00.iconduck.com/assets.00/checkmark-running-icon-1024x1024-aakqv1qi.png' as string,
title: 'Spain trip' as string,
bluePanelMaxHeight: 'auto' as string,
roadmapSelected: true as boolean,
......@@ -50,12 +53,14 @@ export default {
newPrice: 0,
savedSoFar: 0 as number,
currentChallengeIndex: 0,
feedback: "" as string,
};
},
async mounted() {
setTimeout(() => {
this.findCurrentChallenge()
this.disableAllChecksThatNotCurrent()
this.checkIfToAmbitious()
this.togglePanel(this.selectedGoal.challenges[this.currentChallengeIndex])
this.calculateSavedSoFar()
this.onLoadDisableChecks(this.selectedGoal)
......@@ -65,8 +70,18 @@ export default {
},
computed: {
computeImageFilter() {
return (challenge: ChallengeDTO) => {
return challenge ? 'none' : 'grayscale(100%)';
return (challenge: any) => {
const today = new Date()
const startDate = new Date(challenge.startDate)
// Check if the challenge is in the past or future
if (today < startDate) {
// Challenge is in the future, apply grayscale
return 'grayscale(100%)'
} else {
// Challenge is currently active, no grayscale
return 'none';
}
};
}
},
......@@ -115,7 +130,7 @@ export default {
convertTemplateTextToChallengeText(challenge: ChallengeDTO) {
let challengeText: any
challengeText = challenge.challengeTemplate?.text
challengeText = challengeText.replace('{unit_amount}', challenge.challengeTemplate?.amount?.toString())
challengeText = challengeText.replace('{unit_amount}', challenge.amount?.toString())
challengeText = challengeText.replace('{checkDays}', challenge.checkDays?.toString())
challengeText = challengeText.replace('{totalDays}', challenge.totalDays?.toString())
let totalAmount: any
......@@ -132,7 +147,7 @@ export default {
calculateTotalAmountFromChallenges() {
let totalAmountFromChallenges = 0
for (const challenge of this.selectedGoal.challenges) {
totalAmountFromChallenges += challenge.amount
totalAmountFromChallenges += challenge.amount * challenge.checkDays
}
return totalAmountFromChallenges
},
......@@ -231,6 +246,12 @@ export default {
if (today >= startDate && today <= endDate) {
this.currentChallengeIndex = index
} else {
if (today >= endDate) {
console.log("In the past")
} else {
console.log("In the future")
}
}
})
},
......@@ -251,15 +272,10 @@ export default {
},
calculateSavedSoFarPerChallengeInPercent(challenge: ChallengeDTO) {
let savedSoFarOnChallenge = 0
let savedSoFarOnChallenge = this.calculateSavedSoFarPerChallenge(challenge)
let targetAmount = 1
challenge.progressList?.forEach(progress => {
if(progress.amount) {
savedSoFarOnChallenge += progress.amount
}
})
if(challenge.amount) {
targetAmount = challenge.amount
if(challenge.amount && challenge.checkDays) {
targetAmount = challenge.amount * challenge.checkDays
}
return (savedSoFarOnChallenge / targetAmount) * 100
......@@ -273,7 +289,54 @@ export default {
}
})
return savedSoFar
}
},
async updateUnitPrice (challenge: ChallengeDTO) {
const createGoalPayload: MarkChallengeDTO = {
id: challenge.id,
amount: this.newPrice
};
try {
await GoalService.updateChallengeAmount({requestBody: createGoalPayload})
} catch (e: any) {
console.log(e.message)
}
},
checkIfToAmbitious() {
let possibleSaving = this.calculateTotalAmountFromChallenges()
let wantedSaving = this.selectedGoal.targetAmount
console.log(possibleSaving + "," + wantedSaving)
if(wantedSaving > possibleSaving) {
this.feedback = "Vi beundrer din ambisjon, men å oppnå den ettertraktede" +
" summen er ikke lett. Men disse utfordringene tar deg på god vei!"
}
},
getImageSource(challenge: ChallengeDTO) {
const today = new Date();
const endDate = new Date(challenge.endDate as any);
// Check if the challenge is in the past
if (today > endDate) {
// Challenge is in the past, return alternative image source
if(challenge.progressList) {
if(challenge.checkDays == challenge.progressList.length) {
return this.successImage
} else {
return this.failedImage;
}
}
} else {
// Challenge is currently active or in the future, return default image source
return this.image;
}
},
transferMoney(amount: number) {
//need users bank accounts
},
},
};
</script>
......@@ -298,17 +361,19 @@ export default {
<ul class="timeline">
<li v-for="(challenge, index) in selectedGoal.challenges" :key="index" :class="{ 'timeline-inverted': index % 2 !== 0 }">
<div class="timeline-image z-1" @click="togglePanel(challenge)">
<img class="circular-image" :src="challenge.showPanel ? altImage : image" :style="{ filter: computeImageFilter(challenge) }" alt="">
<img class="circular-image" :src="challenge.showPanel ? altImage : getImageSource(challenge)" :style="{ filter: computeImageFilter(challenge) }" alt="">
</div>
<div class="timeline-panel z-3" :id="'panel-' + index" v-show="challenge.showPanel">
<div class="timeline-heading">
<h5 style="margin-top: 12px">{{challenge.points}}<img src="../../assets/items/pigcoin.png" alt="pig coint" style="width: 2rem"></h5>
<h4>Utfordring {{ index +1 }}</h4>
<p style="font-size: 12px">{{formatDate(challenge.startDate)}} til {{formatDate(challenge.endDate)}}</p>
<h4 class="subheading">{{convertTemplateTextToChallengeText(challenge)}}</h4>
</div>
<div class="timeline-body">
<br>
<p>
Pris per enhet: {{challenge.challengeTemplate.amount}} kr <img src="../../assets/icons/edit-button.svg" alt="editIcon" data-bs-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="exampleModal">
Pris per enhet: {{challenge.amount}} kr <img src="../../assets/icons/edit-button.svg" alt="editIcon" data-bs-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="exampleModal">
</p>
<br>
<div class="collapse" id="collapseExample" style="background-color: white; padding: 12px; border-radius: 5px">
......@@ -319,11 +384,12 @@ export default {
</div>
</div>
<br>
<button class="btn btn-success">Bekreft endring</button>
<button @click="updateUnitPrice(challenge)" class="btn btn-success">Bekreft endring</button>
</div>
<br>
<p>Spart: {{ calculateSavedSoFarPerChallenge(challenge)}} Kr</p>
<div class="progress">
<div class="progress-bar" role="progressbar" :style="{ width: calculateSavedSoFarPerChallengeInPercent(challenge) + '%' }" :aria-valuenow="calculateSavedSoFarPerChallengeInPercent(challenge)" aria-valuemin="0" aria-valuemax="100">{{ calculateSavedSoFarPerChallenge(challenge)}} Kr</div>
<div class="progress-bar" role="progressbar" :style="{ width: calculateSavedSoFarPerChallengeInPercent(challenge) + '%' }" :aria-valuenow="calculateSavedSoFarPerChallengeInPercent(challenge)" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<br>
<div class="checkbox-row">
......@@ -341,6 +407,10 @@ export default {
<div v-else>
<div class="row">
<div v-if="feedback != ''" class="feedbackBox">
<h3>Oops!</h3>
<h5 class="">{{ feedback }}</h5>
</div>
<div class="col-sm-3">
<div class="card-box tilebox-one"><i class="icon-layers float-right text-muted"></i>
<h6 class="text-muted text-uppercase mt-0">Du ønsker å spare</h6>
......@@ -384,7 +454,7 @@ export default {
margin-bottom:40px;
padding-bottom: 10px;
color: white;
border-radius: 1em;
border-radius: 20px;
background-color: #003A58;
}
......@@ -393,6 +463,7 @@ export default {
padding:4px 0 0 0;
margin-top:22px;
list-style: none;
margin-bottom: 300px;
}
.timeline>li:nth-child(even) {
......@@ -428,7 +499,8 @@ export default {
text-align: right;
background-color: #003A58;
border-radius: 1em;
margin-left: 110px;
margin-left: 100px;
color: white;
}
.timeline>li .timeline-panel:before {
......@@ -451,7 +523,6 @@ export default {
left: 50%;
border: 7px solid #003A58;
border-radius: 100%;
background-color: #00ffff;
box-shadow: 0 0 5px #00e1ff;
width: 100px;
height: 100px;
......@@ -469,7 +540,7 @@ export default {
float: right;
padding: 0 30px 20px 20px;
text-align: left;
margin-right: 110px;
margin-right: 100px;
}
.timeline>li.timeline-inverted>.timeline-panel:before {
......@@ -491,7 +562,7 @@ export default {
}
.timeline .timeline-heading h4 {
margin-top:22px;
margin-top:0px;
margin-bottom: 4px;
padding:0;
color: white;
......@@ -704,4 +775,11 @@ export default {
margin-right: 10px; /* Adjust as needed */
}
.feedbackBox {
box-shadow: rgba(255, 0, 0, 0.2) 0px 7px 29px 0px;
border-radius: 1em;
margin-bottom: 40px;
margin-top: 10px;
padding: 12px;
}
</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