feat: show identity match hint on registration success page
When a pending identity match is detected after volunteer registration, the API now returns has_existing_account in the response. The success page shows a login suggestion card so the volunteer can link their registration to their existing account. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\IdentityMatchStatus;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V1\VolunteerRegistrationRequest;
|
||||
use App\Http\Resources\Api\V1\PersonResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\PersonIdentityMatch;
|
||||
use App\Services\VolunteerRegistrationService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
final class VolunteerRegistrationController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly VolunteerRegistrationService $registrationService,
|
||||
) {}
|
||||
|
||||
public function __invoke(VolunteerRegistrationRequest $request, Event $event): JsonResponse
|
||||
{
|
||||
$user = auth('sanctum')->user();
|
||||
|
||||
$person = $this->registrationService->register(
|
||||
$event,
|
||||
$request->validated(),
|
||||
$user
|
||||
);
|
||||
|
||||
$person->load('crowdType');
|
||||
|
||||
$hasExistingAccount = PersonIdentityMatch::where('person_id', $person->id)
|
||||
->where('status', IdentityMatchStatus::PENDING)
|
||||
->exists();
|
||||
|
||||
$responseData = [
|
||||
'person' => new PersonResource($person),
|
||||
'has_existing_account' => $hasExistingAccount,
|
||||
];
|
||||
|
||||
if ($person->wasRecentlyCreated) {
|
||||
return $this->created($responseData);
|
||||
}
|
||||
|
||||
return $this->success($responseData);
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,15 @@ export function useRegistrationData(eventSlug: Ref<string>) {
|
||||
})
|
||||
}
|
||||
|
||||
export interface VolunteerRegistrationResponse {
|
||||
person: Record<string, unknown>
|
||||
has_existing_account: boolean
|
||||
}
|
||||
|
||||
export function useSubmitRegistration() {
|
||||
return useMutation({
|
||||
mutationFn: async ({ eventId, form }: { eventId: string; form: VolunteerRegistrationForm }) => {
|
||||
const { data } = await apiClient.post<ApiResponse<Record<string, unknown>>>(
|
||||
const { data } = await apiClient.post<ApiResponse<VolunteerRegistrationResponse>>(
|
||||
`/events/${eventId}/volunteer-register`,
|
||||
form,
|
||||
)
|
||||
|
||||
@@ -622,7 +622,7 @@ async function onSubmit() {
|
||||
if (section_preferences?.length) payload.section_preferences = section_preferences
|
||||
|
||||
try {
|
||||
await submitRegistration({
|
||||
const result = await submitRegistration({
|
||||
eventId: registrationData.value.event.id,
|
||||
form: payload,
|
||||
})
|
||||
@@ -644,6 +644,7 @@ async function onSubmit() {
|
||||
event: registrationData.value.event.name,
|
||||
banner: registrationData.value.event.registration_banner_url ?? '',
|
||||
authenticated: authStore.isAuthenticated ? '1' : '0',
|
||||
hasAccount: result.has_existing_account ? '1' : '0',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ const authStore = useAuthStore()
|
||||
const eventName = computed(() => (route.query.event as string) || 'het evenement')
|
||||
const bannerUrl = computed(() => (route.query.banner as string) || null)
|
||||
const isAuthenticated = computed(() => route.query.authenticated === '1' || authStore.isAuthenticated)
|
||||
const hasExistingAccount = computed(() => route.query.hasAccount === '1' && !isAuthenticated.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -102,6 +103,35 @@ const isAuthenticated = computed(() => route.query.authenticated === '1' || auth
|
||||
</div>
|
||||
</VCard>
|
||||
|
||||
<VAlert
|
||||
v-if="hasExistingAccount"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
class="mt-4"
|
||||
>
|
||||
<div class="font-weight-medium mb-1">
|
||||
Er bestaat al een account met dit e-mailadres
|
||||
</div>
|
||||
<p class="text-body-2 mb-3">
|
||||
Log in om je aanmelding te koppelen aan je bestaande account.
|
||||
Zo kun je straks je diensten bekijken in het portaal.
|
||||
</p>
|
||||
<VBtn
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="flat"
|
||||
:to="{ name: 'login' }"
|
||||
>
|
||||
<VIcon
|
||||
start
|
||||
size="16"
|
||||
>
|
||||
tabler-login
|
||||
</VIcon>
|
||||
Inloggen
|
||||
</VBtn>
|
||||
</VAlert>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="text-center pa-4 text-caption text-medium-emphasis">
|
||||
Powered by Crewli
|
||||
|
||||
Reference in New Issue
Block a user