Added socials.
This commit is contained in:
289
components/edit/socials.vue
Normal file
289
components/edit/socials.vue
Normal file
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<ul
|
||||
class="list nolist"
|
||||
:class="{ disabled: !editing.has('socials') }"
|
||||
>
|
||||
<li
|
||||
v-for="(social, index) in socials"
|
||||
:key="`socials-${social}`"
|
||||
class="list-item"
|
||||
:class="{ deleted: !socials.some((listItem) => listItem.social === social.social || listItem.url === social.url) }"
|
||||
>
|
||||
<a
|
||||
:href="getUrl(social)"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>
|
||||
<Icon
|
||||
v-if="social.platform && env.socials.urls[social.platform]"
|
||||
:icon="iconMap[social.platform] || social.platform"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform}`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.platform"
|
||||
icon="bubbles10"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.url"
|
||||
icon="sphere"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
{{ social.handle || social.url }}
|
||||
</a>
|
||||
|
||||
<Icon
|
||||
v-if="!socials.some((listItem) => listItem.social === social.social || listItem.url === social.url)"
|
||||
icon="checkmark"
|
||||
class="add noselect"
|
||||
@click="socials = socials.concat(social)"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="cross2"
|
||||
class="remove noselect"
|
||||
@click="socials = socials.filter((listItem, listIndex) => listIndex !== index)"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="list-new">
|
||||
<VDropdown>
|
||||
<Icon
|
||||
icon="plus2"
|
||||
class="add noselect"
|
||||
/>
|
||||
|
||||
<template #popper>
|
||||
<form
|
||||
class="new"
|
||||
@submit.prevent="addSocial"
|
||||
>
|
||||
<div class="new-section">
|
||||
<input
|
||||
v-model="platform"
|
||||
list="platforms"
|
||||
class="input"
|
||||
placeholder="Platform"
|
||||
pattern="[a-z]+"
|
||||
>
|
||||
|
||||
<datalist id="platforms">
|
||||
<option value="onlyfans">OnlyFans</option>
|
||||
<option value="twitter">Twitter/X</option>
|
||||
<option value="instagram">Instagram</option>
|
||||
<option value="pornhub">PornHub</option>
|
||||
<option value="linktree">Linktree</option>
|
||||
<option value="fansly">Fansly</option>
|
||||
<option value="loyalfans">LoyalFans</option>
|
||||
<option value="manyvids">ManyVids</option>
|
||||
<option value="cashapp">Cash App</option>
|
||||
</datalist>
|
||||
|
||||
<input
|
||||
v-model="handle"
|
||||
class="input"
|
||||
placeholder="Handle"
|
||||
pattern="[\w-]+"
|
||||
:disabled="!!url"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="new-section">
|
||||
OR<input
|
||||
v-model="url"
|
||||
class="input"
|
||||
placeholder="Website URL"
|
||||
:disabled="!!handle"
|
||||
>
|
||||
|
||||
<button
|
||||
class="button"
|
||||
>Add</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
inject,
|
||||
} from 'vue';
|
||||
|
||||
import formatTemplate from 'template-format';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { env } = pageContext;
|
||||
|
||||
const props = defineProps({
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['socials']);
|
||||
const socials = ref(props.edits.socials);
|
||||
|
||||
const platform = ref('');
|
||||
const handle = ref('');
|
||||
const url = ref('');
|
||||
|
||||
watch(socials, () => emit('socials', socials));
|
||||
|
||||
const iconMap = {
|
||||
twitter: 'twitter-x',
|
||||
};
|
||||
|
||||
function addSocial() {
|
||||
if (!handle.value && !url.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle.value && !platform.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
socials.value = socials.value.concat({
|
||||
platform: platform.value || null,
|
||||
handle: handle.value || null,
|
||||
url: url.value || null,
|
||||
});
|
||||
|
||||
emit('socials', socials.value);
|
||||
|
||||
platform.value = 'onlyfans';
|
||||
handle.value = '';
|
||||
url.value = '';
|
||||
}
|
||||
|
||||
function getUrl(social) {
|
||||
if (social.url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (env.socials.urls[social.platform]) {
|
||||
return formatTemplate(env.socials.urls[social.platform], { handle: social.handle });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.list {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
|
||||
&.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item {
|
||||
.icon-social {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.icon-generic {
|
||||
fill: var(--glass-strong-20);
|
||||
}
|
||||
|
||||
&.deleted {
|
||||
color: var(--glass);
|
||||
text-decoration: line-through;
|
||||
|
||||
.icon.icon-social {
|
||||
fill: var(--glass-weak-10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item,
|
||||
.list-new {
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
background: var(--background);
|
||||
|
||||
.link {
|
||||
padding: .25rem 0 .25rem .5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.add,
|
||||
.remove {
|
||||
padding: 0 .3rem;
|
||||
margin-left: .5rem;
|
||||
border-radius: .25rem;
|
||||
|
||||
&:hover {
|
||||
fill: var(--text-light);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-new .add {
|
||||
padding: .25rem .5rem;
|
||||
background: var(--background);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.new {
|
||||
padding: .25rem;
|
||||
}
|
||||
|
||||
.new-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
padding: .25rem;
|
||||
|
||||
.input {
|
||||
flex-grow: 1;
|
||||
|
||||
&:disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user