From 38e018d0347195ff25fa0aed2862ab19395f7af1 Mon Sep 17 00:00:00 2001 From: ztimson Date: Thu, 4 Jun 2026 18:59:10 -0400 Subject: [PATCH] - Better banner - Removed old communication methods - Connected email form --- package-lock.json | 14 +- package.json | 4 +- .../components/banner/banner.component.html | 8 +- .../components/banner/banner.component.scss | 156 +++++++++++++++++- src/app/components/banner/banner.component.ts | 9 +- .../components/contact/contact.component.html | 51 +++--- .../components/contact/contact.component.ts | 18 +- .../components/footer/footer.component.html | 40 ++--- src/app/containers/app/app.component.ts | 7 +- src/app/services/momentum.service.ts | 8 +- src/app/views/home/home.component.html | 40 +++-- src/index.html | 18 +- tsconfig.json | 3 + 13 files changed, 287 insertions(+), 89 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2d38896..4499b59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@angular/platform-browser": "^14.2.0", "@angular/platform-browser-dynamic": "^14.2.0", "@angular/router": "^14.2.0", - "@ztimson/momentum": "^1.1.11", + "@ztimson/momentum": "^1.2.1", "bootstrap": "^5.2.1", "jquery": "^3.6.1", "ngx-google-analytics": "^14.0.1", @@ -3342,9 +3342,9 @@ "dev": true }, "node_modules/@ztimson/momentum": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@ztimson/momentum/-/momentum-1.1.11.tgz", - "integrity": "sha512-ArFIOJj0mCbvR/P6XBlOjvICytf3ggPClbMmDDsZNtLMGXIZ+HqNjt58LDuEpLr3a8pe0mXEZ3jGkIAv2no8mA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ztimson/momentum/-/momentum-1.2.1.tgz", + "integrity": "sha512-O3Z06SfMin6zXlW0jZjgS16qwcyPtKfJ8hRzV6SuFlN9Il8y7HepUylnV8Hd5RTdWXeztBmo+pNTD/RjPJ37wQ==", "dependencies": { "@ztimson/utils": "0.29.1" }, @@ -14098,9 +14098,9 @@ "dev": true }, "@ztimson/momentum": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@ztimson/momentum/-/momentum-1.1.11.tgz", - "integrity": "sha512-ArFIOJj0mCbvR/P6XBlOjvICytf3ggPClbMmDDsZNtLMGXIZ+HqNjt58LDuEpLr3a8pe0mXEZ3jGkIAv2no8mA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ztimson/momentum/-/momentum-1.2.1.tgz", + "integrity": "sha512-O3Z06SfMin6zXlW0jZjgS16qwcyPtKfJ8hRzV6SuFlN9Il8y7HepUylnV8Hd5RTdWXeztBmo+pNTD/RjPJ37wQ==", "requires": { "@ztimson/utils": "0.29.1" } diff --git a/package.json b/package.json index b5450ce..bec87ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "legio-xxx", - "version": "0.0.0", + "version": "1.0.0", "scripts": { "ng": "ng", "start": "ng serve", @@ -21,7 +21,7 @@ "@angular/platform-browser": "^14.2.0", "@angular/platform-browser-dynamic": "^14.2.0", "@angular/router": "^14.2.0", - "@ztimson/momentum": "^1.1.11", + "@ztimson/momentum": "^1.2.1", "bootstrap": "^5.2.1", "jquery": "^3.6.1", "ngx-google-analytics": "^14.0.1", diff --git a/src/app/components/banner/banner.component.html b/src/app/components/banner/banner.component.html index e2fb4c7..4ce9f22 100644 --- a/src/app/components/banner/banner.component.html +++ b/src/app/components/banner/banner.component.html @@ -12,11 +12,11 @@ play_arrow diff --git a/src/app/components/banner/banner.component.scss b/src/app/components/banner/banner.component.scss index fe947f9..311175f 100644 --- a/src/app/components/banner/banner.component.scss +++ b/src/app/components/banner/banner.component.scss @@ -3,48 +3,192 @@ overflow: hidden; width: 100%; height: 100%; + min-height: 420px; + background: #111; + isolation: isolate; +} + +.banner-container::before { + content: ''; + position: absolute; + inset: 0; + z-index: 1; + background: + linear-gradient(90deg, rgba(0, 0, 0, 0.32), rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.32)), + linear-gradient(180deg, rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.34)); + pointer-events: none; +} + +.banner-container::after { + content: ''; + position: absolute; + inset: auto 0 0; + z-index: 2; + height: 28%; + background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.38)); + pointer-events: none; } .banner-background { width: 100%; height: 100%; - filter: blur(10px); - -webkit-filter: blur(10px); + object-fit: cover; + transform: scale(1.04); + filter: blur(8px) brightness(90%) saturate(112%); + -webkit-filter: blur(8px) brightness(90%) saturate(112%); } .banner-image { position: absolute; + z-index: 1; height: 90%; width: auto; + max-width: 92%; top: 5%; left: 50%; transform: translateX(-50%); + object-fit: contain; + border-radius: 14px; + box-shadow: + 0 18px 44px rgba(0, 0, 0, 0.36), + 0 0 0 1px rgba(255, 255, 255, 0.14); + filter: contrast(102%) saturate(104%); +} + +.banner-next, +.banner-previous, +.banner-pause { + z-index: 4; + display: flex; + align-items: center; + justify-content: center; + width: 52px; + height: 52px; + color: #fff; + cursor: pointer; + border-radius: 999px; + background: rgba(0, 0, 0, 0.34); + border: 1px solid rgba(255, 255, 255, 0.24); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + box-shadow: 0 10px 22px rgba(0, 0, 0, 0.24); + transition: + background 160ms ease, + border-color 160ms ease, + box-shadow 160ms ease, + color 160ms ease; +} + +.banner-next:hover, +.banner-previous:hover, +.banner-pause:hover { + background: rgba(75, 15, 15, 0.55); + border-color: rgba(240, 195, 106, 0.52); + color: #f0c36a; + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.34); +} + +.banner-next mat-icon, +.banner-previous mat-icon, +.banner-pause mat-icon { + font-size: 30px; + width: 30px; + height: 30px; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.42)); } .banner-next { position: absolute; top: 50%; right: 26px; - transform: translate(-50%, -50%); + transform: translateY(-50%); } .banner-previous { position: absolute; top: 50%; - left: 50px; - transform: translate(-50%, -50%); + left: 26px; + transform: translateY(-50%); } .banner-seal { position: absolute; + z-index: 3; top: 50%; left: 50%; transform: translate(-50%, -50%); + text-align: center; + pointer-events: none; +} + +.banner-seal img { + max-width: min(250px, 42vw); + height: auto; + opacity: 0.95; + filter: brightness(108%) drop-shadow(0 10px 16px rgba(0, 0, 0, 0.65)) !important; +} + +.banner-seal a, +.banner-scroll { + pointer-events: auto; + display: inline-flex; + margin-top: 18px; + color: #fff; + opacity: 0.9; + transition: + opacity 160ms ease, + color 160ms ease; +} + +.banner-scroll { + padding: 0; + border: 0; + background: transparent; + cursor: pointer; + filter: drop-shadow(2px 4px 6px black); +} + +.banner-seal a:hover, +.banner-scroll:hover { + color: #f0c36a !important; + opacity: 1; } .banner-pause { position: absolute; bottom: 25px; left: 50%; - transform: translate(-50%, -50%); + transform: translateX(-50%); + width: 46px; + height: 46px; +} + +@media (max-width: 768px) { + .banner-container { + min-height: 340px; + } + + .banner-image { + height: 78%; + max-width: 96%; + border-radius: 12px; + } + + .banner-next, + .banner-previous { + width: 44px; + height: 44px; + } + + .banner-next { + right: 12px; + } + + .banner-previous { + left: 12px; + } + + .banner-pause { + bottom: 16px; + } } diff --git a/src/app/components/banner/banner.component.ts b/src/app/components/banner/banner.component.ts index 8333c97..40226a1 100644 --- a/src/app/components/banner/banner.component.ts +++ b/src/app/components/banner/banner.component.ts @@ -41,7 +41,7 @@ export class BannerComponent implements AfterViewInit, OnDestroy, OnInit { this.sub = interval(this.speed) .subscribe( i => { if(this.manual) return; - this.selected = i % this.images.length + this.selected = i % this.images.length }); } @@ -66,4 +66,11 @@ export class BannerComponent implements AfterViewInit, OnDestroy, OnInit { this.selected--; if(this.selected < 0) this.selected = this.images.length - 1; } + + scrollToAbout() { + document.getElementById('about')?.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } } diff --git a/src/app/components/contact/contact.component.html b/src/app/components/contact/contact.component.html index 91b6757..809c828 100644 --- a/src/app/components/contact/contact.component.html +++ b/src/app/components/contact/contact.component.html @@ -1,9 +1,18 @@
- Coming Soon: This feature is under development + {{error}}
-
+
+ Your message was sent successfully. +
+ +
+ + Name + + +
Email @@ -25,13 +34,10 @@
-
+
- Send me a copy -
-
- - + +
@@ -41,17 +47,24 @@
-
-

Robert Sacco

-

Legio XXX President

-
Portrays: Aquilifer Primus Marius Maximus
- primuspiluslxxx@gmail.com -
-
-

Tom Ross

-

Legio XXX Patronus (Patron)

-
Portrays: Titus Quartinius Saturnalus
- tomlongwoods@gmail.com +
+
+

Robert Sacco

+

Legio XXX President

+
Portrays: Aquilifer Primus Marius Maximus
+ primuspiluslxxx@gmail.com +
+
+

Tom Ross

+

Legio XXX Patronus (Patron)

+
Portrays: Titus Quartinius Saturnalus
+ tomlongwoods@gmail.com +
diff --git a/src/app/components/contact/contact.component.ts b/src/app/components/contact/contact.component.ts index 6fe141a..ead2ed2 100644 --- a/src/app/components/contact/contact.component.ts +++ b/src/app/components/contact/contact.component.ts @@ -1,5 +1,6 @@ import {Component} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; +import {MomentumService} from '../../services/momentum.service'; @Component({ selector: 'app-contact', @@ -7,18 +8,33 @@ import {FormBuilder, FormGroup} from '@angular/forms'; }) export class ContactComponent { public error = false; + public success = false; public form!: FormGroup; - constructor(private fb: FormBuilder) { + constructor(private fb: FormBuilder, private momentum: MomentumService) { this.form = fb.group({ + name: '', email: '', subject: '', body: '', }); } + public async submitEmail(): Promise { + this.error = false; + this.success = false; + + try { + await this.momentum.api.data.create(MomentumService.SCHEMA['contact'], this.form.value); + this.success = true; + } catch (error: any) { + this.error = error.message; + } + } + reset() { this.error = false; + this.success = false; this.form.reset(); } } diff --git a/src/app/components/footer/footer.component.html b/src/app/components/footer/footer.component.html index f4a3e69..330ad75 100644 --- a/src/app/components/footer/footer.component.html +++ b/src/app/components/footer/footer.component.html @@ -1,24 +1,24 @@
@@ -45,7 +45,7 @@
diff --git a/src/app/containers/app/app.component.ts b/src/app/containers/app/app.component.ts index 8b21c22..52130a9 100644 --- a/src/app/containers/app/app.component.ts +++ b/src/app/containers/app/app.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {combineLatest, filter, Subscription} from 'rxjs'; import {BreakpointService} from '../../services/breakpoint.service'; +import {MomentumService} from '../../services/momentum.service'; @Component({ selector: 'app-root', @@ -14,7 +15,7 @@ export class AppComponent { mobile = false; open = false; - constructor(private breakpoint: BreakpointService, private router: Router) { + constructor(private breakpoint: BreakpointService, private momentum: MomentumService, private router: Router) { this.sub = combineLatest([ router.events.pipe(filter(event => event instanceof NavigationEnd)), breakpoint.isMobile$ @@ -24,6 +25,10 @@ export class AppComponent { }) } + ngOnInit(): void { + this.momentum.api.client.inject(); + } + ngOnDestroy() { if(this.sub) this.sub.unsubscribe(); } diff --git a/src/app/services/momentum.service.ts b/src/app/services/momentum.service.ts index 8508178..83f6a41 100644 --- a/src/app/services/momentum.service.ts +++ b/src/app/services/momentum.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {Momentum, type User} from '@ztimson/momentum'; +import {Momentum} from '@ztimson/momentum'; import {BehaviorSubject} from 'rxjs'; import {from, map} from 'rxjs'; import {filter} from 'rxjs/operators'; @@ -18,7 +18,7 @@ declare global { @Injectable({providedIn: 'root'}) export class MomentumService { static SCHEMA: {[key: string]: string} = { - // TODO: Add paths + contact: 'Contact', } api!: Momentum; @@ -29,11 +29,11 @@ export class MomentumService { // @ts-ignore user = new BehaviorSubject(undefined); // Undefined at init, null when logged out, object when logged in. - admin = from(this.user).pipe(filter((u: any) => u !== undefined), map((u: User | null) => u?.groups.includes('admin'))); + admin = from(this.user).pipe(filter(u => u !== undefined), map(u => u?.groups.includes('admin'))); isLoggedIn = from(this.user).pipe(filter(u => u !== undefined), map(Boolean)); constructor() { - this.api = new Momentum("https://legio-30.org", { + this.api = window['momentum'] = new Momentum("https://legio-30.org", { app: "Website", analytics: "prompt", logLevel: "ERROR", diff --git a/src/app/views/home/home.component.html b/src/app/views/home/home.component.html index 9df6b47..517d732 100644 --- a/src/app/views/home/home.component.html +++ b/src/app/views/home/home.component.html @@ -20,29 +20,47 @@ that recreate the lives of soldiers found in Trajan's legions during the 1st - 2nd Century AD

- More + More >>
Legio XXX Standard
-
-
-
- - -
-
+ + + + + + + + + + + + + + + + + + + + + + +
+ +

- Join us on Discord + Join Our Monthly Meetings

- Ask us questions, get involved + Meet the legion, ask questions, and learn how to get involved.

- and celebrate the glory of Rome with us! + Contact us to be added to the event list!

diff --git a/src/index.html b/src/index.html index a4a1872..d9912df 100644 --- a/src/index.html +++ b/src/index.html @@ -3,27 +3,19 @@ + LEGIO · XXX + - - - - - - - - - - - - - LEGIO · XXX + + + diff --git a/tsconfig.json b/tsconfig.json index c85f7fd..69b5f3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,8 @@ "compilerOptions": { "baseUrl": "./", "outDir": "./out-tsc/app", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, @@ -13,6 +15,7 @@ "sourceMap": true, "declaration": false, "downlevelIteration": true, + "skipLibCheck": true, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true,