diff --git a/src/api/services/AuthenticationService.ts b/src/api/services/AuthenticationService.ts index eae8fd5c8b2f6ef8d5cfaf6ed6976edcf0a386d4..48c819ab0a448c84d87fce77baf7d9b54b49dc51 100644 --- a/src/api/services/AuthenticationService.ts +++ b/src/api/services/AuthenticationService.ts @@ -9,6 +9,28 @@ import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; export class AuthenticationService { + /** + * Validate email + * Check that the given email is valid + * @returns any Email is valid + * @throws ApiError + */ + public static validateEmail({ + email, + }: { + email: string, + }): CancelablePromise<Record<string, any>> { + return __request(OpenAPI, { + method: 'POST', + url: '/api/auth/valid-email/{email}', + path: { + 'email': email, + }, + errors: { + 409: `Email already exists`, + }, + }); + } /** * User Signup * Sign up a new user diff --git a/src/assets/icons/piggybank.svg b/src/assets/icons/piggybank.svg new file mode 100644 index 0000000000000000000000000000000000000000..564d95069fffe94a81490c9a98f008152e04f681 --- /dev/null +++ b/src/assets/icons/piggybank.svg @@ -0,0 +1 @@ +<svg id="Graphic_Elements" data-name="Graphic Elements" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200"><defs><style>.cls-1{fill:#faa;}.cls-2{fill:#7f3f3f;}.cls-3{fill:#ff8080;}.cls-4{fill:#f66;}</style></defs><g id="g4153"><path id="path4144" class="cls-1" d="M262.4,166.6a139.75,139.75,0,0,0-43,6.51c21.5,31.23,31.18,70.79,24.87,108.24-46.87,35.34-87.1,80.08-114.33,132.29-15.23-1.68-31.67-2-45.68,5.2C65.24,427.71,51.94,447.19,50,468Q50,562,50,656c.48,31.72,29.75,59.39,61.43,58.11,7.73.77,15.62-.89,23.11-1.25,13.66,23.92,29.51,46.79,48.06,67.13C231,834.5,294.13,874.8,361.77,901.24c-1.7,19.19-.87,39.41-.51,59,3.07,37,34.55,68.89,71.42,72.61,39.47,5.15,79.17-23.53,87.54-62.22,2.89-10.93,2.14-22.31,2.29-33.48,36.7,2.63,73.54,1.35,110.14-2.23.3,10.22-.71,20.52,1,30.65,5.33,34.25,34.78,62.81,69.19,67.07,30.38,4.29,62-10.84,78.36-36.69a83.25,83.25,0,0,0,13.07-46.14c-.27-19.18,1.22-38.69-2.92-57.54,73.33-32.61,140.47-82.62,186.39-149.16,45.16-64.12,67.14-144.81,57-222.9,23.83,1.63,48.88-2.3,69.25-15.31,16-9.89,28.09-25.26,35.41-42.42,8.37-20.38,13-43,9.35-64.9-2.59-16.5-10.57-32.36-23.17-43.45-21.8-19.7-56.23-26.39-82.71-12.36-17.69,9-26.57,31-21.53,49.93,2.17,2.63,4.61,6.21,7.68,7.4,4.92-7.4,8.46-16.07,15.7-21.63,7.35-6.26,17.09-11.74,27.1-9.49,7.86,2.1,13.37,8.9,16.23,16.22,6.08,16,5.07,35.28-4.17,49.94-7,11.73-21.41,17.67-34.69,15.74-13.62-1.27-26.24-7.32-37.71-14.41A359.14,359.14,0,0,0,937.55,326.3c-51.08-53.2-116.54-91.82-186.09-116-120.71-41.59-255.37-40.93-375.81,1.37-1.79.23-3.67,2.13-5.51,1.41-27.41-29.67-67.57-46.36-107.74-46.5Z"/><path id="path6" class="cls-2" d="M556.53,240.31c64.08-1.31,128.63,10,188.05,34.26,1.38,13.17.11,27,.45,40.34-1.6,0-3-1.2-4.47-1.74C643.32,268.58,529.21,264.24,428,297.86c-1.05-11.42-.15-23.1-.45-34.61.48-1.37-.52-3.84,1.9-3.73,41.21-12.23,84.18-18.36,127.1-19.21Z"/><path id="path8" class="cls-3" d="M937.55,326.3a359.53,359.53,0,0,1,73.94,109.12c11.46,7.08,24.08,13.14,37.71,14.41,13.29,1.93,27.74-4,34.7-15.74,9.2-14.66,10.24-33.91,4.17-49.94-2.87-7.32-8.38-14.13-16.23-16.22-10-2.25-19.77,3.23-27.11,9.49-7.22,5.56-10.79,14.23-15.71,21.63-3.09-1.19-5.51-4.77-7.67-7.4-5.06-18.94,3.84-40.88,21.52-49.93,26.47-14,60.91-7.34,82.73,12.36,12.58,11.09,20.55,26.95,23.15,43.45,3.62,21.94-1,44.52-9.38,64.9C1132.08,479.6,1120,495,1104,504.84c-20.4,13-45.42,16.95-69.24,15.33,10.08,78.09-11.88,158.77-57,222.88-45.91,66.56-113,116.56-186.38,149.18,4.17,18.84,2.68,38.34,2.91,57.52a82.9,82.9,0,0,1-13.07,46.13c-16.31,25.87-48,41-78.37,36.74-34.36-4.28-63.85-32.87-69.17-67.12-1.68-10.13-.67-20.41-1-30.64-36.6,3.57-73.45,4.87-110.13,2.23-.11,11.17.6,22.56-2.27,33.51-8.37,38.64-48.1,67.35-87.53,62.21-36.9-3.76-68.37-35.67-71.44-72.64-.36-19.51-1.21-39.76.51-58.93C294.13,874.8,231,834.48,182.6,779.94c80,36,169.69,47.88,256.62,38.91,84.74-8.42,167.42-34.93,241.85-76.1,47.5-26.51,92-58.9,130.3-97.55,42.89-42.88,78.75-93.52,101.27-150,21.56-53.25,30.45-111.63,24.91-168.86Z"/><path id="path10" class="cls-4" d="M243.11,388.83c6.81-1.09,10.71,6.37,13,11.6,7,18.92,7.47,39.87,4.16,59.61-2,9-4.24,19-11.79,25.07-5.12,3.34-10.85-1.29-13.13-5.84-7.32-12.87-8.05-28.15-8.86-42.56.53-12.76,1.71-25.88,7-37.67C235.59,394.88,238.22,390,243.11,388.83Z"/></g></svg> \ No newline at end of file diff --git a/src/components/SavingGoalComponents/SavingGoal.vue b/src/components/SavingGoalComponents/SavingGoal.vue index 87055bfd4ddaa57c1cc0559488a5c6922221da08..89cae3a4258a8c705e15c4146f8c2e479530d7d5 100644 --- a/src/components/SavingGoalComponents/SavingGoal.vue +++ b/src/components/SavingGoalComponents/SavingGoal.vue @@ -20,7 +20,7 @@ export default { if (timelineElement instanceof HTMLElement) { // Calculate the max-height based on the height of the timeline const timelineHeight = timelineElement.offsetHeight; - this.bluePanelMaxHeight = `${timelineHeight*1.25}px`; + this.bluePanelMaxHeight = `${timelineHeight*1.55}px`; } else { this.bluePanelMaxHeight = '700px'; } @@ -41,7 +41,7 @@ export default { <div class="col-lg-4 blue-background overflow-auto" :style="{ 'max-height': bluePanelMaxHeight }"> <h3 style="color: white; margin-bottom: 16px">Your saving goals</h3> <div> - <button class="btn btn-light" 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">Create new saving goal</button> </div> <saving-goal-list @goToSavingGoal="goToSavingGoal"></saving-goal-list> </div> diff --git a/src/components/SavingGoalComponents/SavingGoalCreate.vue b/src/components/SavingGoalComponents/SavingGoalCreate.vue index b23db87fafb28b31bf230da08b90f3bb56da23e6..280af93df3667458a4d0e26e20a9baee66553ca8 100644 --- a/src/components/SavingGoalComponents/SavingGoalCreate.vue +++ b/src/components/SavingGoalComponents/SavingGoalCreate.vue @@ -19,10 +19,9 @@ </div> <!--Change this to date picker?--> - <p>How long should this saving goal last: </p> + <p>When should this saving goal end?:</p> <div class="input-group mb-3"> - <input type="text" class="form-control" aria-label="Amount of days" placeholder="Amount of days (as number)"> - <span class="input-group-text">Days</span> + <input type="date" class="form-control" aria-label="Amount of days" placeholder="Amount of days (as number)"> </div> <p>How much do you want to save during this saving goal: </p> diff --git a/src/components/SavingGoalComponents/SavingGoalList.vue b/src/components/SavingGoalComponents/SavingGoalList.vue index 7ecf2ae93c323b7b8aa5bf3ec4bccc4e7ec02dc1..e792585dbd3ade07037dd7601843b58b121f5b24 100644 --- a/src/components/SavingGoalComponents/SavingGoalList.vue +++ b/src/components/SavingGoalComponents/SavingGoalList.vue @@ -2,7 +2,7 @@ import {ref} from "vue"; const savingGoalList = ref([ - { title: 'Spain trip', MoneyTarget: '200kr', description: 'You wanted to save 200kr on a spain trip' }, + { title: 'Spain trip', MoneyTarget: '200kr', description: 'You wanted to save 200kr for a spain trip' }, { title: 'Italy Escapade', MoneyTarget: '200kr', description: 'Experience the magic of Italy with us! Our goal is to save 200kr for an amazing trip to Italy.' }, { title: 'French Getaway', MoneyTarget: '200kr', description: 'Join us as we plan to save 200kr for a delightful trip to France!' }, { title: 'Exploring Greece', MoneyTarget: '200kr', description: 'Dreaming of Greece? Lets work together to save 200kr for that unforgettable trip!' }, @@ -17,6 +17,10 @@ const emits = defineEmits(['goToSavingGoal']); const goToSavingGoal = () => { emits('goToSavingGoal'); }; + +const deleteSavingGoal = () => { + +}; </script> <template> @@ -28,6 +32,7 @@ const goToSavingGoal = () => { <h5 class="card-title">{{ savingGoal.title }}</h5> <p class="card-text">{{ savingGoal.description }}</p> <a href="#" class="btn btn-light" @click="goToSavingGoal">Go to saving goal</a> + <a href="#" class="btn btn-danger" @click="deleteSavingGoal" style="margin-left: 8px">Delete</a> </div> </div> </template> diff --git a/src/components/SavingGoalComponents/SavingGoalRoadmap.vue b/src/components/SavingGoalComponents/SavingGoalRoadmap.vue index 4532527ffd38a4d8f50542bb90e6e2f4c3c05a6d..74e8d2d54cea2c9a2a0d34d0c7435b0a93f6994d 100644 --- a/src/components/SavingGoalComponents/SavingGoalRoadmap.vue +++ b/src/components/SavingGoalComponents/SavingGoalRoadmap.vue @@ -23,17 +23,31 @@ export default { bluePanelMaxHeight: 'auto' as string }; }, + mounted() { + this.togglePanel(this.steps[2]); + }, methods: { togglePanel(step: Step) { if (step.showPanel) { - // If the clicked panel is already open, close it step.showPanel = false; } else { - //Close all panels before opening new one - //Ensure only one panel open at a time this.steps.forEach((s) => (s.showPanel = false)); - //Open clicked on panel step.showPanel = true; + this.scrollToPanel(step); + } + }, + scrollToPanel(step: Step) { + if (step.showPanel) { + this.$nextTick(() => { + const panel = document.getElementById(`panel-${this.steps.indexOf(step)}`); + console.log(panel); + if (panel) { + setTimeout(() => { + panel.scrollIntoView({ behavior: 'smooth', block: 'center' }); + console.log('I should have scrolled'); + }, 100); // Wait for 1 second before scrolling + } + }); } }, }, @@ -45,10 +59,10 @@ export default { <div class="SavingGoalTitle text-center">{{title}}</div> <ul class="timeline"> <li v-for="(step, index) in steps" :key="index" :class="{ 'timeline-inverted': index % 2 !== 0 }"> - <div class="timeline-image z-1" @click="togglePanel(step)"> - <img class="circular-image" :src="step.showPanel ? altImage : image" alt=""> - </div> - <div class="timeline-panel z-3" v-show="step.showPanel"> + <div class="timeline-image z-1" @click="togglePanel(step)"> + <img class="circular-image" :src="step.showPanel ? altImage : image" alt=""> + </div> + <div class="timeline-panel z-3" :id="'panel-' + index" v-show="step.showPanel"> <div class="timeline-heading"> <h4>{{ step.title }}</h4> <h4 class="subheading">{{step.description}}</h4> @@ -83,15 +97,17 @@ export default { .col-lg-8 { width: 63%; margin-bottom: 20px; + max-height: 1000px; } .SavingGoalTitle { font-weight: 600; font-size: 45px; + margin-top: 20px; margin-bottom:40px; padding-bottom: 10px; color: white; - border-radius: 0 0 1em 1em; + border-radius: 1em; background-color: #0A58CA; } diff --git a/src/components/UserProfile/UserProfileLayout.vue b/src/components/UserProfile/UserProfileLayout.vue index 494e5aea08ee567575c8e4a430612dfbc64e4246..6734d7124f317c8e64a1a11fde23172c4058189d 100644 --- a/src/components/UserProfile/UserProfileLayout.vue +++ b/src/components/UserProfile/UserProfileLayout.vue @@ -2,9 +2,19 @@ import Menu from "@/components/BaseComponents/Menu.vue"; import Footer from "@/components/BaseComponents/Footer.vue"; +import {useRouter} from "vue-router"; + +let numberOfHistory = 6; + +let cardTitles = ["Spain tour", "Food waste", "Coffee", "Concert", "New book", "Pretty clothes"] let points = 0; let streak = 0; + +let route = useRouter() +function toRoadmap(){ + route.push('/roadmap') +} </script> <template> @@ -40,12 +50,73 @@ let streak = 0; </div> <div class="row"> <div class="col"> - History + <!-- Here is the badges of the user --> + <div class="container-fluid"> + <h1 class="mt-5 text-start badges-text">Badges</h1> + <div class="scrolling-wrapper-badges row flex-row flex-nowrap mt-4 pb-4 pt-2"> + + <div class="col-5"> + <div class="card badges-block card-1"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-2"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-3"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-4"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-5"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-6"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-7"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-8"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-9"></div> + </div> + <div class="col-5"> + <div class="card badges-block card-10"></div> + </div> + </div> + </div> </div> </div> <div class="row"> <div class="col"> - Your Badges + <!-- Here is the history of saving target --> + <div class="container-fluid mb-5"> + <h1 class="mt-5 text-start history-text">History</h1> + <div class="row scrolling-wrapper-history"> + <div v-for="index in numberOfHistory" :key="index" class="col-md-4 col-sm-4 col-lg-4 col-xs-4 col-xl-4 control-label"> + <div class="card history-block" > + <div class="card mb-3" style="max-width: 540px;"> + <div class="row g-0"> + <div class="col-md-4"> + <img src="/src/assets/icons/piggybank.svg" class="img-fluid rounded-start h-40 mx-auto d-none d-md-block" alt="..."> + </div> + <div class="col-md-8"> + <div class="card-body"> + <h5 class="card-title">{{cardTitles[index-1]}}</h5> + <p class="card-text">Money saved: 200 <br/>You are one challenge: 21</p> + <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p> + <a href="#" class="btn stretched-link" @click="toRoadmap"></a> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + + </div> </div> </div> </div> @@ -53,5 +124,107 @@ let streak = 0; </template> <style scoped> +.scrolling-wrapper-badges{ + overflow-x: auto; +} + +.scrolling-wrapper-history{ + max-height: 300px; + overflow: auto; +} + + + +.badges-text{ + font-weight: 500; + font-size: 2.0em; +} + +.history-text{ + font-weight: 500; + font-size: 2.0em; +} + +.badges-block{ + height: 200px; + background-color: #fff; + border: none; + background-position: center; + background-size: cover; + transition: all 0.2s ease-in-out !important; + border-radius: 24px; + &:hover{ + transform: translateY(-5px); + box-shadow: none; + opacity: 0.9; + } +} + +.history-block{ + height: 200px; + + background-color: #fff; + border: none; + background-position: center; + background-size: cover; + transition: all 0.2s ease-in-out !important; + border-radius: 24px; + margin: 20px; + &:hover{ + transform: translateY(-5px); + box-shadow: none; + opacity: 0.9; + } +} + +.card-1{ + background-color: #4158D0; + background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%); +} + +.card-2{ + background-color: #0093E9; + background-image: linear-gradient(160deg, #0093E9 0%, #80D0C7 100%); +} + +.card-3{ + background-color: #00DBDE; + background-image: linear-gradient(90deg, #00DBDE 0%, #FC00FF 100%); +} + +.card-4{ + background-color: #FBAB7E; + background-image: linear-gradient(62deg, #FBAB7E 0%, #F7CE68 100%); +} + +.card-5{ + background-color: #85FFBD; + background-image: linear-gradient(45deg, #85FFBD 0%, #FFFB7D 100%); +} + +.card-6{ + background-color: #FA8BFF; + background-image: linear-gradient(45deg, #FA8BFF 0%, #2BD2FF 52%, #2BFF88 90%); +} + +.card-7{ + background-color: #FA8BFF; + background-image: linear-gradient(45deg, #FA8BFF 0%, #2BD2FF 52%, #2BFF88 90%); +} + +.card-8{ + background-color: #FBDA61; + background-image: linear-gradient(45deg, #FBDA61 0%, #FF5ACD 100%); +} + +.card-9{ + background-color: #4158D0; + background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%); +} + +.card-10{ + background-color: #FF3CAC; + background-image: linear-gradient(225deg, #FF3CAC 0%, #784BA0 50%, #2B86C5 100%); +} </style> \ No newline at end of file