user()->currentWorkspace; abort_if(! $workspace, SymfonyResponse::HTTP_FORBIDDEN); $this->authorize('view', $workspace); $term = trim((string) $request->input('q', '')); $members = $workspace->members() ->where('users.id', '!=', $request->user()->id) ->when($term !== '', fn ($query) => $query->where('users.name', 'ilike', '%'.$term.'%')) ->orderBy('users.name') ->limit(50) ->get(['users.id', 'users.name', 'users.email']); return WorkspaceMemberResource::collection($members); } public function index(Request $request): Response { $user = $request->user(); $workspaces = $user->workspaces() ->with('media') ->withCount(['socialAccounts', 'posts']) ->latest() ->get(); return Inertia::render('workspaces/Index', [ 'workspaces' => $workspaces, 'currentWorkspaceId' => $user->current_workspace_id, ]); } public function create(Request $request): Response|RedirectResponse { $user = $request->user(); if (! config('trypost.self_hosted') && $user->ownedWorkspacesCount() > 0 && ! $user->account?->hasActiveSubscription()) { return redirect()->route('app.billing.index') ->with('message', 'Subscribe to create more workspaces.'); } return Inertia::render('workspaces/Create', [ 'availableFonts' => BrandFont::values(), 'availableImageStyles' => ImageStyle::values(), 'availableVoiceTraits' => BrandVoiceTrait::grouped(), 'availableContentLanguages' => ContentLanguage::options(), ]); } public function autofillBrand(AutofillBrandRequest $request, AutofillBrand $autofill): JsonResponse { try { $metadata = $autofill($request->validated('url')); } catch (RuntimeException $e) { return response()->json(['message' => $e->getMessage()], SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY); } return response()->json($metadata->toArray()); } public function store(StoreWorkspaceRequest $request, LogoAttacher $logoAttacher): RedirectResponse { $user = $request->user(); $validated = $request->validated(); $workspace = CreateWorkspace::execute($user, $validated); if ($logoUrl = data_get($validated, 'logo_url')) { try { $logoAttacher->attach($workspace, $logoUrl); } catch (Throwable $e) { Log::warning('Logo attach failed during workspace creation', [ 'workspace_id' => $workspace->id, 'logo_url' => $logoUrl, 'error' => $e->getMessage(), ]); } } return redirect()->route('app.accounts') ->with('success', __('workspaces.create.success')); } public function switch(Request $request, Workspace $workspace): RedirectResponse { $user = $request->user(); if (! $user->belongsToWorkspace($workspace)) { abort(403); } $user->switchWorkspace($workspace); return redirect()->route('app.calendar'); } public function settings(Request $request): Response|RedirectResponse { $user = $request->user(); $workspace = $user->currentWorkspace; if (! $workspace) { return redirect()->route('app.workspaces.create'); } $this->authorize('update', $workspace); return Inertia::render('settings/workspace/Workspace', [ 'workspace' => $workspace, ]); } public function brandSettings(Request $request): Response|RedirectResponse { $user = $request->user(); $workspace = $user->currentWorkspace; if (! $workspace) { return redirect()->route('app.workspaces.create'); } $this->authorize('update', $workspace); return Inertia::render('settings/workspace/Brand', [ 'workspace' => $workspace, 'availableFonts' => BrandFont::values(), 'availableImageStyles' => ImageStyle::values(), 'availableVoiceTraits' => BrandVoiceTrait::grouped(), 'availableContentLanguages' => ContentLanguage::options(), ]); } public function uploadLogo(Request $request): RedirectResponse { $workspace = $request->user()->currentWorkspace; $this->authorize('update', $workspace); $request->validate([ 'photo' => ['required', 'image', 'max:2048'], ]); $workspace->clearMediaCollection('logo'); $workspace->addMedia($request->file('photo'), 'logo'); $workspace->unsetRelation('media'); return back()->with('flash.success', __('settings.flash.logo_updated')); } public function deleteLogo(Request $request): RedirectResponse { $workspace = $request->user()->currentWorkspace; $this->authorize('update', $workspace); $workspace->clearMediaCollection('logo'); $workspace->unsetRelation('media'); return back()->with('flash.success', __('settings.flash.logo_deleted')); } public function updateSettings(UpdateWorkspaceRequest $request, LogoAttacher $logoAttacher): RedirectResponse { $user = $request->user(); $workspace = $user->currentWorkspace; if (! $workspace) { return redirect()->route('app.workspaces.create'); } $this->authorize('update', $workspace); $validated = $request->validated(); $logoUrl = data_get($validated, 'logo_url'); unset($validated['logo_url']); $workspace->update($validated); if ($logoUrl) { try { $logoAttacher->attach($workspace, $logoUrl); } catch (Throwable $e) { Log::warning('Logo attach failed during workspace update', [ 'workspace_id' => $workspace->id, 'logo_url' => $logoUrl, 'error' => $e->getMessage(), ]); } } return back()->with('flash.success', __('settings.flash.workspace_updated')); } public function destroy(Request $request, Workspace $workspace): RedirectResponse { $this->authorize('delete', $workspace); $user = $request->user(); if (! config('trypost.self_hosted') && $workspace->account->workspaces()->count() <= 1) { return back()->with('flash.error', __('workspaces.cannot_delete_last')); } DeleteWorkspace::execute($user, $workspace); return redirect()->route('app.workspaces.index') ->with('flash.success', __('workspaces.flash.deleted')); } }