Env swap #21
| @ -9,14 +9,19 @@ | ||||
|             <component :is="Component" /> | ||||
|           </transition> | ||||
|         </router-view> | ||||
|         <button @click.prevent="showToast('howdy', 'danger')">Show toast</button> | ||||
|       </main> | ||||
|       <app-footer /> | ||||
|       <div aria-live="polite" aria-atomic="true"> | ||||
|         <div class="toast-container position-absolute p-3 bottom-0 start-50 translate-middle-x" id="toasts"></div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue' | ||||
| import { Toast } from 'bootstrap' | ||||
| import AppFooter from './components/layout/AppFooter.vue' | ||||
| import AppNav from './components/layout/AppNav.vue' | ||||
| import TitleBar from './components/layout/TitleBar.vue' | ||||
| @ -30,6 +35,11 @@ export default defineComponent({ | ||||
|     AppFooter, | ||||
|     AppNav, | ||||
|     TitleBar | ||||
|   }, | ||||
|   setup () { | ||||
|     return { | ||||
|       showToast | ||||
|     } | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| @ -42,6 +52,33 @@ export default defineComponent({ | ||||
| export function yesOrNo (cond : boolean) : string { | ||||
|   return cond ? 'Yes' : 'No' | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Show a toast notification | ||||
|  * | ||||
|  * @param text The text of the notification | ||||
|  * @param type The type of notification to show (defaults to 'success') | ||||
|  * @param heading The optional text to use for the heading | ||||
|  */ | ||||
| export function showToast (text : string, type = 'success', heading : string | undefined) : void { | ||||
|   let header : HTMLDivElement | undefined | ||||
|   if (heading) { | ||||
|     header = document.createElement('div') | ||||
|     header.className = 'toast-header' | ||||
|     header.innerHTML = 'The Header' | ||||
|   } | ||||
|   const body = document.createElement('div') | ||||
|   body.className = 'toast-body' | ||||
|   body.innerHTML = text | ||||
| 
 | ||||
|   const toast = document.createElement('div') | ||||
|   if (header) toast.appendChild(header) | ||||
|   toast.appendChild(body) | ||||
|   toast.className = `toast bg-${type} text-white` | ||||
| 
 | ||||
|   ;(document.getElementById('toasts') as HTMLDivElement).appendChild(toast) | ||||
|   new Toast(toast).show() | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="sass"> | ||||
|  | ||||
| @ -1,14 +1,16 @@ | ||||
| <template> | ||||
|   <article class="container"> | ||||
|     <page-title title="Dashboard" /> | ||||
|     <h3>Welcome, {{user.name}}</h3> | ||||
|     <h3 class="pb-4">Welcome, {{user.name}}</h3> | ||||
|     <load-data :load="retrieveData"> | ||||
|       <div class="row row-cols-1 row-cols-md-2"> | ||||
|         <div class="col"> | ||||
|           <div class="card h-100"> | ||||
|             <h5 class="card-header">Your Profile</h5> | ||||
|             <div class="card-body"> | ||||
|               <h6 class="card-subtitle mb-3 text-muted">Last updated <full-date :date="profile.lastUpdatedOn" /></h6> | ||||
|               <h6 class="card-subtitle mb-3 text-muted fst-italic"> | ||||
|                 Last updated <full-date :date="profile.lastUpdatedOn" /> | ||||
|               </h6> | ||||
|               <p v-if="profile" class="card-text"> | ||||
|                 Your profile currently lists {{profile.skills.length}} | ||||
|                 skill<template v-if="profile.skills.length !== 1">s</template>. | ||||
| @ -36,7 +38,7 @@ | ||||
|           <div class="card h-100"> | ||||
|             <h5 class="card-header">Other Citizens</h5> | ||||
|             <div class="card-body"> | ||||
|               <h6 class="card-subtitle mb-3 text-muted"> | ||||
|               <h6 class="card-subtitle mb-3 text-muted fst-italic"> | ||||
|                 <template v-if="profileCount === 0">No</template><template v-else>{{profileCount}} Total</template> | ||||
|                 Employment Profile<template v-if="profileCount !== 1">s</template> | ||||
|               </h6> | ||||
|  | ||||
| @ -111,8 +111,8 @@ import { useRouter } from 'vue-router' | ||||
| import api, { Citizen, LogOnSuccess, Profile, ProfileForm } from '@/api' | ||||
| import { useStore } from '@/store' | ||||
| 
 | ||||
| import MarkdownEditor from '@/components/MarkdownEditor.vue' | ||||
| import LoadData from '@/components/LoadData.vue' | ||||
| import MarkdownEditor from '@/components/MarkdownEditor.vue' | ||||
| import ProfileSkillEdit from '@/components/profile/SkillEdit.vue' | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| @ -197,6 +197,11 @@ export default defineComponent({ | ||||
|       profile.value = form | ||||
|     } | ||||
| 
 | ||||
|     /** Save the current profile values */ | ||||
|     const saveProfile = async () => { | ||||
|       // TODO | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       retrieveData, | ||||
|       user, | ||||
| @ -205,6 +210,7 @@ export default defineComponent({ | ||||
|       continents: computed(() => store.state.continents), | ||||
|       addSkill, | ||||
|       removeSkill, | ||||
|       saveProfile, | ||||
|       viewProfile: () => router.push(`/profile/view/${user.citizenId}`) | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -3,8 +3,8 @@ | ||||
|   <page-title title="Success Story" /> | ||||
|     <load-data :load="retrieveStory"> | ||||
|       <h3>{{citizenName}}’s Success Story</h3> | ||||
|       <h4><full-date-time :date="story.recordedOn" /></h4> | ||||
|       <p v-if="story.fromHere"><em><strong>Found via Jobs, Jobs, Jobs</strong></em></p> | ||||
|       <h4 class="text-muted"><full-date-time :date="story.recordedOn" /></h4> | ||||
|       <p v-if="story.fromHere" class="fst-italic"><strong>Found via Jobs, Jobs, Jobs</strong></p> | ||||
|       <hr> | ||||
|       <div v-if="story.story" v-html="successStory"></div> | ||||
|     </load-data> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user