<template> <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.isPrimary" icon="heart7" class="primary" /> </a> <Icon v-if="!stash.public" v-tooltip="'This stash is private'" icon="eye-blocked" class="private noselect" /> <VDropdown> <Icon v-if="profile.id === user?.id" icon="more2" class="stash-more noselect" /> <template #popper> <ul class="stash-menu nolist"> <li v-if="stash.public" class="menu-item" @click="setPublic(false)" > <Icon icon="eye-blocked" class="noselect" />Set private </li> <li v-else class="menu-item" @click="setPublic(true)" > <Icon icon="eye" class="noselect" />Set public </li> <li v-if="!stash.isPrimary" v-close-popper class="menu-item" @click="showRenameDialog = true" > <Icon icon="pencil5" class="noselect" />Rename </li> <li v-if="!stash.isPrimary" class="menu-item remove" @click="remove()" > <Icon icon="bin" class="noselect" />Remove </li> </ul> </template> </VDropdown> </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> <Dialog v-if="showRenameDialog" title="Rename stash" @close="showRenameDialog = false" @open="stashNameInput?.focus()" > <form class="dialog-body" @submit.prevent="rename" > <input ref="stashNameInput" v-model="stashName" class="input" placeholder="Stash name" maxlength="24" > <button class="button button-submit" >Rename stash</button> </form> </Dialog> </div> </template> <script setup> import { ref, inject } from 'vue'; import { del, patch } from '#/src/api.js'; import abbreviateNumber from '#/src/utils/abbreviate-number.js'; import Dialog from '#/components/dialog/dialog.vue'; const props = defineProps({ stash: { type: Object, default: null, }, profile: { type: Object, default: null, }, }); const emit = defineEmits(['reload']); const pageContext = inject('pageContext'); const user = pageContext.user; const stashName = ref(props.stash.name); const stashNameInput = ref(null); const showRenameDialog = ref(false); const done = ref(true); async function setPublic(isPublic) { if (done.value === false) { return; } done.value = false; await patch(`/stashes/${props.stash.id}`, { public: isPublic }, { undoFeedback: !isPublic && `Stash '${props.stash.name}' set to private`, successFeedback: isPublic && `Stash '${props.stash.name}' set to public`, errorFeedback: 'Failed to update stash', appendErrorMessage: true, }).finally(() => { done.value = true; }); emit('reload'); } async function remove() { if (done.value === false) { return; } if (!confirm(`Are you sure you want to remove the stash '${props.stash.name}' and all its scenes, movies and actors? This is permament, it cannot be undone by you or staff!`)) { // eslint-disable-line no-restricted-globals, no-alert return; } done.value = false; await del(`/stashes/${props.stash.id}`, { undoFeedback: `Stash '${props.stash.name}' removed`, errorFeedback: 'Failed to remove stash', appendErrorMessage: true, }).finally(() => { done.value = true; }); emit('reload'); } async function rename() { if (done.value === false) { return; } done.value = false; await patch(`/stashes/${props.stash.id}`, { name: stashName.value }, { successFeedback: `Stash renamed to ${stashName.value}`, errorFeedback: 'Failed to rename stash', appendErrorMessage: true, }).finally(() => { done.value = true; }); emit('reload'); showRenameDialog.value = false; } </script> <style scoped> .stash { width: 100%; border-radius: .25rem; 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; } .stash-more { display: flex; height: 100%; 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); } } } .icon.private { display: flex; height: auto; fill: var(--shadow-weak-20); padding-left: .5rem; } .menu-item { display: flex; align-items: center; padding: .75rem; .icon { display: flex; margin-right: .75rem; fill: var(--shadow); } &.remove { .icon { fill: var(--error); } } &:hover { color: var(--primary); cursor: pointer; &.remove { color: var(--error); } .icon { fill: var(--primary); } } } .dialog-body { padding: 1rem; .input { margin-bottom: .5rem; } } </style>