feat(onboarding): auto-create a default workspace at signup
- CreateUser now provisions a default "{name}'s Workspace" for non-invite
signups (email, Google, GitHub, seeder), with the owner as Admin and
current_workspace_id set. Invite signups still skip it (they join the
inviter's workspace on acceptance).
- UserSeeder drops its now-redundant explicit CreateWorkspace call.
- After Stripe checkout, billing/processing lands the user on the social
accounts screen with the connect dialog open (was: calendar), so onboarding
flows straight into connecting an account.
Quantity stays correct (1 workspace → checkout quantity 1). The first workspace
is created without brand details; brand setup remains available in Settings and
on the create-workspace screen for additional workspaces.
This commit is contained in:
parent
17449bfe2a
commit
b7374c1adb
6 changed files with 24 additions and 16 deletions
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace App\Actions\User;
|
||||
|
||||
use App\Actions\Workspace\CreateWorkspace;
|
||||
use App\Enums\Plan\Slug;
|
||||
use App\Jobs\PostHog\SyncUser;
|
||||
use App\Models\Account;
|
||||
|
|
@ -48,6 +49,10 @@ public static function execute(array $data, array $utmParameters = []): User
|
|||
|
||||
$account->update(['owner_id' => $user->id]);
|
||||
|
||||
if (! $isInviteRegistration) {
|
||||
CreateWorkspace::execute($user, ['name' => data_get($data, 'name')."'s Workspace"]);
|
||||
}
|
||||
|
||||
return $user;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
namespace Database\Seeders;
|
||||
|
||||
use App\Actions\User\CreateUser;
|
||||
use App\Actions\Workspace\CreateWorkspace;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ public function run(): void
|
|||
return;
|
||||
}
|
||||
|
||||
$user = CreateUser::execute([
|
||||
CreateUser::execute([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@trypost.it',
|
||||
'password' => 'password',
|
||||
|
|
@ -27,8 +26,6 @@ public function run(): void
|
|||
'timezone' => 'UTC',
|
||||
]);
|
||||
|
||||
CreateWorkspace::execute($user, ['name' => 'My Workspace']);
|
||||
|
||||
$this->command->info('Admin account created — change the password on first login:');
|
||||
$this->command->line(' email: admin@trypost.it');
|
||||
$this->command->line(' password: password');
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { IconLoader2 } from '@tabler/icons-vue';
|
|||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { useTracking } from '@/composables/useTracking';
|
||||
import { home } from '@/routes/app';
|
||||
import { accounts } from '@/routes/app';
|
||||
import type { Auth } from '@/types';
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
@ -27,7 +27,7 @@ const { trackPurchase } = useTracking();
|
|||
|
||||
const tracked = ref(false);
|
||||
|
||||
const goHome = () => router.visit(home.url());
|
||||
const goToAccounts = () => router.visit(accounts.url({ query: { openDialog: true } }));
|
||||
|
||||
// Fires `checkout.completed` exactly once for a real checkout. A trial-with-card
|
||||
// subscription is already `subscribed()` (status `trialing`) by the time the
|
||||
|
|
@ -53,7 +53,7 @@ const completePurchase = () => {
|
|||
}
|
||||
}
|
||||
|
||||
goHome();
|
||||
goToAccounts();
|
||||
};
|
||||
|
||||
watch(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
use App\Models\Workspace;
|
||||
use Illuminate\Support\Facades\Bus;
|
||||
|
||||
test('CreateUser creates user with account but no workspace and no current_workspace_id', function () {
|
||||
test('CreateUser creates the owner a default workspace and sets it as current', function () {
|
||||
$user = CreateUser::execute([
|
||||
'name' => 'Jane Doe',
|
||||
'email' => 'jane@example.com',
|
||||
|
|
@ -17,10 +17,14 @@
|
|||
|
||||
expect($user->name)->toBe('Jane Doe');
|
||||
expect($user->email)->toBe('jane@example.com');
|
||||
expect($user->current_workspace_id)->toBeNull();
|
||||
expect($user->account_id)->not->toBeNull();
|
||||
expect(Workspace::count())->toBe(0);
|
||||
expect(Account::find($user->account_id))->not->toBeNull();
|
||||
|
||||
$workspace = $user->workspaces()->first();
|
||||
expect($user->workspaces()->count())->toBe(1);
|
||||
expect($workspace->name)->toBe("Jane Doe's Workspace");
|
||||
expect($workspace->account_id)->toBe($user->account_id);
|
||||
expect($user->fresh()->current_workspace_id)->toBe($workspace->id);
|
||||
});
|
||||
|
||||
test('CreateUser sets account owner_id to the new user', function () {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
$response->assertRedirect(route('register.success', absolute: false));
|
||||
});
|
||||
|
||||
test('new users do not get a default workspace on registration', function () {
|
||||
test('new users get a default workspace on registration', function () {
|
||||
$this->post(route('register.store'), [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
|
|
@ -35,8 +35,9 @@
|
|||
|
||||
expect($user)->not->toBeNull();
|
||||
expect($user->account_id)->not->toBeNull();
|
||||
expect($user->workspaces()->count())->toBe(0);
|
||||
expect($user->current_workspace_id)->toBeNull();
|
||||
expect($user->workspaces()->count())->toBe(1);
|
||||
expect($user->workspaces()->first()->name)->toBe("Test User's Workspace");
|
||||
expect($user->current_workspace_id)->toBe($user->workspaces()->first()->id);
|
||||
});
|
||||
|
||||
test('new users can register with a timezone preference', function () {
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
$user = User::where('email', 'test@example.com')->first();
|
||||
|
||||
expect($user)->not->toBeNull();
|
||||
expect($user->workspaces()->count())->toBe(0);
|
||||
expect($user->workspaces()->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('new users do not have verified email by default', function () {
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@
|
|||
expect($user->name)->toBe('New User');
|
||||
expect($user->email_verified_at)->not->toBeNull();
|
||||
expect($user->account_id)->not->toBeNull();
|
||||
expect($user->workspaces()->count())->toBe(0);
|
||||
expect($user->current_workspace_id)->toBeNull();
|
||||
expect($user->workspaces()->count())->toBe(1);
|
||||
expect($user->workspaces()->first()->name)->toBe("New User's Workspace");
|
||||
expect($user->current_workspace_id)->toBe($user->workspaces()->first()->id);
|
||||
$this->assertAuthenticatedAs($user);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue