Update projects

This commit is contained in:
Kamil Niemczycki 2021-09-02 21:29:46 +02:00
parent 1ccbc2c391
commit d9e097073b
10 changed files with 284 additions and 104 deletions

21
package-lock.json generated
View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^2.0.2", "@fortawesome/vue-fontawesome": "^2.0.2",
"bootstrap": "^5.0.2", "bootstrap": "^5.0.2",
@ -1661,6 +1662,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/@fortawesome/free-regular-svg-icons": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
"integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-solid-svg-icons": { "node_modules/@fortawesome/free-solid-svg-icons": {
"version": "5.15.4", "version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
@ -19045,6 +19058,14 @@
"@fortawesome/fontawesome-common-types": "^0.2.36" "@fortawesome/fontawesome-common-types": "^0.2.36"
} }
}, },
"@fortawesome/free-regular-svg-icons": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
"integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
}
},
"@fortawesome/free-solid-svg-icons": { "@fortawesome/free-solid-svg-icons": {
"version": "5.15.4", "version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",

View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^2.0.2", "@fortawesome/vue-fontawesome": "^2.0.2",
"bootstrap": "^5.0.2", "bootstrap": "^5.0.2",

48
public/api/projects.json Normal file
View File

@ -0,0 +1,48 @@
[
{
"id": 1,
"title": "Test 1",
"category": "prywatne",
"author": "Kamil Niemczycki",
"image": "assets/img/projects/kamilcraft.jpg",
"release_data": "30 sierpnia 2021",
"version": "v1.0.0",
"short_description": "abcdefghijklmnoprestuwxyz"
},
{
"id": 2,
"title": "Test 1",
"category": "wordpress",
"image": "assets/me.jpg",
"release_data": "30 sierpnia 2021",
"version": "v1.0.0",
"short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 3,
"title": "Test 1",
"category": "prywatne",
"image": "assets/me.jpg",
"release_data": "30 sierpnia 2021",
"version": "v1.0.0",
"short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 4,
"title": "Test 1",
"category": "zlecenia",
"image": "assets/me.jpg",
"release_data": "30 sierpnia 2021",
"version": "v1.0.0",
"short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 5,
"title": "Test 1",
"category": "zlecenia",
"image": "assets/me.jpg",
"release_data": "30 sierpnia 2021",
"version": "v1.0.0",
"short_description": "abcdefghijklmnoprestuwxyz"
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -17,6 +17,7 @@
<base-btn has-icon <base-btn has-icon
icon="eye" icon="eye"
is-reverse is-reverse
@click.native="$router.push({ name: 'Project', params: { id: project.id } })"
class="btn">O projekcie</base-btn> class="btn">O projekcie</base-btn>
</div> </div>
</div> </div>
@ -31,6 +32,7 @@
.container { .container {
display: grid; display: grid;
align-items: flex-start;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
grid-auto-rows: minmax(80px, auto); grid-auto-rows: minmax(80px, auto);
column-gap: 25px; column-gap: 25px;
@ -40,6 +42,7 @@
display: grid; display: grid;
position: relative; position: relative;
grid-template-areas: 'image content'; grid-template-areas: 'image content';
grid-template-columns: 200px 1fr;
background-color: #fafafa; background-color: #fafafa;
border: 1px solid rgba(0, 0, 0, .025); border: 1px solid rgba(0, 0, 0, .025);
border-radius: 5px; border-radius: 5px;
@ -121,7 +124,7 @@
@media screen and (max-width: 900px) { @media screen and (max-width: 900px) {
.project { .project {
grid-template-areas: 'image' 'content'; display: block;
.project-image { .project-image {
width: 100%; width: 100%;

View File

@ -7,10 +7,12 @@ import '../scss/default.scss'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons' import { fas } from '@fortawesome/free-solid-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons' import { fab } from '@fortawesome/free-brands-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
library.add(fas) library.add(fas)
library.add(fab) library.add(fab)
library.add(far)
Vue.component('font-awesome-icon', FontAwesomeIcon) Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.config.productionTip = false Vue.config.productionTip = false

View File

@ -3,6 +3,7 @@ import VueRouter from 'vue-router'
import Home from '../views/Home' import Home from '../views/Home'
import About from '../views/About' import About from '../views/About'
import Projects from '../views/Projects' import Projects from '../views/Projects'
import Project from '../views/Project'
import Contact from '../views/Contact' import Contact from '../views/Contact'
import NotFound from '../views/NotFound' import NotFound from '../views/NotFound'
@ -27,6 +28,14 @@ const routes = [
}, },
component: Projects component: Projects
}, },
{
path: '/projects/:id',
name: 'Project',
meta: {
title: 'Projekt'
},
component: Project
},
{ {
path: '/about', path: '/about',
name: 'About', name: 'About',

View File

@ -8,18 +8,42 @@ const moduleSettings = {
header: { header: {
title: null, title: null,
description: null description: null
} },
categories: [],
projects: []
}, },
getters: { getters: {
getHeader (state) { getHeader (state) {
return state.header return state.header
},
getCategories (state) {
return state.categories
},
getProjects (state) {
return state.projects
}
},
actions: {
fetchProjects (store) {
return fetch('/api/projects.json')
.then(response => response.json())
.then(data => {
store.commit('setProjects', data)
return store.getters.getProjects
})
} }
}, },
mutations: { mutations: {
setHeader: (state, payload) => { setCategories: (state, array = []) => {
state.categories = array
},
setProjects: (state, array = []) => {
state.projects = array
},
setHeader: (state, text) => {
state.header = { state.header = {
title: payload.title ?? null, title: text.title ?? null,
description: payload.description ?? null description: text.description ?? null
} }
}, },
resetHeaderTitle (state) { resetHeaderTitle (state) {

138
src/views/Project.vue Normal file
View File

@ -0,0 +1,138 @@
<template>
<section class="project" v-if="project">
<header class="project-header">
<h1>{{ project.title }}</h1>
<ul class="project-info">
<li class="info-text">
<font-awesome-icon class="icon" :icon="['far', 'clock']"/>
<span>{{ project.release_data }}</span>
</li>
<li class="info-text">
<font-awesome-icon class="icon" :icon="['far', 'user']"/>
<span>{{ project.author }}</span>
</li>
<li class="info-text">
<font-awesome-icon class="icon" :icon="['far', 'folder']"/>
<span>{{ getCategoryName(project.category) }}</span>
</li>
<li class="info-text">
<font-awesome-icon class="icon" :icon="['fas', 'code-branch']"/>
<span>{{ project.version }}</span>
</li>
</ul>
</header>
<div class="container">
<component :is="`figure`" class="project-photo">
<img :src="`${publicPath}${project.image}`" :alt="project.title">
</component>
<div class="content">
<p v-for="(description, key) in project.short_description.split('\n')" :key="key">
{{ description }}
</p>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'Project',
data () {
return {
publicPath: process.env.BASE_URL,
project: null
}
},
mounted () {
const project = this.getProjects.find(project => project.id === this.$route.params.id)
this.project = project
},
computed: {
getCategories () {
return this.$store.getters.getCategories
},
getProjects () {
return this.$store.getters.getProjects
}
},
methods: {
getCategoryName (slug) {
const category = this.getCategories.find(category => category.slug === slug)
return category.name
}
}
}
</script>
<style lang="scss" scoped>
@import "scss/default";
.project {
.project-header {
@extend .container;
text-align: center;
margin-bottom: 25px;
h1 {
font-size: 2.2em;
font-weight: lighter;
line-height: 2.4em;
}
.project-info {
display: flex;
list-style: none;
justify-content: center;
.info-text {
display: flex;
align-items: center;
.icon {
width: 2em;
}
span {
font-weight: lighter;
}
&:not(&:last-child) {
margin-right: 15px;
}
}
@media screen and (max-width: 560px) {
display: grid;
grid-template-columns: repeat(2, 1fr);
row-gap: 15px;
.info-text {
&:not(&:last-child) {
margin-right: 0;
}
}
}
}
}
.container {
.project-photo {
box-shadow: 5px 5px 10px rgba(0, 0, 0, .3);
}
.project-photo, .project-photo img {
width: 100%;
}
.project-photo img {
display: block;
object-fit: cover;
max-height: 500px;
}
.content {
margin: 25px 0;
font-weight: lighter;
font-size: .9em;
}
p::first-line {
text-indent: 5px;
}
}
}
</style>

View File

@ -3,7 +3,7 @@
<div class="category-menu"> <div class="category-menu">
<ul class="categories"> <ul class="categories">
<li class="category" <li class="category"
v-for="category in categories.list" v-for="category in $store.getters.getCategories"
:key="category.slug" :key="category.slug"
:class="{ 'category-active': categories.active === category.slug }" :class="{ 'category-active': categories.active === category.slug }"
@click="changeCategory(category.slug)"> @click="changeCategory(category.slug)">
@ -11,8 +11,8 @@
</li> </li>
</ul> </ul>
</div> </div>
<projects :projects="projects.active" /> <projects :projects="projects" />
<div v-if="projects.active.length === 0" class="loading"> <div v-if="projects.length === 0" class="loading">
<div class="loading-animation"></div> <div class="loading-animation"></div>
</div> </div>
</div> </div>
@ -21,6 +21,7 @@
<style lang="scss"> <style lang="scss">
.category-menu { .category-menu {
padding-top: 45px; padding-top: 45px;
.categories { .categories {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -103,122 +104,55 @@ export default {
data () { data () {
return { return {
categories: { categories: {
list: [],
active: 'wszystkie' active: 'wszystkie'
}, },
publicPath: process.env.BASE_URL, publicPath: process.env.BASE_URL,
projects: { projects: []
all: [],
active: []
}
} }
}, },
mounted () { async mounted () {
this.categories.list = [ this.$store.commit('setCategories', [
{ name: 'Wszystkie', slug: 'wszystkie' },
{ name: 'Wordpress', slug: 'wordpress' },
{ name: 'Prywatne', slug: 'prywatne' },
{ name: 'Zlecenia', slug: 'zlecenia' }
]
this.projects.all = [
{ {
title: 'KamilCraft.com', name: 'Wszystkie',
category: 'private', slug: 'wszystkie'
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.1',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
}, },
{ {
title: 'Youtube.com', name: 'Wordpress',
category: 'prywatne', slug: 'wordpress'
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.1',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
}, },
{ {
title: 'Projekt 2', name: 'Prywatne',
category: 'wordpress', slug: 'prywatne'
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.0',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
}, },
{ {
title: 'Projekt 14', name: 'Zlecenia',
category: 'wordpress', slug: 'zlecenia'
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.0',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
},
{
title: 'Projekt 3',
category: 'prywatne',
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.0',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
},
{
title: 'Projekt 4',
category: 'prywatne',
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.0',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
},
{
title: 'Projekt 20',
category: 'zlecenia',
image: `${this.publicPath}assets/me.jpg`,
release_data: '29.08.2021',
version: 'v1.0.0',
short_description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
} }
] ])
this.projects.active = this.projects.all await this.$store.dispatch('fetchProjects').then(projects => {
projects.sort((firstProduct, secondProduct) => {
return secondProduct.id - firstProduct.id
})
this.projects = projects
}).catch(error => {
console.log(error)
})
},
destroyed () {
this.$store.commit('resetHeaderTitle')
this.$store.commit('resetHeaderDescription')
}, },
methods: { methods: {
loadListWhereCategory (category) { loadListWhereCategory (category) {
this.projects.active = [] this.projects = []
setTimeout(() => { setTimeout(() => {
if (category !== 'wszystkie') { if (category !== 'wszystkie') {
const projects = this.projects.all.filter(project => project.category === category) const projects = this.$store.getters.getProjects.filter(project => project.category === category)
this.projects.active = projects this.projects = projects
} else { } else {
this.projects.active = this.projects.all this.projects = this.$store.getters.getProjects
} }
}, 1000) }, 500)
}, },
changeCategory (category) { changeCategory (category) {
this.categories.active = category this.categories.active = category