diff --git a/src/assets/coca.webp b/src/assets/coca.webp new file mode 100644 index 0000000000000000000000000000000000000000..4661c2228d3df393a62fa738bc92654675f6c7f4 Binary files /dev/null and b/src/assets/coca.webp differ diff --git a/src/assets/coke-ad.jpg b/src/assets/coke-ad.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61256d1286257b902528b52b8f46c36140515404 Binary files /dev/null and b/src/assets/coke-ad.jpg differ diff --git a/src/components/BaseComponents/Menu.vue b/src/components/BaseComponents/Menu.vue index 19451c8205366d367b81b2c926b2270789a362ce..2b68b01fc7633822734ce28510d0343817e39284 100644 --- a/src/components/BaseComponents/Menu.vue +++ b/src/components/BaseComponents/Menu.vue @@ -91,7 +91,7 @@ function toStore() { } function toSetting() { - router.push('/news') + router.push('/settings/profile') } function toFeedback() { diff --git a/src/components/LeaderboardComponents/Leaderboard.vue b/src/components/LeaderboardComponents/Leaderboard.vue index 735ef4c014946080061da6e7c1e991b3b6a347eb..7c036fc636865182d21961835072d210b2185118 100644 --- a/src/components/LeaderboardComponents/Leaderboard.vue +++ b/src/components/LeaderboardComponents/Leaderboard.vue @@ -3,9 +3,9 @@ <div class="ribbon"></div> <table> <tbody> - <tr v-for="(entry, index) in leaderboard" :key="entry.user.id" :class="{ 'is-user-5': entry.user.firstName === 'User' }"> + <tr v-for="(entry, index) in leaderboard" :key="entry.user?.id" :class="{ 'is-user-5': entry.user?.firstName === 'User' }"> <td class="number">{{ entry.rank }}</td> - <td class="name" @click="navigateToUserProfile(entry.user.id)">{{ entry.user.firstName }}</td> + <td class="name" @click="navigateToUserProfile(entry.user?.id ?? 0)">{{ entry.user?.firstName }}</td> <td class="points" v-if="index === 0"> {{ entry.score }} <div class="medal"> @@ -20,9 +20,9 @@ <tbody id="line">`</tbody> <tbody v-if="!userInLeaderboard"> <tr></tr> - <tr v-for="(entry, index) in leaderboardExtra" :key="entry.user.id" :class="{ 'is-user-5': entry.user.firstName === userStore.firstname }"> + <tr v-for="(entry, index) in leaderboardExtra" :key="entry.user?.id" :class="{ 'is-user-5': entry.user?.firstName === userStore.firstname }"> <td class="number">{{ entry.rank }}</td> - <td class="name" @click="navigateToUserProfile(entry.user.id)">{{ entry.user.firstName }}</td> + <td class="name" @click="navigateToUserProfile(entry.user?.id ?? 0)">{{ entry.user?.firstName }}</td> <td class="points">{{ entry.score }}</td> </tr> </tbody> @@ -36,26 +36,27 @@ import { computed } from 'vue'; import { useRouter } from 'vue-router'; import { useUserInfoStore } from '@/stores/UserStore'; +import type { LeaderboardEntryDTO } from '@/api/models/LeaderboardEntryDTO'; +import type { PropType } from 'vue'; const router = useRouter(); const userStore = useUserInfoStore(); const props = defineProps({ leaderboard: { - type: Array, + type: Array as PropType<LeaderboardEntryDTO[]>, required: true }, leaderboardExtra: { - type: Array, + type: Array as PropType<LeaderboardEntryDTO[]>, required: true } }); console.log(props.leaderboardExtra); -const userInLeaderboard = computed(() => props.leaderboard.some(entry => entry.user.email === userStore.email)); - -const navigateToUserProfile = () => { +const userInLeaderboard = computed(() => props.leaderboard.some(entry => entry.user && entry.user.email === userStore.email)); +const navigateToUserProfile = (id: number) => { router.push({ name: 'user-profile' }); }; </script> diff --git a/src/components/UserProfile/UserProfileLayout.vue b/src/components/UserProfile/UserProfileLayout.vue index 7036e347b7ad8398651125fc7a8e897c4ab5c76d..4480ec05d5f98beb2ef827b9e802641653c9c324 100644 --- a/src/components/UserProfile/UserProfileLayout.vue +++ b/src/components/UserProfile/UserProfileLayout.vue @@ -24,7 +24,7 @@ const toRoadmap = () => { // Function to navigate to update user settings const toUpdateUserSettings = () => { - router.push('/update-user'); + router.push('/settings/profile'); }; </script> diff --git a/src/router/index.ts b/src/router/index.ts index 189079a9a1423941d18bd1b0c5725c0568c530f3..06441260ef379f90343c17a1bfa2b57e21dad243 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -44,6 +44,38 @@ const routes = [ name: 'update-user', component: UpdateUserView }, + { + path: '/settings', + name: 'settings', + component: () => import('@/views/SettingsView.vue'), + children: [ + { + path: '/settings/account', + name: 'account', + component: () => import('@/views/Settings/SettingsAccountView.vue'), + }, + { + path: '/settings/profile', + name: 'profilesettings', + component: () => import('@/views/Settings/SettingsProfileView.vue'), + }, + { + path: '/settings/security', + name: 'security', + component: () => import('@/views/Settings/SettingsSecurityView.vue'), + }, + { + path: '/settings/notification', + name: 'notification', + component: () => import('@/views/Settings/SettingsNotificationView.vue'), + }, + { + path: '/settings/bank', + name: 'bank', + component: () => import('@/views/Settings/SettingsBankView.vue'), + }, + ] + }, { path: 'roadmap', name: 'roadmap', diff --git a/src/views/BasePageView.vue b/src/views/BasePageView.vue index e46d41355401bd1467b00b2f20a44a6c14859987..a9780ec71399880d811a9690ddc028b96ec94d17 100644 --- a/src/views/BasePageView.vue +++ b/src/views/BasePageView.vue @@ -5,9 +5,16 @@ import Menu from '@/components/BaseComponents/Menu.vue' </script> <template> + <Menu></Menu> + <div style="display: flex; flex-direction: row;"> + <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;"> + </div> <div> <RouterView /> </div> + <div style="display: flex; flex-direction: row;"> + <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;"> + </div> <Footer></Footer> </template> \ No newline at end of file diff --git a/src/views/LeaderboardView.vue b/src/views/LeaderboardView.vue index 16b4ae404a28b1fa484d981980f072ce8fa8824d..8be05c6a348a0ecd3a1e295fcee44c0922cff104 100644 --- a/src/views/LeaderboardView.vue +++ b/src/views/LeaderboardView.vue @@ -26,6 +26,8 @@ </div> <div id="leaderboard"> <h1><img src="@/assets/icons/fire.png" style="width: 2rem"> Highest streak</h1> + let streakLeaderboardData = ref([] as LeaderboardEntryDTO[]); + let streakLeaderboardDataExtra = ref([] as LeaderboardEntryDTO[]); <Leaderboard :leaderboard="streakLeaderboardData" :leaderboardExtra="streakLeaderboardDataExtra" @navigateToUserProfile="navigateToUserProfile" /> </div> </main> @@ -37,19 +39,20 @@ </template> <script setup lang="ts"> -import { onMounted, ref } from 'vue'; +import { onMounted, ref, type PropType } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import Leaderboard from '@/components/LeaderboardComponents/Leaderboard.vue'; import { on } from 'events'; -import { LeaderboardService, UserControllerService } from '@/api'; +import { LeaderboardService } from '@/api'; +import type { LeaderboardEntryDTO } from '@/api/models/LeaderboardEntryDTO'; -let streakLeaderboardData = ref([]); -let currentLeaderboardData = ref([]); -let pointsLeaderboardData = ref([]); +let streakLeaderboardData = ref([] as any); +let currentLeaderboardData = ref([] as any); +let pointsLeaderboardData = ref([] as any); -let streakLeaderboardDataExtra = ref([]); -let currentLeaderboardDataExtra = ref([]); -let pointsLeaderboardDataExtra = ref([]); +let streakLeaderboardDataExtra = ref([] as any); +let currentLeaderboardDataExtra = ref([] as any); +let pointsLeaderboardDataExtra = ref([] as any); const router = useRouter(); diff --git a/src/views/Settings/SettingsAccountView.vue b/src/views/Settings/SettingsAccountView.vue new file mode 100644 index 0000000000000000000000000000000000000000..f3d2c54bd951805dd072af5d700c661f52dec5f1 --- /dev/null +++ b/src/views/Settings/SettingsAccountView.vue @@ -0,0 +1,41 @@ +<script setup lang="ts"> +import { ref, onMounted } from 'vue'; +import BaseInput from '@/components/InputFields/BaseInput.vue'; +import { useUserInfoStore } from "@/stores/UserStore"; + +const firstNameRef = ref() +const surnameRef = ref('') +const emailRef = ref('') +const passwordRef = ref('') +const confirmPasswordRef = ref('') +const formRef = ref() +let samePasswords = ref(true) + +</script> + +<template> + <div class="tab-pane active" id="account"> + <h6>ACCOUNT SETTINGS</h6> + <hr> + <form> + <div class="form-group"> + <BaseInput :model-value="firstNameRef" @input-change-event="handleFirstNameInputEvent" + id="firstNameInputChange" input-id="first-name-new" type="text" label="Username" + placeholder="Enter your username" invalid-message="Please enter your username" /> + </div> + <br> + <div class="form-group"> + <BaseInput :model-value="emailRef" @input-change-event="handleEmailInputEvent" id="emailInput-change" + input-id="email-new" type="email" label="Email" placeholder="Enter your email" + invalid-message="Invalid email" /> + </div> + <hr> + <div class="form-group"> + <label class="d-block text-danger">Delete Account</label> + <p class="text-muted font-size-sm">Once you delete your account, there is no going + back. Please be certain.</p> + </div> + <button class="btn btn-danger" type="button">Delete Account</button> + </form> + </div> +</template> \ No newline at end of file diff --git a/src/views/Settings/SettingsBankView.vue b/src/views/Settings/SettingsBankView.vue new file mode 100644 index 0000000000000000000000000000000000000000..919bcd750256b857b4ebe31bd9d4e23e59fbb330 --- /dev/null +++ b/src/views/Settings/SettingsBankView.vue @@ -0,0 +1,30 @@ +<template> + <div class="tab-pane active" id="billing"> + <h6>BILLING SETTINGS</h6> + <hr> + <form> + <div class="form-group"> + <label class="d-block mb-0">Spending account</label> + <select class="form-control form-control-lg"> + <option>9175 5942 5431 5712</option> + <option>5175 5942 5431 5712</option> + <option>4175 5942 5431 5712</option> + </select> + </div> + <div class="form-group"> + <label class="d-block mb-0">Savings account</label> + <select class="form-control form-control-lg"> + <option>2175 5942 5431 5712</option> + <option>1175 5942 5431 5712</option> + </select> + <br> + </div> + <hr> + <div class="form-group mb-0"> + <label class="d-block">Payment History</label> + <div class="border border-gray-500 bg-gray-200 p-3 text-center font-size-sm">You + have not made any payment.</div> + </div> + </form> + </div> +</template> \ No newline at end of file diff --git a/src/views/Settings/SettingsNotificationView.vue b/src/views/Settings/SettingsNotificationView.vue new file mode 100644 index 0000000000000000000000000000000000000000..233614f32b4d2ecf3d44920879666b16bf7b2628 --- /dev/null +++ b/src/views/Settings/SettingsNotificationView.vue @@ -0,0 +1,64 @@ +<template> + <div class="tab-pane active" id="notification"> + <h6>NOTIFICATION SETTINGS</h6> + <hr> + <form> + <div class="form-group"> + <label class="d-block mb-0">Security Alerts</label> + <div class="small text-muted mb-3">Receive security alert notifications via email + </div> + <div class="custom-control custom-checkbox"> + <input type="checkbox" class="custom-control-input" id="customCheck1" checked=""> + <label class="custom-control-label" for="customCheck1">Email each time a + vulnerability is found</label> + </div> + <div class="custom-control custom-checkbox"> + <input type="checkbox" class="custom-control-input" id="customCheck2" checked=""> + <label class="custom-control-label" for="customCheck2">Email a digest summary of + vulnerability</label> + </div> + </div> + <div class="form-group mb-0"> + <label class="d-block">SMS Notifications</label> + <ul class="list-group list-group-sm"> + <li class="list-group-item has-icon"> + Comments + <div class="custom-control custom-control-nolabel custom-switch ml-auto"> + <input type="checkbox" class="custom-control-input" id="customSwitch1" checked=""> + <label class="custom-control-label" for="customSwitch1"></label> + </div> + </li> + <li class="list-group-item has-icon"> + Updates From People + <div class="custom-control custom-control-nolabel custom-switch ml-auto"> + <input type="checkbox" class="custom-control-input" id="customSwitch2"> + <label class="custom-control-label" for="customSwitch2"></label> + </div> + </li> + <li class="list-group-item has-icon"> + Reminders + <div class="custom-control custom-control-nolabel custom-switch ml-auto"> + <input type="checkbox" class="custom-control-input" id="customSwitch3" checked=""> + <label class="custom-control-label" for="customSwitch3"></label> + </div> + </li> + <li class="list-group-item has-icon"> + Events + <div class="custom-control custom-control-nolabel custom-switch ml-auto"> + <input type="checkbox" class="custom-control-input" id="customSwitch4" checked=""> + <label class="custom-control-label" for="customSwitch4"></label> + </div> + </li> + <li class="list-group-item has-icon"> + Pages You Follow + <div class="custom-control custom-control-nolabel custom-switch ml-auto"> + <input type="checkbox" class="custom-control-input" id="customSwitch5"> + <label class="custom-control-label" for="customSwitch5"></label> + </div> + </li> + </ul> + </div> + </form> + </div> + +</template> \ No newline at end of file diff --git a/src/views/Settings/SettingsProfileView.vue b/src/views/Settings/SettingsProfileView.vue new file mode 100644 index 0000000000000000000000000000000000000000..e082b050b85b9654f1af815a952137422c235dc1 --- /dev/null +++ b/src/views/Settings/SettingsProfileView.vue @@ -0,0 +1,56 @@ +<script setup lang="ts"> +import { ref, onMounted } from 'vue'; +import BaseInput from '@/components/InputFields/BaseInput.vue'; +import { useUserInfoStore } from "@/stores/UserStore"; + +const firstNameRef = ref() +const surnameRef = ref('') +const emailRef = ref('') +const passwordRef = ref('') +const confirmPasswordRef = ref('') +const formRef = ref() +let samePasswords = ref(true) + +</script> + + +<template> + <div class="tab-pane active" id="profile"> + <h6>YOUR PROFILE INFORMATION</h6> + <hr> + <form> + <div class="user-avatar"> + <img id="icon" src="https://bootdey.com/img/Content/avatar/avatar7.png" alt="Maxwell Admin"> + </div> + <div class="btn"> + <div class="mt-2"> + <span class="btn btn-primary"><img src="@/assets/icons/download.svg"></span> + </div> + </div> + <div class="form-group"> + <BaseInput :model-value="firstNameRef" @input-change-event="handleFirstNameInputEvent" + id="firstNameInputChange" input-id="first-name-new" type="text" label="First name" + placeholder="Enter your first name" invalid-message="Please enter your first name" /> + </div> + <br> + <div class="form-group"> + <BaseInput :model-value="surnameRef" @input-change-event="handleSurnameInputEvent" + id="surnameInput-change" input-id="surname-new" type="text" label="Surname" + placeholder="Enter your surname" invalid-message="Please enter your surname" /> + </div> + <br> + <button type="button" class="btn btn-primary">Update Profile</button> + <button type="reset" class="btn btn-light">Reset Changes</button> + </form> + </div> +</template> + +<style scoped> + #icon { + width: 90px; + height: 90px; + -webkit-border-radius: 100px; + -moz-border-radius: 100px; + border-radius: 100px; +} +</style> \ No newline at end of file diff --git a/src/views/Settings/SettingsSecurityView.vue b/src/views/Settings/SettingsSecurityView.vue new file mode 100644 index 0000000000000000000000000000000000000000..7a630539a52df8d8aa62ff711c9fc3e893fb01c9 --- /dev/null +++ b/src/views/Settings/SettingsSecurityView.vue @@ -0,0 +1,17 @@ +<template> + <div class="tab-pane active" id="security"> + <h6>SECURITY SETTINGS</h6> + <hr> + <form> + <div class="form-group"> + <label class="d-block">Change Password</label> + <input type="text" class="form-control" placeholder="Enter your old password"> + <input type="text" class="form-control mt-1" placeholder="New password"> + <input type="text" class="form-control mt-1" placeholder="Confirm new password"> + </div> + <button type="button" class="btn btn-primary">Update Password</button> + <button type="reset" class="btn btn-light">Reset Changes</button> + </form> + <hr> + </div> +</template> \ No newline at end of file diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue new file mode 100644 index 0000000000000000000000000000000000000000..195694c4eb50a14a7eaabaa324c6876bd01b7e3d --- /dev/null +++ b/src/views/SettingsView.vue @@ -0,0 +1,245 @@ +<script setup lang="ts"> +import { ref } from 'vue' +import { useRouter } from 'vue-router' + +const router = useRouter(); + +const activeLink = ref('/settings/profile'); // Default active link + +function setActive(link: string) { + activeLink.value = link; +} + +function toProfile() { + router.push('/settings/profile') +} + +function toAccount() { + router.push('/settings/account') +} + +function toSecurity() { + router.push('/settings/security') +} + +function toNotification() { + router.push('/settings/notification') +} + +function toBilling() { + router.push('/settings/bank') +} + +</script> + +<template> + <div class="container"> + + <div class="row gutters-sm"> + <div class="col-md-3 d-none d-md-block"> + <div class="card"> + <div class="card-body"> + <nav class="nav flex-column nav-pills nav-gap-y-1"> + + <a @click.prevent="setActive('/settings/profile')" @click="toProfile" + :class="['nav-item nav-link has-icon', { 'nav-link-faded': activeLink !== '/settings/profile', 'active': activeLink === '/settings/profile' }]"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-user mr-2"> + <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> + <circle cx="12" cy="7" r="4"></circle> + </svg> + Profile + </a> + + + <a @click.prevent="setActive('/settings/account')" @click="toAccount" + :class="['nav-item nav-link has-icon', { 'nav-link-faded': activeLink !== '/settings/account', 'active': activeLink === '/settings/account' }]"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-settings mr-2"> + <circle cx="12" cy="12" r="3"></circle> + <path + d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"> + </path> + </svg> + Account + </a> + + + <a @click.prevent="setActive('/settings/security')" @click="toSecurity" + :class="['nav-item nav-link has-icon', { 'nav-link-faded': activeLink !== '/settings/security', 'active': activeLink === '/settings/security' }]"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-shield mr-2"> + <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> + </svg> + Security + </a> + + + <a @click.prevent="setActive('/settings/notification')" @click="toNotification" + :class="['nav-item nav-link has-icon', { 'nav-link-faded': activeLink !== '/settings/notification', 'active': activeLink === '/settings/notification' }]"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-bell mr-2"> + <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path> + <path d="M13.73 21a2 2 0 0 1-3.46 0"></path> + </svg>Notification + </a> + <a> + <a @click.prevent="setActive('/settings/bank')" @click="toBilling" + :class="['nav-item nav-link has-icon', { 'nav-link-faded': activeLink !== '/settings/bank', 'active': activeLink === '/settings/bank' }]"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-credit-card mr-2"> + <rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect> + <line x1="1" y1="10" x2="23" y2="10"></line> + </svg> + Bank + </a> + </a> + + + + </nav> + </div> + </div> + </div> + + + <div class="col-md-8"> + <div class="card"> + + + <!-- Tab panes --> + <div class="card-header border-bottom mb-3 d-flex d-md-none"> + <ul class="nav nav-tabs card-header-tabs nav-gap-x-1" role="tablist"> + <li class="nav-item"> + <a href="#profile" data-toggle="tab" class="nav-link has-icon active"><svg + xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-user"> + <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> + <circle cx="12" cy="7" r="4"></circle> + </svg></a> + </li> + <li class="nav-item"> + <a href="#account" data-toggle="tab" class="nav-link has-icon"><svg + xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-settings"> + <circle cx="12" cy="12" r="3"></circle> + <path + d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"> + </path> + </svg></a> + </li> + <li class="nav-item"> + <a href="#security" data-toggle="tab" class="nav-link has-icon"><svg + xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-shield"> + <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> + </svg></a> + </li> + <li class="nav-item"> + <a href="#notification" data-toggle="tab" class="nav-link has-icon"><svg + xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-bell"> + <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path> + <path d="M13.73 21a2 2 0 0 1-3.46 0"></path> + </svg></a> + </li> + <li class="nav-item"> + <a href="#billing" data-toggle="tab" class="nav-link has-icon"><svg + xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" + stroke-linejoin="round" class="feather feather-credit-card"> + <rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect> + <line x1="1" y1="10" x2="23" y2="10"></line> + </svg></a> + </li> + </ul> + </div> + + <div class="card-body tab-content"> + <RouterView></RouterView> + </div> + </div> + </div> + </div> + </div> + +</template> + +<style scoped> +.container { + margin-top: 2rem; + margin-bottom: 4rem; +} + +.main-body { + padding: 15px; +} + +.nav-link { + color: #4a5568; +} + +.card { + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06); +} + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 0 solid rgba(0, 0, 0, .125); + border-radius: .25rem; +} + +.card-body { + flex: 1 1 auto; + min-height: 1px; + padding: 1rem; +} + +.gutters-sm { + margin-right: -8px; + margin-left: -8px; +} + +.gutters-sm>.col, +.gutters-sm>[class*=col-] { + padding-right: 8px; + padding-left: 8px; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.bg-gray-300 { + background-color: #e2e8f0; +} + +.h-100 { + height: 100% !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.routerLink { + text-decoration: none; + color: #4a5568; +} +</style> \ No newline at end of file