-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1287a92
commit 4613521
Showing
4 changed files
with
216 additions
and
7 deletions.
There are no files selected for viewing
101 changes: 101 additions & 0 deletions
101
packages/frontend-2/components/onboarding/JoinTeammates.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<!-- FF-CLEANUP: Remove when workspaces plans released --> | ||
<template> | ||
<div class="flex flex-col items-center gap-2 w-full"> | ||
<CommonCard | ||
v-for="workspace in workspaces" | ||
:key="workspace.id" | ||
class="w-full bg-foundation" | ||
> | ||
<div class="flex gap-4"> | ||
<div> | ||
<WorkspaceAvatar :name="workspace.name" :logo="workspace.logo" size="xl" /> | ||
</div> | ||
<div class="flex flex-col sm:flex-row gap-4 justify-between flex-1"> | ||
<div class="flex flex-col flex-1"> | ||
<h6 class="text-heading-sm">{{ workspace.name }}</h6> | ||
<p class="text-body-2xs text-foreground-2">{{ workspace.description }}</p> | ||
</div> | ||
<FormButton | ||
color="outline" | ||
size="sm" | ||
:loading="loadingStates[workspace.id]" | ||
:disabled="requestedWorkspaces.includes(workspace.id)" | ||
@click="() => processRequest(true, workspace.id)" | ||
> | ||
{{ | ||
requestedWorkspaces.includes(workspace.id) | ||
? 'Requested' | ||
: 'Request to join' | ||
}} | ||
</FormButton> | ||
</div> | ||
</div> | ||
</CommonCard> | ||
<div class="mt-2 w-full"> | ||
<FormButton size="lg" full-width @click="$emit('next')">Continue</FormButton> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import type { LimitedWorkspace } from '~/lib/common/generated/gql/graphql' | ||
import { dashboardRequestToJoinWorkspaceMutation } from '~~/lib/dashboard/graphql/mutations' | ||
import { | ||
convertThrowIntoFetchResult, | ||
getFirstErrorMessage | ||
} from '~~/lib/common/helpers/graphql' | ||
import { useMixpanel } from '~~/lib/core/composables/mp' | ||
import { useMutation } from '@vue/apollo-composable' | ||
|
||
defineProps<{ | ||
workspaces: LimitedWorkspace[] | ||
}>() | ||
|
||
defineEmits(['next']) | ||
|
||
const mixpanel = useMixpanel() | ||
const { triggerNotification } = useGlobalToast() | ||
|
||
const loadingStates = ref<Record<string, boolean>>({}) | ||
|
||
const { mutate: requestToJoin } = useMutation(dashboardRequestToJoinWorkspaceMutation) | ||
|
||
const requestedWorkspaces = ref<string[]>([]) | ||
|
||
const processRequest = async (accept: boolean, workspaceId: string) => { | ||
if (accept) { | ||
loadingStates.value[workspaceId] = true | ||
|
||
try { | ||
const result = await requestToJoin({ | ||
input: { workspaceId } | ||
}).catch(convertThrowIntoFetchResult) | ||
|
||
if (result?.data) { | ||
requestedWorkspaces.value.push(workspaceId) | ||
mixpanel.track('Workspace Join Request Sent', { | ||
workspaceId, | ||
location: 'onboarding', | ||
// eslint-disable-next-line camelcase | ||
workspace_id: workspaceId | ||
}) | ||
|
||
triggerNotification({ | ||
title: 'Request sent', | ||
description: 'Your request to join the workspace has been sent.', | ||
type: ToastNotificationType.Success | ||
}) | ||
} else { | ||
const errorMessage = getFirstErrorMessage(result?.errors) | ||
triggerNotification({ | ||
title: 'Failed to send request', | ||
description: errorMessage, | ||
type: ToastNotificationType.Danger | ||
}) | ||
} | ||
} finally { | ||
loadingStates.value[workspaceId] = false | ||
} | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<!-- FF-CLEANUP: Remove when workspaces plans released --> | ||
<template> | ||
<HeaderWithEmptyPage empty-header> | ||
<template #header-left> | ||
<HeaderLogoBlock no-link /> | ||
</template> | ||
<template #header-right> | ||
<div class="flex gap-2 items-center"> | ||
<FormButton | ||
v-if="!isOnboardingForced" | ||
class="opacity-70 hover:opacity-100 p-1" | ||
size="sm" | ||
color="subtle" | ||
@click="setUserOnboardingComplete()" | ||
> | ||
Skip | ||
</FormButton> | ||
<FormButton color="outline" @click="() => logout({ skipRedirect: false })"> | ||
Sign out | ||
</FormButton> | ||
</div> | ||
</template> | ||
<template v-if="isLoading"> | ||
<div class="py-12 flex flex-col items-center gap-2"> | ||
<CommonLoadingIcon /> | ||
</div> | ||
</template> | ||
<div v-else class="flex flex-col items-center justify-center p-4 max-w-lg mx-auto"> | ||
<h1 class="text-heading-xl text-forefround mb-2 font-normal"> | ||
{{ currentStage === 'join' ? 'Join your teammates' : 'Tell us about yourself' }} | ||
</h1> | ||
<p class="text-center text-body-sm text-foreground-2 mb-8"> | ||
{{ | ||
currentStage === 'join' | ||
? 'We found a workspace that matches your email domain' | ||
: 'Your answers will help us improve' | ||
}} | ||
</p> | ||
|
||
<OnboardingJoinTeammates | ||
v-if="currentStage === 'join' && discoverableWorkspaces.length > 0" | ||
:workspaces="discoverableWorkspaces" | ||
@next="currentStage = 'questions'" | ||
/> | ||
<OnboardingQuestionsForm v-else /> | ||
</div> | ||
</HeaderWithEmptyPage> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useProcessOnboarding } from '~~/lib/auth/composables/onboarding' | ||
import { useAuthManager } from '~/lib/auth/composables/auth' | ||
import { CommonLoadingIcon } from '@speckle/ui-components' | ||
import { useDiscoverableWorkspaces } from '~/lib/workspaces/composables/discoverableWorkspaces' | ||
|
||
useHead({ | ||
title: 'Welcome to Speckle' | ||
}) | ||
|
||
definePageMeta({ | ||
middleware: ['auth'], | ||
layout: 'empty' | ||
}) | ||
|
||
const isOnboardingForced = useIsOnboardingForced() | ||
|
||
const { setUserOnboardingComplete } = useProcessOnboarding() | ||
const { logout } = useAuthManager() | ||
|
||
const isLoading = ref(true) | ||
const currentStage = ref<'join' | 'questions'>('questions') | ||
const isWorkspacesEnabled = useIsWorkspacesEnabled() | ||
|
||
// Use the composable instead of direct query | ||
const { discoverableWorkspaces, hasDiscoverableWorkspaces } = | ||
useDiscoverableWorkspaces() | ||
|
||
onMounted(async () => { | ||
// If workspaces feature is disabled, go straight to questions | ||
if (!isWorkspacesEnabled.value) { | ||
currentStage.value = 'questions' | ||
isLoading.value = false | ||
return | ||
} | ||
|
||
// Short delay to allow the composable to fetch data | ||
await nextTick() | ||
|
||
currentStage.value = hasDiscoverableWorkspaces.value ? 'join' : 'questions' | ||
isLoading.value = false | ||
}) | ||
</script> |