+
Bestätigung
Der Vorgang wurde erfolgreich abgeschlossen.
-
- Balance: {{ balance() | currency: 'EUR' : 'symbol' : '1.2-2' }}
-
@if (!isLoggedIn) {
}
@if (isLoggedIn) {
+
+ Balance: {{ balance() | currency: 'EUR' : 'symbol' : '1.2-2' }}
+
}
diff --git a/frontend/src/app/shared/services/modal-animation.service.ts b/frontend/src/app/shared/services/modal-animation.service.ts
new file mode 100644
index 0000000..f54c2bc
--- /dev/null
+++ b/frontend/src/app/shared/services/modal-animation.service.ts
@@ -0,0 +1,53 @@
+import { Injectable } from '@angular/core';
+import gsap from 'gsap';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class ModalAnimationService {
+ private readonly defaultDuration = 0.3;
+ private readonly defaultEase = 'power2.out';
+
+ openModal(modalElement: HTMLElement, overlayElement: HTMLElement) {
+ gsap.set(overlayElement, { opacity: 0, display: 'block' });
+ gsap.set(modalElement, {
+ opacity: 0,
+ scale: 0.95,
+ y: 20,
+ display: 'block',
+ });
+
+ gsap.to(overlayElement, {
+ opacity: 1,
+ duration: this.defaultDuration,
+ ease: this.defaultEase,
+ });
+
+ gsap.to(modalElement, {
+ opacity: 1,
+ scale: 1,
+ y: 0,
+ duration: this.defaultDuration,
+ ease: this.defaultEase,
+ });
+ }
+
+ closeModal(modalElement: HTMLElement, overlayElement: HTMLElement, onComplete?: () => void) {
+ gsap.to([overlayElement, modalElement], {
+ opacity: 0,
+ duration: this.defaultDuration,
+ ease: this.defaultEase,
+ onComplete: () => {
+ gsap.set([overlayElement, modalElement], { display: 'none' });
+ onComplete?.();
+ },
+ });
+
+ gsap.to(modalElement, {
+ scale: 0.95,
+ y: 20,
+ duration: this.defaultDuration,
+ ease: this.defaultEase,
+ });
+ }
+}
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index 5693d6b..300a61a 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -144,13 +144,33 @@ a {
}
.modal-bg {
- @apply fixed inset-0 bg-black/70 z-50 focus:outline-none focus:ring-2 focus:ring-emerald-light;
+ @apply fixed inset-0 bg-black/80 backdrop-blur-sm z-50 focus:outline-none focus:ring-2 focus:ring-emerald-light;
}
.modal-card {
- @apply bg-deep-blue-contrast overflow-hidden hover:shadow-xl transition-shadow duration-300 p-4 fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 p-6 rounded-lg shadow-lg z-50 min-w-[300px];
+ @apply bg-deep-blue-contrast overflow-hidden hover:shadow-xl transition-shadow duration-300 p-6 rounded-xl shadow-2xl z-50 min-w-[300px] max-w-[400px] w-full mx-auto border border-deep-blue-light/20 fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2;
}
.modal-heading {
- @apply text-xl font-bold text-text-primary;
+ @apply text-2xl font-bold text-text-primary mb-4;
+}
+
+.modal-card input {
+ @apply w-full px-4 py-2.5 bg-deep-blue-light/50 text-white rounded-lg my-1 border border-deep-blue-light/30 focus:border-emerald/50 focus:ring-1 focus:ring-emerald/50 outline-none transition-all duration-200;
+}
+
+.modal-card label {
+ @apply text-text-secondary text-sm font-medium mb-1 block;
+}
+
+.modal-card button {
+ @apply transition-all duration-200;
+}
+
+.modal-card .button-primary {
+ @apply bg-emerald hover:bg-emerald-dark text-text-primary transition-all duration-300 active:scale-95 shadow-lg shadow-emerald/20;
+}
+
+.modal-card .button-secondary {
+ @apply bg-deep-blue-light/50 hover:bg-deep-blue-light w-full py-2.5 my-2 border border-deep-blue-light/30 hover:border-deep-blue-light/50;
}