trypost/resources/js/pages/onboarding/Role.vue
Paulo Castellano bb6d0a2678 fix: Stripe webhook setup completion, notifications routing, billing UI
- Fix StripeEventListener: mark setup as Completed when subscription.created webhook fires
- Fix notifications routes: move outside subscribed middleware (non-critical feature)
- Fix NotificationBell: guard response.ok before parsing JSON
- Fix StripeEventListener: use data_get() for payload access
- Rewrite billing page to use SettingsLayout with download buttons on invoices
- Remove duplicate Unit/Listeners/StripeEventListenerTest (consolidated into Feature)
- Add comprehensive Stripe webhook tests (14 scenarios: happy path, setup transitions, edge cases, error handling)
- Update billing i18n: remove "no credit card" text, add status key
- Move auth layout logo to top-left corner
- Redesign onboarding Role page with compact list layout
- Add persona i18n translations (EN, PT-BR, ES)
- Update README with API, MCP, tech stack, quick start
2026-03-31 13:52:36 -03:00

86 lines
2.7 KiB
Vue

<script setup lang="ts">
import { Head, useForm } from '@inertiajs/vue3';
import { IconBuilding, IconBuildingStore, IconCheck, IconRocket, IconSparkles, IconUser } from '@tabler/icons-vue';
import { storeRole } from '@/actions/App/Http/Controllers/App/OnboardingController';
import { Button } from '@/components/ui/button';
import AuthLayout from '@/layouts/AuthLayout.vue';
interface Persona {
value: string;
label: string;
description: string;
icon: string;
}
interface Props {
personas: Persona[];
}
defineProps<Props>();
const form = useForm({
persona: '',
});
const icons: Record<string, typeof IconRocket> = {
rocket: IconRocket,
sparkles: IconSparkles,
building: IconBuilding,
'building-2': IconBuilding,
store: IconBuildingStore,
user: IconUser,
};
const submit = () => {
form.post(storeRole.url());
};
const isSelected = (value: string) => form.persona === value;
</script>
<template>
<Head :title="$t('onboarding.role.page_title')" />
<AuthLayout
:title="$t('onboarding.role.title')"
:description="$t('onboarding.role.description')"
>
<div class="flex flex-col gap-2">
<button
v-for="persona in personas"
:key="persona.value"
type="button"
class="flex items-center gap-3 rounded-lg border px-4 py-3 text-left transition-all hover:border-primary hover:bg-accent"
:class="{
'border-primary bg-primary/5': isSelected(persona.value),
'border-border': !isSelected(persona.value),
}"
@click="form.persona = persona.value"
>
<div
class="flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-colors"
:class="{
'bg-primary text-primary-foreground': isSelected(persona.value),
'bg-muted text-muted-foreground': !isSelected(persona.value),
}"
>
<component :is="icons[persona.icon]" class="h-4 w-4" />
</div>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium">{{ persona.label }}</p>
<p class="text-xs text-muted-foreground">{{ persona.description }}</p>
</div>
<IconCheck v-if="isSelected(persona.value)" class="h-4 w-4 shrink-0 text-primary" />
</button>
</div>
<Button
class="mt-2 w-full"
:disabled="!form.persona || form.processing"
@click="submit"
>
{{ $t('onboarding.role.submit') }}
</Button>
</AuthLayout>
</template>