Merge pull request #58 from HideyoshiNakazone/devel
Devel - Initial Implementation of Home Page
@@ -9,7 +9,7 @@ RUN apk add gettext
|
|||||||
RUN npm install
|
RUN npm install
|
||||||
RUN npm install -g @angular/cli@16
|
RUN npm install -g @angular/cli@16
|
||||||
|
|
||||||
RUN ng build --configuration=production
|
RUN npm run build:prod
|
||||||
|
|
||||||
EXPOSE 5000-7000
|
EXPOSE 5000-7000
|
||||||
CMD sh -c "envsubst < dist/frontend-hideyoshi.com/assets/env.sample.js > dist/frontend-hideyoshi.com/assets/env.js && npm start"
|
CMD ["npm", "run", "start:prod"]
|
||||||
|
|||||||
@@ -26,13 +26,14 @@
|
|||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/styles.css",
|
"src/styles.css",
|
||||||
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
"node_modules/bootstrap/dist/css/bootstrap.css",
|
||||||
"node_modules/normalize.css/normalize.css",
|
"node_modules/cookieconsent/build/cookieconsent.min.css",
|
||||||
"node_modules/cookieconsent/build/cookieconsent.min.css"
|
"node_modules/@glidejs/glide/dist/css/glide.core.css",
|
||||||
|
"node_modules/@glidejs/glide/dist/css/glide.theme.css"
|
||||||
],
|
],
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"node_modules/jquery/dist/jquery.min.js",
|
"node_modules/jquery/dist/jquery.min.js",
|
||||||
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
|
"node_modules/bootstrap/dist/js/bootstrap.bundle.js",
|
||||||
"node_modules/cookieconsent/build/cookieconsent.min.js"
|
"node_modules/cookieconsent/build/cookieconsent.min.js"
|
||||||
],
|
],
|
||||||
"serviceWorker": true,
|
"serviceWorker": true,
|
||||||
|
|||||||
743
package-lock.json
generated
10
package.json
@@ -2,10 +2,11 @@
|
|||||||
"name": "frontend-hideyoshi.com",
|
"name": "frontend-hideyoshi.com",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./server.js",
|
"start": "node ./set_env.js && node ./server.js",
|
||||||
|
"serve": "node ./set_env.js && ng serve",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"serve": "ng serve",
|
"start:prod": "node ./set_env.js --prod && node ./server.js",
|
||||||
"serve:prod": "ng serve --configuration=production",
|
"serve:prod": "node ./set_env.js --prod && ng serve --configuration=production",
|
||||||
"build:prod": "ng build --configuration=production"
|
"build:prod": "ng build --configuration=production"
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
@@ -31,13 +32,16 @@
|
|||||||
"@fortawesome/free-brands-svg-icons": "^6.1.1",
|
"@fortawesome/free-brands-svg-icons": "^6.1.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||||
|
"@glidejs/glide": "^3.6.0",
|
||||||
"bootstrap": "^4.6.2",
|
"bootstrap": "^4.6.2",
|
||||||
"cookieconsent": "^3.1.1",
|
"cookieconsent": "^3.1.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"envsub": "^4.1.0",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"ngx-cookie-service": "^16.0.1",
|
"ngx-cookie-service": "^16.0.1",
|
||||||
"ngx-cookieconsent": "^4.0.2",
|
"ngx-cookieconsent": "^4.0.2",
|
||||||
|
"ngx-glide": "^16.0.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
"ts-interface-checker": "^1.0.2",
|
"ts-interface-checker": "^1.0.2",
|
||||||
|
|||||||
27
set_env.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
function getPrefix() {
|
||||||
|
if (process.argv.includes('--prod') || process.argv.includes('-p')) {
|
||||||
|
return `${__dirname}/dist/frontend-hideyoshi.com`
|
||||||
|
}
|
||||||
|
return `${__dirname}/src`
|
||||||
|
}
|
||||||
|
|
||||||
|
function readDotEnv() {
|
||||||
|
const dotenv = require('dotenv')
|
||||||
|
dotenv.config()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEnv() {
|
||||||
|
readDotEnv()
|
||||||
|
let prefix = getPrefix()
|
||||||
|
|
||||||
|
let templateFile = `${prefix}/assets/env.sample.js`
|
||||||
|
let outputFile = `${prefix}/assets/env.js`
|
||||||
|
|
||||||
|
const envsub = require('envsub')
|
||||||
|
|
||||||
|
envsub({templateFile, outputFile}).then(() => {}).catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnv()
|
||||||
@@ -11,12 +11,14 @@ import { AppServiceWorkerModule } from './app-service-worker.module';
|
|||||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { FooterComponent } from './footer/footer.component';
|
import { FooterComponent } from './footer/footer.component';
|
||||||
|
import {HomeModule} from "./home/home.module";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent, HomeComponent, FooterComponent],
|
declarations: [AppComponent, FooterComponent],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HeaderModule,
|
HeaderModule,
|
||||||
|
HomeModule,
|
||||||
AppRouterModule,
|
AppRouterModule,
|
||||||
AppServiceWorkerModule,
|
AppServiceWorkerModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
|
|||||||
@@ -20,18 +20,22 @@
|
|||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links a {
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 18px;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-btn {
|
.footer-btn {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
border: 1px solid #ffffff;
|
border: 1px solid #ffffff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin: 0 5px;
|
margin: 0 10px;
|
||||||
|
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-btn a {
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-btn:hover {
|
.footer-btn:hover {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
background-color: #2e2e2e;
|
background-color: #2e2e2e;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
height: 90vh;
|
height: 90vh;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
top: 10vh;
|
top: 10vh;
|
||||||
right: 0;
|
right: 0;
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
|
|||||||
@@ -3,10 +3,17 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100vw;
|
||||||
background-color: #2e2e2e;
|
|
||||||
|
|
||||||
|
background: rgb(46,46,46);
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-spacer {
|
.header-spacer {
|
||||||
@@ -100,6 +107,14 @@ app-header-slider {
|
|||||||
/* ====================== COMPUTER MEDIA FORMAT ======================== */
|
/* ====================== COMPUTER MEDIA FORMAT ======================== */
|
||||||
|
|
||||||
@media only screen and (min-width: 712px) {
|
@media only screen and (min-width: 712px) {
|
||||||
|
.main {
|
||||||
|
max-width: 1333px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
all: unset;
|
all: unset;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|||||||
@@ -54,7 +54,9 @@
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div #nav>
|
</div>
|
||||||
|
|
||||||
|
<div class="slider-container" #nav>
|
||||||
<app-header-slider
|
<app-header-slider
|
||||||
[(state)]="navSliderStatus"
|
[(state)]="navSliderStatus"
|
||||||
[clickOutsideStopWatching]="userSliderStatus"
|
[clickOutsideStopWatching]="userSliderStatus"
|
||||||
@@ -67,9 +69,9 @@
|
|||||||
>
|
>
|
||||||
</app-nav-slider>
|
</app-nav-slider>
|
||||||
</app-header-slider>
|
</app-header-slider>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div #user>
|
<div class="slider-container" #user>
|
||||||
<app-header-slider
|
<app-header-slider
|
||||||
[(state)]="userSliderStatus"
|
[(state)]="userSliderStatus"
|
||||||
[ignoreClickOutside]="[header, nav]"
|
[ignoreClickOutside]="[header, nav]"
|
||||||
@@ -83,6 +85,6 @@
|
|||||||
>
|
>
|
||||||
</app-user-slider>
|
</app-user-slider>
|
||||||
</app-header-slider>
|
</app-header-slider>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header-spacer"></div>
|
<div class="header-spacer"></div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef, ViewEncapsulation,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { LoginComponent } from './header-popup/login/login.component';
|
import { LoginComponent } from './header-popup/login/login.component';
|
||||||
@@ -33,8 +33,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
profileDropdownState: boolean = false;
|
profileDropdownState: boolean = false;
|
||||||
|
|
||||||
signupPopupState: boolean = false;
|
|
||||||
|
|
||||||
navSliderStatus: boolean = false;
|
navSliderStatus: boolean = false;
|
||||||
|
|
||||||
userSliderStatus: boolean = false;
|
userSliderStatus: boolean = false;
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
.me-section {
|
||||||
|
background: rgb(46,46,46);
|
||||||
|
background: linear-gradient(180deg, rgba(46,46,46,1) 35%, rgba(51,51,51,1) 100%);
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
height: 60%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro h1 {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro p {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 100;
|
||||||
|
color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro br {
|
||||||
|
display: block;
|
||||||
|
margin: 10px 0;
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SCROLL BUTTON*/
|
||||||
|
.scroll-btn-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-btn span {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
|
||||||
|
border-left: 1px solid #fff;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
|
||||||
|
-webkit-transform: rotate(-45deg);
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
-webkit-animation: scbt 2s infinite;
|
||||||
|
animation: scbt 2s infinite;
|
||||||
|
}
|
||||||
|
.scroll-btn span:nth-of-type(1) {
|
||||||
|
-webkit-animation-delay: 0s;
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
.scroll-btn span:nth-of-type(2) {
|
||||||
|
-webkit-animation-delay: .15s;
|
||||||
|
animation-delay: .15s;
|
||||||
|
}
|
||||||
|
.scroll-btn span:nth-of-type(3) {
|
||||||
|
-webkit-animation-delay: .3s;
|
||||||
|
animation-delay: .3s;
|
||||||
|
}
|
||||||
|
@-webkit-keyframes scbt {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes scbt {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* STACK SECTION*/
|
||||||
|
.stack-section {
|
||||||
|
background: rgb(241,241,241);
|
||||||
|
/*background: linear-gradient(0deg, rgba(241,241,241,1) 80%, rgba(51,51,51,1) 100%);*/
|
||||||
|
height: 80vh;
|
||||||
|
}
|
||||||
|
.stack {
|
||||||
|
height: 35%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack h2 {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack p {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-slider {
|
||||||
|
height: 65%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*ON MOBILE VIEWPORT*/
|
||||||
|
@media only screen and (max-width: 400px) {
|
||||||
|
.intro {
|
||||||
|
height: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-section {
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
|
.stack {
|
||||||
|
padding-top: 60px;
|
||||||
|
width: 80%;
|
||||||
|
height: 30%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<div #me class="me-section">
|
||||||
|
<div class="intro container">
|
||||||
|
<h1>
|
||||||
|
I'M VITOR HIDEYOSHI
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
I'm a software engineer with a passion for web development
|
||||||
|
and a strong interest in data science. I spend most of my time
|
||||||
|
learning new technologies and improving my skills, searching for
|
||||||
|
new challenges and opportunities to grow as a professional.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
In this search for new challenges I gained experience in different
|
||||||
|
areas of software development, from web development to data science.
|
||||||
|
I'm always looking for new opportunities to learn and improve my skills.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="scroll-btn-container">
|
||||||
|
<a class="scroll-btn" (click)="scrollToElement(stack)">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div #stack class="stack-section">
|
||||||
|
<div class="stack container">
|
||||||
|
<h2>
|
||||||
|
My Stack
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
I'm always looking for new technologies to learn and improve my skills.
|
||||||
|
Here are some of the technologies I've been working with recently:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stack-slider">
|
||||||
|
<app-stack-slider>
|
||||||
|
</app-stack-slider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -7,4 +7,16 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
scrollToElement(element: HTMLElement): void {
|
||||||
|
let block: ScrollLogicalPosition = "start";
|
||||||
|
if (window.innerWidth < 400) {
|
||||||
|
block = "end";
|
||||||
|
}
|
||||||
|
element.scrollIntoView({
|
||||||
|
behavior: "smooth",
|
||||||
|
block: block,
|
||||||
|
inline: "nearest"
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/app/home/home.module.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import {CommonModule, NgOptimizedImage} from '@angular/common';
|
||||||
|
import {HomeComponent} from "./home.component";
|
||||||
|
import {StackSliderComponent} from "./stack-slider/stack-slider.component";
|
||||||
|
import {StackCardComponent} from "./stack-slider/stack-card/stack-card.component";
|
||||||
|
import {NgxGlideComponent} from "ngx-glide";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
HomeComponent,
|
||||||
|
StackSliderComponent,
|
||||||
|
StackCardComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
NgxGlideComponent,
|
||||||
|
NgOptimizedImage
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class HomeModule { }
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
.stack-card {
|
||||||
|
width: 325px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card-image {
|
||||||
|
width: 250px;
|
||||||
|
height: 250px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card-body {
|
||||||
|
padding: 10px;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
width: 250px;
|
||||||
|
height: 130px;
|
||||||
|
inline-size: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card-text {
|
||||||
|
word-break: break-all !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400 !important;
|
||||||
|
font-family: 'Hind', sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*CARD STATE*/
|
||||||
|
.active {
|
||||||
|
opacity: 1;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactive {
|
||||||
|
opacity: 0.7;
|
||||||
|
width: 280px;
|
||||||
|
height: 410px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<div class="card stack-card inactive" [@cardAnimation]="cardState">
|
||||||
|
<div class="card-img-top stack-card-image">
|
||||||
|
<img [ngSrc]="stack.image"
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
alt="Stack Image" priority>
|
||||||
|
</div>
|
||||||
|
<div class="card-body stack-card-body">
|
||||||
|
<h5 class="card-title stack-card-title">{{stack.name}}</h5>
|
||||||
|
<p class="card-text stack-card-text">{{stack.description}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StackCardComponent } from './stack-card.component';
|
||||||
|
|
||||||
|
describe('StackCardComponent', () => {
|
||||||
|
let component: StackCardComponent;
|
||||||
|
let fixture: ComponentFixture<StackCardComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StackCardComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(StackCardComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
37
src/app/home/stack-slider/stack-card/stack-card.component.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {Component, Input} from '@angular/core';
|
||||||
|
import {Stack} from "../../../shared/model/stack/stack.model";
|
||||||
|
import {animate, state, style, transition, trigger} from "@angular/animations";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-stack-card',
|
||||||
|
templateUrl: './stack-card.component.html',
|
||||||
|
styleUrls: ['./stack-card.component.css'],
|
||||||
|
animations: [
|
||||||
|
trigger('cardAnimation', [
|
||||||
|
state('active', style({
|
||||||
|
opacity: 1,
|
||||||
|
width: '325px',
|
||||||
|
height: '425px',
|
||||||
|
})),
|
||||||
|
state('inactive', style({
|
||||||
|
opacity: 0.7,
|
||||||
|
width: '280px',
|
||||||
|
height: '410px',
|
||||||
|
})),
|
||||||
|
transition('* => *', [
|
||||||
|
animate('0.1s')
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class StackCardComponent {
|
||||||
|
@Input()
|
||||||
|
stack!: Stack;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
inFocus: boolean = false;
|
||||||
|
|
||||||
|
get cardState(): 'active'|'inactive' {
|
||||||
|
return this.inFocus ? 'active' : 'inactive';
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/app/home/stack-slider/stack-slider.component.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.slider-card {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
5
src/app/home/stack-slider/stack-slider.component.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<ngx-glide #ngxGlide class="container stack-slider" *ngIf="stacks && stacks.length > 0">
|
||||||
|
<app-stack-card *ngFor="let stack of stacks" class="slider-card" [stack]="stack"
|
||||||
|
[inFocus]="isInFocus(stack)">
|
||||||
|
</app-stack-card>
|
||||||
|
</ngx-glide>
|
||||||
21
src/app/home/stack-slider/stack-slider.component.spec.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StackSliderComponent } from './stack-slider.component';
|
||||||
|
|
||||||
|
describe('StackSliderComponent', () => {
|
||||||
|
let component: StackSliderComponent;
|
||||||
|
let fixture: ComponentFixture<StackSliderComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StackSliderComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(StackSliderComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
124
src/app/home/stack-slider/stack-slider.component.ts
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import {AfterViewInit, ChangeDetectorRef, Component, HostListener, ViewChild} from '@angular/core';
|
||||||
|
import {NgxGlideComponent} from "ngx-glide";
|
||||||
|
import {Stack} from "../../shared/model/stack/stack.model";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-stack-slider',
|
||||||
|
templateUrl: './stack-slider.component.html',
|
||||||
|
styleUrls: ['./stack-slider.component.css']
|
||||||
|
})
|
||||||
|
export class StackSliderComponent implements AfterViewInit {
|
||||||
|
@ViewChild('ngxGlide')
|
||||||
|
ngxGlide!: NgxGlideComponent;
|
||||||
|
|
||||||
|
stacks: Stack[] = [
|
||||||
|
{
|
||||||
|
name: 'Angular',
|
||||||
|
image: './assets/stacks/angular.svg',
|
||||||
|
description: 'Angular is a platform for building mobile and desktop web applications.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Next.js',
|
||||||
|
image: './assets/stacks/nextjs.svg',
|
||||||
|
description: 'React is a JavaScript library for building user interfaces.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'FastAPI',
|
||||||
|
image: './assets/stacks/fastapi.svg',
|
||||||
|
description: 'FastAPI is a modern, fast (high-performance), web framework for building APIs.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Node.js',
|
||||||
|
image: './assets/stacks/nodejs.svg',
|
||||||
|
description: 'Node.js is an open-source, cross-platform, back-end JavaScript runtime environment.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Spring Boot',
|
||||||
|
image: './assets/stacks/spring.svg',
|
||||||
|
description: 'Spring Boot makes it easy to create stand-alone, production-grade APIs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Docker',
|
||||||
|
image: './assets/stacks/docker.svg',
|
||||||
|
description: 'Docker is a set of platform as a service products to deliver software in packages called containers.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kubernetes',
|
||||||
|
image: './assets/stacks/kubernetes.svg',
|
||||||
|
description: 'Kubernetes is an open-source container-orchestration system for automating deployment, scaling, and management.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Terraform',
|
||||||
|
image: './assets/stacks/terraform.svg',
|
||||||
|
description: 'Terraform is an open-source infrastructure as code software tool.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PostgreSQL',
|
||||||
|
image: './assets/stacks/postgresql.svg',
|
||||||
|
description: 'PostgreSQL is a free and open-source relational database.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Redis',
|
||||||
|
image: './assets/stacks/redis.svg',
|
||||||
|
description: 'Redis is an in-memory data structure store.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'AWS',
|
||||||
|
image: './assets/stacks/aws.svg',
|
||||||
|
description: 'Amazon Web Services is a subsidiary of Amazon providing on-demand cloud computing.',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor(private cd: ChangeDetectorRef) { }
|
||||||
|
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
onResize(event: any) {
|
||||||
|
const numberOfCards = this.getNumberOfCards(event.target.innerWidth);
|
||||||
|
this.buildCarousel(numberOfCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (this.ngxGlide) {
|
||||||
|
const numberOfCards = this.getNumberOfCards(window.innerWidth);
|
||||||
|
this.buildCarousel(numberOfCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cd.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCarousel(numberOfCards: number): void {
|
||||||
|
this.ngxGlide.perView = numberOfCards;
|
||||||
|
|
||||||
|
this.ngxGlide.showArrows = false;
|
||||||
|
this.ngxGlide.showBullets = false;
|
||||||
|
this.ngxGlide.type = 'carousel';
|
||||||
|
this.ngxGlide.focusAt = 'center';
|
||||||
|
this.ngxGlide.gap = 10;
|
||||||
|
this.ngxGlide.autoplay = 3000;
|
||||||
|
|
||||||
|
this.ngxGlide.recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentIndex(): number {
|
||||||
|
return this.ngxGlide?.getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
isInFocus(stack: Stack): boolean {
|
||||||
|
return this.stacks.indexOf(stack) === this.currentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getNumberOfCards(windowWidth: number): number {
|
||||||
|
if (windowWidth <= 450) {
|
||||||
|
return 1;
|
||||||
|
} else if (windowWidth <= 768) {
|
||||||
|
return 2;
|
||||||
|
} else if (windowWidth <= 975) {
|
||||||
|
return 3;
|
||||||
|
} else if (windowWidth <= 1440) {
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,9 @@
|
|||||||
|
|
||||||
.popup-background {
|
.popup-background {
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
justify-content: center;
|
position: absolute;
|
||||||
align-content: center;
|
width: 100%;
|
||||||
align-items: center;
|
height: 100%;
|
||||||
overflow-y: hidden;
|
|
||||||
position: fixed;
|
|
||||||
display: flex;
|
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
@@ -25,10 +20,15 @@
|
|||||||
border: 1px solid #dddd;
|
border: 1px solid #dddd;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
position: relative;
|
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-header {
|
.popup-header {
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ import {
|
|||||||
'hide',
|
'hide',
|
||||||
style({
|
style({
|
||||||
opacity: '0',
|
opacity: '0',
|
||||||
|
zIndex: 2
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
state(
|
state(
|
||||||
'show',
|
'show',
|
||||||
style({
|
style({
|
||||||
opacity: '1',
|
opacity: '1',
|
||||||
|
zIndex: 2
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
transition(
|
transition(
|
||||||
|
|||||||
5
src/app/shared/model/stack/stack.model.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export interface Stack {
|
||||||
|
name: string;
|
||||||
|
image: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
1
src/assets/stacks/angular.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="2353" height="2500" viewBox="0 0 256 272" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M.1 45.522L125.908.697l129.196 44.028-20.919 166.45-108.277 59.966-106.583-59.169L.1 45.522z" fill="#E23237"/><path d="M255.104 44.725L125.908.697v270.444l108.277-59.866 20.919-166.55z" fill="#B52E31"/><path d="M126.107 32.274L47.714 206.693l29.285-.498 15.739-39.347h70.325l17.233 39.845 27.99.498-82.179-174.917zm.2 55.882l26.496 55.383h-49.806l23.31-55.383z" fill="#FFF"/></svg>
|
||||||
|
After Width: | Height: | Size: 510 B |
1
src/assets/stacks/aws.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 32 32"><path d="M15.63 31.388l-7.135-2.56V18.373l7.135 2.43zm1.3 0l7.135-2.56V18.373l-7.135 2.432zm-7.7-13.8l7.2-2.033 6.696 2.16-6.696 2.273zm-2.092-.8L0 14.22V3.75l7.135 2.43zm1.307 0l7.135-2.56V3.75L8.443 6.192zm-7.7-13.8l7.2-2.043 6.696 2.16-6.696 2.273zm23.052 13.8l-7.135-2.56V3.75l7.135 2.43zm1.3 0l7.135-2.56V3.75l-7.135 2.43zm-7.7-13.8l7.2-2.033 6.696 2.16-6.696 2.273z" fill="#f90" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 495 B |
1
src/assets/stacks/docker.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64" viewBox="0 0 32 32"><defs><clipPath id="A"><path d="M76 2v46H54v23H35.58l-.206 2c-1.15 12.53 1.036 24.088 6.063 33.97l1.688 3.03c1 1.817 2.2 3.523 3.438 5.188s1.686 2.583 2.47 3.688C62.32 133.8 82.13 141 105 141c50.648 0 93.633-22.438 112.656-72.844C231.153 69.54 244.1 66.08 250 54.563c-9.4-5.424-21.478-3.685-28.437-.187L240 2l-72 46h-23V2z"/></clipPath></defs><g transform="matrix(.679423 0 0 .679423 -2.086149 13.781817)"><path d="M30.305-3.553h4.222V.763h2.135a9.26 9.26 0 0 0 2.934-.492c.46-.156.974-.372 1.426-.644-.596-.778-.9-1.76-1-2.73-.122-1.317.144-3.032 1.036-4.063l.444-.513.53.425c1.332 1.07 2.452 2.565 2.65 4.27 1.603-.472 3.486-.36 4.9.456l.58.335-.305.596c-1.187 2.33-3.687 3.053-6.13 2.925-3.656 9.105-11.615 13.416-21.265 13.416-4.986 0-9.56-1.864-12.164-6.287-.153-.275-.283-.562-.422-.844-.88-1.947-1.173-4.08-.975-6.2l.06-.638h3.6V-3.55h4.222v-4.222h8.445v-4.222h5.067v8.445" fill="#394d54"/><g transform="matrix(.184659 0 0 .184659 3.070472 -11.997864)" clip-path="url(#A)"><g id="B"><g id="C" transform="translate(0 -22.866)"><path d="M123.86 3.8h19.818v19.817H123.86z" fill="#00acd3"/><path d="M123.86 26.676h19.818v19.818H123.86z" fill="#20c2ef"/><path id="D" d="M126.292 21.977V5.46m2.972 16.516V5.46m3.002 16.516V5.46m3.003 16.516V5.46m3.003 16.516V5.46m2.97 16.516V5.46" stroke="#394d54" stroke-width="1.56"/><use xlink:href="#D" y="22.866"/></g><use xlink:href="#C" transform="matrix(1 0 0 -1 22.866 4.572651)"/></g><use xlink:href="#B" x="-91.464" y="45.732"/><use xlink:href="#B" x="-45.732" y="45.732"/><use xlink:href="#B" y="45.732"/><path d="M221.57 54.38c1.533-11.915-7.384-21.275-12.914-25.718-6.373 7.368-7.363 26.678 2.635 34.807-5.58 4.956-17.337 9.448-29.376 9.448H34C32.83 85.484 34 146 34 146h217l-.987-91.424c-9.4-5.424-21.484-3.694-28.443-.197" fill="#17b5eb"/><path d="M34 89v57h217V89" fill-opacity=".17"/><path d="M111.237 140.9c-13.54-6.425-20.972-15.16-25.107-24.694L45 118l21 28 45.237-5.1" fill="#d4edf1"/><path d="M222.5 53.938v.03c-20.86 26.9-50.783 50.38-82.906 62.72-28.655 11.008-53.638 11.06-70.875 2.22-1.856-1.048-3.676-2.212-5.5-3.312-12.637-8.832-19.754-23.44-19.156-42.687H34V146h217V50h-25z" fill-opacity=".085"/></g><path d="M11.496 9.613c2.616.143 5.407.17 7.842-.594" fill="none" stroke="#394d54" stroke-width=".628" stroke-linecap="round"/><path d="M21.937 7.753a1.01 1.01 0 0 1-1.009 1.009 1.01 1.01 0 0 1-1.01-1.009 1.01 1.01 0 0 1 1.01-1.01 1.01 1.01 0 0 1 1.009 1.01z" fill="#d4edf1"/><path d="M21.2 7.08c-.088.05-.148.146-.148.256 0 .163.132.295.295.295.112 0 .2-.062.26-.154a.73.73 0 0 1 .055.277c0 .4-.324.723-.723.723s-.723-.324-.723-.723.324-.723.723-.723a.72.72 0 0 1 .262.049zM3.07 4.65h46.964c-1.023-.26-3.235-.6-2.87-1.95-1.86 2.152-6.344 1.5-7.475.448-1.26 1.828-8.597 1.133-9.108-.3-1.58 1.854-6.475 1.854-8.055 0-.512 1.424-7.848 2.12-9.1.3C12.284 4.2 7.8 4.853 5.94 2.7c.365 1.34-1.848 1.7-2.87 1.95" fill="#394d54"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
1
src/assets/stacks/fastapi.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" height="2500" width="2500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 154 154"><circle cx="77" cy="77" fill="#05998b" r="77"/><path d="M81.375 18.667l-38.75 70H77.5l-3.875 46.666 38.75-70H77.5z" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 236 B |
1
src/assets/stacks/kubernetes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="64" height="64"><path d="M15.9.476a2.14 2.14 0 0 0-.823.218L3.932 6.01c-.582.277-1.005.804-1.15 1.432L.054 19.373c-.13.56-.025 1.147.3 1.627q.057.087.12.168l7.7 9.574c.407.5 1.018.787 1.662.784h12.35c.646.001 1.258-.3 1.664-.793l7.696-9.576c.404-.5.555-1.16.4-1.786L29.2 7.43c-.145-.628-.57-1.155-1.15-1.432L16.923.695A2.14 2.14 0 0 0 15.89.476z" fill="#326ce5"/><path d="M16.002 4.542c-.384.027-.675.356-.655.74v.188c.018.213.05.424.092.633a6.22 6.22 0 0 1 .066 1.21c-.038.133-.114.253-.218.345l-.015.282c-.405.034-.807.096-1.203.186-1.666.376-3.183 1.24-4.354 2.485l-.24-.17c-.132.04-.274.025-.395-.04a6.22 6.22 0 0 1-.897-.81 5.55 5.55 0 0 0-.437-.465l-.148-.118c-.132-.106-.294-.167-.463-.175a.64.64 0 0 0-.531.236c-.226.317-.152.756.164.983l.138.11a5.55 5.55 0 0 0 .552.323c.354.197.688.428.998.7a.74.74 0 0 1 .133.384l.218.2c-1.177 1.766-1.66 3.905-1.358 6.006l-.28.08c-.073.116-.17.215-.286.288a6.22 6.22 0 0 1-1.194.197 5.57 5.57 0 0 0-.64.05l-.177.04h-.02a.67.67 0 0 0-.387 1.132.67.67 0 0 0 .684.165h.013l.18-.02c.203-.06.403-.134.598-.218.375-.15.764-.265 1.162-.34.138.008.27.055.382.135l.3-.05c.65 2.017 2.016 3.726 3.84 4.803l-.122.255c.056.117.077.247.06.376-.165.382-.367.748-.603 1.092a5.58 5.58 0 0 0-.358.533l-.085.18a.67.67 0 0 0 .65 1.001.67.67 0 0 0 .553-.432l.083-.17c.076-.2.14-.404.192-.61.177-.437.273-.906.515-1.196a.54.54 0 0 1 .286-.14l.15-.273a8.62 8.62 0 0 0 6.146.015l.133.255c.136.02.258.095.34.205.188.358.34.733.456 1.12a5.57 5.57 0 0 0 .194.611l.083.17a.67.67 0 0 0 1.187.131.67.67 0 0 0 .016-.701l-.087-.18a5.55 5.55 0 0 0-.358-.531c-.23-.332-.428-.686-.6-1.057a.52.52 0 0 1 .068-.4 2.29 2.29 0 0 1-.111-.269c1.82-1.085 3.18-2.8 3.823-4.82l.284.05c.102-.093.236-.142.373-.138.397.076.786.2 1.162.34.195.09.395.166.598.23.048.013.118.024.172.037h.013a.67.67 0 0 0 .841-.851.67.67 0 0 0-.544-.446l-.194-.046a5.57 5.57 0 0 0-.64-.05c-.404-.026-.804-.092-1.194-.197-.12-.067-.22-.167-.288-.288l-.27-.08a8.65 8.65 0 0 0-1.386-5.993l.236-.218c-.01-.137.035-.273.124-.378.307-.264.64-.497.99-.696a5.57 5.57 0 0 0 .552-.323l.146-.118a.67.67 0 0 0-.133-1.202.67.67 0 0 0-.696.161l-.148.118a5.57 5.57 0 0 0-.437.465c-.264.302-.556.577-.873.823a.74.74 0 0 1-.404.044l-.253.18c-1.46-1.53-3.427-2.48-5.535-2.67 0-.1-.013-.25-.015-.297-.113-.078-.192-.197-.218-.332a6.23 6.23 0 0 1 .076-1.207c.043-.21.073-.42.092-.633v-.2c.02-.384-.27-.713-.655-.74zm-.834 5.166l-.2 3.493h-.015c-.01.216-.137.4-.332.504s-.426.073-.6-.054l-2.865-2.03a6.86 6.86 0 0 1 3.303-1.799c.234-.05.47-.088.707-.114zm1.668 0c1.505.187 2.906.863 3.99 1.924l-2.838 2.017c-.175.14-.415.168-.618.072s-.333-.3-.336-.524zm-6.72 3.227l2.62 2.338v.015c.163.142.234.363.186.574s-.21.378-.417.435v.01l-3.362.967a6.86 6.86 0 0 1 .974-4.34zm11.753 0c.796 1.295 1.148 2.814 1.002 4.327l-3.367-.97v-.013c-.21-.057-.37-.224-.417-.435s.023-.43.186-.574l2.6-2.327zm-6.404 2.52h1.072l.655.832-.238 1.04-.963.463-.965-.463-.227-1.04zm3.434 2.838c.045-.005.1-.005.135 0l3.467.585c-.5 1.44-1.487 2.67-2.775 3.493l-1.34-3.244a.59.59 0 0 1 .509-.819zm-5.823.015c.196.003.377.104.484.268s.124.37.047.55v.013l-1.332 3.218C11 21.54 10.032 20.325 9.517 18.9l3.437-.583c.038-.004.077-.004.116 0zm2.904 1.4a.59.59 0 0 1 .537.308h.013l1.694 3.057-.677.2c-1.246.285-2.547.218-3.758-.194l1.7-3.057c.103-.18.293-.29.5-.295z" fill="#fff" stroke="#fff" stroke-width=".055"/></svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
1
src/assets/stacks/nextjs.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg height="1024pt" viewBox=".5 -.2 1023 1024.1" width="1024pt" xmlns="http://www.w3.org/2000/svg"><path d="m478.5.6c-2.2.2-9.2.9-15.5 1.4-145.3 13.1-281.4 91.5-367.6 212-48 67-78.7 143-90.3 223.5-4.1 28.1-4.6 36.4-4.6 74.5s.5 46.4 4.6 74.5c27.8 192.1 164.5 353.5 349.9 413.3 33.2 10.7 68.2 18 108 22.4 15.5 1.7 82.5 1.7 98 0 68.7-7.6 126.9-24.6 184.3-53.9 8.8-4.5 10.5-5.7 9.3-6.7-.8-.6-38.3-50.9-83.3-111.7l-81.8-110.5-102.5-151.7c-56.4-83.4-102.8-151.6-103.2-151.6-.4-.1-.8 67.3-1 149.6-.3 144.1-.4 149.9-2.2 153.3-2.6 4.9-4.6 6.9-8.8 9.1-3.2 1.6-6 1.9-21.1 1.9h-17.3l-4.6-2.9c-3-1.9-5.2-4.4-6.7-7.3l-2.1-4.5.2-200.5.3-200.6 3.1-3.9c1.6-2.1 5-4.8 7.4-6.1 4.1-2 5.7-2.2 23-2.2 20.4 0 23.8.8 29.1 6.6 1.5 1.6 57 85.2 123.4 185.9s157.2 238.2 201.8 305.7l81 122.7 4.1-2.7c36.3-23.6 74.7-57.2 105.1-92.2 64.7-74.3 106.4-164.9 120.4-261.5 4.1-28.1 4.6-36.4 4.6-74.5s-.5-46.4-4.6-74.5c-27.8-192.1-164.5-353.5-349.9-413.3-32.7-10.6-67.5-17.9-106.5-22.3-9.6-1-75.7-2.1-84-1.3zm209.4 309.4c4.8 2.4 8.7 7 10.1 11.8.8 2.6 1 58.2.8 183.5l-.3 179.8-31.7-48.6-31.8-48.6v-130.7c0-84.5.4-132 1-134.3 1.6-5.6 5.1-10 9.9-12.6 4.1-2.1 5.6-2.3 21.3-2.3 14.8 0 17.4.2 20.7 2z"/><path d="m784.3 945.1c-3.5 2.2-4.6 3.7-1.5 2 2.2-1.3 5.8-4 5.2-4.1-.3 0-2 1-3.7 2.1zm-6.9 4.5c-1.8 1.4-1.8 1.5.4.4 1.2-.6 2.2-1.3 2.2-1.5 0-.8-.5-.6-2.6 1.1zm-5 3c-1.8 1.4-1.8 1.5.4.4 1.2-.6 2.2-1.3 2.2-1.5 0-.8-.5-.6-2.6 1.1zm-5 3c-1.8 1.4-1.8 1.5.4.4 1.2-.6 2.2-1.3 2.2-1.5 0-.8-.5-.6-2.6 1.1zm-7.6 4c-3.8 2-3.6 2.8.2.9 1.7-.9 3-1.8 3-2 0-.7-.1-.6-3.2 1.1z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/stacks/nodejs.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 32 32" preserveAspectRatio="xMidYMid" fill="#8cc84b"><path d="M14.656.427c.8-.453 1.82-.455 2.6 0L29.2 7.16c.747.42 1.247 1.253 1.24 2.114v13.5c.005.897-.544 1.748-1.332 2.16l-11.88 6.702a2.6 2.6 0 0 1-2.639-.073l-3.565-2.06c-.243-.145-.516-.26-.688-.495.152-.204.422-.23.642-.32.496-.158.95-.4 1.406-.656.115-.08.256-.05.366.022l3.04 1.758c.217.125.437-.04.623-.145l11.665-6.583c.144-.07.224-.222.212-.38V9.334c.016-.18-.087-.344-.25-.417L16.19 2.244a.41.41 0 0 0-.465-.001L3.892 8.93c-.16.073-.27.235-.25.415v13.37c-.014.158.07.307.215.375l3.162 1.785c.594.32 1.323.5 1.977.265a1.5 1.5 0 0 0 .971-1.409l.003-13.29c-.014-.197.172-.36.363-.34h1.52c.2-.005.357.207.33.405L12.18 23.88c.001 1.188-.487 2.48-1.586 3.063-1.354.7-3.028.553-4.366-.12l-3.4-1.88c-.8-.4-1.337-1.264-1.332-2.16v-13.5a2.46 2.46 0 0 1 1.282-2.141L14.656.427zM18.1 9.785c1.727-.1 3.576-.066 5.13.785 1.203.652 1.87 2.02 1.892 3.358-.034.18-.222.28-.394.267-.5-.001-1.002.007-1.504-.003-.213.008-.336-.188-.363-.376-.144-.64-.493-1.273-1.095-1.582-.924-.463-1.996-.44-3.004-.43-.736.04-1.527.103-2.15.535-.48.328-.624 1-.453 1.522.16.383.603.506.964.62 2.082.544 4.287.5 6.33 1.207.845.292 1.672.86 1.962 1.745.378 1.186.213 2.604-.63 3.556-.684.784-1.68 1.2-2.675 1.442-1.323.295-2.695.302-4.038.17-1.263-.144-2.577-.476-3.552-1.336-.834-.724-1.24-1.852-1.2-2.94.01-.184.193-.312.37-.297h1.5c.202-.014.35.16.36.35.093.6.322 1.25.854 1.6 1.026.662 2.313.616 3.487.635.973-.043 2.065-.056 2.86-.7.42-.367.543-.98.43-1.508-.123-.446-.6-.653-1-.8-2.055-.65-4.285-.414-6.32-1.15-.826-.292-1.625-.844-1.942-1.693-.443-1.2-.24-2.687.693-3.607.9-.915 2.22-1.268 3.47-1.394z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/stacks/postgresql.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="64" viewBox="0 0 25.6 25.6" width="64"><style><![CDATA[.B{stroke-linecap:round}.C{stroke-linejoin:round}.D{stroke-linejoin:miter}.E{stroke-width:.716}]]></style><g fill="none" stroke="#fff"><path d="M18.983 18.636c.163-1.357.114-1.555 1.124-1.336l.257.023c.777.035 1.793-.125 2.4-.402 1.285-.596 2.047-1.592.78-1.33-2.89.596-3.1-.383-3.1-.383 3.053-4.53 4.33-10.28 3.227-11.687-3.004-3.84-8.205-2.024-8.292-1.976l-.028.005c-.57-.12-1.2-.19-1.93-.2-1.308-.02-2.3.343-3.054.914 0 0-9.277-3.822-8.846 4.807.092 1.836 2.63 13.9 5.66 10.25C8.29 15.987 9.36 14.86 9.36 14.86c.53.353 1.167.533 1.834.468l.052-.044a2.01 2.01 0 0 0 .021.518c-.78.872-.55 1.025-2.11 1.346-1.578.325-.65.904-.046 1.056.734.184 2.432.444 3.58-1.162l-.046.183c.306.245.285 1.76.33 2.842s.116 2.093.337 2.688.48 2.13 2.53 1.7c1.713-.367 3.023-.896 3.143-5.81" fill="#000" stroke="#000" stroke-linecap="butt" stroke-width="2.149" class="D"/><path d="M23.535 15.6c-2.89.596-3.1-.383-3.1-.383 3.053-4.53 4.33-10.28 3.228-11.687-3.004-3.84-8.205-2.023-8.292-1.976l-.028.005a10.31 10.31 0 0 0-1.929-.201c-1.308-.02-2.3.343-3.054.914 0 0-9.278-3.822-8.846 4.807.092 1.836 2.63 13.9 5.66 10.25C8.29 15.987 9.36 14.86 9.36 14.86c.53.353 1.167.533 1.834.468l.052-.044a2.02 2.02 0 0 0 .021.518c-.78.872-.55 1.025-2.11 1.346-1.578.325-.65.904-.046 1.056.734.184 2.432.444 3.58-1.162l-.046.183c.306.245.52 1.593.484 2.815s-.06 2.06.18 2.716.48 2.13 2.53 1.7c1.713-.367 2.6-1.32 2.725-2.906.088-1.128.286-.962.3-1.97l.16-.478c.183-1.53.03-2.023 1.085-1.793l.257.023c.777.035 1.794-.125 2.39-.402 1.285-.596 2.047-1.592.78-1.33z" fill="#336791" stroke="none"/><g class="E"><g class="B"><path d="M12.814 16.467c-.08 2.846.02 5.712.298 6.4s.875 2.05 2.926 1.612c1.713-.367 2.337-1.078 2.607-2.647l.633-5.017M10.356 2.2S1.072-1.596 1.504 7.033c.092 1.836 2.63 13.9 5.66 10.25C8.27 15.95 9.27 14.907 9.27 14.907m6.1-13.4c-.32.1 5.164-2.005 8.282 1.978 1.1 1.407-.175 7.157-3.228 11.687" class="C"/><path d="M20.425 15.17s.2.98 3.1.382c1.267-.262.504.734-.78 1.33-1.054.49-3.418.615-3.457-.06-.1-1.745 1.244-1.215 1.147-1.652-.088-.394-.69-.78-1.086-1.744-.347-.84-4.76-7.29 1.224-6.333.22-.045-1.56-5.7-7.16-5.782S7.99 8.196 7.99 8.196" stroke-linejoin="bevel"/></g><g class="C"><path d="M11.247 15.768c-.78.872-.55 1.025-2.11 1.346-1.578.325-.65.904-.046 1.056.734.184 2.432.444 3.58-1.163.35-.49-.002-1.27-.482-1.468-.232-.096-.542-.216-.94.23z"/><path d="M11.196 15.753c-.08-.513.168-1.122.433-1.836.398-1.07 1.316-2.14.582-5.537-.547-2.53-4.22-.527-4.22-.184s.166 1.74-.06 3.365c-.297 2.122 1.35 3.916 3.246 3.733" class="B"/></g></g><g fill="#fff" class="D"><path d="M10.322 8.145c-.017.117.215.43.516.472s.558-.202.575-.32-.215-.246-.516-.288-.56.02-.575.136z" stroke-width=".239"/><path d="M19.486 7.906c.016.117-.215.43-.516.472s-.56-.202-.575-.32.215-.246.516-.288.56.02.575.136z" stroke-width=".119"/></g><path d="M20.562 7.095c.05.92-.198 1.545-.23 2.524-.046 1.422.678 3.05-.413 4.68" class="B C E"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
1
src/assets/stacks/redis.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="64" viewBox="0 0 32 32" width="64"><g transform="matrix(.848327 0 0 .848327 -7.883573 -9.449691)"><use xlink:href="#B" fill="#a41e11"/><path d="M45.536 34.95c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.936c2.332-.836 3.14-.867 5.126-.14S43.55 31.87 45.51 32.6s2.037 1.31.024 2.36z" fill="#d82c20"/><use xlink:href="#B" y="-6.218" fill="#a41e11"/><use xlink:href="#C" fill="#d82c20"/><path d="M45.536 26.098c-2.013 1.05-12.44 5.337-14.66 6.495s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26V21.55s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z" fill="#a41e11"/><use xlink:href="#C" y="-6.449" fill="#d82c20"/><g fill="#fff"><path d="M29.096 20.712l-1.182-1.965-3.774-.34 2.816-1.016-.845-1.56 2.636 1.03 2.486-.814-.672 1.612 2.534.95-3.268.34zM22.8 24.624l8.74-1.342-2.64 3.872z"/><ellipse cx="20.444" rx="4.672" ry="1.811" cy="21.402"/></g><path d="M42.132 21.138l-5.17 2.042-.004-4.087z" fill="#7a0c00"/><path d="M36.963 23.18l-.56.22-5.166-2.042 5.723-2.264z" fill="#ad2115"/></g><defs ><path id="B" d="M45.536 38.764c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26v-3.813s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z"/><path id="C" d="M45.536 28.733c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.935c2.332-.837 3.14-.867 5.126-.14s12.35 4.853 14.312 5.57 2.037 1.31.024 2.36z"/></defs></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/stacks/spring.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><path d="M58.2 3.365a29.503 29.503 0 0 1-3.419 6.064A32.094 32.094 0 1 0 9.965 55.372l1.186 1.047a32.08 32.08 0 0 0 52.67-22.253c.875-8.17-1.524-18.51-5.62-30.8zM14.53 55.558a2.744 2.744 0 1 1-.404-3.857 2.744 2.744 0 0 1 .404 3.857zm43.538-9.61c-7.92 10.55-24.83 6.99-35.672 7.502 0 0-1.922.113-3.857.43 0 0 .73-.31 1.663-.663 7.614-2.65 11.213-3.16 15.838-5.54 8.708-4.427 17.322-14.122 19.112-24.2-3.313 9.695-13.373 18.032-22.53 21.418-6.276 2.313-17.614 4.566-17.614 4.566l-.457-.245c-7.714-3.75-7.952-20.457 6.077-25.845 6.143-2.366 12.02-1.067 18.654-2.65 7.084-1.683 15.28-6.99 18.615-13.916 3.73 11.08 8.224 28.422.166 39.15z" fill="#68bd45"/></svg>
|
||||||
|
After Width: | Height: | Size: 721 B |
1
src/assets/stacks/terraform.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><style><![CDATA[.C{fill-rule:evenodd}]]></style><g transform="matrix(.826767 0 0 .826767 8.416322 51.138164)" class="C"><path d="M39.1 15.557v-24.43l-21.16-12.22v24.43zm0-27.1l-21.16-12.22v-24.44l21.16 12.22z" fill="#5c4ee5"/><path d="M62.6-23.773v-24.44l-21.17 12.22v24.44z" fill="#4040b2"/><g fill="#5c4ee5"><path d="M15.62-25.193v-24.44l-21.16-12.22v24.44z"/><path d="M53.64-.483"/><path d="M17.94-21.093"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 487 B |
@@ -1,4 +1,5 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Hind:wght@300;400;500;600;700&display=swap');
|
||||||
@import "font-montserrat.css";
|
@import "font-montserrat.css";
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -6,6 +7,13 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
width: 100vw;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@@ -14,3 +22,7 @@ h5,
|
|||||||
h6 {
|
h6 {
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-family: "Hind", sans-serif;
|
||||||
|
}
|
||||||
|
|||||||