DataService WIP, its working with project data for now, inc Skills, Education, Experience, Traits, Phrases

This commit is contained in:
AdamBtech
2025-06-02 21:01:35 +02:00
parent c1d05c005e
commit bec7a32d06
8 changed files with 156 additions and 104 deletions

View File

View File

69
assets/data/projects.json Normal file
View File

@@ -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": "<strong>Challenge 1:</strong> Balancing aesthetic authenticity with web accessibility<br><strong>Solution:</strong> Created high-contrast color schemes that pass WCAG guidelines<br><br><strong>Challenge 2:</strong> Making retro aesthetics work on modern devices<br><strong>Solution:</strong> Responsive design system with flexible typography and layouts<br><br><strong>Challenge 3:</strong> Performance with complex visual effects<br><strong>Solution:</strong> CSS-only animations and optimized asset loading"
},
{
"title": "PERFORMANCE_METRICS",
"content": "• Lighthouse score: <strong>95+</strong><br>• First contentful paint: <strong>< 1.2s</strong><br>• Accessibility score: <strong>98%</strong><br>• Mobile optimization: <strong>Perfect responsive design</strong><br>• Bundle size: <strong>< 500KB gzipped</strong><br>• SEO optimization: <strong>100%</strong>"
}
]
}
},
{
"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
}
]

0
assets/data/skills.json Normal file
View File

0
assets/data/traits.json Normal file
View File

View File

@@ -2,7 +2,12 @@ import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router'; import { provideRouter } from '@angular/router';
import { routes } from './app.routes'; import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideAnimationsAsync()], providers: [
provideRouter(routes),
provideAnimationsAsync(),
provideHttpClient(),
],
}; };

View File

@@ -1,5 +1,5 @@
// projects.component.ts // 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 { SectionTitleComponent } from '../../components/section-title/section-title.component';
import { type Project } from '../../shared/models/project.model'; import { type Project } from '../../shared/models/project.model';
import { ProjectTreeComponent } from './project-tree/project-tree.component'; 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 { ProjectFooterComponent } from './project-footer/project-footer.component';
import { ProjectLoaderDecoratorComponent } from './project-loader-decorator/project-loader-decorator.component'; import { ProjectLoaderDecoratorComponent } from './project-loader-decorator/project-loader-decorator.component';
import { ProjectListComponent } from './projects-list/projects-list.component'; import { ProjectListComponent } from './projects-list/projects-list.component';
import { DataService } from '../../shared/services/data.service';
@Component({ @Component({
selector: 'app-projects', selector: 'app-projects',
@@ -22,13 +23,16 @@ import { ProjectListComponent } from './projects-list/projects-list.component';
styleUrl: './projects.component.css', styleUrl: './projects.component.css',
}) })
export class ProjectsComponent implements OnInit { export class ProjectsComponent implements OnInit {
// Signals private readonly dataService = inject(DataService);
projects = signal<Project[]>([]);
// Use data service signals directly
projects = this.dataService.projects;
// Component-specific signals
selectedProject = signal<Project | null>(null); selectedProject = signal<Project | null>(null);
isLoading = signal(false); isLoading = signal(false);
ngOnInit(): void { ngOnInit(): void {
this.loadProjects();
this.startLoadingAnimation(); this.startLoadingAnimation();
} }
@@ -40,105 +44,6 @@ export class ProjectsComponent implements OnInit {
}, 3000); }, 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: `<strong>Challenge 1:</strong> Balancing aesthetic authenticity with web accessibility<br>
<strong>Solution:</strong> Created high-contrast color schemes that pass WCAG guidelines<br><br>
<strong>Challenge 2:</strong> Making retro aesthetics work on modern devices<br>
<strong>Solution:</strong> Responsive design system with flexible typography and layouts<br><br>
<strong>Challenge 3:</strong> Performance with complex visual effects<br>
<strong>Solution:</strong> CSS-only animations and optimized asset loading`,
},
{
title: 'PERFORMANCE_METRICS',
content: `• Lighthouse score: <strong>95+</strong><br>
• First contentful paint: <strong>< 1.2s</strong><br>
• Accessibility score: <strong>98%</strong><br>
• Mobile optimization: <strong>Perfect responsive design</strong><br>
• Bundle size: <strong>< 500KB gzipped</strong><br>
• SEO optimization: <strong>100%</strong>`,
},
],
},
},
// 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 { openCaseStudy(project: Project): void {
this.selectedProject.set(project); this.selectedProject.set(project);
} }

View File

@@ -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<Project[]>([]);
// Public readonly signals
readonly projects = this._projects.asReadonly();
constructor() {
console.log('DataService initialized');
this.loadInitialData();
}
private async loadInitialData(): Promise<void> {
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<Project[]> {
console.log('Fetching projects from assets/data/projects.json');
const result = await firstValueFrom(
this.http.get<Project[]>('data/projects.json'),
);
console.log('HTTP request completed:', result);
return result;
}
}