added projects to bio page

This commit is contained in:
Fedor Katurov 2022-11-03 18:33:37 +06:00
parent 011f10a429
commit ef6f29803b
16 changed files with 327 additions and 75 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 KiB

BIN
assets/png/orchid-map.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

BIN
assets/png/vault48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

View file

@ -1,5 +1,5 @@
<template>
<section :class="$style.grid">
<div :class="$style.grid">
<div>
<img src="~/assets/svg/howdy.svg" />
</div>
@ -17,7 +17,7 @@
of doing <b>Typescript</b> and <b>Golang</b> backend.
</p>
</div>
</section>
</div>
</template>
<script lang="ts" setup></script>

View file

@ -0,0 +1,106 @@
<template>
<UiCard>
<div :class="$style.card">
<div :class="$style.thumbnail">
<img :src="image" :class="$style.image" :alt="name" />
</div>
<div :class="$style.content">
<div :class="$style.head">
<h3 :class="$style.title">{{ name }}</h3>
<div :class="$style.url">
<NuxtLink :to="url">{{ url }}</NuxtLink>
</div>
</div>
<div :class="$style.description">
{{ description }}
</div>
</div>
<div :class="$style.buttons">
<UiActionButton :href="source" variant="outline" _target="blank">
View Code
<template v-slot:prefix>
<IconsCode width="22" height="22" fill="currentColor" />
</template>
</UiActionButton>
<UiActionButton :href="url" variant="primary" _target="blank">
Visit Page
<template v-slot:suffix>
<IconsArrowRight width="22" height="22" fill="currentColor" />
</template>
</UiActionButton>
</div>
</div>
</UiCard>
</template>
<script lang="ts" setup>
interface Props {
name: string;
description: string;
url: string;
source: string;
image: string;
}
defineProps<Props>();
</script>
<style lang="scss" module>
.card {
display: flex;
flex-direction: column;
height: 100%;
}
.thumbnail {
height: 250px;
border-radius: 8px 8px 0 0;
border-bottom: 1px solid var(--color-line);
overflow: hidden;
}
.image {
object-fit: cover;
width: 100%;
height: auto;
}
.content {
padding: 16px;
display: flex;
flex-direction: column;
flex: 1;
}
.head {
margin-bottom: 16px;
}
.title {
margin: 0 0 4px 0;
}
.url {
font-size: 0.9em;
}
.description {
font-size: 0.9em;
line-height: 1.5em;
color: var(--color-text-secondary);
white-space: pre-line;
}
.buttons {
display: grid;
grid-template-columns: repeat(2, 1fr);
row-gap: 10px;
column-gap: 10px;
padding: 16px;
}
</style>

View file

@ -1,20 +1,30 @@
<template>
<section :class="$style.projects">
<h2>My Projects</h2>
<div :class="$style.projects">
<h2>Projects</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quaerat natus
perspiciatis ad voluptatum nisi saepe, molestiae autem dolores est modi
quod inventore similique omnis asperiores. Qui beatae magnam ab
consequatur.
</p>
</section>
<div :class="$style.grid">
<BioProjectCard
v-for="project in projects"
:key="project.name"
:name="project.name"
:description="project.description"
:url="project.pageUrl"
:source="project.codeUrl"
:image="project.image"
/>
</div>
</div>
</template>
<script lang="ts" setup></script>
<script lang="ts" setup>
import { projects } from "~~/constants/projects";
</script>
<style lang="scss" module>
.projects {
text-align: center;
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
column-gap: 16px;
row-gap: 16px;
}
</style>

View file

@ -3,7 +3,7 @@
<h2>Skills</h2>
<div :class="$style.list">
<SkillsCard
<BioSkillsCard
:title="skill.title"
:level="skill.level"
:description="skill.description ?? ''"
@ -11,7 +11,7 @@
v-for="skill in skills"
>
<img :src="skill.icon" width="48" height="48" />
</SkillsCard>
</BioSkillsCard>
</div>
</div>
</template>

View file

@ -1,5 +1,5 @@
<template>
<div :class="$style.card">
<UiCard>
<div :class="$style.grid">
<div :class="$style.icon">
<slot />
@ -14,7 +14,7 @@
<div :class="$style.description">
{{ description }}
</div>
</div>
</UiCard>
</template>
<script lang="ts" setup>
@ -28,21 +28,6 @@ defineProps<Props>();
</script>
<style lang="scss" module>
.card {
border-radius: 8px;
border: 1px solid var(--color-line);
transition: all 0.25s;
&:hover {
background-color: var(--color-line);
&,
& > .grid {
border-color: var(--color-text-secondary);
}
}
}
.grid {
display: grid;
grid-template-columns: 48px 1fr;

View file

@ -0,0 +1,17 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
height="48"
width="48"
viewBox="0 0 48 48"
>
<path
xmlns="http://www.w3.org/2000/svg"
d="m16 35.9-12-12 12.1-12.1 2.15 2.15L8.3 23.9l9.85 9.85Zm15.9.1-2.15-2.15 9.95-9.95-9.85-9.85L32 11.9l12 12Z"
/>
</svg>
</template>
<script lang="ts" setup></script>
<style lang="scss" module></style>

View file

@ -30,7 +30,7 @@
interface Props {
href: string;
size?: "md";
variant?: "outline";
variant?: "outline" | "text" | "primary";
}
withDefaults(defineProps<Props>(), {
@ -44,11 +44,15 @@ withDefaults(defineProps<Props>(), {
color: white;
border-radius: 8px;
text-decoration: none;
&.variant-outline {
display: inline-flex;
align-items: center;
justify-content: center;
&.variant-primary {
background-color: var(--color-primary);
}
&.variant-outline {
box-shadow: var(--color-text) 0 0 0 1px;
color: var(--color-text);
overflow: hidden;
@ -68,7 +72,6 @@ withDefaults(defineProps<Props>(), {
}
&:hover {
color: var(--color-background);
box-shadow: var(--color-background) 0 0 0 1px;
&::after {
@ -96,6 +99,8 @@ withDefaults(defineProps<Props>(), {
.title {
z-index: 1;
position: relative;
flex: 1;
text-align: center;
.size-md.prefixed & {
padding-left: 10px;

20
components/ui/UiCard.vue Normal file
View file

@ -0,0 +1,20 @@
<template>
<div :class="[$style.card, $attrs.class]">
<slot />
</div>
</template>
<script lang="ts" setup></script>
<style lang="scss" module>
.card {
border-radius: 8px;
border: 1px solid var(--color-line);
transition: all 0.25s;
&:hover {
background-color: var(--color-code-background);
border-color: var(--color-text-secondary);
}
}
</style>

55
constants/projects.ts Normal file
View file

@ -0,0 +1,55 @@
import { Technology } from "./technologies";
import vault from "~~/assets/png/vault48.png";
import orchid from "~~/assets/png/orchid-map.png";
import obsidian from "~~/assets/png/obsidian-garden.png";
interface Project {
name: string;
description: string;
pageUrl: string;
codeUrl: string;
image: string;
technologies: Technology[];
}
export const projects: Project[] = [
{
name: "Vault48",
description: `Community blog with a long 13-year history, features photo, video and audio embedding.\n\nBeeing initially written with Drupal 5, went through refactoring to Laravel + Vue and then, nowadays works on React and Golang stack.`,
pageUrl: "https://vault48.org",
codeUrl: "https://github.com/muerwre/vault-frontend",
image: vault,
technologies: [
Technology.React,
Technology.ReactSSR,
Technology.GoLang,
Technology.Postgres,
],
},
{
name: "Orchid Map",
description: `Local cycling community Web Maps made with React, Leaflet, and Golang.\n\nImplements automatic route building with OSRM and map rasterization with canvas. Used by users in local cycling communities for ride sharing.`,
pageUrl: "https://map.vault48.org",
codeUrl: "https://github.com/muerwre/orchidmap-front",
image: orchid,
technologies: [
Technology.React,
Technology.ReactSSR,
Technology.GoLang,
Technology.Postgres,
],
},
{
name: "Obsidian Garden",
description: `Frontend for personal knowledge database managed by Obsidian.md software.\n\nMade with nuxt3, nuxt-content plugin and some customizations. Deployed with drone-ci directly to github-pages.`,
pageUrl: "https://muerwre.github.io",
codeUrl: "https://github.com/muerwre/muerwre.github.io",
image: obsidian,
technologies: [
Technology.React,
Technology.ReactSSR,
Technology.GoLang,
Technology.Postgres,
],
},
];

View file

@ -1,16 +1,4 @@
import ReactLogo from "@/assets/svg/react-logo.svg";
import ReactNativeLogo from "@/assets/svg/react-native-logo.svg";
import ReactSSR from "@/assets/svg/react-ssr-logo.svg";
import TsLogo from "@/assets/svg/ts-logo.svg";
import GoLangLogo from "@/assets/svg/golang-logo.svg";
import HTMLLogo from "@/assets/svg/html-logo.svg";
import SVGLogo from "@/assets/svg/svg-logo.svg";
import ArchLogo from "@/assets/svg/arch-logo.svg";
import GQLLogo from "@/assets/svg/gql-logo.svg";
import SwaggerLogo from "@/assets/svg/swagger-logo.svg";
import VueLogo from "@/assets/svg/vue-logo.svg";
import PostgresLogo from "@/assets/svg/postgres-logo.svg";
import DockerLogo from "@/assets/svg/docker-logo.svg";
import { Technology, technologyIcons, technologyTitles } from "./technologies";
interface Skill {
title: string;
@ -21,80 +9,80 @@ interface Skill {
export const skills: Skill[] = [
{
title: "React",
title: technologyTitles[Technology.React],
description: "Classes and FC-s, hooks, context, redux, redux-saga, mobx",
level: 5,
icon: ReactLogo,
icon: technologyIcons[Technology.React],
},
{
title: "Typescript",
title: technologyTitles[Technology.ReactNative],
description:
"For both frontend and backend development: generics, guards, infers",
level: 4,
icon: TsLogo,
icon: technologyIcons[Technology.Ts],
},
{
title: "SSR (Next, Gatsby)",
title: technologyTitles[Technology.ReactSSR],
description: `Automated generation, incremental, static, and dynamic rendering`,
level: 4,
icon: ReactSSR,
icon: technologyIcons[Technology.ReactSSR],
},
{
title: "Vue.js & Nuxt",
title: technologyTitles[Technology.Ts],
description: `Common SPA-s and SSR blogs like this one, with composition API, and Vuex`,
level: 3,
icon: VueLogo,
icon: technologyIcons[Technology.Vue],
},
{
title: "React Native",
title: technologyTitles[Technology.GoLang],
description: `Basic developing and releasing experience without native modules`,
level: 3,
icon: ReactNativeLogo,
icon: technologyIcons[Technology.ReactNative],
},
{
title: "Golang",
title: technologyTitles[Technology.HTML],
description: "Monolith and microservice apps with REST, GraphQL, and GRPC",
level: 2,
icon: GoLangLogo,
icon: technologyIcons[Technology.GoLang],
},
{
title: "Docker",
title: technologyTitles[Technology.Arch],
description:
"Docker, docker-compose, private registries, gitlab-ci, and drone-ci",
level: 4,
icon: DockerLogo as string,
icon: technologyIcons[Technology.Docker],
},
{
title: "HTML, CSS, SVG",
title: technologyTitles[Technology.GQL],
description:
"Adaptive markup, all modern techniques, preprocessors, and CSS-in-JS",
level: 5,
icon: HTMLLogo,
icon: technologyIcons[Technology.HTML],
},
{
title: "Linux Shell",
title: technologyTitles[Technology.Swagger],
description:
"Linux user since 2003, can write scripts to automate my work. BTW, I use Arch!",
level: 4,
icon: ArchLogo as string,
icon: technologyIcons[Technology.Arch],
},
{
title: "GraphQL",
title: technologyTitles[Technology.Vue],
description:
"Both server- and client-side. Queries, mutations, cache manipulation",
level: 4,
icon: GQLLogo as string,
icon: technologyIcons[Technology.GQL],
},
{
title: "REST API",
title: technologyTitles[Technology.Postgres],
description: "With Axios, fetch, express, gorilla-mux, and gin-gonic",
level: 4,
icon: SwaggerLogo as string,
icon: technologyIcons[Technology.Swagger],
},
{
title: "SQL",
title: technologyTitles[Technology.Docker],
description: "Base queries, JOIN-s, indexes and simpl query optimizations",
level: 2,
icon: PostgresLogo as string,
icon: technologyIcons[Technology.Postgres],
},
];

57
constants/technologies.ts Normal file
View file

@ -0,0 +1,57 @@
import ReactLogo from "@/assets/svg/react-logo.svg";
import ReactNativeLogo from "@/assets/svg/react-native-logo.svg";
import ReactSSRLogo from "@/assets/svg/react-ssr-logo.svg";
import TsLogo from "@/assets/svg/ts-logo.svg";
import GoLangLogo from "@/assets/svg/golang-logo.svg";
import HTMLLogo from "@/assets/svg/html-logo.svg";
import ArchLogo from "@/assets/svg/arch-logo.svg";
import GQLLogo from "@/assets/svg/gql-logo.svg";
import SwaggerLogo from "@/assets/svg/swagger-logo.svg";
import VueLogo from "@/assets/svg/vue-logo.svg";
import PostgresLogo from "@/assets/svg/postgres-logo.svg";
import DockerLogo from "@/assets/svg/docker-logo.svg";
export enum Technology {
React = "React",
ReactNative = "ReactNative",
ReactSSR = "ReactSSR",
Ts = "Ts",
GoLang = "GoLang",
HTML = "HTML",
Arch = "Arch",
GQL = "GQL",
Swagger = "Swagger",
Vue = "Vue",
Postgres = "Postgres",
Docker = "Docker",
}
export const technologyIcons: Record<Technology, string> = {
[Technology.React]: ReactLogo,
[Technology.ReactNative]: ReactNativeLogo,
[Technology.ReactSSR]: ReactSSRLogo,
[Technology.Ts]: TsLogo,
[Technology.GoLang]: GoLangLogo,
[Technology.HTML]: HTMLLogo,
[Technology.Arch]: ArchLogo,
[Technology.GQL]: GQLLogo,
[Technology.Swagger]: SwaggerLogo,
[Technology.Vue]: VueLogo,
[Technology.Postgres]: PostgresLogo,
[Technology.Docker]: DockerLogo,
};
export const technologyTitles: Record<Technology, string> = {
[Technology.React]: "React",
[Technology.ReactNative]: "Typescript",
[Technology.ReactSSR]: "SSR (Next, Gatsby)",
[Technology.Ts]: "Vue.js & Nuxt",
[Technology.GoLang]: "React Native",
[Technology.HTML]: "Golang",
[Technology.Arch]: "Docker",
[Technology.GQL]: "HTML, CSS, SVG",
[Technology.Swagger]: "Linux Shell",
[Technology.Vue]: "GraphQL",
[Technology.Postgres]: "REST API",
[Technology.Docker]: "SQL",
};

5
custom.d.ts vendored
View file

@ -2,3 +2,8 @@ declare module "*.svg" {
const content: string;
export default content;
}
declare module "*.png" {
const content: string;
export default content;
}

View file

@ -7,6 +7,10 @@
<section :class="$style.section">
<BioSkills />
</section>
<section :class="$style.section">
<BioProjects />
</section>
</article>
</template>