diff --git a/components/user/Social.vue b/components/user/Social.vue deleted file mode 100644 index 60e05e76..00000000 --- a/components/user/Social.vue +++ /dev/null @@ -1,18 +0,0 @@ -<template> - <div class="social-container"> - This is a social container - </div> -</template> - -<script lang="ts"> -import Vue from 'vue'; - -export default Vue.extend({ - props: { - userId: { - type: String, - default: '', - }, - }, -}); -</script> diff --git a/components/user/social/Box.vue b/components/user/social/Box.vue new file mode 100644 index 00000000..4178c533 --- /dev/null +++ b/components/user/social/Box.vue @@ -0,0 +1,88 @@ +<template> + <Component :is="connectionMeta.link ? 'a' : 'div'" :href="connectionMeta.link" class="social-link-container"> + <p>{{ connectionMeta.header || connection.platform }}</p> + <FontAwesomeIcon :icon="connectionMeta.icon" class="icon fa-6x" /> + <p>{{ connection.username }}</p> + </Component> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { Connection, ConnectionMeta, ConnectionMetas } from '~/types/api/user'; + +export default Vue.extend({ + props: { + connection: { + type: Object as () => Connection, + default: undefined, + }, + }, + + computed: { + connectionMeta(): Partial<ConnectionMeta> { + const connectionMeta = this.connectionMetas[this.connection?.platform] ?? { }; + if (connectionMeta.linkBase) { + connectionMeta.link = connectionMeta.linkBase(this.connection.username); + } + return connectionMeta; + }, + }, + + /* eslint-disable-next-line vue/order-in-components */ // Here, data is way less interesting than computed + data() { + return { + connectionMetas: { + DISCORD: { + icon: [ 'fab', 'discord' ], + }, + EMAIL: { + linkBase: fragment => `mailto:${fragment}`, + icon: [ 'fas', 'envelope' ], + }, + FACEBOOK: { + linkBase: fragment => `https://www.facebook.com/${fragment}`, + icon: [ 'fab', 'facebook-f' ], + }, + INSTAGRAM: { + linkBase: fragment => `https://www.instagram.com/${fragment}`, + icon: [ 'fab', 'instagram' ], + }, + PHONE: { + linkBase: fragment => `tel:${fragment}`, + icon: [ 'fas', 'phone' ], + }, + NICO: { + linkBase: fragment => `https://com.nicovideo.jp/community/${fragment}`, + icon: [ 'fas', 'tv' ], + }, + SNAPCHAT: { + linkBase: fragment => `https://www.snapchat.com/add/${fragment}`, + icon: [ 'fab', 'snapchat-ghost' ], + }, + SPEEDRUNCOM: { + linkBase: fragment => `https://speedrun.com/user/${fragment}`, + icon: [ 'fas', 'trophy' ], + }, + TWITCH: { + linkBase: fragment => `https://www.twitch.tv/${fragment}`, + icon: [ 'fab', 'twitch' ], + }, + TWITTER: { + linkBase: fragment => `https://www.twitter.com/${fragment}`, + icon: [ 'fab', 'twitter' ], + }, + } as ConnectionMetas, + }; + }, +}); +</script> + +<style lang="scss" scoped> +.social-link-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + padding: var(--spacing); +} +</style> diff --git a/components/user/social/Social.vue b/components/user/social/Social.vue new file mode 100644 index 00000000..178e1272 --- /dev/null +++ b/components/user/social/Social.vue @@ -0,0 +1,48 @@ +<template> + <div v-if="user && !user._fetching && user.connections.length" class="social-container"> + <UserSocialBox v-for="connection of user.connections" :key="connection.id" :connection="connection" /> + </div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { mapActions } from 'vuex'; +import { User, UserState } from '~/types/api/user'; + +export default Vue.extend({ + props: { + userId: { + type: String, + default: '', + }, + }, + + async fetch(): Promise<void> { + await Promise.allSettled([ + this.getUser(this.userId), + ]); + }, + + computed: { + user(): User|undefined { + return (this.$store.state.api.user as UserState).users[this.userId]; + }, + }, + + methods: { + ...mapActions({ + getUser: 'api/user/get', + }), + }, +}); +</script> + +<style lang="scss" scoped> +.social-container { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + border-block: 1px solid; +} +</style> diff --git a/configs/font-awesome.config.js b/configs/font-awesome.config.js index dee257ce..4b547113 100644 --- a/configs/font-awesome.config.js +++ b/configs/font-awesome.config.js @@ -19,17 +19,24 @@ const solid = [ 'Desktop', 'Donate', 'DotCircle', + 'Envelope', 'Home', 'Language', 'MoneyBill', 'PaperPlane', + 'Phone', 'Plus', + 'Trophy', + 'Tv', ]; const brands = [ 'Discord', + 'FacebookF', 'Github', + 'Instagram', 'Patreon', + 'SnapchatGhost', 'Twitch', 'Twitter', ]; diff --git a/types/api/user.d.ts b/types/api/user.d.ts index 9f89cb9d..05d603f5 100644 --- a/types/api/user.d.ts +++ b/types/api/user.d.ts @@ -33,10 +33,31 @@ export interface UserState extends OengusState { searches: { [query: string]: Array<User>; }; } -export type ConnectionPlatform = 'DISCORD'|'TWITCH'|'TWITTER'|'' +// This ended up being kinda social. Move to its own file? + +export type ConnectionPlatform = + 'DISCORD' | + 'EMAIL' | + 'FACEBOOK' | + 'INSTAGRAM' | + 'PHONE' | + 'NICO' | + 'SNAPCHAT' | + 'SPEEDRUNCOM' | + 'TWITCH' | + 'TWITTER'; export interface Connection { id: number; platform: ConnectionPlatform; username: string; } + +export interface ConnectionMeta { + linkBase?: (fragment: string) => string; + icon: Array<String>; + header?: string; + link?: string; +} + +export type ConnectionMetas = Record<ConnectionPlatform, ConnectionMeta>;