diff --git a/src/assets/skill_level.json b/src/assets/skill_level.json
index a73f184..5e5faaf 100644
--- a/src/assets/skill_level.json
+++ b/src/assets/skill_level.json
@@ -1,7 +1,22 @@
{
- "1": "bis 6 Monate",
- "2": "bis 1 Jahr",
- "3": "bis 3 Jahre",
- "4": "bis 5 Jahre",
- "5": "mehr als 5 Jahre"
-}
\ No newline at end of file
+ "1": {
+ "short": "≤ 6M",
+ "long": "bis 6 Monate"
+ },
+ "2":{
+ "short": "≤ 1J",
+ "long": "bis 1 Jahr"
+ },
+ "3": {
+ "short": "≤ 3J",
+ "long": "bis 3 Jahre"
+ },
+ "4": {
+ "short": "≤ 5J",
+ "long": "bis 5 Jahre"
+ },
+ "5": {
+ "short": "> 5J",
+ "long": "mehr als 5 Jahre"
+ }
+}
diff --git a/src/components/ProfileList.vue b/src/components/ProfileList.vue
index 22366f9..2ade5ee 100644
--- a/src/components/ProfileList.vue
+++ b/src/components/ProfileList.vue
@@ -32,7 +32,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
:value="key"
:key="key"
>
- {{ value }}
+ {{ value.long || value }}
@@ -90,11 +90,11 @@ SPDX-License-Identifier: AGPL-3.0-or-later
+
+
diff --git a/src/components/ViewError.vue b/src/components/ViewError.vue
new file mode 100644
index 0000000..5724a90
--- /dev/null
+++ b/src/components/ViewError.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
nullptr :/
+
Du hast noch kein Profil
+
+ Jetzt Profil erstellen
+
+
+
+
nullptr :/
+
+ Profil nicht gefunden
+
+
+
+
+ Kernel panic :/
+ Das Profil konnte nicht geladen werden
+
+
+
+
+
+
diff --git a/src/components/profile/Contact.vue b/src/components/profile/Contact.vue
new file mode 100644
index 0000000..3f996b6
--- /dev/null
+++ b/src/components/profile/Contact.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/profile/Header.vue b/src/components/profile/Header.vue
new file mode 100644
index 0000000..dd53e63
--- /dev/null
+++ b/src/components/profile/Header.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+ {{ profile.nickname }}
+
+ ({{ profile.pronouns }})
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/profile/Language.vue b/src/components/profile/Language.vue
new file mode 100644
index 0000000..45e545b
--- /dev/null
+++ b/src/components/profile/Language.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
{{ profileLanguage.language.name }}
+
{{ level }}
+
+
+
+
+
+
+
+
diff --git a/src/components/profile/Section.vue b/src/components/profile/Section.vue
new file mode 100644
index 0000000..1056dbc
--- /dev/null
+++ b/src/components/profile/Section.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/src/router/index.js b/src/router/index.js
index 4688ce1..5680ec4 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -46,7 +46,14 @@ const routes = [
{
path: '/',
name: 'Index',
- component: Index
+ component: Index,
+ beforeEnter: (_to, _from, next) => {
+ if (store.state.token) {
+ next({name: 'Search'})
+ } else {
+ next()
+ }
+ }
},
]
diff --git a/src/store/index.js b/src/store/index.js
index c36f364..c7a3260 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -4,6 +4,7 @@
import { createStore } from 'vuex'
+import profile from './profile'
import search from './search'
const localStorageKeys = {
@@ -13,13 +14,13 @@ const localStorageKeys = {
export default createStore({
modules: {
+ profile,
search,
},
state() {
return {
currentUserId: JSON.parse(localStorage.getItem(localStorageKeys.currentUserId)),
token: JSON.parse(localStorage.getItem(localStorageKeys.token)),
- currentProfile: null
}
},
mutations: {
@@ -42,9 +43,6 @@ export default createStore({
state.token = token
localStorage.setItem(localStorageKeys.token, JSON.stringify(token))
},
- setCurrentProfile(state, profile) {
- state.currentProfile = profile
- }
},
actions: {
clear(context) {
diff --git a/src/store/profile.js b/src/store/profile.js
new file mode 100644
index 0000000..1cf28c6
--- /dev/null
+++ b/src/store/profile.js
@@ -0,0 +1,117 @@
+// SPDX-FileCopyrightText: WTF Kooperative eG
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+export default {
+ namespaced: true,
+ state() {
+ return {
+ loading: false,
+ showSpinner: false,
+ profileId: null,
+ profile: null,
+ isOwnProfile: false,
+ error: false,
+ notFound: false
+ }
+ },
+ mutations: {
+ setProfileId(state, profileId) {
+ state.profileId = profileId
+ },
+ clearProfileId(state) {
+ state.profileId = null
+ },
+ setProfile(state, profile) {
+ state.profile = profile
+ },
+ clearProfile(state) {
+ state.profile = null
+ },
+ setLoading(state) {
+ state.loading = true
+ },
+ setNotLoading(state) {
+ state.loading = false
+ },
+ setError(state) {
+ state.error = true
+ },
+ clearError(state) {
+ state.error = false
+ },
+ showSpinner(state) {
+ state.showSpinner = true
+ },
+ hideSpinner(state) {
+ state.showSpinner = false
+ },
+ setNotFound(state, notFound) {
+ state.notFound = notFound
+ },
+ setIsOwnProfile(state, isOwnProfile) {
+ state.isOwnProfile = isOwnProfile
+ }
+ },
+ actions: {
+ onError({commit}) {
+ commit('setError')
+ commit('clearProfileId')
+ commit('clearProfile')
+ commit('setNotLoading')
+ commit('hideSpinner')
+ },
+ onNotFound({commit, dispatch}) {
+ dispatch('onError')
+ commit('setNotFound', true)
+ },
+ async load({state, commit, dispatch, rootState}, profileId) {
+ if (state.loading) {
+ return
+ }
+
+ commit('setProfileId', profileId)
+ commit('setIsOwnProfile', rootState.currentUserId === profileId)
+ commit('setLoading')
+
+ const timeoutId = setTimeout(() => {
+ commit('showSpinner')
+ commit('clearProfile')
+ }, 0)
+
+ commit('clearError')
+ commit('setNotFound', false)
+
+ const url = new URL(`${window.ki.apiUrl}/users/${profileId}/profile`)
+ const headers = {
+ Authorization: `Bearer ${rootState.token}`
+ }
+
+ let response
+
+ try {
+ response = await fetch(url, {headers})
+ } catch {
+ dispatch('onError')
+ return
+ }
+
+ clearTimeout(timeoutId)
+
+ if (response.status === 404) {
+ dispatch('onNotFound')
+ return
+ }
+
+ if (!response.ok) {
+ dispatch('onError')
+ return
+ }
+
+ const responseData = await response.json()
+ commit('setProfile', responseData.profile)
+ commit('hideSpinner')
+ commit('setNotSearching')
+ }
+ }
+}
diff --git a/src/views/Index.vue b/src/views/Index.vue
index e3dd905..0d5e66f 100644
--- a/src/views/Index.vue
+++ b/src/views/Index.vue
@@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
id="exampleInputusername1"
v-model="username"
required
+ autofocus
/>
diff --git a/src/views/Search.vue b/src/views/Search.vue
index b585cc6..ae36c63 100644
--- a/src/views/Search.vue
+++ b/src/views/Search.vue
@@ -100,9 +100,9 @@ export default {
},
watch: {
searching(value) {
- if (value) {
+ if (!value) {
if (this.$refs.searchTextInput) {
- this.$refs.searchTextInput.focus()
+ this.focusSearchText()
}
}
}
@@ -111,6 +111,11 @@ export default {
handleSubmit() {
this.$router.push({ query: { query: this.searchText }})
this.$store.dispatch('search/search')
+ },
+ focusSearchText() {
+ this.$nextTick(() => {
+ this.$refs.searchTextInput.focus()
+ })
}
},
created() {
diff --git a/src/views/profile/View.vue b/src/views/profile/View.vue
index bce1417..3f76f9b 100644
--- a/src/views/profile/View.vue
+++ b/src/views/profile/View.vue
@@ -5,60 +5,131 @@ SPDX-License-Identifier: AGPL-3.0-or-later
-->
-
-
- {{profile.nickname}}
- ({{profile.pronouns}})
-
-
{{profile.freetext}}
-
{{profile.volunteerwork}}
-
{{profile.availability}}
-
Das kann ich:
-
-
Das suche ich:
-
-
Meine Kontaktmöglichkeiten:
-
-
Ich Spreche Folgende Sprachen:
-
-
-
Meine Location:
- {{profile.address.city}} ({{profile.address.postcode}}), {{profile.address.country}}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ profile.availability }}
+
+
+
+
+
+
+
Über mich
+ {{ profile.freetext }}
+
+
+
Ehrentamtliche Arbeit
+ {{ profile.volunteerwork }}
+
+
+
+
+