feat: implement workspace management and update localization strings across multiple languages
This commit is contained in:
parent
7733d573da
commit
d83ac0612f
18 changed files with 39 additions and 46 deletions
|
|
@ -111,7 +111,6 @@ public function store(StoreWorkspaceRequest $request, LogoAttacher $logoAttacher
|
|||
}
|
||||
|
||||
$validated = $request->validated();
|
||||
$isFirstWorkspace = ! $user->workspaces()->exists();
|
||||
|
||||
$workspace = CreateWorkspace::execute($user, $validated);
|
||||
|
||||
|
|
@ -127,9 +126,8 @@ public function store(StoreWorkspaceRequest $request, LogoAttacher $logoAttacher
|
|||
}
|
||||
}
|
||||
|
||||
return $isFirstWorkspace
|
||||
? redirect()->route('app.accounts')->with('success', __('workspaces.create.first_workspace_success'))
|
||||
: redirect()->route('app.calendar')->with('success', __('workspaces.create.success'));
|
||||
return redirect()->route('app.accounts', ['openDialog' => 'true'])
|
||||
->with('success', __('workspaces.create.success'));
|
||||
}
|
||||
|
||||
public function switch(Request $request, Workspace $workspace): RedirectResponse
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ public function index(Request $request): Response|RedirectResponse
|
|||
'filters' => [
|
||||
'search' => $request->input('search', ''),
|
||||
],
|
||||
'openDialog' => $request->boolean('openDialog'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@
|
|||
'background_color' => 'Background color',
|
||||
'text_color' => 'Text color',
|
||||
'submit' => 'Create workspace',
|
||||
'first_workspace_success' => 'Workspace created. Connect a social account to start posting.',
|
||||
'success' => 'Workspace created.',
|
||||
'success' => 'Workspace created. Connect a social account to start posting.',
|
||||
],
|
||||
|
||||
'limit_reached' => 'You have reached your plan limit for workspaces.',
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@
|
|||
'background_color' => 'Color de fondo',
|
||||
'text_color' => 'Color de texto',
|
||||
'submit' => 'Crear workspace',
|
||||
'first_workspace_success' => 'Workspace creado. Conecta una cuenta social para empezar a publicar.',
|
||||
'success' => 'Workspace creado.',
|
||||
'success' => 'Workspace creado. Conecta una cuenta social para empezar a publicar.',
|
||||
],
|
||||
|
||||
'limit_reached' => 'Has alcanzado el límite de workspaces de tu plan.',
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -49,8 +49,7 @@
|
|||
'background_color' => 'Cor de fundo',
|
||||
'text_color' => 'Cor do texto',
|
||||
'submit' => 'Criar workspace',
|
||||
'first_workspace_success' => 'Workspace criado. Conecte uma conta social para começar a postar.',
|
||||
'success' => 'Workspace criado.',
|
||||
'success' => 'Workspace criado. Conecte uma conta social para começar a postar.',
|
||||
],
|
||||
|
||||
'limit_reached' => 'Você atingiu o limite de workspaces do seu plano.',
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ const huePointerStyle = computed(() => ({
|
|||
<button
|
||||
type="button"
|
||||
:disabled="disabled"
|
||||
class="size-9 shrink-0 cursor-pointer rounded-md border-2 border-foreground bg-card shadow-xs transition-shadow hover:shadow-sm disabled:cursor-not-allowed disabled:opacity-50"
|
||||
class="size-10 shrink-0 cursor-pointer rounded-md border-2 border-foreground bg-card shadow-xs transition-shadow hover:shadow-sm disabled:cursor-not-allowed disabled:opacity-50"
|
||||
:style="swatchColor ? { backgroundColor: swatchColor } : undefined"
|
||||
:aria-label="placeholder"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ export const buttonVariants = cva(
|
|||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
"default": "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
"sm": "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||
"lg": "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||
"icon": "size-9",
|
||||
"icon-sm": "size-8",
|
||||
"icon-lg": "size-10",
|
||||
"default": "h-10 px-4 py-2 has-[>svg]:px-3",
|
||||
"sm": "h-9 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||
"lg": "h-11 rounded-md px-6 has-[>svg]:px-4",
|
||||
"icon": "size-10",
|
||||
"icon-sm": "size-9",
|
||||
"icon-lg": "size-11",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const modelValue = useVModel(props, "modelValue", emits, {
|
|||
|
||||
<template>
|
||||
<input v-model="modelValue" data-slot="input" :class="cn(
|
||||
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-2 border-foreground h-9 w-full min-w-0 rounded-md bg-card px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-2 border-foreground h-10 w-full min-w-0 rounded-md bg-card px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
||||
props.class,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
|||
:data-size="size"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn(
|
||||
'border-2 border-foreground data-[placeholder]:text-foreground/50 [&_svg:not([class*=\'text-\'])]:text-foreground/60 focus-visible:ring-foreground/20 aria-invalid:border-destructive flex w-fit items-center justify-between gap-2 rounded-lg bg-card px-3.5 py-2 text-sm font-medium text-foreground whitespace-nowrap shadow-2xs transition-shadow outline-none focus:shadow-xs focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
||||
'border-2 border-foreground data-[placeholder]:text-foreground/50 [&_svg:not([class*=\'text-\'])]:text-foreground/60 focus-visible:ring-foreground/20 aria-invalid:border-destructive flex w-fit items-center justify-between gap-2 rounded-lg bg-card px-3.5 py-2 text-sm font-medium text-foreground whitespace-nowrap shadow-2xs transition-shadow outline-none focus:shadow-xs focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-10 data-[size=sm]:h-9 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const delegatedProps = reactiveOmit(props, "class")
|
|||
data-slot="tabs-list"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn(
|
||||
'inline-flex w-fit items-center gap-2',
|
||||
'inline-flex h-10 w-fit items-center gap-2',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
|||
<TabsTrigger
|
||||
data-slot="tabs-trigger"
|
||||
:class="cn(
|
||||
'inline-flex h-9 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md border-2 border-foreground bg-card px-3 text-sm font-bold text-foreground shadow-xs transition-all hover:bg-accent hover:shadow-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-amber-200 data-[state=active]:hover:bg-amber-300 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
||||
'inline-flex h-10 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md border-2 border-foreground bg-card px-3 text-sm font-bold text-foreground shadow-xs transition-all hover:bg-accent hover:shadow-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-amber-200 data-[state=active]:hover:bg-amber-300 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
||||
props.class,
|
||||
)"
|
||||
v-bind="forwardedProps"
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import AuthLayout from '@/layouts/auth/AuthSplitLayout.vue';
|
||||
|
||||
withDefaults(defineProps<{
|
||||
defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
showLegal?: boolean;
|
||||
}>(), {
|
||||
showLegal: false,
|
||||
});
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthLayout :title="title" :description="description" :show-legal="showLegal">
|
||||
<AuthLayout :title="title" :description="description">
|
||||
<slot />
|
||||
</AuthLayout>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,10 @@ import {
|
|||
import { trans } from 'laravel-vue-i18n';
|
||||
import { onBeforeUnmount, onMounted, ref, computed } from 'vue';
|
||||
|
||||
withDefaults(defineProps<{
|
||||
defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
showLegal?: boolean;
|
||||
}>(), {
|
||||
showLegal: false,
|
||||
});
|
||||
}>();
|
||||
|
||||
const slideKeys = ['calendar', 'scheduling', 'media', 'video', 'team', 'signatures'] as const;
|
||||
|
||||
|
|
@ -112,13 +109,6 @@ const platforms = [
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div
|
||||
v-if="showLegal"
|
||||
class="text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-primary"
|
||||
v-html="trans('auth.legal')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -70,11 +70,12 @@ interface Props {
|
|||
accounts: ScrollAccounts;
|
||||
platforms: AvailablePlatform[];
|
||||
filters: { search: string };
|
||||
openDialog: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const isAddDialogOpen = ref(false);
|
||||
const isAddDialogOpen = ref(props.openDialog);
|
||||
const deleteModal = ref<InstanceType<typeof ConfirmDeleteModal> | null>(null);
|
||||
const searchQuery = ref(props.filters.search);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { Form, Head } from '@inertiajs/vue3';
|
||||
import { Form, Head, usePage } from '@inertiajs/vue3';
|
||||
import { IconEye, IconEyeOff } from '@tabler/icons-vue';
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import SocialLogin from '@/components/auth/SocialLogin.vue';
|
||||
import InputError from '@/components/InputError.vue';
|
||||
|
|
@ -28,13 +28,15 @@ defineProps<{
|
|||
const showPassword = ref(false);
|
||||
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
const page = usePage();
|
||||
const isSelfHosted = computed(() => Boolean(page.props.selfHosted));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthBase
|
||||
:title="$t('auth.register.title')"
|
||||
:description="$t('auth.register.description')"
|
||||
:show-legal="true"
|
||||
>
|
||||
<Head :title="$t('auth.register.page_title')" />
|
||||
|
||||
|
|
@ -135,6 +137,13 @@ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|||
>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div
|
||||
v-if="!isSelfHosted"
|
||||
class="text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-primary"
|
||||
v-html="$t('auth.legal')"
|
||||
/>
|
||||
</div>
|
||||
</AuthBase>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in a new issue