Skip to content

Commit

Permalink
refact: web: tweak ui (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
crlssn authored Dec 14, 2024
1 parent cce0c30 commit 0e51cc7
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 59 deletions.
4 changes: 2 additions & 2 deletions web/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import UserDashboard from '@/ui/components/UserDashboard.vue'
import AppDashboard from '@/ui/components/AppDashboard.vue'
const authStore = useAuthStore()
</script>

<template>
<UserDashboard v-if="authStore.accessToken" />
<AppDashboard v-if="authStore.authorised()" />
<RouterView v-else />
</template>
5 changes: 5 additions & 0 deletions web/src/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { usePageTitleStore } from '@/stores/pageTitle'
import { logout as logoutRequest } from '@/http/requests.ts'
import { useNotificationStore } from '@/stores/notifications.ts'
import { createRouter, createWebHistory, type Router } from 'vue-router'
import { useActionButton } from '@/stores/actionButton.ts'

const router: Router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
Expand Down Expand Up @@ -191,8 +192,12 @@ const router: Router = createRouter({
})

router.beforeEach((to, from, next) => {
const actionButton = useActionButton()
actionButton.reset()

const pageTitleStore = usePageTitleStore()
pageTitleStore.setPageTitle(to.meta.title as string)

next()
})

Expand Down
29 changes: 29 additions & 0 deletions web/src/stores/actionButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { computed, type FunctionalComponent, ref } from 'vue'
import { defineStore } from 'pinia'

interface Button {
action: () => void
icon: FunctionalComponent
}

export const useActionButton = defineStore('actionButton', () => {
const a = ref(() => {})
const i = ref<FunctionalComponent>()

const set = (button: Button) => {
// action: () => {}, icon: FunctionalComponent
a.value = button.action
i.value = button.icon
}

const reset = () => {
a.value = () => {}
i.value = undefined
}

const active = computed(() => {
return a.value !== (() => {}) && i.value !== undefined
})

return { action: a, icon: i, set, reset, active }
})
14 changes: 12 additions & 2 deletions web/src/stores/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const useAuthStore = defineStore(
const accessTokenRefreshInterval = ref(0)

const setAccessToken = (token: string) => {
console.log('setting access token', token)
if (userId.value === '') {
const claims = jwtDecode(token) as AccessToken
userId.value = claims.userId
Expand All @@ -30,7 +29,18 @@ export const useAuthStore = defineStore(
accessTokenRefreshInterval.value = interval
}

return { accessToken, logout, setAccessToken, setAccessTokenRefreshInterval, userId }
const authorised = () => {
return accessToken.value !== ''
}

return {
accessToken,
logout,
setAccessToken,
setAccessTokenRefreshInterval,
userId,
authorised,
}
},
{
persist: true,
Expand Down
4 changes: 2 additions & 2 deletions web/src/ui/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const fetchFeedItems = async () => {
</script>

<template>
<div v-for="item in feedItems" :key="item.type.value?.id">
<template v-for="item in feedItems" :key="item.type.value?.id">
<CardWorkout v-if="item.type.case === 'workout'" compact :workout="item.type.value" />
</div>
</template>
<div v-if="hasMorePages" v-infinite-scroll="fetchFeedItems"></div>
</template>
21 changes: 21 additions & 0 deletions web/src/ui/components/ActionButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
import type { FunctionalComponent } from 'vue'
const props = defineProps<{
action: () => void
icon?: FunctionalComponent
}>()
const emits = defineEmits(['onClick'])
const onClick = async () => {
props.action()
emits('onClick')
}
</script>

<template>
<component :is="props.icon" class="size-6 cursor-pointer" @click="onClick" />
</template>

<style scoped></style>
14 changes: 6 additions & 8 deletions web/src/ui/components/AppButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ const computedClasses = computed(() => {
</script>

<template>
<div :class="containerClass" class="lg:px-0">
<RouterLink v-if="props.type === 'link'" :to="props.to as string" :class="computedClasses">
<slot />
</RouterLink>
<button v-else :type="props.type" :class="computedClasses">
<slot />
</button>
</div>
<RouterLink v-if="props.type === 'link'" :to="props.to as string" :class="computedClasses">
<slot />
</RouterLink>
<button v-else :type="props.type" :class="computedClasses">
<slot />
</button>
</template>

<style scoped>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ import AppNavTop from '@/ui/components/AppNavTop.vue'

<style scoped>
main {
@apply mx-auto max-w-7xl bg-gray-100 py-4;
@apply mx-auto max-w-7xl bg-gray-100 py-4 px-2;
}
</style>
3 changes: 1 addition & 2 deletions web/src/ui/components/AppList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ const onFetch = async () => {

<style scoped>
ul {
@apply divide-y divide-gray-100 bg-white border-t border-b border-gray-200 mb-4;
@apply lg:rounded-md lg:border-x;
@apply divide-y divide-gray-100 bg-white border border-gray-200 mb-4 rounded-md;
li.fetching {
@apply h-16 flex justify-center items-center text-gray-800;
Expand Down
2 changes: 1 addition & 1 deletion web/src/ui/components/AppListItemInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ const onChange = () => {
<style scoped>
input {
@apply block w-full border-0 bg-white px-4 py-5 text-gray-900 focus:ring-0 placeholder:text-gray-400 font-medium;
@apply lg:rounded-md;
@apply rounded-md;
}
</style>
13 changes: 11 additions & 2 deletions web/src/ui/components/AppNavTop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import { searchUsers } from '@/http/requests.ts'
import { usePageTitleStore } from '@/stores/pageTitle.ts'
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid'
import { XMarkIcon } from '@heroicons/vue/24/outline'
import ActionButton from '@/ui/components/ActionButton.vue'
import { useActionButton } from '@/stores/actionButton.ts'
const searchBarOpen = ref(false)
const input = ref<HTMLInputElement | null>(null)
const users = ref(Array<User>())
const searchBarOpen = ref(false)
const actionButton = useActionButton()
const pageTitleStore = usePageTitleStore()
const openSearchBar = () => {
searchBarOpen.value = true
nextTick(() => {
Expand Down Expand Up @@ -72,7 +76,12 @@ const onSearchUsers = async () => {
{{ pageTitleStore.pageTitle }}
</p>
</div>
<MagnifyingGlassIcon class="w-8 h-6 cursor-pointer" @click="openSearchBar" />
<ActionButton
v-if="actionButton.active"
:action="actionButton.action"
:icon="actionButton.icon"
/>
<ActionButton v-else :action="openSearchBar" :icon="MagnifyingGlassIcon" />
</template>
</div>
</nav>
Expand Down
2 changes: 1 addition & 1 deletion web/src/ui/components/CardWorkout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const formatComment = computed(() => {
<template>
<div
v-if="!workoutDeleted"
class="divide-y divide-gray-100 bg-white mb-4 border-t border-b border-gray-200 lg:rounded-md lg:border-x"
class="divide-y divide-gray-100 bg-white rounded-md border border-gray-200 mb-4"
>
<div class="px-4 py-4">
<div class="flex items-center justify-between">
Expand Down
18 changes: 13 additions & 5 deletions web/src/ui/exercises/CreateExercise.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useAlertStore } from '@/stores/alerts'
import { createExercise } from '@/http/requests'
import AppList from '@/ui/components/AppList.vue'
import AppButton from '@/ui/components/AppButton.vue'
import AppListItemInput from '@/ui/components/AppListItemInput.vue'
import { type CreateExerciseRequest } from '@/proto/api/v1/exercise_service_pb'
import { useActionButton } from '@/stores/actionButton.ts'
import { CheckIcon } from '@heroicons/vue/24/outline'
import AppButton from '@/ui/components/AppButton.vue'
const router = useRouter()
const alertStore = useAlertStore()
const actionButton = useActionButton()
onMounted(() => {
actionButton.set({
icon: CheckIcon,
action: onSubmit,
})
})
const req = ref<CreateExerciseRequest>({
$typeName: 'api.v1.CreateExerciseRequest',
Expand Down Expand Up @@ -42,8 +52,6 @@ const onSubmit = async () => {
/>
</AppList>

<AppButton text="Create" type="submit" colour="primary" container-class="px-4 pb-4">
Save Exercise
</AppButton>
<AppButton text="Create" type="submit" colour="primary"> Save Exercise </AppButton>
</form>
</template>
5 changes: 3 additions & 2 deletions web/src/ui/exercises/ListExercises.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { type Exercise } from '@/proto/api/v1/shared_pb.ts'
import { onMounted, ref } from 'vue'
import { listExercises } from '@/http/requests.ts'
import AppList from '@/ui/components/AppList.vue'
import AppButton from '@/ui/components/AppButton.vue'
import { ChevronRightIcon } from '@heroicons/vue/20/solid'
import AppListItemLink from '@/ui/components/AppListItemLink.vue'
import usePagination from '@/utils/usePagination.ts'
import AppButton from '@/ui/components/AppButton.vue'
const exercises = ref([] as Exercise[])
const { hasMorePages, pageToken, resolvePageToken } = usePagination()
onMounted(async () => {
Expand All @@ -25,7 +26,7 @@ const fetchExercises = async () => {
</script>

<template>
<AppButton type="link" to="/exercises/create" colour="primary" container-class="px-4 pb-4">
<AppButton type="link" to="/exercises/create" colour="primary" class="mb-4">
Create Exercise
</AppButton>
<AppList :can-fetch="hasMorePages" @fetch="fetchExercises">
Expand Down
2 changes: 1 addition & 1 deletion web/src/ui/routines/ListRoutines.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const fetchRoutines = async () => {
</script>

<template>
<AppButton type="link" to="/routines/create" colour="primary" container-class="px-4 pb-4">
<AppButton type="link" to="/routines/create" colour="primary" class="mb-4">
Create Routine
</AppButton>
<AppList>
Expand Down
7 changes: 1 addition & 6 deletions web/src/ui/routines/ViewRoutine.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@ const onDeleteRoutine = async () => {
</script>

<template>
<AppButton
type="link"
:to="`/workouts/routine/${route.params.id}`"
colour="primary"
container-class="px-4 pb-4"
>
<AppButton type="link" :to="`/workouts/routine/${route.params.id}`" colour="primary" class="mb-4">
Start Workout
</AppButton>
<h6>Exercises</h6>
Expand Down
20 changes: 4 additions & 16 deletions web/src/ui/users/UserView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,11 @@ const updateTab = (event: Event) => {
</script>

<template>
<div v-if="user.id !== authStore.userId">
<AppButton
v-if="user.followed"
colour="gray"
type="button"
container-class="px-4 pb-4"
@click="onUnfollowUser"
>
<div v-if="user.id !== authStore.userId" class="mb-4">
<AppButton v-if="user.followed" colour="gray" type="button" @click="onUnfollowUser">
Unfollow {{ user.firstName }}
</AppButton>
<AppButton
v-else
colour="primary"
type="button"
container-class="px-4 pb-4"
@click="onFollowUser"
>
<AppButton v-else colour="primary" type="button" @click="onFollowUser">
Follow {{ user.firstName }}
</AppButton>
</div>
Expand All @@ -85,7 +73,7 @@ const updateTab = (event: Event) => {
<select
id="tabs"
name="tabs"
class="block w-full border-gray-300 focus:ring-0 py-4 px-4 font-medium"
class="block w-full border-gray-200 rounded-md py-4 px-4 font-medium"
@change="updateTab"
>
<option
Expand Down
11 changes: 3 additions & 8 deletions web/src/ui/workouts/StartWorkout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,14 @@ const setEndDateTime = (value: string) => {
/>
</AppList>

<AppButton type="submit" colour="primary" container-class="px-4 pb-4">
Finish Workout
</AppButton>
<AppButton type="button" colour="gray" container-class="px-4 pb-4" @click="cancelWorkout">
Cancel Workout
</AppButton>
<AppButton type="submit" colour="primary" class="mb-4"> Finish Workout </AppButton>
<AppButton type="button" colour="gray" @click="cancelWorkout"> Cancel Workout </AppButton>
</form>
</template>

<style scoped>
.table-container {
@apply bg-white px-3 py-4 mb-4 border-t border-b border-gray-200;
@apply lg:rounded-md lg:border-x;
@apply bg-white px-3 py-4 mb-4 border border-gray-200 rounded-md;
}
table {
Expand Down

0 comments on commit 0e51cc7

Please sign in to comment.