diff --git a/app/Actions/User/CreateUser.php b/app/Actions/User/CreateUser.php index c5af71fe..f6c0c1eb 100644 --- a/app/Actions/User/CreateUser.php +++ b/app/Actions/User/CreateUser.php @@ -30,7 +30,7 @@ public static function execute(array $data, array $utmParameters = []): User if (! $requiresCardForTrial) { $accountAttributes['plan_id'] = Plan::where('slug', Slug::Workspace)->value('id'); - $accountAttributes['trial_ends_at'] = now()->addDays(config('cashier.trial_days', 7)); + $accountAttributes['trial_ends_at'] = now()->addDays(config('cashier.trial_days')); } $account = Account::create($accountAttributes); diff --git a/app/Enums/User/Persona.php b/app/Enums/User/Persona.php index 3a8b6c2b..4b1f6cb6 100644 --- a/app/Enums/User/Persona.php +++ b/app/Enums/User/Persona.php @@ -12,27 +12,4 @@ enum Persona: string case Agency = 'agency'; case SmallBusiness = 'small_business'; case Other = 'other'; - - public function label(): string - { - return match ($this) { - self::Creator => 'Creator', - self::Freelancer => 'Freelancer', - self::Startup => 'Startup', - self::Agency => 'Agency', - self::SmallBusiness => 'Small business', - self::Other => 'Other', - }; - } - - /** - * @return array - */ - public static function options(): array - { - return array_map( - fn (self $persona): array => ['value' => $persona->value, 'label' => $persona->label()], - self::cases(), - ); - } } diff --git a/app/Http/Controllers/App/BillingController.php b/app/Http/Controllers/App/BillingController.php index a6e9b73b..32a0cec9 100644 --- a/app/Http/Controllers/App/BillingController.php +++ b/app/Http/Controllers/App/BillingController.php @@ -4,9 +4,7 @@ namespace App\Http\Controllers\App; -use App\Actions\Billing\StartSubscriptionCheckout; use App\Models\Account; -use App\Models\Plan; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; @@ -23,33 +21,6 @@ public function subscribe(): RedirectResponse return redirect()->route('app.onboarding'); } - public function checkout(Request $request, Plan $plan, StartSubscriptionCheckout $checkout): SymfonyResponse|RedirectResponse - { - if (config('trypost.self_hosted')) { - return redirect()->route('app.calendar'); - } - - $user = $request->user(); - $account = $user->account; - - abort_unless($user->isAccountOwner(), SymfonyResponse::HTTP_FORBIDDEN); - abort_if($plan->is_archived, SymfonyResponse::HTTP_NOT_FOUND); - - $request->validate([ - 'price_id' => ['required', 'string'], - ]); - - $priceId = $request->input('price_id'); - - abort_unless( - $priceId === $plan->stripe_monthly_price_id || $priceId === $plan->stripe_yearly_price_id, - 422, - 'Invalid price for this plan', - ); - - return $checkout->redirect($account, $priceId, route('app.onboarding')); - } - public function processing(Request $request): Response|RedirectResponse { if (config('trypost.self_hosted')) { @@ -163,7 +134,7 @@ public function swapToYearly(Request $request): RedirectResponse return redirect()->route('app.billing.index'); } - $authorization = Gate::inspect('swapPlan', [$account, $plan]); + $authorization = Gate::inspect('swapPlan', [$account]); if ($authorization->denied()) { return back()->with('flash.error', $authorization->message()); diff --git a/app/Http/Controllers/App/OnboardingController.php b/app/Http/Controllers/App/OnboardingController.php index f82e1b0e..65986b02 100644 --- a/app/Http/Controllers/App/OnboardingController.php +++ b/app/Http/Controllers/App/OnboardingController.php @@ -32,7 +32,7 @@ public function index(Request $request): Response|RedirectResponse } return Inertia::render('onboarding/Index', [ - 'personas' => Persona::options(), + 'personas' => array_map(fn (Persona $persona): string => $persona->value, Persona::cases()), 'selected' => $user->persona?->value, ]); } diff --git a/app/Http/Controllers/App/Settings/UsageController.php b/app/Http/Controllers/App/Settings/UsageController.php index 3c27b608..926db259 100644 --- a/app/Http/Controllers/App/Settings/UsageController.php +++ b/app/Http/Controllers/App/Settings/UsageController.php @@ -34,7 +34,6 @@ public function index(Request $request): Response|RedirectResponse } return Inertia::render('settings/account/Usage', [ - 'plan' => $account->plan, 'usage' => [ 'workspaceCount' => $account->workspaces()->count(), 'socialAccountCount' => $totalSocialAccounts, diff --git a/app/Http/Controllers/App/WorkspaceController.php b/app/Http/Controllers/App/WorkspaceController.php index 4b4d3dd1..8fecc6b1 100644 --- a/app/Http/Controllers/App/WorkspaceController.php +++ b/app/Http/Controllers/App/WorkspaceController.php @@ -10,6 +10,7 @@ use App\Enums\Workspace\BrandFont; use App\Enums\Workspace\BrandVoiceTrait; use App\Enums\Workspace\ImageStyle; +use App\Http\Requests\App\Workspace\AutofillBrandRequest; use App\Http\Requests\App\Workspace\StoreWorkspaceRequest; use App\Http\Requests\App\Workspace\UpdateWorkspaceRequest; use App\Http\Resources\App\WorkspaceMemberResource; @@ -82,14 +83,10 @@ public function create(Request $request): Response|RedirectResponse ]); } - public function autofillBrand(Request $request, AutofillBrand $autofill): JsonResponse + public function autofillBrand(AutofillBrandRequest $request, AutofillBrand $autofill): JsonResponse { - $validated = $request->validate([ - 'url' => ['required', 'string', 'max:255'], - ]); - try { - $metadata = $autofill(data_get($validated, 'url')); + $metadata = $autofill(data_get($request->validated(), 'url')); } catch (RuntimeException $e) { return response()->json(['message' => $e->getMessage()], SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY); } diff --git a/app/Http/Controllers/Auth/FacebookController.php b/app/Http/Controllers/Auth/FacebookController.php index 4c554aff..b1dc6f78 100644 --- a/app/Http/Controllers/Auth/FacebookController.php +++ b/app/Http/Controllers/Auth/FacebookController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -131,6 +132,8 @@ public function callback(Request $request): View|RedirectResponse ]); return redirect()->route('app.social.facebook.select-page'); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Facebook OAuth Error', [ 'error' => $e->getMessage(), @@ -256,6 +259,8 @@ public function select(Request $request): View session()->forget(['facebook_oauth', 'social_reconnect_id']); return $this->popupCallback(true, __('accounts.popup_callback.connected'), $this->platform->value); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Facebook page selection error', [ 'error' => $e->getMessage(), diff --git a/app/Http/Controllers/Auth/InstagramController.php b/app/Http/Controllers/Auth/InstagramController.php index 6cd595c3..f90ebb55 100644 --- a/app/Http/Controllers/Auth/InstagramController.php +++ b/app/Http/Controllers/Auth/InstagramController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -100,6 +101,8 @@ public function callback(Request $request): View ); return $this->popupCallback(true, __('accounts.popup_callback.connected'), $this->platform->value); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Instagram OAuth Error', [ 'error' => $e->getMessage(), diff --git a/app/Http/Controllers/Auth/InstagramFacebookController.php b/app/Http/Controllers/Auth/InstagramFacebookController.php index 8cdef9d4..4dc59605 100644 --- a/app/Http/Controllers/Auth/InstagramFacebookController.php +++ b/app/Http/Controllers/Auth/InstagramFacebookController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -110,6 +111,8 @@ public function callback(Request $request): View|RedirectResponse ]); return redirect()->route('app.social.instagram-facebook.select-page'); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Instagram via Facebook OAuth Error', [ 'error' => $e->getMessage(), @@ -182,6 +185,8 @@ public function select(Request $request): View session()->forget(['instagram_facebook_oauth', 'social_reconnect_id']); return $result; + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Instagram via Facebook page selection error', ['error' => $e->getMessage()]); diff --git a/app/Http/Controllers/Auth/LinkedInPageController.php b/app/Http/Controllers/Auth/LinkedInPageController.php index ca5a9f89..e72ac86e 100644 --- a/app/Http/Controllers/Auth/LinkedInPageController.php +++ b/app/Http/Controllers/Auth/LinkedInPageController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use App\Services\Social\LinkedInTokenSynchronizer; use Illuminate\Http\RedirectResponse; @@ -222,6 +223,8 @@ public function select(Request $request): View session()->forget(['linkedin_page_pending', 'linkedin_page_reconnect_id']); return $this->popupCallback(true, __('accounts.popup_callback.connected'), $this->platform->value); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('LinkedIn Page selection error', [ 'error' => $e->getMessage(), diff --git a/app/Http/Controllers/Auth/ThreadsController.php b/app/Http/Controllers/Auth/ThreadsController.php index 76d9414e..3455226e 100644 --- a/app/Http/Controllers/Auth/ThreadsController.php +++ b/app/Http/Controllers/Auth/ThreadsController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -157,6 +158,8 @@ public function callback(Request $request): View session()->forget(['threads_oauth_state', 'social_reconnect_id']); return $this->popupCallback(true, __('accounts.popup_callback.connected'), $this->platform->value); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('Threads OAuth Error', [ 'error' => $e->getMessage(), diff --git a/app/Http/Controllers/Auth/YouTubeController.php b/app/Http/Controllers/Auth/YouTubeController.php index f4686c00..559d5d31 100644 --- a/app/Http/Controllers/Auth/YouTubeController.php +++ b/app/Http/Controllers/Auth/YouTubeController.php @@ -6,6 +6,7 @@ use App\Enums\SocialAccount\Platform as SocialPlatform; use App\Enums\SocialAccount\Status; +use App\Exceptions\SocialAccount\NetworkAlreadyConnectedException; use App\Models\Workspace; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -116,6 +117,8 @@ public function callback(Request $request): View|RedirectResponse ]); return redirect()->route('app.social.youtube.select-channel'); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('YouTube OAuth Error', [ 'error' => $e->getMessage(), @@ -250,6 +253,8 @@ public function select(Request $request): View session()->forget(['youtube_oauth', 'social_reconnect_id']); return $this->popupCallback(true, __('accounts.popup_callback.connected'), $this->platform->value); + } catch (NetworkAlreadyConnectedException) { + return $this->popupCallback(false, __('accounts.popup_callback.network_taken'), $this->platform->value); } catch (\Exception $e) { Log::error('YouTube channel selection error', [ 'error' => $e->getMessage(), diff --git a/app/Http/Requests/App/Workspace/AutofillBrandRequest.php b/app/Http/Requests/App/Workspace/AutofillBrandRequest.php new file mode 100644 index 00000000..1e63a91e --- /dev/null +++ b/app/Http/Requests/App/Workspace/AutofillBrandRequest.php @@ -0,0 +1,25 @@ + + */ + public function rules(): array + { + return [ + 'url' => ['required', 'string', 'max:255'], + ]; + } +} diff --git a/app/Policies/AccountPolicy.php b/app/Policies/AccountPolicy.php index a11a9eca..b7042f16 100644 --- a/app/Policies/AccountPolicy.php +++ b/app/Policies/AccountPolicy.php @@ -5,7 +5,6 @@ namespace App\Policies; use App\Models\Account; -use App\Models\Plan; use App\Models\User; use App\Support\BillingCycle; use Illuminate\Auth\Access\Response; @@ -59,7 +58,7 @@ public function useAi(User $user, Account $account): Response * account owner may change billing; per-workspace pricing has no plan tiers * to downgrade between, so there are no usage-based restrictions. */ - public function swapPlan(User $user, Account $account, Plan $plan): Response + public function swapPlan(User $user, Account $account): Response { if ($user->id !== $account->owner_id) { return Response::deny(__('billing.flash.cannot_manage')); diff --git a/app/Support/BillingCycle.php b/app/Support/BillingCycle.php index 9c3b88f6..cb4b1c56 100644 --- a/app/Support/BillingCycle.php +++ b/app/Support/BillingCycle.php @@ -18,6 +18,13 @@ */ class BillingCycle { + /** @var array{0: CarbonImmutable, 1: CarbonImmutable}|null */ + private ?array $window = null; + + private ?Subscription $subscription = null; + + private bool $subscriptionResolved = false; + private function __construct(private readonly Account $account) {} public static function for(Account $account): self @@ -71,6 +78,14 @@ public function periodEnd(): CarbonImmutable * @return array{0: CarbonImmutable, 1: CarbonImmutable} */ private function window(): array + { + return $this->window ??= $this->computeWindow(); + } + + /** + * @return array{0: CarbonImmutable, 1: CarbonImmutable} + */ + private function computeWindow(): array { $subscription = $this->subscription(); @@ -116,6 +131,11 @@ private function onTrial(): bool private function subscription(): ?Subscription { - return $this->account->subscription(Account::SUBSCRIPTION_NAME); + if (! $this->subscriptionResolved) { + $this->subscription = $this->account->subscription(Account::SUBSCRIPTION_NAME); + $this->subscriptionResolved = true; + } + + return $this->subscription; } } diff --git a/database/migrations/2026_06_21_184042_drop_limit_columns_from_plans_table.php b/database/migrations/2026_06_21_184042_drop_limit_columns_from_plans_table.php index ef729301..d10fc473 100644 --- a/database/migrations/2026_06_21_184042_drop_limit_columns_from_plans_table.php +++ b/database/migrations/2026_06_21_184042_drop_limit_columns_from_plans_table.php @@ -1,5 +1,7 @@ 'Search accounts...', 'added' => 'Added :date', - 'limit_reached' => 'You have reached your plan limit for social accounts.', - 'not_connected' => 'Not connected', 'connect' => 'Connect', 'connection_lost' => 'Connection lost', diff --git a/lang/en/billing.php b/lang/en/billing.php index ef9df49e..196e8e45 100644 --- a/lang/en/billing.php +++ b/lang/en/billing.php @@ -16,35 +16,11 @@ ], 'subscribe' => [ - 'page_title' => 'Choose your plan', - 'eyebrow' => 'Pricing', - 'title' => 'Choose the right plan for you', - 'description' => 'Pick the plan that fits you. Billed monthly or annually.', - 'trial_info' => ':days-day free trial, then billed automatically', - 'monthly' => 'Monthly', - 'yearly' => 'Yearly', - 'per_month' => 'monthly', - 'per_year' => 'yearly', 'billed_monthly' => 'Billed monthly', 'billed_yearly' => 'Billed annually', - 'features_included' => "What's included:", - 'everything_in' => 'Everything in :plan, plus:', - 'save_months' => '2 months free', - 'popular' => 'Most popular', - 'start_trial' => 'Start :days-day free trial', - 'subscribe_cta' => 'Subscribe', 'prices' => [ 'workspace' => ['monthly' => '$12', 'yearly_per_month' => '$10', 'yearly' => '$120'], ], - 'features' => [ - 'per_workspace_credits' => ':count AI credits per workspace/mo', - 'one_per_network' => 'One account per social network', - 'unlimited_members' => 'Unlimited team members', - 'all_platforms' => 'Publish to every supported platform', - ], - 'credit_tooltips' => [ - 'workspace' => 'Each workspace includes 2,500 AI credits per month — about 160 AI images or 280 AI text generations.', - ], ], 'plan' => [ diff --git a/lang/en/common.php b/lang/en/common.php index 7d29a8b0..b90f4a9e 100644 --- a/lang/en/common.php +++ b/lang/en/common.php @@ -4,11 +4,6 @@ return [ - 'discord' => [ - 'label' => 'Discord', - 'join' => 'Join our Discord community', - ], - 'back' => 'Back', 'confirm_modal' => [ diff --git a/lang/en/workspaces.php b/lang/en/workspaces.php index 5f57dbf9..e43c5e8e 100644 --- a/lang/en/workspaces.php +++ b/lang/en/workspaces.php @@ -42,7 +42,6 @@ 'success' => 'Workspace created. Connect a social account to start posting.', ], - 'limit_reached' => 'You have reached your plan limit for workspaces.', 'cannot_delete_last' => 'You cannot delete your only workspace. Cancel your subscription in billing settings to close your account.', 'flash' => [ diff --git a/lang/es/accounts.php b/lang/es/accounts.php index 9918a354..1596a02b 100644 --- a/lang/es/accounts.php +++ b/lang/es/accounts.php @@ -15,8 +15,6 @@ 'search' => 'Buscar cuentas...', 'added' => 'Agregada :date', - 'limit_reached' => 'Has alcanzado el límite de cuentas sociales de tu plan.', - 'not_connected' => 'No conectado', 'connect' => 'Conectar', 'connection_lost' => 'Conexión perdida', diff --git a/lang/es/billing.php b/lang/es/billing.php index 221048be..9a51050d 100644 --- a/lang/es/billing.php +++ b/lang/es/billing.php @@ -16,35 +16,11 @@ ], 'subscribe' => [ - 'page_title' => 'Elige tu plan', - 'eyebrow' => 'Precios', - 'title' => 'Elige el plan ideal para ti', - 'description' => 'Elige el plan que te queda. Facturación mensual o anual.', - 'trial_info' => 'Prueba gratuita de :days días, luego se cobra automáticamente', - 'monthly' => 'Mensual', - 'yearly' => 'Anual', - 'per_month' => 'mensual', - 'per_year' => 'anual', 'billed_monthly' => 'Facturado mensualmente', 'billed_yearly' => 'Facturado anualmente', - 'features_included' => 'Qué incluye:', - 'everything_in' => 'Todo lo de :plan, más:', - 'save_months' => '2 meses gratis', - 'popular' => 'Más popular', - 'start_trial' => 'Comenzar prueba de :days días', - 'subscribe_cta' => 'Suscribirse', 'prices' => [ 'workspace' => ['monthly' => '$12', 'yearly_per_month' => '$10', 'yearly' => '$120'], ], - 'features' => [ - 'per_workspace_credits' => ':count créditos de IA por workspace/mes', - 'one_per_network' => 'Una cuenta por red social', - 'unlimited_members' => 'Miembros del equipo ilimitados', - 'all_platforms' => 'Publica en todas las plataformas compatibles', - ], - 'credit_tooltips' => [ - 'workspace' => 'Cada workspace incluye 2.500 créditos de IA al mes — alrededor de 160 imágenes o 280 textos generados con IA.', - ], ], 'plan' => [ diff --git a/lang/es/common.php b/lang/es/common.php index 115c0549..c85c9c0f 100644 --- a/lang/es/common.php +++ b/lang/es/common.php @@ -4,11 +4,6 @@ return [ - 'discord' => [ - 'label' => 'Discord', - 'join' => 'Unite a nuestra comunidad en Discord', - ], - 'back' => 'Volver', 'confirm_modal' => [ diff --git a/lang/es/workspaces.php b/lang/es/workspaces.php index 466ef073..78789e5f 100644 --- a/lang/es/workspaces.php +++ b/lang/es/workspaces.php @@ -42,7 +42,6 @@ 'success' => 'Workspace creado. Conecta una cuenta social para empezar a publicar.', ], - 'limit_reached' => 'Has alcanzado el límite de workspaces de tu plan.', 'cannot_delete_last' => 'No puedes eliminar tu único workspace. Cancela tu suscripción en la configuración de facturación para cerrar tu cuenta.', 'flash' => [ diff --git a/lang/pt-BR/accounts.php b/lang/pt-BR/accounts.php index 60def2aa..d9cecdc4 100644 --- a/lang/pt-BR/accounts.php +++ b/lang/pt-BR/accounts.php @@ -15,8 +15,6 @@ 'search' => 'Buscar contas...', 'added' => 'Adicionada :date', - 'limit_reached' => 'Você atingiu o limite de contas sociais do seu plano.', - 'not_connected' => 'Não conectado', 'connect' => 'Conectar', 'connection_lost' => 'Conexão perdida', diff --git a/lang/pt-BR/billing.php b/lang/pt-BR/billing.php index ca33b3d3..f78d5879 100644 --- a/lang/pt-BR/billing.php +++ b/lang/pt-BR/billing.php @@ -16,35 +16,11 @@ ], 'subscribe' => [ - 'page_title' => 'Escolha seu plano', - 'eyebrow' => 'Preços', - 'title' => 'Escolha o plano ideal pra você', - 'description' => 'Escolha o plano que combina com você. Cobrança mensal ou anual.', - 'trial_info' => ':days dias grátis, depois cobrança automática', - 'monthly' => 'Mensal', - 'yearly' => 'Anual', - 'per_month' => 'mensal', - 'per_year' => 'anual', 'billed_monthly' => 'Cobrança mensal', 'billed_yearly' => 'Cobrança anual', - 'features_included' => 'O que está incluído:', - 'everything_in' => 'Tudo do :plan, mais:', - 'save_months' => '2 meses grátis', - 'popular' => 'Mais popular', - 'start_trial' => 'Iniciar teste de :days dias', - 'subscribe_cta' => 'Assinar', 'prices' => [ 'workspace' => ['monthly' => 'R$ 60', 'yearly_per_month' => 'R$ 50', 'yearly' => 'R$ 600'], ], - 'features' => [ - 'per_workspace_credits' => ':count créditos de IA por workspace/mês', - 'one_per_network' => 'Uma conta por rede social', - 'unlimited_members' => 'Membros da equipe ilimitados', - 'all_platforms' => 'Publique em todas as plataformas suportadas', - ], - 'credit_tooltips' => [ - 'workspace' => 'Cada workspace inclui 2.500 créditos de IA por mês — cerca de 160 imagens ou 280 textos gerados por IA.', - ], ], 'plan' => [ diff --git a/lang/pt-BR/common.php b/lang/pt-BR/common.php index 9826eebc..6cfae2e2 100644 --- a/lang/pt-BR/common.php +++ b/lang/pt-BR/common.php @@ -4,11 +4,6 @@ return [ - 'discord' => [ - 'label' => 'Discord', - 'join' => 'Entre na nossa comunidade no Discord', - ], - 'back' => 'Voltar', 'confirm_modal' => [ diff --git a/lang/pt-BR/workspaces.php b/lang/pt-BR/workspaces.php index 040945f3..403d7e4f 100644 --- a/lang/pt-BR/workspaces.php +++ b/lang/pt-BR/workspaces.php @@ -42,7 +42,6 @@ 'success' => 'Workspace criado. Conecte uma conta social para começar a postar.', ], - 'limit_reached' => 'Você atingiu o limite de workspaces do seu plano.', 'cannot_delete_last' => 'Você não pode excluir seu único workspace. Cancele sua assinatura nas configurações de cobrança para encerrar sua conta.', 'flash' => [ diff --git a/resources/js/components/DiscordWidget.vue b/resources/js/components/DiscordWidget.vue deleted file mode 100644 index 52e3d339..00000000 --- a/resources/js/components/DiscordWidget.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/resources/js/composables/useFeatureAccess.ts b/resources/js/composables/useFeatureAccess.ts deleted file mode 100644 index e0618c01..00000000 --- a/resources/js/composables/useFeatureAccess.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { usePage } from '@inertiajs/vue3'; -import { computed } from 'vue'; - -import type { Usage } from '@/types'; - -interface Plan { - id: string; - slug: string; - name: string; -} - -interface Features { - monthlyCreditsLimit: number; -} - -export const useFeatureAccess = () => { - const page = usePage(); - - const isSelfHosted = computed(() => page.props.selfHosted as boolean); - const plan = computed(() => (page.props.auth as { plan: Plan | null }).plan ?? null); - const usage = computed(() => (page.props.usage as Usage | null) ?? null); - const features = computed(() => (page.props.features as Features | null) ?? null); - - const monthlyCreditsLimit = computed(() => features.value?.monthlyCreditsLimit ?? 0); - - const canCreateWorkspace = computed(() => true); - const canConnectSocialAccount = computed(() => true); - const canInviteMember = computed(() => true); - - const hasCreditsLeft = computed(() => { - if (isSelfHosted.value) return true; - if (!usage.value) return true; - return usage.value.creditsUsed < monthlyCreditsLimit.value; - }); - - return { - plan, - usage, - features, - isSelfHosted, - monthlyCreditsLimit, - canCreateWorkspace, - canConnectSocialAccount, - canInviteMember, - hasCreditsLeft, - }; -}; diff --git a/resources/js/pages/onboarding/Index.vue b/resources/js/pages/onboarding/Index.vue index 2dfeb5d4..37f6753a 100644 --- a/resources/js/pages/onboarding/Index.vue +++ b/resources/js/pages/onboarding/Index.vue @@ -15,17 +15,12 @@ import type { FunctionalComponent } from 'vue'; import { store } from '@/routes/app/onboarding'; -interface Persona { - value: string; - label: string; -} - -const { selected } = defineProps<{ - personas: Persona[]; +const props = defineProps<{ + personas: string[]; selected?: string | null; }>(); -const form = useForm({ persona: selected ?? '' }); +const form = useForm({ persona: props.selected ?? '' }); const icons: Record = { creator: IconUser, @@ -77,22 +72,22 @@ const submit = (): void => {