feat: add organization onboarding
All checks were successful
deploy-socialize / image (push) Successful in 1m8s
deploy-socialize / deploy (push) Successful in 19s

This commit is contained in:
2026-05-07 20:07:50 -04:00
parent 4aaa1a7f90
commit db16e79d9f
9 changed files with 699 additions and 80 deletions

View File

@@ -1,4 +1,6 @@
import { useAuthStore } from '@/features/auth/stores/authStore.js';
import { useOrganizationStore } from '@/features/organizations/stores/organizationStore.js';
import { useWorkspaceStore } from '@/features/workspaces/stores/workspaceStore.js';
import { createRouter, createWebHistory } from 'vue-router';
const LoginView = () => import('@/features/auth/views/LoginView.vue');
@@ -18,6 +20,7 @@ const CampaignsView = () => import('@/features/campaigns/views/CampaignsView.vue
const CampaignDetailView = () => import('@/features/campaigns/views/CampaignDetailView.vue');
const MediaLibraryView = () => import('@/features/content/views/MediaLibraryView.vue');
const WorkspaceCreateView = () => import('@/features/workspaces/views/WorkspaceCreateView.vue');
const OrganizationOnboardingView = () => import('@/features/organizations/views/OrganizationOnboardingView.vue');
const OrganizationSettingsView = () => import('@/features/organizations/views/OrganizationSettingsView.vue');
const SettingsLayoutView = () => import('@/features/settings/views/SettingsLayoutView.vue');
const UserSettingsView = () => import('@/features/user-profile/views/UserSettingsView.vue');
@@ -132,6 +135,12 @@ const routes = [
component: DeveloperFeedbackDetailView,
meta: { requiresAuth: true, roles: ['developer'] },
},
{
path: '/app/onboarding',
name: 'organization-onboarding',
component: OrganizationOnboardingView,
meta: { requiresAuth: true },
},
{
path: '/app/organizations/:organizationId/settings',
name: 'organization-settings',
@@ -148,7 +157,7 @@ const routes = [
path: '/app/workspaces/new',
name: 'workspace-create',
component: WorkspaceCreateView,
meta: { requiresAuth: true, roles: ['administrator', 'manager'] },
meta: { requiresAuth: true },
},
{
path: '/app/settings',
@@ -243,8 +252,33 @@ const router = createRouter({
routes,
});
async function loadAccessScope() {
const organizationStore = useOrganizationStore();
const workspaceStore = useWorkspaceStore();
await Promise.all([
organizationStore.fetchOrganizations(),
workspaceStore.fetchWorkspaces(),
]);
}
function hasNoOrganizationOrWorkspaceAccess() {
const organizationStore = useOrganizationStore();
const workspaceStore = useWorkspaceStore();
return organizationStore.organizations.length === 0 && workspaceStore.workspaces.length === 0;
}
async function getAuthenticatedHomeRoute() {
await loadAccessScope();
return hasNoOrganizationOrWorkspaceAccess()
? { name: 'organization-onboarding' }
: { name: 'dashboard' };
}
// Navigation guards
router.beforeEach((to) => {
router.beforeEach(async (to) => {
const authStore = useAuthStore();
if (to.matched.some(record => record.meta.requiresAuth)) {
@@ -255,6 +289,12 @@ router.beforeEach((to) => {
};
}
await loadAccessScope();
if (hasNoOrganizationOrWorkspaceAccess() && to.name !== 'organization-onboarding') {
return { name: 'organization-onboarding' };
}
const requiredRoles = to.matched.flatMap(record => record.meta.roles ?? []);
if (requiredRoles.length > 0 && !authStore.hasAnyRole(requiredRoles)) {
return { name: 'dashboard' };
@@ -264,9 +304,7 @@ router.beforeEach((to) => {
}
if (to.matched.some(record => record.meta.notAuthenticated)) {
return authStore.isAuthenticated
? { name: 'dashboard' }
: true;
return authStore.isAuthenticated ? await getAuthenticatedHomeRoute() : true;
}
return true;