Skip to content

Commit

Permalink
Add social media editing
Browse files Browse the repository at this point in the history
  • Loading branch information
Bettelstab committed Aug 14, 2024
1 parent 6ed6919 commit cc7887f
Show file tree
Hide file tree
Showing 19 changed files with 321 additions and 73 deletions.
1 change: 1 addition & 0 deletions frontend/src/assets/icons/discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions frontend/src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Camera from './camera.svg?component'
import Cockpit from './cockpit.svg?component'
import Data from './data.svg?component'
import Date from './date.svg?component'
import Discord from './discord.svg?component'
import Ellipsis from './ellipsis.svg?component'
import Facebook from './facebook.svg?component'
import Instagram from './instagram.svg?component'
Expand All @@ -14,6 +15,8 @@ import Message from './message.svg?component'
import Pinterest from './pinterest.svg?component'
import Place from './place.svg?component'
import Share from './share.svg?component'
import Telegram from './telegram.svg?component'
import Tiktok from './tiktok.svg?component'
import Triangle from './triangle.svg?component'
import Website from './website.svg?component'
import WorldCafe from './worldCafe.svg?component'
Expand All @@ -30,6 +33,7 @@ const aliases: Partial<IconAliases> = {
cockpit: Cockpit,
data: Data,
date: Date,
discord: Discord,
ellipsis: Ellipsis,
facebook: Facebook,
instagram: Instagram,
Expand All @@ -40,6 +44,8 @@ const aliases: Partial<IconAliases> = {
pinterest: Pinterest,
place: Place,
share: Share,
telegram: Telegram,
tiktok: Tiktok,
triange: Triangle,
website: Website,
'world-cafe': WorldCafe,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/assets/icons/telegram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/src/assets/icons/tiktok.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 1 addition & 8 deletions frontend/src/assets/icons/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions frontend/src/assets/icons/xing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 29 additions & 11 deletions frontend/src/components/cockpit/about-me/AboutMe.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@
:social="user.social"
:user-image="avatar"
:initials="initials"
@edit="() => setMode('edit')"
@edit-details="() => setMode('edit-details')"
@edit-social="() => setMode('edit-social')"
@update-availability="updateAvailability"
@update-name="updateName"
@update-introduction="updateIntroduction"
></AboutMeView>
/>
<EditUserDetails
v-if="user && mode === 'edit'"
:username="user.username"
:name="user.name"
:availability="user.availability"
:introduction="user.introduction"
v-if="user && mode === 'edit-details'"
:details="user.details"
:social="user.social"
@back="() => setMode('view')"
@add-detail="addDetail"
@remove-detail="removeDetail"
></EditUserDetails>
/>
<EditSocialMedia
v-if="user && mode === 'edit-social'"
:socials="user.social"
@back="() => setMode('view')"
@add-social="addSocial"
@remove-social="removeSocial"
/>
</ClientOnly>
</template>

Expand All @@ -36,12 +39,18 @@ import { ref } from 'vue'
import ClientOnly from '#components/ClientOnly.vue'
import globalErrorHandler from '#plugins/globalErrorHandler'
import { useUserStore, UserAvailability, AddUserDetailInput } from '#stores/userStore'
import {
useUserStore,
UserAvailability,
AddUserDetailInput,
AddSocialMediaInput,
} from '#stores/userStore'
import AboutMeView from './AboutMeView.vue'
import EditSocialMedia from './EditSocialMedia.vue'
import EditUserDetails from './EditUserDetails.vue'
type Mode = 'view' | 'edit'
type Mode = 'view' | 'edit-details' | 'edit-social'
const mode = ref<Mode>('view')
const setMode = (newMode: Mode) => (mode.value = newMode)
Expand Down Expand Up @@ -86,4 +95,13 @@ const addDetail = async (detail: AddUserDetailInput) => {
const removeDetail = async (detailId: number) => {
await userStore.removeUserDetail(detailId)
}
const addSocial = async (social: AddSocialMediaInput) => {
await userStore.addSocialMedia(social)
social.link = ''
}
const removeSocial = async (socialId: number) => {
await userStore.removeSocialMedia(socialId)
}
</script>
31 changes: 21 additions & 10 deletions frontend/src/components/cockpit/about-me/AboutMeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,22 @@
/>
</template>
</div>
<button @click="$emit('edit')">
<button @click="$emit('edit-details')">
<Details :details="props.details" />
</button>
<ul class="social">
<li v-for="item in props.social" :key="item.type">
<a :href="item.link" target="_blank" rel="noopener noreferrer">
<v-icon :icon="`mdi-${item.type}`"></v-icon>
</a>
</li>
</ul>
<button @click="$emit('edit-social')">
<ul v-if="props.social.length > 0" class="social">
<li v-for="item in props.social" :key="item.type">
<a :href="item.link" target="_blank" rel="noopener noreferrer">
<v-icon :icon="`mdi-${item.type}`"></v-icon>
</a>
</li>
</ul>
<div v-else class="social">
<v-icon icon="mdi mdi-share-variant-outline" />
{{ $t('cockpit.about-me.empty-social-media') }}
</div>
</button>
</template>
</CockpitCard>
</template>
Expand Down Expand Up @@ -88,7 +94,8 @@ const props = defineProps<{
}>()
const emit = defineEmits<{
(e: 'edit'): void
(e: 'edit-details'): void
(e: 'edit-social'): void
(e: 'update-availability', status: UserAvailability): void
(e: 'update-name', name: string): void
(e: 'update-introduction', introduction: string): void
Expand Down Expand Up @@ -205,10 +212,14 @@ const updateIntroduction = (event: Event) => {
}
.social {
margin-top: 10px;
display: flex;
min-height: 30px;
padding: 0;
width: 300px;
padding: 10px;
list-style: none;
border-radius: 10px;
background: rgba(93, 102, 112, 0.55);
}
hr {
Expand Down
122 changes: 122 additions & 0 deletions frontend/src/components/cockpit/about-me/EditSocialMedia.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<template>
<CockpitCard narrow>
<template #header>
<div class="header">
<button class="back" @click="$emit('back')"><v-icon icon="$back"></v-icon></button>
<h2>{{ $t('cockpit.about-me.edit.title') }}</h2>
</div>
</template>
<template #default>
<v-form class="add-social" @submit.prevent="addSocial">
<v-select
v-model="newSocial.type"
flat
rounded
:items="socialMediaTypes"
class="select-category"
>
<template #selection="{ item }">
<v-icon :icon="getSocialMediaIcon(item.value)"></v-icon>
</template>
<template #item="{ item, props: listProps }">
<v-list-item v-bind="listProps" title="">
<v-icon :icon="getSocialMediaIcon(item.value)"></v-icon>
</v-list-item>
</template>
</v-select>
<v-text-field
v-model="newSocial.link"
name="text"
clearable
rounded
flat
density="compact"
variant="solo"
class="add-social-text"
maxlength="60"
></v-text-field>
<v-btn type="submit" :disabled="newSocial.link?.length === 0" variant="flat" rounded>
<v-icon icon="mdi mdi-plus"></v-icon>
</v-btn>
</v-form>
<ul class="social-media-list">
<li v-for="(social, index) in props.socials" :key="index">
<v-chip class="social">
<v-icon :icon="getSocialMediaIcon(social.type)" class="mr-2" />
{{ buildSocialMediaLink(social.type, social.link) }}
<v-icon
v-if="social.id >= 0"
icon="$close"
@click="$emit('remove-social', social.id)"
/>
</v-chip>
</li>
</ul>
</template>
</CockpitCard>
</template>

<script lang="ts" setup>
import { reactive } from 'vue'
import CockpitCard from '#components/cockpit/cockpitCard/CockpitCard.vue'
import { getSocialMediaIcon, socialMediaTypes, buildSocialMediaLink } from './socialMediaPlatforms'
import type { SocialMedia, AddSocialMediaInput } from '#stores/userStore'
const props = defineProps<{
socials: SocialMedia[]
}>()
const emit = defineEmits<{
(e: 'back'): void
(e: 'add-social', social: AddSocialMediaInput): void
(e: 'remove-social', id: number): void
}>()
const newSocial = reactive<AddSocialMediaInput>({
type: 'instagram',
link: '',
})
const addSocial = () => {
emit('add-social', newSocial)
}
</script>

<style scoped>
.back {
width: 40px;
}
.header {
display: flex;
gap: 20px;
}
.add-social {
display: flex;
gap: 8px;
align-items: center;
justify-content: center;
&:deep(.v-input__socials) {
display: none;
}
}
.select-category {
max-width: 80px;
&:deep(.v-field__outline) {
display: none;
}
}
.add-social-text {
&:deep(.v-field) {
background: grey; /* TODO set correct color */
}
}
</style>
11 changes: 2 additions & 9 deletions frontend/src/components/cockpit/about-me/EditUserDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,13 @@ import { reactive } from 'vue'
import CockpitCard from '#components/cockpit/cockpitCard/CockpitCard.vue'
import { detailCategories } from './detailCategories'
import { detailCategoryToIcon } from './detailCategoryToIcon'
import { detailCategories, detailCategoryToIcon } from './detailCategories'
import Details from './UserDetails.vue'
import type { UserDetail, SocialMedia, AddUserDetailInput } from '#stores/userStore'
import type { UserDetail, AddUserDetailInput } from '#stores/userStore'
const props = defineProps<{
username: string
name: string
userImage?: string
initials?: string
introduction?: string
details: UserDetail[]
social: SocialMedia[]
}>()
const emit = defineEmits<{
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/components/cockpit/about-me/UserDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
import { computed, Ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { detailCategories } from './detailCategories'
import { detailCategoryToIcon } from './detailCategoryToIcon'
import { detailCategories, detailCategoryToIcon } from './detailCategories'
import type { UserDetail } from '#stores/userStore'
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/components/cockpit/about-me/detailCategories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,20 @@ export const detailCategories: UserDetailCategory[] = [
'feeling',
'language',
]

export function detailCategoryToIcon(category: UserDetailCategory) {
switch (category) {
case 'place':
return 'mdi mdi-map-marker-outline'
case 'work':
return 'mdi mdi-briefcase-outline'
case 'language':
return 'mdi mdi-web'
case 'education':
return 'mdi mdi-school-outline'
case 'feeling':
return 'mdi mdi-emoticon-outline'
default:
throw new Error(`Unknown category`)
}
}
18 changes: 0 additions & 18 deletions frontend/src/components/cockpit/about-me/detailCategoryToIcon.ts

This file was deleted.

Loading

0 comments on commit cc7887f

Please sign in to comment.