traxxx-web/pages/users/@username/+Page.vue

214 lines
4.0 KiB
Vue

<template>
<div class="profile">
<div class="profile-header">
<img
v-if="profile.avatar"
:src="profile.avatar"
class="avatar"
>
<h2 class="username">{{ profile.username }}</h2>
</div>
<ul class="stashes nolist">
<li
v-for="stash in profile.stashes"
:key="`stash-${stash.id}`"
>
<div class="stash">
<div class="stash-header">
<a
:href="`/stash/${profile.username}/${stash.slug}`"
class="stash-name ellipsis nolink"
>
<span class="ellipsis">{{ stash.name }}</span>
<Icon
v-if="stash.primary"
icon="heart7"
class="primary"
/>
</a>
<Icon
v-if="profile.id === user?.id && stash.public"
icon="eye"
class="public noselect"
@click="setStashPublic(stash, false)"
/>
<Icon
v-else-if="profile.id === user?.id"
icon="eye-blocked"
class="public noselect"
@click="setStashPublic(stash, true)"
/>
</div>
<div class="stash-counts">
<a
:href="`/stash/${profile.username}/${stash.slug}/scenes`"
class="stash-count nolink"
><Icon icon="clapboard-play" />{{ abbreviateNumber(stash.stashedScenes) }}</a>
<a
:href="`/stash/${profile.username}/${stash.slug}/actors`"
class="stash-count nolink"
><Icon icon="star" />{{ abbreviateNumber(stash.stashedActors) }}</a>
<a
:href="`/stash/${profile.username}/${stash.slug}/movies`"
class="stash-count nolink"
><Icon icon="movie" />{{ abbreviateNumber(stash.stashedMovies) }}</a>
</div>
</div>
</li>
</ul>
</div>
</template>
<script setup>
import { ref, inject } from 'vue';
import { get, patch } from '#/src/api.js';
import events from '#/src/events.js';
const pageContext = inject('pageContext');
const profile = ref(pageContext.pageProps.profile);
const user = pageContext.user;
const done = ref(true);
function abbreviateNumber(number) {
return number?.toLocaleString('en-US', { notation: 'compact' }) || 0;
}
async function setStashPublic(stash, isPublic) {
if (done.value === false) {
return;
}
try {
done.value = false;
await patch(`/stashes/${stash.id}`, { public: isPublic });
profile.value = await get(`/users/${profile.value.id}`);
events.emit('feedback', {
type: isPublic ? 'success' : 'remove',
message: isPublic
? `Stash '${stash.name}' is public`
: `Stash '${stash.name}' is private`,
});
} catch (error) {
console.error(error);
events.emit('feedback', {
type: 'error',
message: 'Failed to update stash',
});
}
done.value = true;
}
</script>
<style scoped>
.profile-header {
display: flex;
align-items: center;
padding: .5rem 1rem;
color: var(--highlight-strong-30);
background: var(--grey-dark-40);
}
.username {
margin: 0;
font-size: 1.25rem;
}
.avatar {
width: 1.5rem;
height: 1.5rem;
border-radius: .25rem;
margin-right: 1rem;
}
.stashes {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
gap: 1rem;
padding: 1rem;
}
.stash {
width: 100%;
background: var(--background);
box-shadow: 0 0 3px var(--shadow-weak-30);
&:hover {
box-shadow: 0 0 3px var(--shadow-weak-20);
}
}
.stash-header {
display: flex;
align-items: stretch;
border-bottom: solid 1px var(--shadow-weak-30);
font-weight: bold;
}
.icon.public {
display: flex;
height: auto;
padding: 0 .75rem;
fill: var(--shadow);
&:hover {
cursor: pointer;
fill: var(--shadow-strong-30);
}
}
.stash-name {
display: flex;
flex-grow: 1;
padding: .5rem;
overflow: hidden;
.icon {
margin-left: .75rem;
}
.icon.primary {
fill: var(--primary);
transform: translateY(1px);
}
}
.stash-counts {
display: flex;
justify-content: space-between;
}
.stash-count {
display: inline-flex;
align-items: center;
padding: .5rem;
flex-grow: 1;
font-size: .9rem;
.icon {
margin-right: .5rem;
fill: var(--shadow);
}
&:hover {
color: var(--primary);
.icon {
fill: var(--primary);
}
}
}
</style>