fixes
Build And Push Image / docker (push) Successful in 2m55s Details

This commit is contained in:
Matt 2025-08-08 19:55:32 +02:00
parent 5535b7905d
commit 4365cc53ff
2 changed files with 337 additions and 90 deletions

View File

@ -56,19 +56,32 @@
<p class="mb-4">Manage user accounts, roles, and permissions for the MonacoUSA Portal.</p>
<v-row>
<v-col cols="12" md="4">
<v-col cols="12" md="3">
<v-btn
color="primary"
block
size="large"
@click="manageUsers"
@click="navigateTo('/dashboard/member-list')"
>
<v-icon start>mdi-account-cog</v-icon>
Manage Users
</v-btn>
</v-col>
<v-col cols="12" md="4">
<v-col cols="12" md="3">
<v-btn
color="success"
variant="outlined"
block
size="large"
@click="showCreateUserDialog = true"
>
<v-icon start>mdi-account-plus</v-icon>
Create User Account
</v-btn>
</v-col>
<v-col cols="12" md="3">
<v-btn
color="secondary"
variant="outlined"
@ -81,13 +94,13 @@
</v-btn>
</v-col>
<v-col cols="12" md="4">
<v-col cols="12" md="3">
<v-btn
color="secondary"
variant="outlined"
block
size="large"
@click="portalSettings"
@click="showAdminConfig = true"
>
<v-icon start>mdi-cog</v-icon>
Portal Settings
@ -145,6 +158,85 @@
v-model="showNocoDBSettings"
@settings-saved="handleSettingsSaved"
/>
<!-- Admin Configuration Dialog -->
<AdminConfigurationDialog
v-model="showAdminConfig"
@settings-saved="handleAdminConfigSaved"
/>
<!-- Create User Dialog -->
<v-dialog v-model="showCreateUserDialog" max-width="600">
<v-card>
<v-card-title class="text-h5">
<v-icon left>mdi-account-plus</v-icon>
Create User Account
</v-card-title>
<v-card-text>
<v-alert type="info" variant="tonal" class="mb-4">
<v-alert-title>Create Portal Account</v-alert-title>
This will create a new user account in the MonacoUSA Portal with email verification.
</v-alert>
<v-form ref="createUserForm" v-model="createUserValid">
<v-row>
<v-col cols="6">
<v-text-field
v-model="newUser.firstName"
label="First Name"
:rules="[v => !!v || 'First name is required']"
variant="outlined"
required
/>
</v-col>
<v-col cols="6">
<v-text-field
v-model="newUser.lastName"
label="Last Name"
:rules="[v => !!v || 'Last name is required']"
variant="outlined"
required
/>
</v-col>
</v-row>
<v-text-field
v-model="newUser.email"
label="Email Address"
type="email"
:rules="[
v => !!v || 'Email is required',
v => /.+@.+\..+/.test(v) || 'Email must be valid'
]"
variant="outlined"
required
/>
<v-select
v-model="newUser.role"
label="User Role"
:items="roleOptions"
item-title="title"
item-value="value"
variant="outlined"
required
/>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn text @click="showCreateUserDialog = false">Cancel</v-btn>
<v-btn
color="primary"
:loading="creatingUser"
:disabled="!createUserValid"
@click="createUserAccount"
>
Create Account
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
@ -159,6 +251,24 @@ const { firstName } = useAuth();
// Reactive data
const userCount = ref(0);
const loading = ref(false);
const showCreateUserDialog = ref(false);
const showAdminConfig = ref(false);
// Create user dialog data
const createUserValid = ref(false);
const creatingUser = ref(false);
const newUser = ref({
firstName: '',
lastName: '',
email: '',
role: 'user'
});
const roleOptions = [
{ title: 'User', value: 'user' },
{ title: 'Board Member', value: 'board' },
{ title: 'Administrator', value: 'admin' }
];
const recentActivity = ref([
{
@ -234,6 +344,43 @@ const handleSettingsSaved = () => {
console.log('NocoDB settings saved successfully');
};
const handleAdminConfigSaved = () => {
console.log('Admin configuration saved successfully');
showAdminConfig.value = false;
};
const createUserAccount = async () => {
if (!createUserValid.value) return;
creatingUser.value = true;
try {
console.log('Creating user account:', newUser.value);
// TODO: Implement actual user creation using enhanced Keycloak API
// For now, just show success
await new Promise(resolve => setTimeout(resolve, 2000)); // Simulate API call
// Reset form
newUser.value = {
firstName: '',
lastName: '',
email: '',
role: 'user'
};
showCreateUserDialog.value = false;
console.log('User account created successfully');
// TODO: Show success notification
// TODO: Refresh user list
} catch (error) {
console.error('Failed to create user account:', error);
// TODO: Show error notification
} finally {
creatingUser.value = false;
}
};
const createUser = () => {
console.log('Create new user');
// TODO: Implement create user dialog/form

View File

@ -1,21 +1,28 @@
<template>
<div class="fill-height">
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="6" lg="4">
<v-card class="elevation-12" :loading="loading">
<v-toolbar color="primary" dark flat>
<v-toolbar-title class="text-h5 font-weight-bold">
<v-icon left>mdi-account-plus</v-icon>
Join MonacoUSA
</v-toolbar-title>
</v-toolbar>
<v-card-text class="py-6">
<div class="text-body-1 text-center mb-6">
Register as a member of MonacoUSA Association
<div class="signup-container">
<v-container fluid class="fill-height">
<v-row class="fill-height" justify="center" align="center">
<v-col cols="12" sm="10" md="8" lg="6" xl="5">
<v-card class="signup-card" elevation="24" :loading="loading">
<v-card-text class="pa-8">
<!-- Logo and Welcome -->
<div class="text-center mb-6">
<v-img
src="/MONACOUSA-Flags_376x376.png"
width="80"
height="80"
class="mx-auto mb-3"
alt="MonacoUSA Logo"
/>
<h1 class="text-h4 font-weight-bold mb-2" style="color: #a31515;">
Join MonacoUSA
</h1>
<p class="text-body-1 text-medium-emphasis">
Register as a member of MonacoUSA Association
</p>
</div>
<!-- Registration Form -->
<v-form ref="form" v-model="valid" @submit.prevent="submitRegistration">
<v-row>
<v-col cols="12" sm="6">
@ -23,8 +30,9 @@
v-model="form.first_name"
label="First Name"
:rules="nameRules"
prepend-icon="mdi-account"
prepend-inner-icon="mdi-account"
variant="outlined"
:disabled="loading"
required
/>
</v-col>
@ -34,6 +42,7 @@
label="Last Name"
:rules="nameRules"
variant="outlined"
:disabled="loading"
required
/>
</v-col>
@ -44,8 +53,9 @@
label="Email Address"
type="email"
:rules="emailRules"
prepend-icon="mdi-email"
prepend-inner-icon="mdi-email"
variant="outlined"
:disabled="loading"
required
/>
@ -53,6 +63,7 @@
v-model="form.phone"
label="Phone Number"
:rules="phoneRules"
:disabled="loading"
required
/>
@ -61,8 +72,9 @@
label="Date of Birth"
type="date"
:rules="dobRules"
prepend-icon="mdi-calendar"
prepend-inner-icon="mdi-calendar"
variant="outlined"
:disabled="loading"
required
/>
@ -70,9 +82,10 @@
v-model="form.address"
label="Address"
:rules="addressRules"
prepend-icon="mdi-map-marker"
prepend-inner-icon="mdi-map-marker"
variant="outlined"
rows="3"
:disabled="loading"
required
/>
@ -80,6 +93,7 @@
v-model="form.nationality"
label="Nationality"
:rules="nationalityRules"
:disabled="loading"
required
/>
@ -102,96 +116,96 @@
</v-alert>
</div>
<!-- Error Alert -->
<v-alert
v-if="errorMessage"
type="error"
variant="tonal"
class="mb-4"
closable
@click:close="errorMessage = ''"
>
<v-alert-title>Registration Failed</v-alert-title>
{{ 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"
color="primary"
size="large"
block
:disabled="!valid || !recaptchaToken"
:disabled="!valid || !recaptchaToken || loading"
:loading="loading"
class="mt-4"
class="mb-4"
style="background-color: #a31515 !important; color: white !important;"
>
<v-icon left>mdi-account-plus</v-icon>
Register
</v-btn>
</v-form>
</v-card-text>
<!-- Payment Information -->
<v-divider />
<v-card-text>
<v-card
class="pa-4"
color="blue-grey-lighten-5"
variant="outlined"
>
<v-card-title class="text-h6 pb-2">
<v-icon left color="primary">mdi-bank</v-icon>
Membership Dues Payment
</v-card-title>
<v-card-text class="pt-2">
<div class="text-body-1 mb-3">
<!-- Payment Information -->
<v-divider class="my-6" />
<div class="payment-info">
<div class="d-flex align-center mb-4">
<v-icon color="#a31515" class="mr-2">mdi-bank</v-icon>
<h3 class="text-h6" style="color: #a31515;">Membership Dues Payment</h3>
</div>
<div class="payment-details" style="color: #000 !important;">
<p class="text-body-1 mb-3" style="color: #000 !important;">
After registration, please transfer your annual membership dues:
</div>
</p>
<v-row dense>
<v-col cols="4" class="text-body-2 font-weight-bold">Amount:</v-col>
<v-col cols="8" class="text-body-2">{{ registrationConfig.membershipFee }}/year</v-col>
<v-row dense class="mb-2">
<v-col cols="4">
<span class="text-body-2 font-weight-bold" style="color: #000 !important;">Amount:</span>
</v-col>
<v-col cols="8">
<span class="text-body-2" style="color: #000 !important;">{{ registrationConfig.membershipFee }}/year</span>
</v-col>
</v-row>
<v-row dense v-if="registrationConfig.iban">
<v-col cols="4" class="text-body-2 font-weight-bold">IBAN:</v-col>
<v-col cols="8" class="text-body-2 font-family-monospace">{{ registrationConfig.iban }}</v-col>
<v-row dense class="mb-2" v-if="registrationConfig.iban">
<v-col cols="4">
<span class="text-body-2 font-weight-bold" style="color: #000 !important;">IBAN:</span>
</v-col>
<v-col cols="8">
<span class="text-body-2 font-family-monospace" style="color: #000 !important;">{{ registrationConfig.iban }}</span>
</v-col>
</v-row>
<v-row dense v-if="registrationConfig.accountHolder">
<v-col cols="4" class="text-body-2 font-weight-bold">Account:</v-col>
<v-col cols="8" class="text-body-2">{{ registrationConfig.accountHolder }}</v-col>
<v-row dense class="mb-2" v-if="registrationConfig.accountHolder">
<v-col cols="4">
<span class="text-body-2 font-weight-bold" style="color: #000 !important;">Account:</span>
</v-col>
<v-col cols="8">
<span class="text-body-2" style="color: #000 !important;">{{ registrationConfig.accountHolder }}</span>
</v-col>
</v-row>
<v-divider class="my-3" />
<div class="text-body-2 text-medium-emphasis">
<v-icon size="small" class="mr-1">mdi-information</v-icon>
<div class="text-body-2 d-flex align-center" style="color: #666 !important;">
<v-icon size="small" class="mr-2" color="#666">mdi-information</v-icon>
Your account will be activated once payment is verified by our administrators.
</div>
</v-card-text>
</v-card>
</div>
</div>
</v-card-text>
</v-card>
<!-- Success/Error Messages -->
<v-alert
v-if="successMessage"
type="success"
class="mt-4"
variant="tonal"
>
<v-alert-title>Registration Successful!</v-alert-title>
{{ successMessage }}
</v-alert>
<v-alert
v-if="errorMessage"
type="error"
class="mt-4"
variant="tonal"
>
<v-alert-title>Registration Failed</v-alert-title>
{{ errorMessage }}
</v-alert>
<!-- Back to Login Link -->
<div class="text-center mt-6">
<v-btn
variant="text"
color="primary"
to="/login"
>
<v-icon left>mdi-arrow-left</v-icon>
Back to Login
</v-btn>
</div>
</v-col>
</v-row>
</v-container>
@ -367,8 +381,94 @@ onMounted(async () => {
</script>
<style scoped>
.fill-height {
.signup-container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: linear-gradient(rgba(163, 21, 21, 0.7), rgba(0, 0, 0, 0.5)),
url('/monaco_high_res.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
display: flex;
align-items: center;
justify-content: center;
}
.signup-card {
backdrop-filter: blur(15px);
background: rgba(255, 255, 255, 0.95) !important;
border-radius: 20px !important;
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
transition: all 0.3s ease;
max-width: 600px;
width: 100%;
}
.signup-card:hover {
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4) !important;
}
.payment-info {
background: rgba(163, 21, 21, 0.05);
border-radius: 12px;
padding: 20px;
border: 1px solid rgba(163, 21, 21, 0.1);
}
.payment-details * {
color: #000 !important;
}
/* Custom scrollbar for mobile */
::-webkit-scrollbar {
width: 4px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(163, 21, 21, 0.5);
border-radius: 2px;
}
/* Responsive adjustments */
@media (max-width: 600px) {
.signup-container {
background-attachment: scroll;
padding: 16px;
}
.signup-card {
margin: 0;
}
}
/* Loading state styles */
.v-btn--loading {
pointer-events: none;
}
/* Form field focus styles */
.v-field--focused {
border-color: #a31515 !important;
}
.v-field--focused .v-field__outline {
border-color: #a31515 !important;
}
/* Ensure PhoneInputWrapper and MultipleNationalityInput align properly */
:deep(.v-field) {
width: 100%;
}
:deep(.v-input) {
width: 100%;
}
:deep(.v-text-field) {
width: 100%;
}
</style>