Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build:vercel": "ng build --configuration production",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
Expand Down
Binary file removed public/CV.pdf
Binary file not shown.
Binary file removed public/me.png
Binary file not shown.
12 changes: 12 additions & 0 deletions src/app/app.component.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@

/* Loading transition */
.body {
opacity: 0;
transform: translateY(20px);
transition: all 0.8s ease-in-out;
}

.body.loaded {
opacity: 1;
transform: translateY(0);
}

.navTitles {
cursor: pointer;
margin: 0 10px;
Expand Down
6 changes: 5 additions & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<div class="body">
<!-- Loading Screen -->
<app-loading-screen *ngIf="isLoading"></app-loading-screen>

<!-- Main Content -->
<div class="body" [class.loaded]="!isLoading">
<app-homepage></app-homepage>
<app-footer></app-footer>
</div>
47 changes: 44 additions & 3 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,56 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HomepageComponent } from './pages/homepage/homepage.component';
import { FooterComponent } from './pages/footer/footer.component';
import { LoadingScreenComponent } from './components/loading-screen/loading-screen.component';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterModule, HomepageComponent, FooterComponent],
imports: [RouterModule, HomepageComponent, FooterComponent, LoadingScreenComponent, CommonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
export class AppComponent implements OnInit {
title = 'my-portfolio';
isLoading = true;

ngOnInit() {
// Check if this is the first visit
const hasVisited = sessionStorage.getItem('hasVisited');

if (!hasVisited) {
// First visit - show full loading screen
this.showLoadingScreen();
sessionStorage.setItem('hasVisited', 'true');
} else {
// Subsequent visits - shorter loading or no loading
this.isLoading = false;
}
}

private showLoadingScreen() {
// Minimum loading time of 2 seconds for UX
const minLoadTime = 2000;
const startTime = Date.now();

// Wait for page to be fully loaded
if (document.readyState === 'complete') {
this.hideLoadingAfterDelay(minLoadTime, startTime);
} else {
window.addEventListener('load', () => {
this.hideLoadingAfterDelay(minLoadTime, startTime);
});
}
}

private hideLoadingAfterDelay(minLoadTime: number, startTime: number) {
const elapsedTime = Date.now() - startTime;
const remainingTime = Math.max(0, minLoadTime - elapsedTime);

setTimeout(() => {
this.isLoading = false;
}, remainingTime);
}
}
136 changes: 136 additions & 0 deletions src/app/components/loading-screen/loading-screen.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

.loading-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #25e0d7, #1bb6ae);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
overflow: hidden;
opacity: 1;
transition: opacity 0.8s ease-out;
}

.loading-screen.fade-out {
opacity: 0;
visibility: hidden;
}

.container {
position: relative;
width: 400px;
height: 400px;
}

.circle {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-radius: 50%;
background: rgba(37, 224, 215, 0.02);
}

.circle:nth-of-type(1) {
width: 200px;
height: 180px;
animation: rt 6s infinite linear;
box-shadow: 0 0 1px 0 #bafcf8,
inset 0 0 10px 0 #d1fdfb;
}

.circle:nth-of-type(2) {
width: 180px;
height: 200px;
animation: rt 10s infinite linear;
box-shadow: 0 0 1px 0 #defdfb,
inset 0 0 10px 0 #effefd;
}

.circle:nth-of-type(3) {
width: 210px;
height: 190px;
animation: rt 5s infinite linear;
box-shadow: 0 0 1px 0 #a5faf6,
inset 0 0 10px 0 #cbfcf9;
}

.circle:nth-of-type(4) {
width: 190px;
height: 210px;
animation: rt 15s infinite linear;
box-shadow: 0 0 1px 0 #f2fffe,
inset 0 0 10px 0 #aeebe7;
}

@keyframes rt {
100% {
transform: rotate(360deg);
}
}

/* Responsive Design */
@media (max-width: 768px) {
.container {
width: 300px;
height: 300px;
}

.circle:nth-of-type(1) {
width: 150px;
height: 135px;
}

.circle:nth-of-type(2) {
width: 135px;
height: 150px;
}

.circle:nth-of-type(3) {
width: 157px;
height: 142px;
}

.circle:nth-of-type(4) {
width: 142px;
height: 157px;
}
}

@media (max-width: 480px) {
.container {
width: 250px;
height: 250px;
}

.circle:nth-of-type(1) {
width: 125px;
height: 112px;
}

.circle:nth-of-type(2) {
width: 112px;
height: 125px;
}

.circle:nth-of-type(3) {
width: 131px;
height: 118px;
}

.circle:nth-of-type(4) {
width: 118px;
height: 131px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="loading-screen">
<div class="container">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
13 changes: 13 additions & 0 deletions src/app/components/loading-screen/loading-screen.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-loading-screen',
standalone: true,
imports: [CommonModule],
templateUrl: './loading-screen.component.html',
styleUrl: './loading-screen.component.css'
})
export class LoadingScreenComponent {

}
4 changes: 2 additions & 2 deletions src/app/pages/about/about.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<div class="content-wrapper">
<div class="image-container">
<img src="/assets/aboutimage.png" alt="My image" class="profile-image" />
<img src="https://ik.imagekit.io/pr2222/Portfolio-assets/aboutimage.png?updatedAt=1759135627147" alt="My image" class="profile-image" />
</div>
<div class="text-container">

Expand All @@ -25,7 +25,7 @@
Driven by innovation, problem-solving, and continuous learning, I’m passionate about exploring how technology and design can come together to create impactful real-world solutions.
</p>
<div class="button-container">
<a href="https://drive.google.com/file/d/1F6keTZNaDknWdQVgWQyabL8B_TWnowIP/view?usp=sharing" class="cv-button" target="_blank">Grab My CV</a>
<a href="https://drive.google.com/file/d/1cZ9dEhCFIpckUav4nUHFmFLuibjGSmIw/view?usp=sharing" class="cv-button" target="_blank">Grab My CV</a>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/art-section/art-section.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
.art-section {
font-family: 'Poppins', sans-serif;
color: #fff;
background-image: url('https://res.cloudinary.com/dfbvnb3vx/image/upload/v1748347146/Untitled_design_2_edqcdf.jpg');
background-image: url('https://ik.imagekit.io/pr2222/Portfolio-assets/Untitled_design_2_edqcdf.jpg?updatedAt=1759211440783');
background-size: cover;
background-repeat: no-repeat;
background-position: 35% center;
Expand Down
58 changes: 40 additions & 18 deletions src/app/pages/art-section/art-section.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,35 +92,57 @@ export class ArtSectionComponent implements OnInit {
}

populateArtworkList(): void {
// Charcoal Portraits (1-5)
for (let i = 1; i <= 5; i++) {
const extension = (i === 4) ? 'png' : 'jpg';
// Charcoal Portraits (1-5) - Sample portrait URLs
const charcoalPortraits = [
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/1-2.jpg?updatedAt=1759210284283',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/2-2.jpg?updatedAt=1759210284905',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/3-2.jpg?updatedAt=1759210285275',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/4-2.jpg?updatedAt=1759210284549',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/5-2.jpg?updatedAt=1759210284401'
];

charcoalPortraits.forEach((url, index) => {
this.artworkList.push({
image: `assets/art/${i}.${extension}`,
id: i,
image: url,
id: index + 1,
category: 'Charcoal Portraits'
});
}
});

// Paintings (6-10)
for (let i = 6; i <= 10; i++) {
const extension = (i === 13) ? 'png' : 'jpg';
// Paintings (6-10) - Sample painting URLs
const paintings = [
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/6.jpg?updatedAt=1759136374642',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/7.jpg?updatedAt=1759136374160',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/8-2.jpg?updatedAt=1759210662773',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/9.jpg?updatedAt=1759136373712',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/10.jpg?updatedAt=1759136376075'
];

paintings.forEach((url, index) => {
this.artworkList.push({
image: `assets/art/${i}.${extension}`,
id: i,
image: url,
id: index + 6,
category: 'Paintings'
});
}
});

// Digital Creations (11-16) - Sample digital art URLs
const digitalCreations = [
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/11-2.jpg?updatedAt=1759210662633',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/12.jpg?updatedAt=1759136374250',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/13.png?updatedAt=1759136375967',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/14--2.jpg?updatedAt=1759210662475',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/15.jpg?updatedAt=1759136375945',
'https://ik.imagekit.io/pr2222/Portfolio-assets/art/16.jpg?updatedAt=1759136375631'
];

// Digital Creations (11-14)
for (let i = 11; i <= 14; i++) {
const extension = (i === 13) ? 'png' : 'jpg';
digitalCreations.forEach((url, index) => {
this.artworkList.push({
image: `assets/art/${i}.${extension}`,
id: i,
image: url,
id: index + 11,
category: 'Digital Creations'
});
}
});

console.log('Artwork list:', this.artworkList); // Debug log
}
Expand Down
16 changes: 15 additions & 1 deletion src/app/pages/contact/contact.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.contact-section {
overflow: hidden;
height: 100vh;
background-image: url('https://res.cloudinary.com/dfbvnb3vx/image/upload/v1748353997/Untitled_design_5_znsii3.jpg');
background-image: url('https://ik.imagekit.io/pr2222/Portfolio-assets/Untitled_design_5_znsii3-2.jpg?updatedAt=1759211441083');
background-size: cover;
background-color: #25e0d7;
z-index: 1;
Expand Down Expand Up @@ -117,6 +117,20 @@ textarea.form-control {
margin-top: 1rem;
border-radius: 4px;
font-size: 15px;
opacity: 1;
transition: opacity 0.5s ease-in-out;
animation: slideInUp 0.3s ease-out;
}

@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

.success-message {
Expand Down
Loading
Loading