From bec7a32d0600eb3b429b09b4299dc0a94a12e5cf Mon Sep 17 00:00:00 2001
From: AdamBtech <60339324+AdamBtech@users.noreply.github.com>
Date: Mon, 2 Jun 2025 21:01:35 +0200
Subject: [PATCH] DataService WIP, its working with project data for now, inc
Skills, Education, Experience, Traits, Phrases
---
assets/data/education.json | 0
assets/data/experiences.json | 0
assets/data/projects.json | 69 ++++++++++++
assets/data/skills.json | 0
assets/data/traits.json | 0
src/app/app.config.ts | 7 +-
src/app/pages/projects/projects.component.ts | 111 ++-----------------
src/app/shared/services/data.service.ts | 73 ++++++++++++
8 files changed, 156 insertions(+), 104 deletions(-)
create mode 100644 assets/data/education.json
create mode 100644 assets/data/experiences.json
create mode 100644 assets/data/projects.json
create mode 100644 assets/data/skills.json
create mode 100644 assets/data/traits.json
create mode 100644 src/app/shared/services/data.service.ts
diff --git a/assets/data/education.json b/assets/data/education.json
new file mode 100644
index 0000000..e69de29
diff --git a/assets/data/experiences.json b/assets/data/experiences.json
new file mode 100644
index 0000000..e69de29
diff --git a/assets/data/projects.json b/assets/data/projects.json
new file mode 100644
index 0000000..5ccb854
--- /dev/null
+++ b/assets/data/projects.json
@@ -0,0 +1,69 @@
+[
+ {
+ "id": "portfolio",
+ "title": "PORTFOLIO_SYSTEM.EXE",
+ "status": "[MISSION_ACTIVE]",
+ "classification": "Personal Showcase Platform",
+ "objective": "Professional presentation interface with NieR aesthetic",
+ "statusDescription": "LIVE | CONTINUOUS_UPDATE",
+ "techStack": ["ANGULAR", "TYPESCRIPT", "TAILWIND", "VERCEL"],
+ "demoUrl": "https://adambenyekkoudev.vercel.app/",
+ "codeUrl": "https://github.com/adam-benyekkou/angular_portfolio",
+ "isRedacted": false,
+ "caseStudy": {
+ "title": "PORTFOLIO_SYSTEM.EXE",
+ "sections": [
+ {
+ "title": "PROJECT_OVERVIEW",
+ "content": "A NieR: Automata inspired personal portfolio showcasing development projects and skills. The design captures the game's distinctive UI aesthetic while maintaining modern web standards and accessibility. Built to stand out from typical developer portfolios while remaining professional and functional."
+ },
+ {
+ "title": "DESIGN_PHILOSOPHY",
+ "content": "Recreated the authentic NieR: Automata interface with parchment backgrounds, geometric layouts, and terminal-style typography. The design system uses CSS custom properties for theme consistency and implements dark/light mode switching that maintains the aesthetic in both contexts. Every element is carefully crafted to feel like it belongs in the game's world while serving a practical purpose."
+ },
+ {
+ "title": "TECHNICAL_IMPLEMENTATION",
+ "content": "Built with Angular 19 and Tailwind CSS using a custom design system. The architecture follows Angular best practices with standalone components, lazy loading, and optimized build processes. Implemented responsive grid layouts, smooth animations, and interactive elements that respond to user interactions while maintaining the game's UI feel. Special attention was paid to performance optimization and accessibility standards."
+ },
+ {
+ "title": "CHALLENGES_SOLVED",
+ "content": "Challenge 1: Balancing aesthetic authenticity with web accessibility
Solution: Created high-contrast color schemes that pass WCAG guidelines
Challenge 2: Making retro aesthetics work on modern devices
Solution: Responsive design system with flexible typography and layouts
Challenge 3: Performance with complex visual effects
Solution: CSS-only animations and optimized asset loading"
+ },
+ {
+ "title": "PERFORMANCE_METRICS",
+ "content": "• Lighthouse score: 95+
• First contentful paint: < 1.2s
• Accessibility score: 98%
• Mobile optimization: Perfect responsive design
• Bundle size: < 500KB gzipped
• SEO optimization: 100%"
+ }
+ ]
+ }
+ },
+ {
+ "id": "redacted-1",
+ "title": "REDACTED_PROJECT_1",
+ "status": "[REDACTED]",
+ "classification": "",
+ "objective": "",
+ "statusDescription": "",
+ "techStack": [],
+ "isRedacted": true
+ },
+ {
+ "id": "redacted-2",
+ "title": "REDACTED_PROJECT_2",
+ "status": "[REDACTED]",
+ "classification": "",
+ "objective": "",
+ "statusDescription": "",
+ "techStack": [],
+ "isRedacted": true
+ },
+ {
+ "id": "redacted-3",
+ "title": "REDACTED_PROJECT_3",
+ "status": "[REDACTED]",
+ "classification": "",
+ "objective": "",
+ "statusDescription": "",
+ "techStack": [],
+ "isRedacted": true
+ }
+]
diff --git a/assets/data/skills.json b/assets/data/skills.json
new file mode 100644
index 0000000..e69de29
diff --git a/assets/data/traits.json b/assets/data/traits.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index 43074b8..9a051f8 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -2,7 +2,12 @@ import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
+import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
- providers: [provideRouter(routes), provideAnimationsAsync()],
+ providers: [
+ provideRouter(routes),
+ provideAnimationsAsync(),
+ provideHttpClient(),
+ ],
};
diff --git a/src/app/pages/projects/projects.component.ts b/src/app/pages/projects/projects.component.ts
index d793a49..0c24271 100644
--- a/src/app/pages/projects/projects.component.ts
+++ b/src/app/pages/projects/projects.component.ts
@@ -1,5 +1,5 @@
// projects.component.ts
-import { Component, signal, OnInit } from '@angular/core';
+import { Component, signal, OnInit, inject, computed } from '@angular/core';
import { SectionTitleComponent } from '../../components/section-title/section-title.component';
import { type Project } from '../../shared/models/project.model';
import { ProjectTreeComponent } from './project-tree/project-tree.component';
@@ -7,6 +7,7 @@ import { ProjectModalComponent } from './project-modal/project-modal.component';
import { ProjectFooterComponent } from './project-footer/project-footer.component';
import { ProjectLoaderDecoratorComponent } from './project-loader-decorator/project-loader-decorator.component';
import { ProjectListComponent } from './projects-list/projects-list.component';
+import { DataService } from '../../shared/services/data.service';
@Component({
selector: 'app-projects',
@@ -22,13 +23,16 @@ import { ProjectListComponent } from './projects-list/projects-list.component';
styleUrl: './projects.component.css',
})
export class ProjectsComponent implements OnInit {
- // Signals
- projects = signal([]);
+ private readonly dataService = inject(DataService);
+
+ // Use data service signals directly
+ projects = this.dataService.projects;
+
+ // Component-specific signals
selectedProject = signal(null);
isLoading = signal(false);
ngOnInit(): void {
- this.loadProjects();
this.startLoadingAnimation();
}
@@ -40,105 +44,6 @@ export class ProjectsComponent implements OnInit {
}, 3000);
}
- private loadProjects(): void {
- const projectsData: Project[] = [
- {
- id: 'portfolio',
- title: 'PORTFOLIO_SYSTEM.EXE',
- status: '[MISSION_ACTIVE]',
- classification: 'Personal Showcase Platform',
- objective: 'Professional presentation interface with NieR aesthetic',
- statusDescription: 'LIVE | CONTINUOUS_UPDATE',
- techStack: ['ANGULAR', 'TYPESCRIPT', 'TAILWIND', 'VERCEL'],
- demoUrl: 'https://adambenyekkoudev.vercel.app/',
- codeUrl: 'https://github.com/adam-benyekkou/angular_portfolio',
- isRedacted: false,
- caseStudy: {
- title: 'PORTFOLIO_SYSTEM.EXE',
- sections: [
- {
- title: 'PROJECT_OVERVIEW',
- content: `A NieR: Automata inspired personal portfolio showcasing development projects and skills.
- The design captures the game's distinctive UI aesthetic while maintaining modern web standards
- and accessibility. Built to stand out from typical developer portfolios while remaining
- professional and functional.`,
- },
- {
- title: 'DESIGN_PHILOSOPHY',
- content: `Recreated the authentic NieR: Automata interface with parchment backgrounds,
- geometric layouts, and terminal-style typography. The design system uses CSS custom properties
- for theme consistency and implements dark/light mode switching that maintains
- the aesthetic in both contexts. Every element is carefully crafted to feel like
- it belongs in the game's world while serving a practical purpose.`,
- },
- {
- title: 'TECHNICAL_IMPLEMENTATION',
- content: `Built with Angular 19 and Tailwind CSS using a custom design system.
- The architecture follows Angular best practices with standalone components,
- lazy loading, and optimized build processes. Implemented responsive grid layouts,
- smooth animations, and interactive elements that respond to user interactions
- while maintaining the game's UI feel. Special attention was paid to performance
- optimization and accessibility standards.`,
- },
- {
- title: 'CHALLENGES_SOLVED',
- content: `Challenge 1: Balancing aesthetic authenticity with web accessibility
- Solution: Created high-contrast color schemes that pass WCAG guidelines
-
- Challenge 2: Making retro aesthetics work on modern devices
- Solution: Responsive design system with flexible typography and layouts
-
- Challenge 3: Performance with complex visual effects
- Solution: CSS-only animations and optimized asset loading`,
- },
- {
- title: 'PERFORMANCE_METRICS',
- content: `• Lighthouse score: 95+
- • First contentful paint: < 1.2s
- • Accessibility score: 98%
- • Mobile optimization: Perfect responsive design
- • Bundle size: < 500KB gzipped
- • SEO optimization: 100%`,
- },
- ],
- },
- },
- // Redacted projects
- {
- id: 'redacted-1',
- title: 'REDACTED_PROJECT_1',
- status: '[REDACTED]',
- classification: '',
- objective: '',
- statusDescription: '',
- techStack: [],
- isRedacted: true,
- },
- {
- id: 'redacted-2',
- title: 'REDACTED_PROJECT_2',
- status: '[REDACTED]',
- classification: '',
- objective: '',
- statusDescription: '',
- techStack: [],
- isRedacted: true,
- },
- {
- id: 'redacted-3',
- title: 'REDACTED_PROJECT_3',
- status: '[REDACTED]',
- classification: '',
- objective: '',
- statusDescription: '',
- techStack: [],
- isRedacted: true,
- },
- ];
-
- this.projects.set(projectsData);
- }
-
openCaseStudy(project: Project): void {
this.selectedProject.set(project);
}
diff --git a/src/app/shared/services/data.service.ts b/src/app/shared/services/data.service.ts
new file mode 100644
index 0000000..b845efe
--- /dev/null
+++ b/src/app/shared/services/data.service.ts
@@ -0,0 +1,73 @@
+import { Injectable, signal, inject } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { type Project } from '../models/project.model';
+import { firstValueFrom } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DataService {
+ private readonly http = inject(HttpClient);
+
+ // Private signals for state management
+ private _projects = signal([]);
+
+ // Public readonly signals
+ readonly projects = this._projects.asReadonly();
+
+ constructor() {
+ console.log('DataService initialized');
+ this.loadInitialData();
+ }
+
+ private async loadInitialData(): Promise {
+ try {
+ console.log('Starting to load projects...');
+ const projects = await this.fetchProjects();
+ console.log('Projects loaded successfully:', projects);
+ console.log('Number of projects:', projects.length);
+ this._projects.set(projects);
+ console.log('Projects signal updated');
+ } catch (error) {
+ console.error('Error loading data:', error);
+
+ // Fallback to hardcoded data for debugging
+ console.log('Loading fallback data...');
+ const fallbackProjects: Project[] = [
+ {
+ id: 'portfolio',
+ title: 'PORTFOLIO_SYSTEM.EXE',
+ status: '[MISSION_ACTIVE]',
+ classification: 'Personal Showcase Platform',
+ objective: 'Professional presentation interface with NieR aesthetic',
+ statusDescription: 'LIVE | CONTINUOUS_UPDATE',
+ techStack: ['ANGULAR', 'TYPESCRIPT', 'TAILWIND', 'VERCEL'],
+ demoUrl: 'https://adambenyekkoudev.vercel.app/',
+ codeUrl: 'https://github.com/adam-benyekkou/angular_portfolio',
+ isRedacted: false,
+ },
+ {
+ id: 'redacted-1',
+ title: 'REDACTED_PROJECT_1',
+ status: '[REDACTED]',
+ classification: '',
+ objective: '',
+ statusDescription: '',
+ techStack: [],
+ isRedacted: true,
+ },
+ ];
+ this._projects.set(fallbackProjects);
+ console.log('Fallback data loaded');
+ }
+ }
+
+ private async fetchProjects(): Promise {
+ console.log('Fetching projects from assets/data/projects.json');
+ const result = await firstValueFrom(
+ this.http.get('data/projects.json'),
+ );
+ console.log('HTTP request completed:', result);
+ return result;
+ }
+}