From a626a909d47d5374af2aa49c7e172d2191cefedf Mon Sep 17 00:00:00 2001 From: AdamBtech <60339324+AdamBtech@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:19:24 +0200 Subject: [PATCH] Refactoring personal info column and preparing other history components for refactoring --- .../column-education-info.component.css | 0 .../column-education-info.component.html | 0 .../column-education-info.component.ts | 9 + .../column-personal-info.component.css | 398 ++++++++++++++++++ .../column-personal-info.component.html | 49 +++ .../column-personal-info.component.ts | 22 + .../column-professional-info.component.css | 0 .../column-professional-info.component.html | 1 + .../column-professional-info.component.ts | 11 + .../operative-history.component.html | 49 +-- .../operative-history.component.ts | 15 +- 11 files changed, 493 insertions(+), 61 deletions(-) create mode 100644 src/app/pages/experience/operative-history/column-education-info/column-education-info.component.css create mode 100644 src/app/pages/experience/operative-history/column-education-info/column-education-info.component.html create mode 100644 src/app/pages/experience/operative-history/column-education-info/column-education-info.component.ts create mode 100644 src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.css create mode 100644 src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.html create mode 100644 src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.ts create mode 100644 src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.css create mode 100644 src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.html create mode 100644 src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.ts diff --git a/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.css b/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.html b/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.html new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.ts b/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.ts new file mode 100644 index 0000000..4fe5600 --- /dev/null +++ b/src/app/pages/experience/operative-history/column-education-info/column-education-info.component.ts @@ -0,0 +1,9 @@ +import { Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-column-education-info', + imports: [], + templateUrl: './column-education-info.component.html', + styleUrl: './column-education-info.component.css', +}) +export class ColumnEducationInfoComponent {} diff --git a/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.css b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.css new file mode 100644 index 0000000..3cc1896 --- /dev/null +++ b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.css @@ -0,0 +1,398 @@ +/* Personal Column Container */ +.personal-column { + display: flex; + flex-direction: column; + gap: var(--card-gap); + min-height: 0; + padding-right: 0.5rem; + + /* Hide overflow initially */ + overflow: hidden; + animation: enableColumnScrollAfterAnimation 0s ease-out 3s forwards; + + /* Initial state for animation */ + opacity: 0; + transform: translateY(20px); + animation: fadeInUp var(--animation-duration) ease-out calc(var(--animation-delay-base) * 5) forwards, enableColumnScrollAfterAnimation 0s ease-out 3s forwards; +} + +/* Column Title */ +.column-title { + font-family: var(--font-terminal); + font-size: 1rem; + color: var(--color-nier-accent); + letter-spacing: 0.1em; + text-align: center; + margin-bottom: var(--card-gap); + padding: 0.5rem; + border-bottom: 1px solid var(--color-nier-border); + flex-shrink: 0; + position: sticky; + top: 0; + background: var(--color-nier-bg); + z-index: 10; + + /* Title animation */ + opacity: 0; + transform: translateX(-10px); + animation: slideInLeft 0.4s ease-out calc(var(--animation-delay-base) * 7) forwards; +} + +/* Info Card Styles */ +.info-card { + border: 2px solid var(--color-nier-border); + background: var(--color-nier-bg); + position: relative; + transition: var(--transition-smooth); + margin-bottom: var(--card-gap); + flex-shrink: 0; + border-radius: var(--border-radius); + + /* Card initial state */ + opacity: 0; + transform: translateY(30px) scale(0.95); + animation: cardFadeIn var(--animation-duration) ease-out calc(var(--animation-delay-base) * 10) forwards; +} + +.info-card:hover { + transform: translateY(-1px) scale(1.01); + box-shadow: var(--shadow-subtle); +} + +.info-header { + background: linear-gradient(135deg, var(--color-nier-dark) 0%, var(--color-nier-highlight) 100%); + color: var(--color-nier-text-light); + padding: 0.5rem; + font-family: var(--font-terminal); + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.05em; + border-bottom: 2px solid var(--color-nier-border); + position: relative; + overflow: hidden; +} + +.info-content { + padding: var(--card-padding); + background: var(--color-nier-bg); + font-size: 0.85rem; + line-height: 1.4; +} + +/* Personal Info Grid */ +.trait-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 0.25rem; +} + +.trait-item { + background: linear-gradient(135deg, var(--color-nier-accent) 0%, var(--color-nier-highlight) 100%); + color: var(--color-nier-text-light); + padding: 0.375rem 0.25rem; + font-size: 0.7rem; + font-family: var(--font-terminal); + text-transform: uppercase; + letter-spacing: 0.05em; + border-radius: 3px; + white-space: nowrap; + transition: var(--transition-smooth); + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + text-align: center; + + /* Initial state for staggered animation */ + opacity: 0; + transform: scale(0.8) translateY(10px); + animation: techItemFadeIn 0.4s ease-out forwards; + animation-delay: calc(var(--animation-delay-base) * 19); +} + +.trait-item:hover { + transform: translateY(-2px) scale(1.05); + box-shadow: 0 6px 12px rgba(0,0,0,0.2); +} + +.interest-item { + margin-bottom: 0.5rem; + display: flex; + align-items: center; + padding: 0.25rem; + border-radius: 2px; + transition: background-color 0.3s ease, transform 0.3s ease; + + /* Interest item animation */ + opacity: 0; + transform: translateX(-10px); + animation: slideInLeft 0.3s ease-out calc(var(--animation-delay-base) * 20) forwards; +} + +.interest-item:hover { + background-color: rgba(41, 41, 37, 0.05); + transform: translateX(2px); +} + +.interest-label { + font-family: var(--font-terminal); + font-size: 0.7rem; + color: var(--color-nier-text-dark); + text-transform: uppercase; + letter-spacing: 0.05em; + width: 60px; + flex-shrink: 0; + opacity: 0.8; + margin-right: 1rem; +} + +.interest-value { + font-family: var(--font-noto-jp); + font-size: 0.8rem; + color: var(--color-nier-text-dark); +} + +/* Enhanced Philosophy Section */ +.philosophy-text { + font-size: 0.8rem; + line-height: 1.5; + font-style: italic; + margin-bottom: var(--card-gap); + position: relative; + padding-left: 1rem; + + /* Philosophy text animation */ + opacity: 0; + animation: fadeIn 0.6s ease-out calc(var(--animation-delay-base) * 22) forwards; +} + +.philosophy-text::before { + content: '"'; + position: absolute; + left: 0; + top: -0.25rem; + font-size: 1.5rem; + color: var(--color-nier-accent); + opacity: 0; + animation: fadeIn 0.4s ease-out calc(var(--animation-delay-base) * 23) forwards; +} + +.philosophy-note { + font-family: var(--font-terminal); + font-size: 0.75rem; + color: var(--color-nier-text-dark); + opacity: 0; + margin-top: var(--card-gap); + padding-top: var(--card-gap); + border-top: 1px solid var(--color-nier-border); + line-height: 1.4; + animation: fadeIn 0.4s ease-out calc(var(--animation-delay-base) * 24) forwards; +} + +/* Keyframe animations (needed for this component) */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes enableColumnScrollAfterAnimation { + to { + overflow-y: auto; + } +} + +@keyframes cardFadeIn { + from { + opacity: 0; + transform: translateY(30px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@keyframes slideInLeft { + from { + opacity: 0; + transform: translateX(-10px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes techItemFadeIn { + from { + opacity: 0; + transform: scale(0.8) translateY(10px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* Responsive Design - Personal Column Specific */ +@media (max-width: 480px) { + .personal-column { + gap: 0.5rem; + padding-right: 0.25rem; + + /* Ensure columns are visible on mobile */ + min-height: auto; + + /* Simplified mobile column animations */ + animation-name: fadeInUp, enableColumnScrollAfterAnimation; + animation-duration: 0.3s, 0s; + animation-timing-function: ease-out, ease-out; + animation-delay: 0.25s, 1.5s; + animation-fill-mode: forwards, forwards; + } + + .column-title { + font-size: 0.9rem; + padding: 0.375rem; + margin-bottom: 0.5rem; + + /* Simplified title animation */ + animation-name: slideInLeft; + animation-duration: 0.3s; + animation-timing-function: ease-out; + animation-delay: 0.3s; + animation-fill-mode: forwards; + } + + .info-header { + padding: 0.75rem 0.5rem 0.5rem 0.5rem; + } + + .info-content { + padding: 0.75rem 0.5rem; + font-size: 0.85rem; + line-height: 1.4; + } + + .trait-grid { + grid-template-columns: 1fr; + gap: 0.375rem; + } + + .trait-item { + padding: 0.5rem 0.375rem; + font-size: 0.75rem; + + /* Simplified trait animation */ + animation-name: techItemFadeIn; + animation-duration: 0.2s; + animation-timing-function: ease-out; + animation-delay: 0.7s; + animation-fill-mode: forwards; + } + + .interest-item { + margin-bottom: 0.75rem; + padding: 0.5rem 0.25rem; + + /* Simplified interest animation */ + animation-name: slideInLeft; + animation-duration: 0.2s; + animation-timing-function: ease-out; + animation-delay: 0.8s; + animation-fill-mode: forwards; + } + + .interest-label { + font-size: 0.75rem; + width: 70px; + } + + .interest-value { + font-size: 0.85rem; + } + + .philosophy-text { + font-size: 0.8rem; + padding-left: 0.75rem; + line-height: 1.5; + margin-bottom: 1rem; + + /* Simplified philosophy animation */ + animation-name: fadeIn; + animation-duration: 0.3s; + animation-timing-function: ease-out; + animation-delay: 0.9s; + animation-fill-mode: forwards; + } + + .philosophy-text::before { + /* Simple fade for quote mark */ + animation-name: fadeIn; + animation-duration: 0.2s; + animation-timing-function: ease-out; + animation-delay: 1s; + animation-fill-mode: forwards; + } + + .philosophy-note { + font-size: 0.75rem; + line-height: 1.4; + padding-top: 1rem; + + /* Simplified note animation */ + animation-name: fadeIn; + animation-duration: 0.2s; + animation-timing-function: ease-out; + animation-delay: 1.1s; + animation-fill-mode: forwards; + } + + /* Remove complex animations on very small screens */ + @media (max-width: 360px) { + .trait-item, + .interest-item, + .philosophy-text, + .philosophy-text::before, + .philosophy-note { + animation: none !important; + opacity: 1 !important; + transform: none !important; + } + } +} + +@media (max-width: 1200px) and (min-width: 769px) { + .personal-column { + grid-column: 1 / -1; + } +} + +/* Reduced Motion Support - Personal Column */ +@media (prefers-reduced-motion: reduce) { + .personal-column, + .column-title, + .info-card, + .trait-item, + .interest-item, + .philosophy-text, + .philosophy-text::before, + .philosophy-note { + animation: none !important; + transition: none !important; + opacity: 1 !important; + transform: none !important; + } +} diff --git a/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.html b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.html new file mode 100644 index 0000000..f3a9e87 --- /dev/null +++ b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.html @@ -0,0 +1,49 @@ + +
+

[PERSONAL_DATA]

+ +
+
INTERESTS
+
+
+ READINGS: + Science Fiction, Philosophy, Fantasy +
+
+ INTERESTS: + Digital & Tabletop Games, Hiking, Drawing +
+
+ PETS: + Proud Dad of 6 Guinea Pigs (You read right!) +
+
+
+ +
+
CORE_TRAITS
+
+
+ CURIOUS + PERSISTENT + ANALYTICAL + CREATIVE + ADAPTIVE + SELF-LEARNER +
+
+
+ +
+
PHILOSOPHY
+
+

+ "The most elegant code emerges from understanding both the technical substrate and the consciousness it serves." +

+
+ {{ personalNote() }} +
+
+
+
+ diff --git a/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.ts b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.ts new file mode 100644 index 0000000..be49a5e --- /dev/null +++ b/src/app/pages/experience/operative-history/column-personal-info/column-personal-info.component.ts @@ -0,0 +1,22 @@ +import { Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-column-personal-info', + imports: [], + templateUrl: './column-personal-info.component.html', + styleUrl: './column-personal-info.component.css', +}) +export class ColumnPersonalInfoComponent { + private readonly _personalNote = signal( + 'In the spaces between keystrokes and compiler runs, I contemplate the philosophical implications of our digital convergence. When not debugging the matrix, I tend to six small organic beings who remind me that even in our increasingly automated world, care and attention to living creatures remains profoundly important.', + ); + + private readonly _philosophyText = signal([ + 'Four years navigating the intersection between human needs and machine logic has taught me that the most elegant code emerges from understanding both the technical substrate and the consciousness it serves. My journey through enterprise system matrices—from military-grade security protocols to corporate data synthesis—has prepared me for a world where the line between human intention and digital execution grows ever thinner.', + 'I approach development like a philosopher examining the nature of existence: with persistent curiosity and the understanding that every system, no matter how complex, serves a fundamentally human purpose. In a cyberpunk reality where APIs are neural pathways and databases are digital memories, I believe in crafting code that honors both computational efficiency and human dignity.', + 'The future belongs to those who can bridge the organic and the synthetic, who understand that behind every elegant algorithm lies a human story waiting to be told.', + ] as const); + + readonly personalNote = this._personalNote.asReadonly(); + readonly philosophyText = this._philosophyText.asReadonly(); +} diff --git a/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.css b/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.html b/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.html new file mode 100644 index 0000000..816caf0 --- /dev/null +++ b/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.html @@ -0,0 +1 @@ +

column-professional-info works!

diff --git a/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.ts b/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.ts new file mode 100644 index 0000000..d374e13 --- /dev/null +++ b/src/app/pages/experience/operative-history/column-professional-info/column-professional-info.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-column-professional-info', + imports: [], + templateUrl: './column-professional-info.component.html', + styleUrl: './column-professional-info.component.css' +}) +export class ColumnProfessionalInfoComponent { + +} diff --git a/src/app/pages/experience/operative-history/operative-history.component.html b/src/app/pages/experience/operative-history/operative-history.component.html index 23b7121..1ceddd1 100644 --- a/src/app/pages/experience/operative-history/operative-history.component.html +++ b/src/app/pages/experience/operative-history/operative-history.component.html @@ -94,52 +94,5 @@ - -
-

[PERSONAL_DATA]

- -
-
INTERESTS
-
-
- READINGS: - Science Fiction, Philosophy, Fantasy -
-
- INTERESTS: - Digital & Tabletop Games, Hiking, Drawing -
-
- PETS: - Proud Dad of 6 Guinea Pigs (You read right!) -
-
-
- -
-
CORE_TRAITS
-
-
- CURIOUS - PERSISTENT - ANALYTICAL - CREATIVE - ADAPTIVE - SELF-LEARNER -
-
-
- -
-
PHILOSOPHY
-
-

- "The most elegant code emerges from understanding both the technical substrate and the consciousness it serves." -

-
- {{ personalNote() }} -
-
-
-
+ diff --git a/src/app/pages/experience/operative-history/operative-history.component.ts b/src/app/pages/experience/operative-history/operative-history.component.ts index 9653379..2f33c31 100644 --- a/src/app/pages/experience/operative-history/operative-history.component.ts +++ b/src/app/pages/experience/operative-history/operative-history.component.ts @@ -1,6 +1,7 @@ // operative-history.component.ts import { Component, signal, computed } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { ColumnPersonalInfoComponent } from './column-personal-info/column-personal-info.component'; interface Experience { readonly id: string; @@ -17,7 +18,7 @@ interface Experience { @Component({ selector: 'app-operative-history', standalone: true, - imports: [CommonModule], + imports: [CommonModule, ColumnPersonalInfoComponent], templateUrl: './operative-history.component.html', styleUrl: './operative-history.component.css', }) @@ -88,21 +89,9 @@ export class OperativeHistoryComponent { isCurrent: true, } as const); - private readonly _philosophyText = signal([ - 'Four years navigating the intersection between human needs and machine logic has taught me that the most elegant code emerges from understanding both the technical substrate and the consciousness it serves. My journey through enterprise system matrices—from military-grade security protocols to corporate data synthesis—has prepared me for a world where the line between human intention and digital execution grows ever thinner.', - 'I approach development like a philosopher examining the nature of existence: with persistent curiosity and the understanding that every system, no matter how complex, serves a fundamentally human purpose. In a cyberpunk reality where APIs are neural pathways and databases are digital memories, I believe in crafting code that honors both computational efficiency and human dignity.', - 'The future belongs to those who can bridge the organic and the synthetic, who understand that behind every elegant algorithm lies a human story waiting to be told.', - ] as const); - - private readonly _personalNote = signal( - 'In the spaces between keystrokes and compiler runs, I contemplate the philosophical implications of our digital convergence. When not debugging the matrix, I tend to six small organic beings who remind me that even in our increasingly automated world, care and attention to living creatures remains profoundly important.', - ); - // Public computed signals for template readonly experiences = this._experiences.asReadonly(); readonly currentTraining = this._currentTraining.asReadonly(); - readonly philosophyText = this._philosophyText.asReadonly(); - readonly personalNote = this._personalNote.asReadonly(); // Computed signals for derived data readonly totalExperience = computed(() => this.experiences().length);