Skip to content

Commit

Permalink
32 dashboard page (#56)
Browse files Browse the repository at this point in the history
* create pages/sbc/dashboard file
* update header with main nav links
* create dashboard layout and rename other layout files
* create dashboard sub header component
* add translations for dashboard subheader
* separate tab sections into components
* add name input to api key modal, fix dark mode colours
* make api key copyable
* create modal on revoke api click
* add translations for dashboard page
* start full screen menu for mobile menu
* separate content nav creation into utils
* provide nav item values in layouts to main header component
* add mobile menu sub items
* fix mobile styling for dashboard sub header
* set ssr back to true
  • Loading branch information
deetz99 authored Mar 16, 2024
1 parent ece110b commit 8a14309
Show file tree
Hide file tree
Showing 25 changed files with 1,057 additions and 199 deletions.
115 changes: 102 additions & 13 deletions web/site/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,116 @@ export default defineAppConfig({
}
},
button: {
color: {
white: {
link: 'text-white text-base font-semibold tracking-wide dark:text-white hover:bg-white/[0.1] dark:bg-gray-900 dark:hover:bg-gray-800/75 focus-visible:ring-2 focus-visible:ring-white dark:focus-visible:ring-white transition-colors duration-300 ease-in-out',
solid: 'shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-900 dark:text-white bg-white hover:bg-gray-50 disabled:bg-white dark:bg-gray-900 dark:hover:bg-gray-800/50 dark:disabled:bg-gray-900 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-white'
}
},
variant: {
accordian_trigger: 'text-bcGovColor-darkGray font-semibold dark:text-white dark:hover:bg-bcGovBlue-100/10 hover:bg-bcGovBlue-50 disabled:bg-{color}-500 dark:disabled:bg-{color}-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-{color}-500 dark:focus-visible:outline-white transition-colors duration-300 ease-in-out',
link: 'text-{color}-500 tracking-wide text-base hover:text-{color}-600 disabled:text-{color}-500 dark:text-white dark:hover:text-bcGovBlue-300 dark:disabled:text-{color}-400 underline-offset-4 hover:underline focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-{color}-500 dark:focus-visible:ring-white',
solid: 'shadow-sm text-white dark:text-gray-900 bg-{color}-500 hover:bg-{color}-600 disabled:bg-{color}-500 dark:bg-[#E0E7ED] dark:hover:bg-bcGovGray-500 dark:disabled:bg-{color}-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-{color}-500 dark:focus-visible:outline-white',
outline: 'ring-1 ring-inset ring-current text-{color}-500 dark:text-[#E0E7ED] hover:bg-{color}-50 disabled:bg-transparent dark:hover:bg-[#E0E7ED]/25 dark:disabled:bg-transparent focus-visible:ring-2 focus-visible:ring-{color}-500 dark:focus-visible:ring-white'
}
},
card: {
ring: 'ring-1 ring-gray-200 dark:ring-gray-300/50',
divide: 'divide-y divide-gray-200 dark:divide-gray-300/50'
},
divider: {
border: {
base: 'flex border-bcGovGray-500 dark:border-gray-300/50'
}
},
pagination: {
wrapper: 'flex items-center -space-x-px',
base: '',
rounded: 'first:rounded-s-md last:rounded-e-md',
default: {
size: 'sm',
activeButton: {
color: 'primary'
},
inactiveButton: {
color: 'white'
},
firstButton: {
color: 'white',
class: 'rtl:[&_span:first-child]:rotate-180',
icon: 'i-heroicons-chevron-double-left-20-solid'
},
lastButton: {
color: 'white',
class: 'rtl:[&_span:last-child]:rotate-180',
icon: 'i-heroicons-chevron-double-right-20-solid'
},
prevButton: {
color: 'white',
class: 'rtl:[&_span:first-child]:rotate-180',
icon: 'i-heroicons-chevron-left-20-solid'
},
nextButton: {
color: 'white',
class: 'rtl:[&_span:last-child]:rotate-180',
icon: 'i-heroicons-chevron-right-20-solid'
}
}
},
table: {
divide: 'divide-y divide-gray-300 dark:divide-gray-300/50',
tbody: 'divide-y divide-gray-200 dark:divide-gray-300/50',
th: {
color: 'text-bcGovColor-darkGray dark:text-white'
},
td: {
color: 'text-bcGovColor-midGray dark:text-gray-300'
}
},
tabs: {
wrapper: 'relative space-y-2',
container: 'relative w-full',
base: 'focus:outline-none',
list: {
base: 'relative',
background: 'bg-gray-200 dark:bg-gray-800',
rounded: 'rounded-lg',
shadow: '',
padding: 'p-1',
height: 'h-10',
width: 'w-full',
marker: {
wrapper: 'absolute top-[4px] left-[4px] duration-200 ease-out focus:outline-none',
base: 'w-full h-full',
background: 'bg-white dark:bg-gray-900',
rounded: 'rounded-md',
shadow: 'shadow-sm'
},
tab: {
base: 'relative inline-flex items-center justify-center flex-shrink-0 w-full ui-focus-visible:outline-0 ui-focus-visible:ring-2 ui-focus-visible:ring-primary-500 dark:ui-focus-visible:ring-white dark:focus-visible:ring-white ui-not-focus-visible:outline-none focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors duration-200 ease-out',
background: '',
active: 'text-bcGovColor-activeBlue font-semibold dark:text-white',
inactive: 'text-bcGovColor-darkGray dark:text-gray-300',
height: 'h-8',
padding: 'px-3',
size: 'text-sm',
font: 'font-medium',
rounded: 'rounded-md',
shadow: ''
}
}
},
toggle: {
active: 'bg-{color}-500 dark:bg-{color}-500',
inactive: 'bg-gray-200 dark:bg-gray-700',
ring: 'focus-visible:ring-2 focus-visible:ring-{color}-500 dark:focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-white',
container: {
base: 'pointer-events-none relative inline-block rounded-full bg-white dark:bg-white shadow transform ring-0 transition ease-in-out duration-200'
}
},
verticalNavigation: {
wrapper: 'border-s border-gray-500 dark:border-[#94A3B8] space-y-2',
base: 'group block border-s -ms-px leading-6 before:hidden focus-visible:rounded',
padding: 'p-0 ps-4',
rounded: '',
font: '',
ring: 'focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-white',
active: 'text-primary-500 dark:text-[#7BB5EF] border-[#94A3B8] dark:border-[#7BB5EF] font-semibold',
inactive: 'border-transparent hover:border-gray-900 dark:hover:border-white text-gray-700 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white'
active: 'text-bcGovColor-activeBlue dark:text-white font-semibold',
inactive: 'text-bcGovColor-midGray dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:before:bg-gray-50 dark:hover:before:bg-gray-800/50'
}
}
})

// declare module '@nuxt/schema' {
// interface AppConfigInput {
// }
// }
29 changes: 15 additions & 14 deletions web/site/app.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
// const { locale } = useI18n()
const { locale } = useI18n()
const i18nHead = useLocaleHead({
addDirAttribute: true,
addSeoAttributes: true
Expand All @@ -12,20 +12,21 @@ useHead({
}
})
// const { data: navigation } = await useAsyncData(
// 'content-navigation',
// () => {
// return queryContent()
// .where({ _locale: locale.value, _extension: { $eq: 'md' } })
// .sort({ _dir: 1 })
// .find()
// },
// {
// watch: [locale]
// }
// )
// fetch content files using composable from nuxt-content https://content.nuxt.com/composables/fetch-content-navigation
const { data: navigation } = await useAsyncData(
'content-navigation',
() => fetchContentNavigation(
queryContent('products') // pass custom query to fetchContentNavigation
.where({ _locale: locale.value, _extension: { $eq: 'md' } }) // only return md files that match current locale
.sort({ _dir: 1 }) // sort alphabetically
), {
watch: [locale] // fetch new values whenever the locale changes
}
)
// const navKey = Symbol('content-nav') as InjectionKey<string>
// console.log(navigation.value)
provide('navKey', navigation)
</script>
<template>
<NuxtLayout>
Expand Down
49 changes: 49 additions & 0 deletions web/site/components/Sbc/AccordianNavigation.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
defineProps<{
navItems: AccordianNavItem[] | undefined
}>()
</script>
<template>
<div class="flex flex-col">
<!-- creates an accordian for each object in navItems array -->
<UAccordion
:items="navItems || []"
multiple
>
<!-- default slot is the accordian button itself, so we use a custom button variant here to match theme -->
<template #default="{ item, open }">
<UButton
variant="accordian_trigger"
>
<span class="truncate">{{ item.label }}</span>

<template #trailing>
<UIcon
name="i-mdi-menu-up"
class="ms-auto size-7 transition-transform duration-200"
:class="[!open && 'rotate-180']"
/>
</template>
</UButton>
</template>
<!-- item slot is the content inside each accordian, so for each accordian item, pass the children array into UVerticalNavigation -->
<template #item="{ item }">
<UVerticalNavigation
class="mx-2"
:links="item.children"
:ui="{
wrapper: 'border-s border-gray-500 dark:border-[#94A3B8] space-y-2',
base: 'group block border-s -ms-px leading-6 before:hidden focus-visible:rounded',
padding: 'p-0 ps-4',
rounded: '',
font: '',
ring: 'focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-white',
active: 'text-primary-500 dark:text-[#7BB5EF] border-[#94A3B8] dark:border-[#7BB5EF] font-semibold',
inactive: 'border-transparent hover:border-gray-900 dark:hover:border-white text-gray-700 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white'
}"
/>
</template>
</UAccordion>
</div>
</template>
58 changes: 58 additions & 0 deletions web/site/components/Sbc/Dashboard/Modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script setup lang="ts">
// import type { FormError, FormSubmitEvent } from '#ui/types'
defineProps<{
title: string,
content: string,
formLabel: string,
submitFn: Function
}>()
const modalOpen = defineModel({ type: Boolean, default: false })
const state = reactive({
name: undefined
})
// const validate = (state: any): FormError[] => {
// const errors = []
// if (!state.name) {
// errors.push({ path: 'name', message: 'Required' })
// }
// return errors
// }
// function onSubmit (event: FormSubmitEvent<any>) {
// // Do something with data
// console.log(event.data)
// }
watch(modalOpen, () => {
if (!modalOpen.value) {
state.name = undefined
}
})
</script>
<template>
<UModal v-model="modalOpen">
<UCard>
<template #header>
<div class="flex flex-col">
<span class="text-lg font-semibold text-bcGovColor-darkGray dark:text-white">{{ title }}</span>
</div>
</template>
<span class="text-bcGovColor-midGray dark:text-[#d1d5db]">{{ content }}</span>
<template #footer>
<UForm :state="state" class="space-y-4" autocomplete="off" @submit="submitFn">
<UFormGroup label="Name" name="name">
<UInput v-model="state.name" />
</UFormGroup>

<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
</UCard>
</UModal>
</template>
33 changes: 33 additions & 0 deletions web/site/components/Sbc/Dashboard/ProfileCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
</script>
<template>
<UCard>
<template #header>
<div class="flex items-center gap-4">
<UAvatar
size="3xl"
src="https://avatars.githubusercontent.com/u/739984?v=4"
alt="Avatar"
/>
<div class="flex flex-col">
<span class="text-lg font-semibold text-bcGovColor-darkGray dark:text-white">John Doe</span>
<span class="text-bcGovColor-midGray dark:text-[#d1d5db]">[email protected]</span>
</div>
</div>
</template>

<UFormGroup label="Name" name="name" class="mb-3">
<UInput v-model="accountForm.name" />
</UFormGroup>
<UFormGroup label="Username" name="username">
<UInput v-model="accountForm.username" />
</UFormGroup>

<template #footer>
<UButton type="submit" color="black">
Save account
</UButton>
</template>
</UCard>
</template>
34 changes: 34 additions & 0 deletions web/site/components/Sbc/Dashboard/SubHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script setup lang="ts">
const sandboxMode = ref(false)
</script>
<template>
<div
class="w-full border-b p-2 sm:px-4"
:class="sandboxMode ? 'bg-bcGovColor-navDivider dark:border-bcGovColor-navDivider' : 'bg-white dark:bg-bcGovColor-darkGray border-bcGovGray-500'"
>
<div class="relative m-auto flex h-full max-w-[1360px] flex-col items-center justify-between gap-2 sm:flex-row">
<span
v-if="sandboxMode"
class="flex items-center gap-1 text-bcGovColor-darkGray lg:absolute lg:left-1/2 lg:-translate-x-1/2"
>
<span class="inline-flex pb-0.5 align-middle">
<UIcon name="i-mdi-information-slab-circle scale-150 mr-2" />
</span>
<span>{{ $t('page.dashboard.sandboxMode.infoText') }}</span>
</span>
<span
class="ml-auto whitespace-nowrap font-semibold"
:class="sandboxMode ? 'text-bcGovColor-darkGray' : 'dark:text-white'"
>
{{ $t('page.dashboard.sandboxMode.text') }}
<span class="ml-1 inline-flex align-middle">
<UToggle
v-model="sandboxMode"
size="lg"
:aria-label="sandboxMode ? $t('page.dashboard.sandboxMode.btnActive') : $t('page.dashboard.sandboxMode.btnInactive')"
/>
</span>
</span>
</div>
</div>
</template>
Loading

0 comments on commit 8a14309

Please sign in to comment.