fixes
Build And Push Image / docker (push) Successful in 3m7s Details

This commit is contained in:
Matt 2025-08-08 21:52:21 +02:00
parent aed8dc68fc
commit 15dd090d44
5 changed files with 366 additions and 15 deletions

View File

@ -34,8 +34,6 @@
'country-selector--open': dropdownOpen,
'country-selector--mobile': isMobile
}"
@click="toggleDropdown"
@touchstart="handleTouchStart"
>
<img
:src="flagUrl"

View File

@ -0,0 +1,335 @@
<template>
<v-dialog
:model-value="modelValue"
@update:model-value="$emit('update:model-value', $event)"
max-width="600"
persistent
scrollable
>
<v-card class="registration-success-card">
<v-card-title class="d-flex align-center pa-6 bg-success">
<v-icon class="mr-3 text-white" size="32">mdi-check-circle</v-icon>
<h2 class="text-h5 text-white font-weight-bold flex-grow-1">
Registration Successful!
</h2>
</v-card-title>
<v-card-text class="pa-6">
<!-- Success Message -->
<div class="text-center mb-6">
<v-avatar size="80" class="mb-4" color="success">
<v-icon size="48" color="white">mdi-account-check</v-icon>
</v-avatar>
<h3 class="text-h6 mb-3">
Welcome to MonacoUSA Association!
</h3>
<p class="text-body-1 mb-2">
Your membership application has been submitted successfully.
</p>
<v-chip
v-if="memberData?.memberId"
color="success"
variant="outlined"
size="small"
class="ma-1"
>
<v-icon start size="14">mdi-identifier</v-icon>
Member ID: {{ memberData.memberId }}
</v-chip>
</div>
<v-divider class="mb-6" />
<!-- Next Steps -->
<div class="mb-6">
<h4 class="text-h6 mb-3 d-flex align-center">
<v-icon class="mr-2" color="primary">mdi-format-list-checks</v-icon>
Next Steps
</h4>
<v-timeline density="compact" side="end">
<v-timeline-item
dot-color="success"
size="small"
icon="mdi-check"
>
<template #opposite>
<strong class="text-body-2">Step 1</strong>
</template>
<div class="mb-2">
<strong class="text-body-2">Registration Complete</strong>
<p class="text-body-2 text-medium-emphasis mb-0">
Your account has been created in our system.
</p>
</div>
</v-timeline-item>
<v-timeline-item
dot-color="warning"
size="small"
icon="mdi-email"
>
<template #opposite>
<strong class="text-body-2">Step 2</strong>
</template>
<div class="mb-2">
<strong class="text-body-2">Check Your Email</strong>
<p class="text-body-2 text-medium-emphasis mb-0">
We've sent a verification email to <strong>{{ memberData?.email }}</strong>.
Click the link in the email to verify your account and set your password.
</p>
</div>
</v-timeline-item>
<v-timeline-item
dot-color="info"
size="small"
icon="mdi-bank"
>
<template #opposite>
<strong class="text-body-2">Step 3</strong>
</template>
<div class="mb-2">
<strong class="text-body-2">Pay Membership Dues</strong>
<p class="text-body-2 text-medium-emphasis mb-0">
Transfer your annual membership dues using the banking details below.
</p>
</div>
</v-timeline-item>
<v-timeline-item
dot-color="success"
size="small"
icon="mdi-account-check"
>
<template #opposite>
<strong class="text-body-2">Step 4</strong>
</template>
<div>
<strong class="text-body-2">Account Activation</strong>
<p class="text-body-2 text-medium-emphasis mb-0">
Once payment is verified, your account will be activated and you can access the member portal.
</p>
</div>
</v-timeline-item>
</v-timeline>
</div>
<v-divider class="mb-6" />
<!-- Payment Information -->
<div class="payment-info mb-6">
<h4 class="text-h6 mb-3 d-flex align-center">
<v-icon class="mr-2" color="primary">mdi-bank</v-icon>
Payment Instructions
</h4>
<v-card variant="outlined" class="pa-4" color="primary-lighten-5">
<v-row dense>
<v-col cols="12" sm="4">
<span class="text-body-2 font-weight-bold">Amount:</span>
</v-col>
<v-col cols="12" sm="8">
<span class="text-body-1 font-weight-bold">{{ paymentInfo?.membershipFee || '50' }}/year</span>
</v-col>
</v-row>
<v-row dense v-if="paymentInfo?.iban" class="mb-2">
<v-col cols="12" sm="4">
<span class="text-body-2 font-weight-bold">IBAN:</span>
</v-col>
<v-col cols="12" sm="8">
<div class="d-flex align-center">
<span class="text-body-2 font-family-monospace mr-2">{{ paymentInfo.iban }}</span>
<v-btn
icon="mdi-content-copy"
size="x-small"
variant="text"
@click="copyToClipboard(paymentInfo.iban)"
:title="'Copy IBAN'"
/>
</div>
</v-col>
</v-row>
<v-row dense v-if="paymentInfo?.accountHolder">
<v-col cols="12" sm="4">
<span class="text-body-2 font-weight-bold">Account:</span>
</v-col>
<v-col cols="12" sm="8">
<span class="text-body-2">{{ paymentInfo.accountHolder }}</span>
</v-col>
</v-row>
<v-row dense>
<v-col cols="12" sm="4">
<span class="text-body-2 font-weight-bold">Reference:</span>
</v-col>
<v-col cols="12" sm="8">
<span class="text-body-2">Member {{ memberData?.memberId || 'Registration' }}</span>
</v-col>
</v-row>
</v-card>
</div>
<!-- Important Notes -->
<v-alert
type="info"
variant="tonal"
class="mb-4"
>
<template #title>Important Notes</template>
<ul class="text-body-2 ml-4">
<li>Check your spam folder if you don't receive the verification email within 10 minutes</li>
<li>Your membership will be activated within 2-3 business days after payment verification</li>
<li>Contact our administrators if you need assistance with the verification process</li>
</ul>
</v-alert>
<!-- Copy Notification -->
<v-snackbar
v-model="showCopyNotification"
timeout="2000"
color="success"
location="bottom"
>
IBAN copied to clipboard!
</v-snackbar>
</v-card-text>
<v-card-actions class="pa-6 pt-0">
<v-spacer />
<v-btn
variant="outlined"
@click="closeDialog"
class="mr-3"
>
Close
</v-btn>
<v-btn
color="primary"
@click="goToLogin"
>
<v-icon start>mdi-login</v-icon>
Go to Login
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
interface Props {
modelValue: boolean;
memberData?: {
memberId: string;
email: string;
};
paymentInfo?: {
membershipFee: number;
iban: string;
accountHolder: string;
};
}
interface Emits {
(e: 'update:model-value', value: boolean): void;
(e: 'go-to-login'): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
const showCopyNotification = ref(false);
// Methods
const closeDialog = () => {
emit('update:model-value', false);
};
const goToLogin = () => {
emit('go-to-login');
closeDialog();
};
const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text);
showCopyNotification.value = true;
} catch (error) {
console.error('Failed to copy to clipboard:', error);
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showCopyNotification.value = true;
}
};
</script>
<style scoped>
.registration-success-card {
border-radius: 16px !important;
}
.bg-success {
background: linear-gradient(135deg, #4caf50 0%, #66bb6a 100%) !important;
}
.payment-info .v-card {
border-radius: 12px !important;
}
/* Timeline styling */
.v-timeline :deep(.v-timeline-item__body) {
padding-bottom: 16px;
}
.v-timeline :deep(.v-timeline-item__opposite) {
padding-inline-end: 16px;
}
/* Copy button styling */
.v-btn--size-x-small {
min-width: 24px !important;
width: 24px;
height: 24px;
}
/* Responsive adjustments */
@media (max-width: 600px) {
.v-card-title {
padding: 16px !important;
}
.v-card-text {
padding: 16px !important;
}
.v-card-actions {
padding: 16px !important;
padding-top: 0 !important;
}
.v-timeline :deep(.v-timeline-item__opposite) {
display: none;
}
}
/* Print styles (if user wants to print) */
@media print {
.v-card-actions {
display: none;
}
.payment-info .v-card {
border: 2px solid #ddd !important;
}
}
</style>

View File

@ -144,16 +144,6 @@
{{ errorMessage }}
</v-alert>
<!-- Success Alert -->
<v-alert
v-if="successMessage"
type="success"
variant="tonal"
class="mb-4"
>
<v-alert-title>Registration Successful!</v-alert-title>
{{ successMessage }}
</v-alert>
<v-btn
type="submit"
@ -224,6 +214,14 @@
</v-col>
</v-row>
</v-container>
<!-- Registration Success Dialog -->
<RegistrationSuccessDialog
v-model="showSuccessDialog"
:member-data="registrationResult"
:payment-info="registrationConfig"
@go-to-login="goToLogin"
/>
</div>
</template>
@ -232,8 +230,7 @@ import type { RegistrationFormData, RecaptchaConfig, RegistrationConfig } from '
// Page metadata
definePageMeta({
layout: false,
middleware: 'guest'
layout: false
});
// Head configuration
@ -271,6 +268,10 @@ const recaptchaToken = ref('');
const successMessage = ref('');
const errorMessage = ref('');
// Success dialog state
const showSuccessDialog = ref(false);
const registrationResult = ref<{ memberId: string; email: string } | null>(null);
// Configs
const recaptchaConfig = ref<RecaptchaConfig>({ siteKey: '', secretKey: '' });
const registrationConfig = ref<RegistrationConfig>({
@ -357,7 +358,15 @@ async function submitRegistration() {
}) as any;
if (response?.success) {
successMessage.value = response.message || 'Registration successful!';
// Set registration result data for dialog
registrationResult.value = {
memberId: response.data?.memberId || 'N/A',
email: form.value.email
};
// Show success dialog instead of just alert
showSuccessDialog.value = true;
// Reset form by resetting individual refs
firstName.value = '';
lastName.value = '';
@ -383,6 +392,11 @@ async function submitRegistration() {
}
}
// Navigation methods
const goToLogin = () => {
navigateTo('/login');
};
// Load configurations on mount
onMounted(async () => {
try {

View File

@ -1,3 +1,5 @@
import { createSessionManager } from '~/server/utils/session';
export default defineEventHandler(async (event) => {
console.log('[api/admin/recaptcha-config.post] =========================');
console.log('[api/admin/recaptcha-config.post] POST /api/admin/recaptcha-config - Save reCAPTCHA configuration');

View File

@ -1,3 +1,5 @@
import { createSessionManager } from '~/server/utils/session';
export default defineEventHandler(async (event) => {
console.log('[api/admin/registration-config.post] =========================');
console.log('[api/admin/registration-config.post] POST /api/admin/registration-config - Save registration configuration');